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 com.opencsv.ICSVParser;
19  import com.opencsv.bean.util.OpencsvUtils;
20  import com.opencsv.exceptions.CsvBadConverterException;
21  import com.opencsv.exceptions.CsvConstraintViolationException;
22  import com.opencsv.exceptions.CsvDataTypeMismatchException;
23  import org.apache.commons.lang3.StringUtils;
24  
25  import java.lang.reflect.Field;
26  import java.util.Locale;
27  import java.util.ResourceBundle;
28  import java.util.regex.Matcher;
29  import java.util.regex.Pattern;
30  
31  /**
32   * This class concerns itself with handling single-valued bean fields.
33   * 
34   * @param <T> The type of the bean being populated
35   * @param <I> Type of the index into a multivalued field
36   * @author Andrew Rucker Jones
37   * @since 4.2
38   */
39  public class BeanFieldSingleValue<T, I> extends AbstractBeanField<T, I> {
40  
41      /**
42       * The regular expression to be used for capturing part of the input for
43       * processing. If there was no regular expression specified, this field
44       * is {@code null}.
45       */
46      protected final Pattern capture;
47  
48      /**
49       * The format string used for packaging values to be written. If
50       * {@code null} or empty, it is ignored.
51       */
52      protected final String writeFormat;
53      
54      /**
55       * Simply calls the same constructor in the base class.
56       *
57       * @param type The type of the class in which this field is found. This is
58       *             the type as instantiated by opencsv, and not necessarily the
59       *             type in which the field is declared in the case of
60       *             inheritance.
61       * @param field A {@link java.lang.reflect.Field} object.
62       * @param required Whether or not this field is required in input
63       * @param errorLocale The errorLocale to use for error messages.
64       * @param converter The converter to be used to perform the actual data
65       *   conversion
66       * @param capture See {@link CsvBindByName#capture()}
67       * @param format The format string used for packaging values to be written.
68       *               If {@code null} or empty, it is ignored.
69       * @see AbstractBeanField#AbstractBeanField(Class, Field, boolean, Locale, CsvConverter)
70       */
71      public BeanFieldSingleValue(Class<?> type, Field field, boolean required,
72                                  Locale errorLocale, CsvConverter converter,
73                                  String capture, String format) {
74          super(type, field, required, errorLocale, converter);
75          this.capture = OpencsvUtils.compilePatternAtLeastOneGroup(
76                  capture, 0, BeanFieldSingleValue.class, this.errorLocale);
77          this.writeFormat = format;
78  
79          // Verify that the format string works as expected
80          OpencsvUtils.verifyFormatString(this.writeFormat, BeanFieldSingleValue.class, this.errorLocale);
81      }
82  
83      /**
84       * Passes the string to be converted to the converter.
85       * @throws CsvBadConverterException If the converter is null
86       */
87      // The rest of the Javadoc is inherited
88      @Override
89      protected Object convert(String value) throws CsvDataTypeMismatchException, CsvConstraintViolationException {
90          String convertValue = value;
91          if(capture != null && value != null) {
92              Matcher m = capture.matcher(value);
93              if(m.matches()) {
94                  convertValue = m.group(1);
95              }
96              // Otherwise value remains intentionally unchanged
97          }
98          if(converter != null) {
99              return converter.convertToRead(convertValue);
100         }
101         throw new CsvBadConverterException(ResourceBundle.getBundle(ICSVParser.DEFAULT_BUNDLE_NAME, errorLocale).getString("no.converter.specified"));
102     }
103     
104     /**
105      * Passes the object to be converted to the converter.
106      * @throws CsvBadConverterException If the converter is null
107      */
108     // The rest of the Javadoc is inherited
109     @Override
110     protected String convertToWrite(Object value) throws CsvDataTypeMismatchException {
111         if(converter != null) {
112             String s = converter.convertToWrite(value);
113             if(StringUtils.isNotEmpty(this.writeFormat)
114                     && StringUtils.isNotEmpty(s)) {
115                 s = String.format(this.writeFormat, s);
116             }
117             return s;
118         }
119         throw new CsvBadConverterException(ResourceBundle.getBundle(ICSVParser.DEFAULT_BUNDLE_NAME, errorLocale).getString("no.converter.specified"));
120     }
121 }