1 /*
2 * Copyright 2017 Andrew Rucker Jones.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package com.opencsv.bean;
17
18 import java.lang.annotation.*;
19 import java.util.Collection;
20 import java.util.regex.Matcher;
21
22 /**
23 * This annotation interprets one field of the input as a collection that will
24 * be split up into its components and assigned to a collection-based bean field.
25 *
26 * @author Andrew Rucker Jones
27 * @since 4.2
28 */
29 @Documented
30 @Retention(RetentionPolicy.RUNTIME)
31 @Target(ElementType.FIELD)
32 @Repeatable(CsvBindAndSplitByPositions.class)
33 public @interface CsvBindAndSplitByPosition {
34
35 /**
36 * Whether or not the annotated field is required to be present in every
37 * data set of the input.
38 * This means that the input cannot be empty. The output after conversion is
39 * not guaranteed to be non-empty. "Input" means the string from the field
40 * in the CSV file on reading and the bean member variable on writing.
41 *
42 * @return If the field is required to contain information.
43 */
44 boolean required() default false;
45
46 /**
47 * The column position in the input that is used to fill the annotated
48 * field.
49 *
50 * @return The position of the column in the CSV file from which this field
51 * should be taken. This column number is zero-based.
52 */
53 int position();
54
55 /**
56 * Defines the locale to be used for decoding the argument.
57 * <p>If not specified, the current default locale is used. The locale must be
58 * one recognized by {@link java.util.Locale}. Locale conversion is supported
59 * for the following data types:<ul>
60 * <li>byte and {@link java.lang.Byte}</li>
61 * <li>float and {@link java.lang.Float}</li>
62 * <li>double and {@link java.lang.Double}</li>
63 * <li>int and {@link java.lang.Integer}</li>
64 * <li>long and {@link java.lang.Long}</li>
65 * <li>short and {@link java.lang.Short}</li>
66 * <li>{@link java.math.BigDecimal}</li>
67 * <li>{@link java.math.BigInteger}</li>
68 * <li>All time data types supported by {@link com.opencsv.bean.CsvDate}</li></ul>
69 * <p>The locale must be in a format accepted by
70 * {@link java.util.Locale#forLanguageTag(java.lang.String)}</p>
71 * <p>Caution must be exercised with the default locale, for the default
72 * locale for numerical types does not mean the locale of the running
73 * program, such as en-US or de-DE, but rather <em>no</em> locale. Numbers
74 * will be parsed more or less the way the Java compiler would parse them.
75 * That means, for instance, that thousands separators in long numbers are
76 * not permitted, even if the locale of the running program would accept
77 * them. When dealing with locale-sensitive data, it is always best to
78 * specify the locale explicitly.</p>
79 *
80 * @return The locale selected. The default is indicated by an empty string.
81 */
82 String locale() default "";
83
84 /**
85 * Whether or not the same locale is used for writing as for reading.
86 * If this is true, {@link #locale()} is used for both reading and writing
87 * and {@link #writeLocale()} is ignored.
88 *
89 * @return Whether the read locale is used for writing as well
90 * @since 5.0
91 */
92 boolean writeLocaleEqualsReadLocale() default true;
93
94 /**
95 * The locale for writing.
96 * This field is ignored unless {@link #writeLocaleEqualsReadLocale()} is
97 * {@code false}. The format is identical to {@link #locale()}.
98 *
99 * @return The locale for writing, if one is in use
100 * @see #locale()
101 * @see #writeLocaleEqualsReadLocale()
102 * @since 5.0
103 */
104 String writeLocale() default "";
105
106 /**
107 * Defines a regular expression for splitting the input.
108 * The input string is split using the value of this attribute and the
109 * result is put into a collection. The default splits on whitespace.
110 *
111 * @return The regular expression used for splitting the input
112 */
113 String splitOn() default "\\s+";
114
115 /**
116 * When writing a collection from a bean, this string will be used to
117 * separate elements of the collection.
118 * Defaults to one space.
119 *
120 * @return Delimiter between elements for writing a collection
121 */
122 String writeDelimiter() default " ";
123
124 /**
125 * Defines the class used for the collection.
126 * <p>This must be a specific implementation of a collection, and not an
127 * interface! The default is set to {@code Collection.class} as a signal to
128 * use the default for the interface supplied in the bean to be populated.</p>
129 * <p>The logic for determining which class to instantiate for the
130 * collection is as follows. In all cases, the implementation must have a
131 * nullary constructor.</p>
132 * <ol><li>If the bean declares a specific implementation instead of the
133 * associated interface (e.g. {@link java.util.ArrayList} vs.
134 * {@link java.util.List}), that specific implementation will always be
135 * used.</li>
136 * <li>Otherwise, the implementation named in this field will be used, if it
137 * is not an interface.</li>
138 * <li>If no implementation is specified in this field (i.e. if
139 * an interface is specified, as is the default), a default is used
140 * based on the interface of the bean field annotated. These are:
141 * <ul><li>{@link java.util.ArrayList} for {@link java.util.Collection}</li>
142 * <li>{@link java.util.ArrayList} for {@link java.util.List}</li>
143 * <li>{@link java.util.HashSet} for {@link java.util.Set} unless
144 * {@link #elementType()} is an enumeration type, in which case
145 * {@link java.util.EnumSet} is used</li>
146 * <li>{@link java.util.TreeSet} for {@link java.util.SortedSet}</li>
147 * <li>{@link java.util.TreeSet} for {@link java.util.NavigableSet}</li>
148 * <li>{@link java.util.ArrayDeque} for {@link java.util.Queue}</li>
149 * <li>{@link java.util.ArrayDeque} for {@link java.util.Deque}</li>
150 * <li>{@link org.apache.commons.collections4.bag.HashBag} for {@link org.apache.commons.collections4.Bag}</li>
151 * <li>{@link org.apache.commons.collections4.bag.TreeBag} for {@link org.apache.commons.collections4.SortedBag}</ul></li></ol>
152 *
153 * @return A class implementing {@link java.util.Collection}
154 */
155 Class<? extends Collection> collectionType() default Collection.class;
156
157 /**
158 * Defines what type the elements of the collection should have.
159 * It is necessary to instantiate elements of the collection, and it is not
160 * always possible to determine the type of the given collection at runtime.
161 * A perfect example of this is {@code List<? extends Number>}.
162 *
163 * @return The type of the collection elements
164 */
165 Class<?> elementType();
166
167 /**
168 * Once the input has been split, a custom converter can optionally be
169 * specified for conversion of each of the data points.
170 *
171 * @return The converter applied to each of the data points extracted from
172 * the input
173 * @since 4.3
174 */
175 Class<? extends AbstractCsvConverter> converter() default AbstractCsvConverter.class;
176
177 /**
178 * If this is anything but an empty string, it will be used as a regular
179 * expression to extract part of the input before conversion to the bean
180 * field.
181 * <p>An empty string behaves as if the regular expression {@code ^(.*)$}
182 * had been specified.</p>
183 * <p>The regular expression will be compiled and every field of input will
184 * be passed through it, naturally after the input has been normalized
185 * (quotations and escape characters removed). The first capture group will
186 * be extracted, and that string will be passed on to the appropriate
187 * conversion routine for the bean field in question.</p>
188 * <p>This makes it possible to easily convert input fields with forms like
189 * {@code Grade: 94.2} into {@code 94.2}, which can then be converted to a
190 * floating point bean field, all without writing a custom converter.</p>
191 * <p>In the case of splitting the input, which is what this annotation
192 * does, the input will be split <em>before</em> this regular expression is
193 * then applied to every element of the list resulting from splitting the
194 * input. This regular expression is <em>not</em> applied to the entire
195 * input field before splitting.</p>
196 * <p>The regular expression is applied to the entire string in question
197 * (i.e. with {@link Matcher#matches()}), instead of just the beginning of
198 * the string ({@link Matcher#lookingAt()}) or anywhere in the string
199 * ({@link Matcher#find()}). If it fails to match, the input string is
200 * passed unchanged to the appropriate conversion routine for the bean
201 * field. The reason for this is two-fold:</p>
202 * <ol><li>The matching may occur against an empty string. If the field is
203 * not required, this is legitimate, but it's likely the regular expression
204 * is not written to accommodate this possibility, and it may indeed not be
205 * at all desirable to.</li>
206 * <li>If there is an error in either the regular expression or the input
207 * that causes the match to fail, there is a good likelihood that the
208 * subsequent conversion will fail with a
209 * {@link com.opencsv.exceptions.CsvDataTypeMismatchException} if the
210 * input is not being converted into a simple string.</li></ol>
211 * <p>This is the inverse operation of {@link #format()}.</p>
212 *
213 * @return A regular expression, the first capture group of which will be
214 * used for conversion to the bean field
215 * @since 4.3
216 */
217 String capture() default "";
218
219 /**
220 * If this is anything but an empty string, it will be used as a format
221 * string for {@link java.lang.String#format(String, Object...)} on
222 * writing.
223 * <p>An empty string behaves as if the format string {@code "%s"} had been
224 * specified.</p>
225 * <p>The format string, if it is not empty, should contain one and only
226 * one {@code %s}, which will be replaced by the string value of the bean
227 * field after conversion. If, however, the bean field is empty, then the
228 * output will be empty as well, as opposed to passing an empty string to
229 * this format string and using that as the output.</p>
230 * <p>This formatting will be applied to every element of the input
231 * collection separately before writing.</p>
232 * <p>This is the inverse operation of {@link #capture()}.</p>
233 *
234 * @return A format string for writing fields
235 * @since 4.3
236 */
237 String format() default "";
238
239 /**
240 * A profile can be used to annotate the same field differently for
241 * different inputs or outputs.
242 * <p>Perhaps you have multiple input sources, and they all use different
243 * header names or positions for the same data. With profiles, you don't
244 * have to create different beans with the same fields and different
245 * annotations for each input. Simply annotate the same field multiple
246 * times and specify the profile when you parse the input.</p>
247 * <p>The same applies to output: if you want to be able to represent the
248 * same data in multiple CSV formats (that is, with different headers or
249 * orders), annotate the bean fields multiple times with different profiles
250 * and specify which profile you want to use on writing.</p>
251 * <p>Results are undefined if profile names are not unique.</p>
252 * <p>If the same configuration applies to multiple profiles, simply list
253 * all applicable profile names here. This parameter is an array of
254 * strings.</p>
255 * <p>The empty string, which is the default value, specifies the default
256 * profile and will be used if no annotation for the specific profile
257 * being used can be found, or if no profile is specified.</p>
258 *
259 * @return The names of the profiles this configuration is for
260 * @since 5.4
261 */
262 String[] profiles() default "";
263 }