com.googlecode.jmapper.config.ConfigReader Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jmapper-core Show documentation
Show all versions of jmapper-core Show documentation
JMapper Framework is a java bean mapper based on javassist. JMapper exposes
interesting features as relational mapping, dynamic conversions and more
/**
* Copyright (C) 2012 - 2016 Alessandro Vurro.
*
* 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.googlecode.jmapper.config;
import static com.googlecode.jmapper.config.Constants.DEFAULT_FIELD_VALUE;
import static com.googlecode.jmapper.config.Constants.THE_FIELD_IS_NOT_CONFIGURED;
import static com.googlecode.jmapper.util.ClassesManager.fieldName;
import static com.googlecode.jmapper.util.ClassesManager.getAllsuperClasses;
import static com.googlecode.jmapper.util.GeneralUtility.*;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.googlecode.jmapper.annotations.Annotation;
import com.googlecode.jmapper.annotations.JGlobalMap;
import com.googlecode.jmapper.annotations.JMap;
import com.googlecode.jmapper.operations.beans.MappedField;
import com.googlecode.jmapper.xml.Attribute;
import com.googlecode.jmapper.xml.Global;
import com.googlecode.jmapper.xml.SimplyAttribute;
import com.googlecode.jmapper.xml.XML;
/**
* This Class reads the configuration of a specific field (analyzing XML or annotation) and finds the target field name.
*
* @author Alessandro Vurro
*
*/
public final class ConfigReader {
/** configured class*/
private final Class> configuredClass;
/** target class */
private final Class> targetClass;
/** xml object */
private final XML xml;
public ConfigReader(Class> aConfiguredClass, Class> aTargetClass, XML aXml) {
configuredClass = aConfiguredClass;
targetClass = aTargetClass;
xml = aXml;
}
/**
* This method compare the name of the target field with the DEFAULT_FIELD_VALUE and returns the final value.
*
* @param value configuration parameter
* @param mappedFieldName name of the configured field
* @return the name of target field
*
* @see Constants#DEFAULT_FIELD_VALUE
*/
private String getValue(final String value, final String mappedFieldName) {
if (isNull(value)) return null;
return value.equals(DEFAULT_FIELD_VALUE)?mappedFieldName:value;
}
/**
* This method finds the target field name from mapped parameters.
* @param attributes target list of field names
* @param classes list of target classes
* @param value name of target attribute
* @param mappedFieldName name of mapped attribute
* @param configuredClass configured Class
* @param targetClass target Class
* @return the name of the target field if exist, null otherwise
*/
private String getValue(final List attributes,final List> classes,String value,final String mappedFieldName,final Class> configuredClass,final Class> targetClass){
String regex = getValue(value,mappedFieldName);
String mappedClassName = configuredClass.getSimpleName();
String targetClassName = targetClass.getSimpleName();
/* IF ATTRIBUTES AND CLASSES ARE EMPTY */
if( attributes.isEmpty() && classes.isEmpty() ){
String targetFieldName = fieldName(targetClass,regex);
if(!isNull(targetFieldName))
return targetFieldName;
Error.mapping(mappedFieldName, mappedClassName, regex, targetClassName);
}
/* IF ATTRIBUTES IS EMPTY AND CLASSES NOT */
if( attributes.isEmpty() && !classes.isEmpty() ){
if(classes.contains(targetClass)){
String targetFieldName = fieldName(targetClass,regex);
if(!isNull(targetFieldName))
return targetFieldName;
}
Error.mapping(mappedFieldName, mappedClassName, regex, targetClassName);
}
/* IF ATTRIBUTES AND CLASSES ARE VALUED AND THEY HAVE THE SAME LENGTH */
if( !attributes.isEmpty() && !classes.isEmpty() )
if(attributes.size()==classes.size())
if(classes.contains(targetClass)){
// get the attribute from attributes, positioned at the same index of targetClass in classes
String targetClassValue = attributes.get(classes.indexOf(targetClass));
regex = getValue(targetClassValue,mappedFieldName);
String targetFieldName = fieldName(targetClass,regex);
if(!isNull(targetFieldName))
return targetFieldName;
Error.mapping(mappedFieldName, mappedClassName, regex, targetClassName);
}else
Error.mapping(mappedFieldName, mappedClassName, targetClassName);
else
Error.mapping(mappedFieldName, mappedClassName);
/* IF ATTRIBUTES IS FULL AND CLASSES IS EMPTY */
if( !attributes.isEmpty() && classes.isEmpty() )
for (String str : attributes){
regex = getValue(str,mappedFieldName);
// if exist the target field in targetClass
String targetFieldName = fieldName(targetClass,regex);
if(!isNull(targetFieldName))
//returns the corresponding name
return targetFieldName;
}
Error.mapping(mappedFieldName, configuredClass,targetClass);
return "this return is never used";
}
/**
* Returns the target field name of the configured field given in input, null otherwise.
* @param field configured field
* @return target field name, null otherwise
*/
public String retrieveTargetFieldName(final Field field){
// this list contains the configuredClass with super classes
List> classes = getAllsuperClasses(configuredClass);
// in case of override only the last global configuration must be analyzed
Global global = null;
// If configuredClass exists in XML configuration file
for (Class> clazz : classes){
if(!xml.isMapped(clazz))continue;
// only if global configuration is null will be searched global configuration on super classes
if(isNull(global)){
global = xml.loadGlobals().get(clazz.getName());
if( !isNull(global)
&& !isPresent(global.getExcluded(), field.getName())
&& ( isEmpty(global.getAttributes())
|| isPresent(global.getAttributes(), new SimplyAttribute(field.getName()))
)
){
// get the classes of the xmlField
List> globalClasses = toList(global.getClasses());
// if mapped field hasn't targetClass in classes parameter
if(!globalClasses.isEmpty() && !globalClasses.contains(targetClass)) continue;
// get value of xmlField
String value = global.getValue();
// If the Value is empty,
// then the name of the target field is equal to the configuredField name,
// therefore we pass the default value we use to indicate equality
if(isNull(value)) value = DEFAULT_FIELD_VALUE;
// loaded all variables, calculates and returns the correspondence
return getValue(Collections.emptyList(), globalClasses, value, field.getName(), clazz, targetClass);
}
}
// loads all configured attributes
for(Attribute attribute :xml.loadAttributes().get(clazz.getName())){
// verifies that exists the attribute written in XML in the configured Class
if(isNull(fieldName(clazz,attribute.getName())))
Error.attributeAbsent(clazz, attribute);
// if the field given in input isn't equal to xmlField continue with the cycle
if(!attribute.getName().equals(field.getName())) continue;
// get the classes of the xmlField
List> attributeClasses = toList(attribute.getClasses());
// if mapped field hasn't targetClass in classes parameter
if(!attributeClasses.isEmpty() && !attributeClasses.contains(targetClass)) continue;
// get the attributes names of xmlField
List attributes = new ArrayList();
if(attribute.getAttributes() != null)
for (SimplyAttribute targetAttribute : attribute.getAttributes())
attributes.add(targetAttribute.getName());
// get value of xmlField
String value = null;
if(!isNull(attribute.getValue()))
value = attribute.getValue().getName();
// If the Value and Attributes parameters are empty,
// then the name of the target field is equal to the configuredField name,
// therefore we pass the default value we use to indicate equality
if(isNull(value) && attributes.isEmpty()) value = DEFAULT_FIELD_VALUE;
// loaded all variables, calculates and returns the correspondence
return getValue(attributes, attributeClasses, value, field.getName(), clazz, targetClass);
}
}
// if class is configured in xml the annotated configuration is not searched
// if it has a configured superclass it's ignored, the priority is valid only for principal class
if(xml.isInheritedMapped(configuredClass))return THE_FIELD_IS_NOT_CONFIGURED;
// if the XML configuration doesn't exist, checks the annotation existence
for (Class> clazz : classes){
JGlobalMap jglobalMap = clazz.getAnnotation(JGlobalMap.class);
//if the field configuration is defined in the global map
if( !isNull(jglobalMap)){
if(!isPresent(jglobalMap.excluded(), field.getName())
&& ( isEmpty(jglobalMap.attributes())
|| isPresent(jglobalMap.attributes(), field.getName())
)){
// get the list of target classes
List> globalClasses = toList(jglobalMap.classes());
// if mapped field hasn't targetClass in classes parameter
if(!globalClasses.isEmpty() && !globalClasses.contains(targetClass)) return THE_FIELD_IS_NOT_CONFIGURED;
// get value of configuredField
String value = jglobalMap.value();
// loaded all variables, calculates and returns the correspondence
return getValue(Collections.emptyList(), globalClasses, value, field.getName(), configuredClass, targetClass);
}
// If global mapping is defined on this level, global mapping of super classes is ignored.
// This is necessary to apply configuration override.
break;
}
}
JMap jmap = field.getAnnotation(JMap.class);
if(isNull(jmap)) return THE_FIELD_IS_NOT_CONFIGURED;
// get the list of target classes
List> targetClasses = toList(jmap.classes());
// if mapped field hasn't targetClass in classes parameter
if(!targetClasses.isEmpty() && !targetClasses.contains(targetClass)) return THE_FIELD_IS_NOT_CONFIGURED;
// get the list of target attributes
List attributes = toList(jmap.attributes());
// get value of configuredField
String value = jmap.value();
// loaded all variables, calculates and returns the correspondence
return getValue(attributes, targetClasses, value, field.getName(), configuredClass, targetClass);
}
/**
* Fill fields with they custom methods.
*
* @param configuredField configured field
* @param targetField target field
*/
public void loadAccessors(MappedField configuredField, MappedField targetField) {
loadAccessors(targetClass, configuredField, targetField);
}
/**
* Fill fields with they custom methods.
*
* @param targetClass class of the target field
* @param configuredField configured field
* @param targetField target field
*/
public void loadAccessors(Class> targetClass, MappedField configuredField, MappedField targetField) {
// First checks xml configuration
xml.fillMappedField(configuredClass, configuredField)
.fillMappedField(targetClass, targetField)
// fill target field with custom methods defined in the configured field
.fillOppositeField(configuredClass, configuredField, targetField);
// If no present custom methods in XML, it checks annotations
Annotation.fillMappedField(configuredClass,configuredField);
Annotation.fillMappedField(targetClass,targetField);
// fill target field with custom methods defined in the configured field
Annotation.fillOppositeField(configuredClass,configuredField,targetField);
}
}