Class AbstractMappingStrategy<I,K extends Comparable<K>,C extends ComplexFieldMapEntry<I,K,T>,T>
- Type Parameters:
I
- The initializer type used to build the internal many-to-one mappingK
- The type of the key used for internal indexingC
- The type of the internal many-to-one mappingT
- Type of object that is being processed.
- All Implemented Interfaces:
MappingStrategy<T>
- Direct Known Subclasses:
ColumnPositionMappingStrategy
,HeaderNameBaseMappingStrategy
This mapping strategy knows of the existence of binding annotations, but
assumes through getBindingAnnotations()
they are not in use.
Anyone is welcome to use it as a base class for their own mapping strategies.
- Since:
- 4.2
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionprotected static class
Encapsulates a bean type and all of the member variables that need to be recursed into. -
Field Summary
FieldsModifier and TypeFieldDescriptionprotected Locale
Locale for error messages.Set of classes where recursion is not allowed.protected final HeaderIndex
Maintains a bi-directional mapping between column position(s) and header name.Storage for all manually excluded class/field pairs.protected String
The profile for configuring bean fields.protected AbstractMappingStrategy.RecursiveType
A tree of the types encountered during recursion through the root bean type.This is the class of the bean to be manipulated. -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionprivate void
assembleCompleteFieldList
(AbstractMappingStrategy.RecursiveType root, org.apache.commons.collections4.ListValuedMap<Class<?>, Field> encounteredFields) Creates a non-tree (fairly flat) representation of all of the fields bound from all types.protected abstract K
chooseMultivaluedFieldIndexFromHeaderIndex
(int index) ForBeanField.indexAndSplitMultivaluedField(java.lang.Object, java.lang.Object)
it is necessary to determine which index to pass in.Implementation will return a bean of the type of object being mapped.private static void
createSubordinateBeans
(AbstractMappingStrategy.RecursiveType typeTree, Map<Class<?>, Object> instanceMap, Object containingObject) protected CsvConverter
determineConverter
(Field field, Class<?> elementType, String locale, String writeLocale, Class<? extends AbstractCsvConverter> customConverter) Given the information provided, determines the appropriate built-in converter to be passed in to theBeanField
being created.filterIgnoredFields
(Class<?> type, Field[] fields) Filters all fields that opencsv has been instructed to ignore and returns a list of the rest.findField
(int col) Gets the field for a given column position.abstract String
findHeader
(int col) Gets the name (or position number) of the header for the given column number.String[]
generateHeader
(T bean) This method generates a header that can be used for writing beans of the type provided back to a file.protected Set
<Class<? extends Annotation>> Returns a set of the annotations that are used for binding in this mapping strategy.protected String
getColumnName
(int col) Get the column name for a given column position.Returns theFieldMap
associated with this mapping strategy.getType()
Get the class type that the strategy is mapping.void
ignoreFields
(org.apache.commons.collections4.MultiValuedMap<Class<?>, Field> fields) When processing a bean for reading or writing, ignore the given fields from the given classes completely, including all annotations and requirements.Creates an index of necessary types according to the mapping strategy and existing instances of (subordinate) beans.private static void
indexSubordinateBeans
(AbstractMappingStrategy.RecursiveType typeTree, Map<Class<?>, Object> instanceMap, Object containingObject) protected abstract void
Creates an empty binding-type-specific field map that can be filled in later steps.instantiateCustomConverter
(Class<? extends AbstractBeanField<T, K>> converter) Attempts to instantiate the class of the custom converter specified.protected boolean
isForbiddenClassForRecursion
(Class<?> type) protected void
loadAnnotatedFieldMap
(org.apache.commons.collections4.ListValuedMap<Class<?>, Field> fields) Creates a map of annotated fields in the bean to be processed.protected void
Builds a map of columns from the input to fields of the bean type.protected AbstractMappingStrategy.RecursiveType
loadRecursiveClasses
(Class<?> newType, Set<Class<?>> encounteredTypes) Creates a tree of beans embedded in each other.protected abstract void
loadUnadornedFieldMap
(org.apache.commons.collections4.ListValuedMap<Class<?>, Field> fields) Creates a map of fields in the bean to be processed that have no annotations.Partitions all non-synthetic fields of the bean type being processed into annotated and non-annotated fields according togetBindingAnnotations()
.populateNewBean
(String[] line) Takes a line of input from a CSV file and creates a bean out of it.protected <A extends Annotation>
AselectAnnotationForProfile
(A[] annotations, Function<A, String[]> getProfiles) Determines which one of a list of annotations applies to the currently selected profile.void
setErrorLocale
(Locale errorLocale) Sets the locale for all error messages.protected void
setFieldValue
(Map<Class<?>, Object> beanTree, String value, int column) Populates the field corresponding to the column position indicated of the bean passed in according to the rules of the mapping strategy.void
setProfile
(String profile) Sets the profile this mapping strategy will use when configuring bean fields.void
Sets the class type that is being mapped.String[]
transmuteBean
(T bean) Transmutes a bean instance into an array ofString
s to be written to a CSV file.protected abstract void
verifyLineLength
(int numberOfFields) Must be called once the length of input for a line/record is known to verify that the line was complete.Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
Methods inherited from interface com.opencsv.bean.MappingStrategy
captureHeader, isAnnotationDriven
-
Field Details
-
FORBIDDEN_CLASSES_FOR_RECURSION
Set of classes where recursion is not allowed. Using HashSet because, given the large number of types, the contains method is quicker than an Array or ArrayList (Granted the number where Set is more efficient is different per Java release and system configuration). And being a Set we are noting that each value is unique. -
type
This is the class of the bean to be manipulated. -
headerIndex
Maintains a bi-directional mapping between column position(s) and header name. -
recursiveTypeTree
A tree of the types encountered during recursion through the root bean type. These are only the types (and associated fields) specifically annotated withCsvRecurse
. -
ignoredFields
Storage for all manually excluded class/field pairs. -
errorLocale
Locale for error messages. -
profile
The profile for configuring bean fields.
-
-
Constructor Details
-
AbstractMappingStrategy
public AbstractMappingStrategy()
-
-
Method Details
-
chooseMultivaluedFieldIndexFromHeaderIndex
ForBeanField.indexAndSplitMultivaluedField(java.lang.Object, java.lang.Object)
it is necessary to determine which index to pass in.- Parameters:
index
- The current column position while transmuting a bean to CSV output- Returns:
- The index to be used for this mapping strategy for
BeanField.indexAndSplitMultivaluedField(java.lang.Object, java.lang.Object)
-
getFieldMap
Returns theFieldMap
associated with this mapping strategy.- Returns:
- The
FieldMap
used by this strategy
-
getBindingAnnotations
Returns a set of the annotations that are used for binding in this mapping strategy. The default implementation returns the empty set.- Returns:
- Annotations of the sort
CsvBindByName
orCsvBindByPosition
that are relevant for binding input fields to bean members in this mapping strategy - Since:
- 5.0
-
loadAnnotatedFieldMap
protected void loadAnnotatedFieldMap(org.apache.commons.collections4.ListValuedMap<Class<?>, Field> fields) Creates a map of annotated fields in the bean to be processed.This method is called by
loadFieldMap()
when at least one relevant annotation is found on a member variable.The default implementation assumes there are no annotations and does nothing.
- Parameters:
fields
- A list of fields annotated with a binding annotation in the bean to be processed- Since:
- 5.0
-
loadUnadornedFieldMap
protected abstract void loadUnadornedFieldMap(org.apache.commons.collections4.ListValuedMap<Class<?>, Field> fields) Creates a map of fields in the bean to be processed that have no annotations. This method is called byloadFieldMap()
when absolutely no annotations that are relevant for this mapping strategy are found in the type of bean being processed.- Parameters:
fields
- A list of all non-synthetic fields in the bean to be processed- Since:
- 5.0
-
initializeFieldMap
protected abstract void initializeFieldMap()Creates an empty binding-type-specific field map that can be filled in later steps.This method may be called multiple times and must erase any state information from previous calls.
- Since:
- 5.0
-
findField
Gets the field for a given column position.- Parameters:
col
- The column to find the field for- Returns:
- BeanField containing the field for a given column position, or null if one could not be found
- Throws:
CsvBadConverterException
- If a custom converter for a field cannot be initialized
-
verifyLineLength
Must be called once the length of input for a line/record is known to verify that the line was complete. Complete in this context means, no required fields are missing. The issue here is, as long as a column is present but empty, we can check whether the field is required and throw an exception if it is not, but if the data end prematurely, we never have this chance without indication that no more data are on the way. Another validation is that the number of fields must match the number of headers to prevent a data mismatch situation.- Parameters:
numberOfFields
- The number of fields present in the line of input- Throws:
CsvRequiredFieldEmptyException
- If a required column is missing- Since:
- 4.0
-
createBean
protected Map<Class<?>,Object> createBean() throws CsvBeanIntrospectionException, IllegalStateExceptionImplementation will return a bean of the type of object being mapped.- Returns:
- A new instance of the class being mapped.
- Throws:
CsvBeanIntrospectionException
- Thrown on error creating object.IllegalStateException
- If the type of the bean has not been initialized throughsetType(java.lang.Class)
-
createSubordinateBeans
private static void createSubordinateBeans(AbstractMappingStrategy.RecursiveType typeTree, Map<Class<?>, Object> instanceMap, Object containingObject) throws InstantiationException, IllegalAccessException, InvocationTargetException -
indexBean
protected Map<Class<?>,Object> indexBean(T bean) throws IllegalAccessException, InvocationTargetException Creates an index of necessary types according to the mapping strategy and existing instances of (subordinate) beans.- Parameters:
bean
- The root bean to be indexed- Returns:
- The index from type to instance
- Throws:
IllegalAccessException
- If there are problems accessing a subordinate beanInvocationTargetException
- If there are problems accessing a subordinate bean- Since:
- 5.0
-
indexSubordinateBeans
private static void indexSubordinateBeans(AbstractMappingStrategy.RecursiveType typeTree, Map<Class<?>, Object> instanceMap, Object containingObject) throws IllegalAccessException, InvocationTargetException -
findHeader
Gets the name (or position number) of the header for the given column number. The column numbers are zero-based.- Parameters:
col
- The column number for which the header is sought- Returns:
- The name of the header
-
generateHeader
This method generates a header that can be used for writing beans of the type provided back to a file.The ordering of the headers is determined by the
FieldMap
in use.This method should be called first by all overriding classes to make certain
headerIndex
is properly initialized.- Specified by:
generateHeader
in interfaceMappingStrategy<I>
- Parameters:
bean
- One fully populated bean from which the header can be derived. This is important in the face of joining and splitting. If we have a MultiValuedMap as a field that is the target for a join on reading, that same field must be split into multiple columns on writing. Since the joining is done via regular expressions, it is impossible for opencsv to know what the column names are supposed to be on writing unless this bean includes a fully populated map.- Returns:
- An array of column names for a header. This may be an empty array
if no header should be written, but it must not be
null
. - Throws:
CsvRequiredFieldEmptyException
- If a required header is missing while attempting to write. Since every other header is hard-wired through the bean fields and their associated annotations, this can only happen with multi-valued fields.
-
getColumnName
Get the column name for a given column position.- Parameters:
col
- Column position.- Returns:
- The column name or null if the position is larger than the header array or there are no headers defined.
-
getType
Get the class type that the strategy is mapping.- Returns:
- Class of the object that this
MappingStrategy
will create.
-
populateNewBean
public T populateNewBean(String[] line) throws CsvBeanIntrospectionException, CsvFieldAssignmentException, CsvChainedException Description copied from interface:MappingStrategy
Takes a line of input from a CSV file and creates a bean out of it.- Specified by:
populateNewBean
in interfaceMappingStrategy<I>
- Parameters:
line
- A line of input returned fromCSVReader
- Returns:
- A bean containing the converted information from the input
- Throws:
CsvBeanIntrospectionException
- Generally, if some part of the bean cannot be accessed and used as neededCsvFieldAssignmentException
- A more specific subclass of this exception is thrown for any problem decoding and assigning a field of the input to a bean fieldCsvChainedException
- If multiple exceptions are thrown for the same input line
-
setType
Sets the class type that is being mapped. Also initializes the mapping between column names and bean fields and attempts to create one example bean to be certain there are no fundamental problems with creation.- Specified by:
setType
in interfaceMappingStrategy<I>
- Parameters:
type
- Class type.- Throws:
CsvBadConverterException
- If a field in the bean is annotated with a custom converter that cannot be initialized. If you are not using custom converters that you have written yourself, it should be safe to catch this exception and ignore it.
-
setProfile
Sets the profile this mapping strategy will use when configuring bean fields.- Specified by:
setProfile
in interfaceMappingStrategy<I>
- Parameters:
profile
- The profile to use
-
ignoreFields
public void ignoreFields(org.apache.commons.collections4.MultiValuedMap<Class<?>, Field> fields) throws IllegalArgumentExceptionDescription copied from interface:MappingStrategy
When processing a bean for reading or writing, ignore the given fields from the given classes completely, including all annotations and requirements. This method has two compelling applications:
- If you are not able to modify the source code of the beans you use, or
- If you use a mapping strategy without annotations and want to exclude a small number of fields from a bean with a large number of fields.
Calling this method overwrites the fields passed in from any previous calls. It is legal to call this method before calling
MappingStrategy.setType(Class)
, and it may be more efficient to do so.Caution must be exercised with this method when letting opencsv automatically determine the mapping strategy. When a field is ignored, opencsv pretends it does not exist at all. If, for instance, all fields annotated with opencsv binding annotations are ignored, opencsv will automatically switch to
HeaderColumnNameMappingStrategy
and assume header names exactly match field names.An implementation of this interface is not required to implement this method. The default implementation throws
UnsupportedOperationException
.- Specified by:
ignoreFields
in interfaceMappingStrategy<I>
- Parameters:
fields
- All fields to be ignored, mapped from the classes of which they are members. These are the classes as opencsv encounters them, not necessarily the declaring classes if any fields are inherited. May benull
.- Throws:
IllegalArgumentException
- If any entry in the map has anull
key, anull
value, or if the value is not a field in the class represented by the key- See Also:
-
filterIgnoredFields
Filters all fields that opencsv has been instructed to ignore and returns a list of the rest.- Parameters:
type
- The class from whichfields
come. This must be the class as opencsv would seek to instantiate it, which in the case of inheritance is not necessarily the declaring class.fields
- The fields to be filtered- Returns:
- A list of fields that exist for opencsv
-
loadFieldMap
Builds a map of columns from the input to fields of the bean type.- Throws:
CsvBadConverterException
- If there is a problem instantiating the custom converter for an annotated field
-
isForbiddenClassForRecursion
- Parameters:
type
- Class to be checked- Returns:
- Whether the type may be recursed into (
false
), or must be considered a leaf node for recursion (true
). This implementation considers the boxed primitives forbidden.
-
loadRecursiveClasses
protected AbstractMappingStrategy.RecursiveType loadRecursiveClasses(Class<?> newType, Set<Class<?>> encounteredTypes) Creates a tree of beans embedded in each other. These are the member variables annotated withCsvRecurse
and their associated types. This method is used recursively.- Parameters:
newType
- The type that is meant to be added to the treeencounteredTypes
- A set of types already encountered during recursion, as types may not be recursed into more than once.- Returns:
- A representation of this type and all of the types beneath it in a tree
- Throws:
CsvRecursionException
- If recursion is attempted into a primitive type or a previously encountered type is added again or a member variable annotated withCsvRecurse
is also annotated with a binding annotation
-
assembleCompleteFieldList
private void assembleCompleteFieldList(AbstractMappingStrategy.RecursiveType root, org.apache.commons.collections4.ListValuedMap<Class<?>, Field> encounteredFields) Creates a non-tree (fairly flat) representation of all of the fields bound from all types. This method is used recursively.- Parameters:
root
- The root of the type tree at this level of recursionencounteredFields
- A collection of all fields thus far included in the new representation. This collection will be added to and is the result of this method.
-
partitionFields
protected Map<Boolean,org.apache.commons.collections4.ListValuedMap<Class<?>, partitionFields()Field>> Partitions all non-synthetic fields of the bean type being processed into annotated and non-annotated fields according togetBindingAnnotations()
.- Returns:
- A multi-valued map (class to multiple fields in that class) in
which all annotated fields are mapped under
Boolean.TRUE
, and all non-annotated fields are mapped underBoolean.FALSE
. - Since:
- 5.0
-
instantiateCustomConverter
protected BeanField<T,K> instantiateCustomConverter(Class<? extends AbstractBeanField<T, K>> converter) throws CsvBadConverterExceptionAttempts to instantiate the class of the custom converter specified.- Parameters:
converter
- The class for a custom converter- Returns:
- The custom converter
- Throws:
CsvBadConverterException
- If the class cannot be instantiated
-
setErrorLocale
Description copied from interface:MappingStrategy
Sets the locale for all error messages. The default implementation does nothing, as it is expected that most implementations of this interface will not support multiple languages.- Specified by:
setErrorLocale
in interfaceMappingStrategy<I>
- Parameters:
errorLocale
- Locale for error messages. If null, the default locale is used.
-
setFieldValue
protected void setFieldValue(Map<Class<?>, Object> beanTree, String value, int column) throws CsvDataTypeMismatchException, CsvRequiredFieldEmptyException, CsvConstraintViolationException, CsvValidationExceptionPopulates the field corresponding to the column position indicated of the bean passed in according to the rules of the mapping strategy. This method performs conversion on the input string and assigns the result to the proper field in the provided bean.- Parameters:
beanTree
- Object containing the field to be set.value
- String containing the value to set the field to.column
- The column position from the CSV file under which this value was found.- Throws:
CsvDataTypeMismatchException
- When the result of data conversion returns an object that cannot be assigned to the selected fieldCsvRequiredFieldEmptyException
- When a field is mandatory, but there is no input datum in the CSV fileCsvConstraintViolationException
- When the internal structure of data would be violated by the data in the CSV fileCsvValidationException
- If a user-supplied validator determines that the input is invalid- Since:
- 4.2
-
transmuteBean
Description copied from interface:MappingStrategy
Transmutes a bean instance into an array ofString
s to be written to a CSV file.- Specified by:
transmuteBean
in interfaceMappingStrategy<I>
- Parameters:
bean
- The bean to be transmuted- Returns:
- The converted values of the bean fields in the correct order,
ready to be passed to a
CSVWriter
- Throws:
CsvFieldAssignmentException
- A more specific subclass of this exception is thrown for any problem decoding and assigning a field of the input to a bean fieldCsvChainedException
- If multiple exceptions are thrown for the same input line
-
determineConverter
protected CsvConverter determineConverter(Field field, Class<?> elementType, String locale, String writeLocale, Class<? extends AbstractCsvConverter> customConverter) throws CsvBadConverterException Given the information provided, determines the appropriate built-in converter to be passed in to theBeanField
being created.- Parameters:
field
- The field of the bean type in questionelementType
- The type to be generated by the converter (on reading)locale
- The locale for conversion on reading. May be null or an empty string if a locale is not in use.writeLocale
- The locale for conversion on writing. May be null or an empty string if a locale is not in use.customConverter
- An optional custom converter- Returns:
- The appropriate converter for the necessary conversion
- Throws:
CsvBadConverterException
- If the converter cannot be instantiated- Since:
- 4.2
-
selectAnnotationForProfile
protected <A extends Annotation> A selectAnnotationForProfile(A[] annotations, Function<A, String[]> getProfiles) Determines which one of a list of annotations applies to the currently selected profile. If no annotation specific to the profile is found, the annotation for the default profile is returned. If neither is found,null
is returned.- Type Parameters:
A
- The annotation type being tested- Parameters:
annotations
- All annotations of a given typegetProfiles
- A function mapping an annotation of typeA
to the list of profiles it applies to- Returns:
- The annotation with the appropriate profile or
null
if nothing appropriate is found - Since:
- 5.4
-