All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.opencsv.bean.HeaderColumnNameMappingStrategy Maven / Gradle / Ivy

There is a newer version: 5.10
Show newest version
package com.opencsv.bean;

import org.apache.commons.collections4.ListValuedMap;
import org.apache.commons.lang3.StringUtils;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.*;

/*
 * Copyright 2007 Kyle Miller.
 *
 * 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.
 */

/**
 * Maps data to objects using the column names in the first row of the CSV file
 * as reference. This way the column order does not matter.
 *
 * @param  Type of the bean to be returned
 */
public class HeaderColumnNameMappingStrategy extends HeaderNameBaseMappingStrategy {

    /**
     * Default constructor. Considered stable.
     * @see HeaderColumnNameMappingStrategyBuilder
     */
    public HeaderColumnNameMappingStrategy() {
    }

    /**
     * Constructor to allow setting options for header name mapping.
     * Not considered stable. As new options are introduced for the mapping
     * strategy, they will be introduced here. You are encouraged to use
     * {@link HeaderColumnNameMappingStrategyBuilder}.
     *
     * @param forceCorrectRecordLength If set, every record will be shortened
     *                                 or lengthened to match the number of
     *                                 headers
     * @see HeaderColumnNameMappingStrategyBuilder
     */
    public HeaderColumnNameMappingStrategy(boolean forceCorrectRecordLength) {
        super(forceCorrectRecordLength);
    }

    /**
     * Register a binding between a bean field and a custom converter.
     *
     * @param annotation The annotation attached to the bean field
     * @param localType The class/type in which the field resides
     * @param localField The bean field
     */
    private void registerCustomBinding(CsvCustomBindByName annotation, Class localType, Field localField) {
        String columnName = annotation.column().toUpperCase().trim();
        if(StringUtils.isEmpty(columnName)) {
            columnName = localField.getName().toUpperCase();
        }
        @SuppressWarnings("unchecked")
        Class> converter = (Class>)annotation
                .converter();
        BeanField bean = instantiateCustomConverter(converter);
        bean.setType(localType);
        bean.setField(localField);
        bean.setRequired(annotation.required());
        fieldMap.put(columnName, bean);
    }

    /**
     * Register a binding between a bean field and a collection converter that
     * splits input into multiple values.
     *
     * @param annotation The annotation attached to the bean field
     * @param localType The class/type in which the field resides
     * @param localField The bean field
     */
    private void registerSplitBinding(CsvBindAndSplitByName annotation, Class localType, Field localField) {
        String columnName = annotation.column().toUpperCase().trim();
        String locale = annotation.locale();
        String writeLocale = annotation.writeLocaleEqualsReadLocale()
                ? locale : annotation.writeLocale();
        Class elementType = annotation.elementType();

        CsvConverter converter = determineConverter(
                localField, elementType, locale,
                writeLocale, annotation.converter());
        if (StringUtils.isEmpty(columnName)) {
            fieldMap.put(localField.getName().toUpperCase(),
                    new BeanFieldSplit<>(
                            localType, localField, annotation.required(),
                            errorLocale, converter, annotation.splitOn(),
                            annotation.writeDelimiter(),
                            annotation.collectionType(), elementType,
                            annotation.capture(), annotation.format()));
        } else {
            fieldMap.put(columnName, new BeanFieldSplit<>(
                    localType, localField, annotation.required(),
                    errorLocale, converter, annotation.splitOn(),
                    annotation.writeDelimiter(), annotation.collectionType(),
                    elementType, annotation.capture(), annotation.format()));
        }
    }

    /**
     * Register a binding between a bean field and a multi-valued converter
     * that joins values from multiple columns.
     *
     * @param annotation The annotation attached to the bean field
     * @param localType The class/type in which the field resides
     * @param localField The bean field
     */
    private void registerJoinBinding(CsvBindAndJoinByName annotation, Class localType, Field localField) {
        String columnRegex = annotation.column();
        String locale = annotation.locale();
        String writeLocale = annotation.writeLocaleEqualsReadLocale()
                ? locale : annotation.writeLocale();

        CsvConverter converter = determineConverter(
                localField, annotation.elementType(), locale,
                writeLocale, annotation.converter());
        if (StringUtils.isEmpty(columnRegex)) {
            fieldMap.putComplex(localField.getName(),
                    new BeanFieldJoinStringIndex<>(
                            localType, localField, annotation.required(),
                            errorLocale, converter, annotation.mapType(),
                            annotation.capture(), annotation.format()));
        } else {
            fieldMap.putComplex(columnRegex, new BeanFieldJoinStringIndex<>(
                    localType, localField, annotation.required(), errorLocale,
                    converter, annotation.mapType(), annotation.capture(),
                    annotation.format()));
        }
    }

    /**
     * Register a binding between a bean field and a simple converter.
     *
     * @param annotation The annotation attached to the bean field
     * @param localType The class/type in which the field resides
     * @param localField The bean field
     */
    private void registerBinding(CsvBindByName annotation, Class localType, Field localField) {
        String columnName = annotation.column().toUpperCase().trim();
        String locale = annotation.locale();
        String writeLocale = annotation.writeLocaleEqualsReadLocale()
                ? locale : annotation.writeLocale();
        CsvConverter converter = determineConverter(
                localField,
                localField.getType(), locale,
                writeLocale, null);

        if (StringUtils.isEmpty(columnName)) {
            fieldMap.put(localField.getName().toUpperCase(),
                    new BeanFieldSingleValue<>(
                            localType, localField, annotation.required(),
                            errorLocale, converter, annotation.capture(),
                            annotation.format()));
        } else {
            fieldMap.put(columnName, new BeanFieldSingleValue<>(
                    localType, localField, annotation.required(),
                    errorLocale, converter, annotation.capture(),
                    annotation.format()));
        }
    }

    /**
     * Creates a map of annotated fields in the bean to be processed.
     * 

This method is called by {@link #loadFieldMap()} when at least one * relevant annotation is found on a member variable.

*/ @Override protected void loadAnnotatedFieldMap(ListValuedMap, Field> fields) { for (Map.Entry, Field> classField : fields.entries()) { Class localType = classField.getKey(); Field localField = classField.getValue(); // Always check for a custom converter first. if (localField.isAnnotationPresent(CsvCustomBindByName.class) || localField.isAnnotationPresent(CsvCustomBindByNames.class)) { CsvCustomBindByName annotation = selectAnnotationForProfile( localField.getAnnotationsByType(CsvCustomBindByName.class), CsvCustomBindByName::profiles); if(annotation != null) { registerCustomBinding(annotation, localType, localField); } } // Then check for a collection else if(localField.isAnnotationPresent(CsvBindAndSplitByName.class) || localField.isAnnotationPresent(CsvBindAndSplitByNames.class)) { CsvBindAndSplitByName annotation = selectAnnotationForProfile( localField.getAnnotationsByType(CsvBindAndSplitByName.class), CsvBindAndSplitByName::profiles); if (annotation != null) { registerSplitBinding(annotation, localType, localField); } } // Then for a multi-column annotation else if(localField.isAnnotationPresent(CsvBindAndJoinByName.class) || localField.isAnnotationPresent(CsvBindAndJoinByNames.class)) { CsvBindAndJoinByName annotation = selectAnnotationForProfile( localField.getAnnotationsByType(CsvBindAndJoinByName.class), CsvBindAndJoinByName::profiles); if (annotation != null) { registerJoinBinding(annotation, localType, localField); } } // Otherwise it must be CsvBindByName. else { CsvBindByName annotation = selectAnnotationForProfile( localField.getAnnotationsByType(CsvBindByName.class), CsvBindByName::profiles); if (annotation != null) { registerBinding(annotation, localType, localField); } } } } /** * Returns a set of the annotations that are used for binding in this * mapping strategy. *

In this mapping strategy, those are currently:

    *
  • {@link CsvBindByName}
  • *
  • {@link CsvCustomBindByName}
  • *
  • {@link CsvBindAndJoinByName}
  • *
  • {@link CsvBindAndSplitByName}
  • *

*/ @Override protected Set> getBindingAnnotations() { // With Java 9 this can be done more easily with Set.of() return new HashSet<>(Arrays.asList( CsvBindByNames.class, CsvCustomBindByNames.class, CsvBindAndSplitByNames.class, CsvBindAndJoinByNames.class, CsvBindByName.class, CsvCustomBindByName.class, CsvBindAndSplitByName.class, CsvBindAndJoinByName.class)); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy