View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   https://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.commons.csv.issues;
20  
21  import static org.junit.jupiter.api.Assertions.assertEquals;
22  
23  import java.io.IOException;
24  import java.io.StringReader;
25  
26  import org.apache.commons.csv.CSVFormat;
27  import org.apache.commons.csv.CSVParser;
28  import org.apache.commons.csv.CSVRecord;
29  import org.apache.commons.csv.QuoteMode;
30  import org.junit.jupiter.api.Test;
31  
32  /**
33   * Add more tests about null value.
34   * <p>
35   * QuoteMode:ALL_NON_NULL (Quotes all non-null fields, null will not be quoted but not null will be quoted). when
36   * withNullString("NULL"), NULL String value ("NULL") and null value (null) will be formatted as '"NULL",NULL'. So it
37   * also should be parsed as NULL String value and null value (["NULL", null]), It should be distinguish in parsing. And
38   * when don't set nullString in CSVFormat, String '"",' should be parsed as "" and null (["", null]) according to null
39   * will not be quoted but not null will be quoted. QuoteMode:NON_NUMERIC, same as ALL_NON_NULL.
40   * </p>
41   * <p>
42   * This can solve the problem of distinguishing between empty string columns and absent value columns which just like
43   * Jira CSV-253 to a certain extent.
44   * </p>
45   */
46  class JiraCsv93Test {
47      private static Object[] objects1 = {"abc", "", null, "a,b,c", 123};
48  
49      private static Object[] objects2 = {"abc", "NULL", null, "a,b,c", 123};
50  
51      private void every(final CSVFormat csvFormat, final Object[] objects, final String format, final String[] data)
52          throws IOException {
53          final String source = csvFormat.format(objects);
54          assertEquals(format, csvFormat.format(objects));
55          try (CSVParser csvParser = csvFormat.parse(new StringReader(source))) {
56              final CSVRecord csvRecord = csvParser.iterator().next();
57              for (int i = 0; i < data.length; i++) {
58                  assertEquals(csvRecord.get(i), data[i]);
59              }
60          }
61      }
62  
63      @Test
64      void testWithNotSetNullString() throws IOException {
65          // @formatter:off
66          every(CSVFormat.DEFAULT,
67                  objects1,
68                  "abc,,,\"a,b,c\",123",
69                  new String[]{"abc", "", "", "a,b,c", "123"});
70          every(CSVFormat.DEFAULT.builder().setQuoteMode(QuoteMode.ALL).get(),
71                  objects1,
72                  "\"abc\",\"\",,\"a,b,c\",\"123\"",
73                  new String[]{"abc", "", "", "a,b,c", "123"});
74          every(CSVFormat.DEFAULT.builder().setQuoteMode(QuoteMode.ALL_NON_NULL).get(),
75                  objects1,
76                  "\"abc\",\"\",,\"a,b,c\",\"123\"",
77                  new String[]{"abc", "", null, "a,b,c", "123"});
78          every(CSVFormat.DEFAULT.builder().setQuoteMode(QuoteMode.MINIMAL).get(),
79                  objects1,
80                  "abc,,,\"a,b,c\",123",
81                  new String[]{"abc", "", "", "a,b,c", "123"});
82          every(CSVFormat.DEFAULT.builder().setEscape('?').setQuoteMode(QuoteMode.NONE).get(),
83                  objects1,
84                  "abc,,,a?,b?,c,123",
85                  new String[]{"abc", "", "", "a,b,c", "123"});
86          every(CSVFormat.DEFAULT.builder().setQuoteMode(QuoteMode.NON_NUMERIC).get(),
87                  objects1,
88                  "\"abc\",\"\",,\"a,b,c\",123",
89                  new String[]{"abc", "", null, "a,b,c", "123"});
90          // @formatter:on
91      }
92  
93      @Test
94      void testWithSetNullStringEmptyString() throws IOException {
95          // @formatter:off
96          every(CSVFormat.DEFAULT.builder().setNullString("").get(),
97                  objects1,
98                  "abc,,,\"a,b,c\",123",
99                  new String[]{"abc", null, null, "a,b,c", "123"});
100         every(CSVFormat.DEFAULT.builder().setNullString("").setQuoteMode(QuoteMode.ALL).get(),
101                 objects1,
102                 "\"abc\",\"\",\"\",\"a,b,c\",\"123\"",
103                 new String[]{"abc", null, null, "a,b,c", "123"});
104         every(CSVFormat.DEFAULT.builder().setNullString("").setQuoteMode(QuoteMode.ALL_NON_NULL).get(),
105                 objects1,
106                 "\"abc\",\"\",,\"a,b,c\",\"123\"",
107                 new String[]{"abc", "", null, "a,b,c", "123"});
108         every(CSVFormat.DEFAULT.builder().setNullString("").setQuoteMode(QuoteMode.MINIMAL).get(),
109                 objects1,
110                 "abc,,,\"a,b,c\",123",
111                 new String[]{"abc", null, null, "a,b,c", "123"});
112         every(CSVFormat.DEFAULT.builder().setNullString("").setEscape('?').setQuoteMode(QuoteMode.NONE).get(),
113                 objects1,
114                 "abc,,,a?,b?,c,123",
115                 new String[]{"abc", null, null, "a,b,c", "123"});
116         every(CSVFormat.DEFAULT.builder().setNullString("").setQuoteMode(QuoteMode.NON_NUMERIC).get(),
117                 objects1,
118                 "\"abc\",\"\",,\"a,b,c\",123",
119                 new String[]{"abc", "", null, "a,b,c", "123"});
120         // @formatter:on
121     }
122 
123     @Test
124     void testWithSetNullStringNULL() throws IOException {
125         // @formatter:off
126         every(CSVFormat.DEFAULT.builder().setNullString("NULL").get(),
127                 objects2,
128                 "abc,NULL,NULL,\"a,b,c\",123",
129                 new String[]{"abc", null, null, "a,b,c", "123"});
130         every(CSVFormat.DEFAULT.builder().setNullString("NULL").setQuoteMode(QuoteMode.ALL).get(),
131                 objects2,
132                 "\"abc\",\"NULL\",\"NULL\",\"a,b,c\",\"123\"",
133                 new String[]{"abc", null, null, "a,b,c", "123"});
134         every(CSVFormat.DEFAULT.builder().setNullString("NULL").setQuoteMode(QuoteMode.ALL_NON_NULL).get(),
135                 objects2,
136                 "\"abc\",\"NULL\",NULL,\"a,b,c\",\"123\"",
137                 new String[]{"abc", "NULL", null, "a,b,c", "123"});
138         every(CSVFormat.DEFAULT.builder().setNullString("NULL").setQuoteMode(QuoteMode.MINIMAL).get(),
139                 objects2,
140                 "abc,NULL,NULL,\"a,b,c\",123",
141                 new String[]{"abc", null, null, "a,b,c", "123"});
142         every(CSVFormat.DEFAULT.builder().setNullString("NULL").setEscape('?').setQuoteMode(QuoteMode.NONE).get(),
143                 objects2,
144                 "abc,NULL,NULL,a?,b?,c,123",
145                 new String[]{"abc", null, null, "a,b,c", "123"});
146         every(CSVFormat.DEFAULT.builder().setNullString("NULL").setQuoteMode(QuoteMode.NON_NUMERIC).get(),
147                 objects2,
148                 "\"abc\",\"NULL\",NULL,\"a,b,c\",123",
149                 new String[]{"abc", "NULL", null, "a,b,c", "123"});
150         // @formatter:on
151     }
152 }