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