View Javadoc
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.regex.Matcher;
20  
21  import org.apache.commons.collections4.MultiValuedMap;
22  
23  /**
24   * Joins the values of multiple columns from the input into one bean field based
25   * on a selection of column positions.
26   * 
27   * @author Andrew Rucker Jones
28   * @since 4.2
29   */
30  @Documented
31  @Retention(RetentionPolicy.RUNTIME)
32  @Target(ElementType.FIELD)
33  @Repeatable(CsvBindAndJoinByPositions.class)
34  public @interface CsvBindAndJoinByPosition {
35  
36      /**
37       * Whether or not the annotated field is required to be present in every
38       * data set of the input.
39       * This means that the input cannot be empty. The output after conversion is
40       * not guaranteed to be non-empty. "Input" means the string from every
41       * matching field in the CSV file on reading and the bean member variable on
42       * writing.
43       *
44       * @return If the field is required to contain information.
45       */
46      boolean required() default false;
47  
48      /**
49       * The column position(s) in the input that is/are used to fill the
50       * annotated field.
51       * This field allows comma-separated lists of columns, e.g. "2,4,6", as well
52       * as ranges, including open-ended ranges, e.g. "3-5", "10-" or "-3". With
53       * the open-ended versions the implicit ends are the first and last column.
54       * A mixture of these forms is naturally possible, e.g. "2,4,6-10". Nothing
55       * bad will happen if you make a silly list, like "4,2,-0,1000-,10-5".
56       *
57       * @return The position(s) of the column(s) in the CSV file from which this
58       * field should be taken. The column numbers are zero-based.
59       */
60      String position();
61  
62      /**
63       * Defines the locale to be used for decoding the argument.
64       * <p>If not specified, the current default locale is used. The locale must be
65       * one recognized by {@link java.util.Locale}. Locale conversion is supported
66       * for the following data types:<ul>
67       * <li>byte and {@link java.lang.Byte}</li>
68       * <li>float and {@link java.lang.Float}</li>
69       * <li>double and {@link java.lang.Double}</li>
70       * <li>int and {@link java.lang.Integer}</li>
71       * <li>long and {@link java.lang.Long}</li>
72       * <li>short and {@link java.lang.Short}</li>
73       * <li>{@link java.math.BigDecimal}</li>
74       * <li>{@link java.math.BigInteger}</li>
75       * <li>All time data types supported by {@link com.opencsv.bean.CsvDate}</li></ul>
76       * <p>The locale must be in a format accepted by
77       * {@link java.util.Locale#forLanguageTag(java.lang.String)}</p>
78       * <p>Caution must be exercised with the default locale, for the default
79       * locale for numerical types does not mean the locale of the running
80       * program, such as en-US or de-DE, but rather <em>no</em> locale. Numbers
81       * will be parsed more or less the way the Java compiler would parse them.
82       * That means, for instance, that thousands separators in long numbers are
83       * not permitted, even if the locale of the running program would accept
84       * them. When dealing with locale-sensitive data, it is always best to
85       * specify the locale explicitly.</p>
86       *
87       * @return The locale selected. The default is indicated by an empty string.
88       */
89      String locale() default "";
90  
91      /**
92       * Whether or not the same locale is used for writing as for reading.
93       * If this is true, {@link #locale()} is used for both reading and writing
94       * and {@link #writeLocale()} is ignored.
95       *
96       * @return Whether the read locale is used for writing as well
97       * @since 5.0
98       */
99      boolean writeLocaleEqualsReadLocale() default true;
100 
101     /**
102      * The locale for writing.
103      * This field is ignored unless {@link #writeLocaleEqualsReadLocale()} is
104      * {@code false}. The format is identical to {@link #locale()}.
105      *
106      * @return The locale for writing, if one is in use
107      * @see #locale()
108      * @see #writeLocaleEqualsReadLocale()
109      * @since 5.0
110      */
111     String writeLocale() default "";
112 
113     /**
114      * Defines the class used for the multi-valued map.
115      * <p>This must be a specific implementation of
116      * {@link org.apache.commons.collections4.MultiValuedMap}, and not an
117      * interface! The default is set to {@code MultiValuedMap.class} as a signal
118      * to use the default for the interface supplied in the bean to be
119      * populated.</p>
120      * <p>The logic for determining which class to instantiate for the
121      * multi-valued map is as follows. In all cases, the implementation must
122      * have a nullary constructor.</p>
123      * <ol><li>If the bean declares a specific implementation instead of the
124      * associated interface
125      * (e.g. {@link org.apache.commons.collections4.multimap.ArrayListValuedHashMap}
126      * vs.
127      * {@link org.apache.commons.collections4.ListValuedMap}), that specific
128      * implementation will always be used.</li>
129      * <li>Otherwise, the implementation named in this field will be used, if it
130      * is not an interface.</li>
131      * <li>If no implementation is specified in this field (i.e. if
132      * an interface is specified, as is the default), a default is used
133      * based on the interface of the bean field annotated. These are:
134      * <ul><li>{@link org.apache.commons.collections4.multimap.ArrayListValuedHashMap} for {@link org.apache.commons.collections4.MultiValuedMap}</li>
135      * <li>{@link org.apache.commons.collections4.multimap.ArrayListValuedHashMap} for {@link org.apache.commons.collections4.ListValuedMap}</li>
136      * <li>{@link org.apache.commons.collections4.multimap.HashSetValuedHashMap} for {@link org.apache.commons.collections4.SetValuedMap}</li></ul></li></ol>
137      * 
138      * @return A class implementing {@link org.apache.commons.collections4.MultiValuedMap}
139      */
140     Class<? extends MultiValuedMap> mapType() default MultiValuedMap.class;
141     
142     /**
143      * Defines what type the elements of the map should have.
144      * It is necessary to instantiate elements of the map, and it is not
145      * always possible to determine the type of the elements at runtime.
146      * A perfect example of this is {@code Map<String, ? extends Number>}.
147      * 
148      * @return The type of the map elements
149      */
150     Class<?> elementType();
151 
152     /**
153      * Once the data points have been recovered from the various columns of the
154      * input, a custom converter can optionally be specified for conversion of
155      * each of the data points before they are joined in a
156      * {@link org.apache.commons.collections4.MultiValuedMap}.
157      *
158      * @return The converter applied to each of the data points extracted from
159      * the input
160      * @since 4.3
161      */
162     Class<? extends AbstractCsvConverter> converter() default AbstractCsvConverter.class;
163 
164     /**
165      * If this is anything but an empty string, it will be used as a regular
166      * expression to extract part of the input before conversion to the bean
167      * field.
168      * <p>An empty string behaves as if the regular expression {@code ^(.*)$}
169      * had been specified.</p>
170      * <p>The regular expression will be compiled and every field of input will
171      * be passed through it, naturally after the input has been normalized
172      * (quotations and escape characters removed). The first capture group will
173      * be extracted, and that string will be passed on to the appropriate
174      * conversion routine for the bean field in question.</p>
175      * <p>This makes it possible to easily convert input fields with forms like
176      * {@code Grade: 94.2} into {@code 94.2}, which can then be converted to a
177      * floating point bean field, all without writing a custom converter.</p>
178      * <p>The regular expression is applied to the entire string in question
179      * (i.e. with {@link Matcher#matches()}), instead of just the beginning of
180      * the string ({@link Matcher#lookingAt()}) or anywhere in the string
181      * ({@link Matcher#find()}). If it fails to match, the input string is
182      * passed unchanged to the appropriate conversion routine for the bean
183      * field. The reason for this is two-fold:</p>
184      * <ol><li>The matching may occur against an empty string. If the field is
185      * not required, this is legitimate, but it's likely the regular expression
186      * is not written to accommodate this possibility, and it may indeed not be
187      * at all desirable to.</li>
188      * <li>If there is an error in either the regular expression or the input
189      * that causes the match to fail, there is a good likelihood that the
190      * subsequent conversion will fail with a
191      * {@link com.opencsv.exceptions.CsvDataTypeMismatchException} if the
192      * input is not being converted into a simple string.</li></ol>
193      * <p>This is the inverse operation of {@link #format()}.</p>
194      *
195      * @return A regular expression, the first capture group of which will be
196      * used for conversion to the bean field
197      * @since 4.3
198      */
199     String capture() default "";
200 
201     /**
202      * If this is anything but an empty string, it will be used as a format
203      * string for {@link java.lang.String#format(String, Object...)} on
204      * writing.
205      * <p>An empty string behaves as if the format string {@code "%s"} had been
206      * specified.</p>
207      * <p>The format string, if it is not empty, should contain one and only
208      * one {@code %s}, which will be replaced by the string value of the bean
209      * field after conversion. If, however, the bean field is empty, then the
210      * output will be empty as well, as opposed to passing an empty string to
211      * this format string and using that as the output.</p>
212      * <p>This is the inverse operation of {@link #capture()}.</p>
213      *
214      * @return A format string for writing fields
215      * @since 4.3
216      */
217     String format() default "";
218 
219     /**
220      * A profile can be used to annotate the same field differently for
221      * different inputs or outputs.
222      * <p>Perhaps you have multiple input sources, and they all use different
223      * header names or positions for the same data. With profiles, you don't
224      * have to create different beans with the same fields and different
225      * annotations for each input. Simply annotate the same field multiple
226      * times and specify the profile when you parse the input.</p>
227      * <p>The same applies to output: if you want to be able to represent the
228      * same data in multiple CSV formats (that is, with different headers or
229      * orders), annotate the bean fields multiple times with different profiles
230      * and specify which profile you want to use on writing.</p>
231      * <p>Results are undefined if profile names are not unique.</p>
232      * <p>If the same configuration applies to multiple profiles, simply list
233      * all applicable profile names here. This parameter is an array of
234      * strings.</p>
235      * <p>The empty string, which is the default value, specifies the default
236      * profile and will be used if no annotation for the specific profile
237      * being used can be found, or if no profile is specified.</p>
238      *
239      * @return The names of the profiles this configuration is for
240      * @since 5.4
241      */
242     String[] profiles() default "";
243 }