/*
 * Copyright 2016 Andrew Rucker Jones.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.opencsv.bean;

import com.opencsv.ICSVParser;
import com.opencsv.exceptions.CsvBadConverterException;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.reflect.FieldUtils;

import java.util.IllegalFormatException;
import java.util.Locale;
import java.util.ResourceBundle;
import java.util.concurrent.BlockingQueue;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import java.util.stream.Stream;

This class is meant to be a collection of general purpose static methods useful in processing mapping strategies.
Author:Andrew Rucker Jones
Since:3.9
/** * This class is meant to be a collection of general purpose static methods * useful in processing mapping strategies. * * @author Andrew Rucker Jones * @since 3.9 */
public final class OpencsvUtils {
This class can't be instantiated.
/** This class can't be instantiated. */
private OpencsvUtils() {}
Determines which mapping strategy is appropriate for this bean. The algorithm is:
  1. If annotations CsvBindByPosition, CsvCustomBindByPosition, CsvBindAndSplitByPosition or CsvBindAndJoinByPosition are present, ColumnPositionMappingStrategy is chosen.
  2. Otherwise, HeaderColumnNameMappingStrategy is chosen. If annotations are present, they will be used, otherwise the field names will be used as the column names.
Params:
  • type – The class of the bean for which the mapping strategy is sought
  • errorLocale – The locale to use for all error messages. If null, the default locale is used.
Type parameters:
  • <T> – The type of the bean for which the mapping strategy is sought
Returns:A functional mapping strategy for the bean in question
/** * Determines which mapping strategy is appropriate for this bean. * The algorithm is:<ol> * <li>If annotations {@link CsvBindByPosition}, * {@link CsvCustomBindByPosition}, {@link CsvBindAndSplitByPosition} or * {@link CsvBindAndJoinByPosition} are present, * {@link ColumnPositionMappingStrategy} is chosen.</li> * <li>Otherwise, {@link HeaderColumnNameMappingStrategy} is chosen. If * annotations are present, they will be used, otherwise the field names * will be used as the column names.</li></ol> * * @param <T> The type of the bean for which the mapping strategy is sought * @param type The class of the bean for which the mapping strategy is sought * @param errorLocale The locale to use for all error messages. If null, the * default locale is used. * @return A functional mapping strategy for the bean in question */
static <T> MappingStrategy<T> determineMappingStrategy(Class<? extends T> type, Locale errorLocale) { // Check for annotations boolean positionAnnotationsPresent = Stream.of(FieldUtils.getAllFields(type)).anyMatch( f -> f.isAnnotationPresent(CsvBindByPosition.class) || f.isAnnotationPresent(CsvBindAndSplitByPosition.class) || f.isAnnotationPresent(CsvBindAndJoinByPosition.class) || f.isAnnotationPresent(CsvCustomBindByPosition.class)); // Set the mapping strategy according to what we've found. MappingStrategy<T> mappingStrategy = positionAnnotationsPresent ? new ColumnPositionMappingStrategy<>() : new HeaderColumnNameMappingStrategy<>(); mappingStrategy.setErrorLocale(errorLocale); mappingStrategy.setType(type); return mappingStrategy; }
I find it annoying that when I want to queue something in a blocking queue, the thread might be interrupted and I have to try again; this method fixes that.
Params:
  • queue – The queue the object should be added to
  • object – The object to be queued
Type parameters:
  • <E> – The type of the object to be queued
Since:4.0
/** * I find it annoying that when I want to queue something in a blocking * queue, the thread might be interrupted and I have to try again; this * method fixes that. * @param <E> The type of the object to be queued * @param queue The queue the object should be added to * @param object The object to be queued * @since 4.0 */
public static <E> void queueRefuseToAcceptDefeat(BlockingQueue<E> queue, E object) { boolean interrupted = true; while(interrupted) { try { queue.put(object); interrupted = false; } catch(InterruptedException ie) {/* Do nothing. */} } }
Compiles a regular expression into a Pattern, throwing an exception that is proper in the context of opencsv if the regular expression is not valid, or if it does not have at least one capturing group.
Params:
  • regex – The regular expression to be compiled. May be null or an empty string, in which case null is returned. Must have at least one capturing group if not null or empty.
  • regexFlags – Flags for compiling the regular expression, as in Pattern.compile(String, int).
  • callingClass – The class from which this method is being called. Used for generating helpful exceptions.
  • errorLocale – The locale to be used for error messages. If null, the default locale is used.
Throws:
  • CsvBadConverterException – If the regular expression is not empty but invalid or valid but does not have at least one capturing group
Returns:A compiled pattern, or null if the input was null or empty
Since:4.3
/** * Compiles a regular expression into a {@link java.util.regex.Pattern}, * throwing an exception that is proper in the context of opencsv if the * regular expression is not valid, or if it does not have at least one * capturing group. * * @param regex The regular expression to be compiled. May be {@code null} * or an empty string, in which case {@code null} is returned. * Must have at least one capturing group if not {@code null} * or empty. * @param regexFlags Flags for compiling the regular expression, as in * {@link java.util.regex.Pattern#compile(String, int)}. * @param callingClass The class from which this method is being called. * Used for generating helpful exceptions. * @param errorLocale The locale to be used for error messages. If * {@code null}, the default locale is used. * @return A compiled pattern, or {@code null} if the input was null or * empty * @throws CsvBadConverterException If the regular expression is not empty * but invalid or valid but does not have at least one capturing group * @since 4.3 */
static Pattern compilePatternAtLeastOneGroup(String regex, int regexFlags, Class<?> callingClass, Locale errorLocale) throws CsvBadConverterException { Pattern tempPattern = compilePattern(regex, regexFlags, callingClass, errorLocale); Locale exceptionLocale = errorLocale == null ? Locale.getDefault() : errorLocale; // Verify that the pattern has at least one capture group. This does // not appear to be possible without matching a string first. if(tempPattern != null) { Matcher m = tempPattern.matcher(StringUtils.EMPTY); if(m.groupCount() < 1) { throw new CsvBadConverterException(callingClass, String.format(ResourceBundle.getBundle( ICSVParser.DEFAULT_BUNDLE_NAME, exceptionLocale).getString("regex.without.capture.group"), regex)); } } return tempPattern; }
Compiles a regular expression into a Pattern, throwing an exception that is proper in the context of opencsv if the regular expression is not valid. This method may be used by custom converters if they are required to compile regular expressions that are unknown at compile time.
Params:
  • regex – The regular expression to be compiled. May be null or an empty string, in which case null is returned.
  • regexFlags – Flags for compiling the regular expression, as in Pattern.compile(String, int).
  • callingClass – The class from which this method is being called. Used for generating helpful exceptions.
  • errorLocale – The locale to be used for error messages. If null, the default locale is used.
Throws:
Returns:A compiled pattern, or null if the input was null or empty
Since:4.3
/** * Compiles a regular expression into a {@link java.util.regex.Pattern}, * throwing an exception that is proper in the context of opencsv if the * regular expression is not valid. * This method may be used by custom converters if they are required to * compile regular expressions that are unknown at compile time. * * @param regex The regular expression to be compiled. May be {@code null} * or an empty string, in which case {@code null} is returned. * @param regexFlags Flags for compiling the regular expression, as in * {@link java.util.regex.Pattern#compile(String, int)}. * @param callingClass The class from which this method is being called. * Used for generating helpful exceptions. * @param errorLocale The locale to be used for error messages. If * {@code null}, the default locale is used. * @return A compiled pattern, or {@code null} if the input was null or * empty * @throws CsvBadConverterException If the regular expression is not empty * but invalid * @since 4.3 */
static Pattern compilePattern(String regex, int regexFlags, Class<?> callingClass, Locale errorLocale) throws CsvBadConverterException { Pattern tempPattern = null; Locale exceptionLocale = errorLocale == null ? Locale.getDefault() : errorLocale; // Set up the regular expression for extraction of the value to be // converted if(StringUtils.isNotEmpty(regex)) { try { tempPattern = Pattern.compile(regex, regexFlags); } catch(PatternSyntaxException e) { CsvBadConverterException csve = new CsvBadConverterException( callingClass, String.format(ResourceBundle.getBundle( ICSVParser.DEFAULT_BUNDLE_NAME, exceptionLocale).getString("invalid.regex"), regex)); csve.initCause(e); throw csve; } } return tempPattern; }
Verifies that the given format string works with one string parameter.
Params:
  • format – A format string for String.format(String, Object...)
  • callingClass – The class from which this method is being called. Used for generating helpful exceptions.
  • errorLocale – The locale to be used for error messages. If null, the default locale is used.
/** * Verifies that the given format string works with one string parameter. * * @param format A format string for {@link java.lang.String#format(String, Object...)} * @param callingClass The class from which this method is being called. * Used for generating helpful exceptions. * @param errorLocale The locale to be used for error messages. If * {@code null}, the default locale is used. */
static void verifyFormatString(String format, Class<?> callingClass, Locale errorLocale) { Locale exceptionLocale = errorLocale == null ? Locale.getDefault() : errorLocale; try { if(StringUtils.isNotEmpty(format)) { String okayToIgnore = String.format(format, StringUtils.SPACE); } } catch(IllegalFormatException e) { CsvBadConverterException csve = new CsvBadConverterException( callingClass, String.format(ResourceBundle.getBundle( ICSVParser.DEFAULT_BUNDLE_NAME, exceptionLocale).getString("invalid.one.parameter.format.string"), format)); csve.initCause(e); throw csve; } } }