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

com.googlecode.jmapper.xml.Converter Maven / Gradle / Ivy

Go to download

JMapper Framework is a java bean mapper based on javassist. JMapper exposes interesting features as relational mapping, dynamic conversions and more

There is a newer version: 1.6.4
Show newest version
/**
 * 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.xml;

import static com.googlecode.jmapper.annotations.JMapConversion.ALL;
import static com.googlecode.jmapper.config.Constants.CONTENT_ALREADY_DEFINED;
import static com.googlecode.jmapper.config.Constants.DEFAULT_FIELD_VALUE;
import static com.googlecode.jmapper.conversions.explicit.ConversionMethod.ParameterNumber.ONE;
import static com.googlecode.jmapper.conversions.explicit.ConversionMethod.ParameterNumber.TWO;
import static com.googlecode.jmapper.conversions.explicit.ConversionMethod.ParameterNumber.ZERO;
import static com.googlecode.jmapper.conversions.explicit.ConversionPlaceholder.destination;
import static com.googlecode.jmapper.conversions.explicit.ConversionPlaceholder.source;
import static com.googlecode.jmapper.util.GeneralUtility.isEmpty;
import static com.googlecode.jmapper.util.GeneralUtility.isNull;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;

import com.googlecode.jmapper.annotations.Annotation;
import com.googlecode.jmapper.annotations.JGlobalMap;
import com.googlecode.jmapper.annotations.JMap;
import com.googlecode.jmapper.annotations.JMapAccessor;
import com.googlecode.jmapper.annotations.JMapConversion;
import com.googlecode.jmapper.annotations.JMapConversion.Type;
import com.googlecode.jmapper.config.Constants;
import com.googlecode.jmapper.config.Error;
import com.googlecode.jmapper.conversions.explicit.ConversionMethod;
import com.googlecode.jmapper.conversions.explicit.ConversionMethod.ParameterNumber;
import com.googlecode.jmapper.exceptions.ConversionParameterException;
import com.googlecode.jmapper.exceptions.DynamicConversionBodyException;
import com.googlecode.jmapper.exceptions.DynamicConversionMethodException;
import com.googlecode.jmapper.exceptions.DynamicConversionParameterException;
import com.googlecode.jmapper.exceptions.XmlConversionNameException;
import com.googlecode.jmapper.exceptions.XmlConversionParameterException;
import com.googlecode.jmapper.exceptions.XmlConversionTypeException;
import com.googlecode.jmapper.xml.beans.XmlAttribute;
import com.googlecode.jmapper.xml.beans.XmlClass;
import com.googlecode.jmapper.xml.beans.XmlConversion;
import com.googlecode.jmapper.xml.beans.XmlGlobal;
import com.googlecode.jmapper.xml.beans.XmlTargetAttribute;
import com.googlecode.jmapper.xml.beans.XmlExcludedAttribute;
import com.googlecode.jmapper.xml.beans.XmlTargetClass;

/**
 * Converter simplifies the manipulation of xml mapping file and annotations.
 * 
 * @author Alessandro Vurro
 *
 */
public class Converter {
	
	/**
	 * This method transforms a Class given in input, into a XmlClass.
	 * @param aClass Class to trasform in XmlClass
	 * @return a Class converted to XmlClass
	 */
	public static XmlClass toXmlClass(Class aClass){
		XmlClass xmlClass = new XmlClass();
		xmlClass.name = aClass.getName();
		xmlClass.attributes = new ArrayList();
		
		if(aClass.getAnnotation(JGlobalMap.class) != null)
			xmlClass.global = toXmlGlobal(aClass);
		
		for (Field field : aClass.getDeclaredFields())
			if(field.getAnnotation(JMap.class) != null)
				xmlClass.attributes.add(toXmlAttribute(aClass,field));
			
		return xmlClass;
	}
	
	/**
	 * This method transforms a XmlConversion given in input, into a ConversionMethod.
	 * @param xmlConversion xmlConversion to transform in ConversionMethod
	 * @return a ConversionMethod
	 */
	public static ConversionMethod toConversionMethod(XmlConversion xmlConversion){

		if(isEmpty(xmlConversion.name)){
			xmlConversion.name = "undefinedName";
			throw new XmlConversionNameException("it's mandatory define a name");
		}
		
		String name = xmlConversion.name;
		String conversionType = xmlConversion.type;
		boolean avoidSet = xmlConversion.avoidSet;
		
		Type type = conversionType == null ? JMapConversion.Type.STATIC // default type value
				   		                   : conversionType.equalsIgnoreCase("STATIC")
				   		                   		 ? Type.STATIC
				   		                   		 : conversionType.equalsIgnoreCase("DYNAMIC") 
				   		                   				? Type.DYNAMIC 
				   		                   				: null;
		
		if(type == null) 
			throw new XmlConversionTypeException("wrong type defined, only STATIC and DYNAMIC options are permitted");
		
		String[] from = xmlConversion.from == null ? new String[]{ALL} // default from value
		                                           : trim(xmlConversion.from.split(","));
		String[] to = xmlConversion.to == null     ? new String[]{ALL} // default to   value
        										   : trim(xmlConversion.to.split(","));
		String content = xmlConversion.content.trim();
		
		if(!content.contains(source) && content.contains(destination))
			throw new XmlConversionParameterException("the use of the destination isn't permitted without the use of the source");
		
		ParameterNumber number = content.contains(source)?content.contains(destination)?TWO:ONE:ZERO;
		
		return new ConversionMethod(name, from, to, type, number, content, avoidSet);
	}
	
	/**
	 * This method transforms a Method given in input, into a ConversionMethod.
	 * @param aMethod Method to transform in ConversionMethod
	 * @return a ConversionMethod
	 */
	public static ConversionMethod toConversionMethod(Method aMethod){
		JMapConversion conversion = aMethod.getAnnotation(JMapConversion.class);
		
		String name = aMethod.getName();
		String[] from = trim(conversion.from());
		String[] to = trim(conversion.to());
		Type type = conversion.type();
		boolean avoidSet = conversion.avoidSet();
		
		ParameterNumber number = null;
		String body = null;
		
		switch(type){
			case STATIC: 
				switch(aMethod.getParameterTypes().length){
					case 1: number = ONE; break;
					case 2: number = TWO; break;
					default: 
						throw new ConversionParameterException("is allowed to use from one to two parameters");
				}
				body = CONTENT_ALREADY_DEFINED;
			break;
			case DYNAMIC: 
				if(aMethod.getParameterTypes().length != 0)
					throw new DynamicConversionParameterException("is not allowed parameters usage in a dynamic method");
				
				try { 
					body = (String) aMethod.invoke(null, new Object[]{});
				} catch (Exception e) {
					throw new DynamicConversionMethodException("the method don't respects the conventions");
				}
				
				if(!body.contains(source) && body.contains(destination))
					throw new DynamicConversionBodyException("the use of the destination isn't permitted without the use of the source");
				
				number = body.contains(source)? body.contains(destination)?TWO:ONE:ZERO;
			break;
		}
			
		return new ConversionMethod(name, from, to, type, number, body, avoidSet);
	}
	
	/**
	 * This method transforms a XmlAttribute into an Attribute.
	 * @param xmlAttribute xml attribute node
	 * @return an instance of Attribute
	 */
	public static Attribute toAttribute(XmlAttribute xmlAttribute) {
		String name = xmlAttribute.name;
		
		Value value = null;
		if(!isNull(xmlAttribute.value))
			value = new Value(xmlAttribute.value);
		
		String get = xmlAttribute.get;
		String set = xmlAttribute.set;
		
		SimplyAttribute[] attributes = null;
		Class[] classes  = null;

		if(!isEmpty(xmlAttribute.attributes)){
			attributes = new SimplyAttribute[xmlAttribute.attributes.size()];
			for (int i = xmlAttribute.attributes.size(); i --> 0;) 
				attributes[i] = new SimplyAttribute(xmlAttribute.attributes.get(i));
		}

		if(!isEmpty(xmlAttribute.classes)){
			classes = new Class[xmlAttribute.classes.size()];
			for (int i = xmlAttribute.classes.size(); i --> 0;){
				try { 	  		      classes[i] = Class.forName(xmlAttribute.classes.get(i).name); } 
				catch (Exception e) { Error.classInexistent(xmlAttribute.classes.get(i).name);	}
			}
		}
		
		return new Attribute(name, value, get, set, attributes, classes);
	}
	
	/**
	 * This method transforms a XmlGlobal into a Global.
	 * @param xmlGlobal xml global node
	 * @return an instance of Global
	 */
	public static Global toGlobal(XmlGlobal xmlGlobal){
		
		String name =!isNull(xmlGlobal.value) && !isNull(xmlGlobal.value.name)? xmlGlobal.value.name:null;
		String get = !isNull(xmlGlobal.value) && !isNull(xmlGlobal.value.get)? xmlGlobal.value.get:null;
		String set = !isNull(xmlGlobal.value) && !isNull(xmlGlobal.value.set)? xmlGlobal.value.set:null;
		
		SimplyAttribute[] attributes = null;
		Class[] classes = null;
		String[] excluded = null;
		
		if(!isEmpty(xmlGlobal.attributes)){
			attributes = new SimplyAttribute[xmlGlobal.attributes.size()];
			for (int i = xmlGlobal.attributes.size(); i --> 0;) 
				attributes[i] = new SimplyAttribute(xmlGlobal.attributes.get(i));
		}

		if(!isEmpty(xmlGlobal.classes)){
			classes = new Class[xmlGlobal.classes.size()];
			for (int i = xmlGlobal.classes.size(); i --> 0;)
				try { 	  		      classes[i] = Class.forName(xmlGlobal.classes.get(i).name); } 
				catch (Exception e) { Error.classInexistent(xmlGlobal.classes.get(i).name);	}
		}
		
		if(!isEmpty(xmlGlobal.excluded)){
			excluded = new String[xmlGlobal.excluded.size()];
			for (int i = xmlGlobal.excluded.size(); i --> 0;) 
				excluded[i] = xmlGlobal.excluded.get(i).name;
		}
		
		return new Global(name, get, set, attributes, classes, excluded);
	}

	/**
	 * This method transforms a Global bean to an instance of XmlGlobal.
	 * @param global global to transform
	 * @return a new instance of XmlGlobal
	 */
	public static XmlGlobal toXmlGlobal(Global global){
		 return toXmlGlobal(global.getValue(), global.getGet(), global.getSet(), global.getAttributes(), global.getClasses(), global.getExcluded());
	}
	
	/**
	 * This method transforms a JGlobalMap annotation to XmlGlobal.
	 * @param aClass class to check
	 * @return a new instance of XmlGlobal
	 */
	private static XmlGlobal toXmlGlobal(Class aClass){
		JGlobalMap globalMap = aClass.getAnnotation(JGlobalMap.class);
		JMapAccessor targetAccessor = aClass.getAnnotation(JMapAccessor.class);
		String get = targetAccessor != null ? targetAccessor.get(): Constants.DEFAULT_ACCESSOR_VALUE;
		String set = targetAccessor != null ? targetAccessor.set(): Constants.DEFAULT_ACCESSOR_VALUE;
		SimplyAttribute[] targetAttributes = toTargetAttributes(globalMap.attributes());
		return toXmlGlobal(globalMap.value(), get, set, targetAttributes, globalMap.classes(), globalMap.excluded());
	}
	
	/**
	 * Shared method. Starting from general parameters returns an instance of XmlGlobal.
	 * @param value name of target field
	 * @param get get method of target field
	 * @param set set method of target field
	 * @param attributes names of target fields
	 * @param classes list of target classes
	 * @param excluded list of excluded fields
	 * @return a XmlAttribute instance
	 */
	private static XmlGlobal toXmlGlobal(String value, String get, String set, SimplyAttribute[] attributes, Class[] classes, String[] excluded){
		
		XmlGlobal xmlGlobal = new XmlGlobal();
		
		if(!isEmpty(value))
			xmlGlobal.value = new XmlTargetAttribute(value);
		
		if(!isEmpty(get))
			xmlGlobal.value.get = get;
		
		if(!isEmpty(set))
			xmlGlobal.value.set = set;
		
		if(!isEmpty(attributes)){
			xmlGlobal.attributes = new ArrayList();
			for (SimplyAttribute attribute : attributes)
				xmlGlobal.attributes.add(new XmlTargetAttribute(attribute));
		}
		
		if(!isEmpty(classes)){
			xmlGlobal.classes = new ArrayList();
			for (Class clazz : classes) 
				xmlGlobal.classes.add(new XmlTargetClass(clazz.getName()));
		}
		
		if(!isEmpty(excluded)){
			xmlGlobal.excluded = new ArrayList();
			for (String attribute : excluded)
				xmlGlobal.excluded.add(new XmlExcludedAttribute(attribute));
		}
		
		return xmlGlobal;
	}
	
	/**
	 * Conversion from attributes in String array form to TargetAttribute array form.
	 * @param attributes attributes to convert
	 * @return the converted array of SimplyAttribute type
	 */
	public static SimplyAttribute[] toTargetAttributes(String[] attributes){
		SimplyAttribute[] targetAttributes = new SimplyAttribute[attributes.length];
		for (int i = 0; i < attributes.length; i++) 
			targetAttributes[i] = new SimplyAttribute(attributes[i]);
		return targetAttributes;
	}
	
	/**
	 * This method transforms a Field given in input, into a XmlAttribute.
	 * @param clazz field's class
	 * @param field field to transform in XmlAttribute
	 * @return a field converted to XmlAttribute
	 */
	public static XmlAttribute toXmlAttribute(Class clazz, Field field){
		JMap jMap = field.getAnnotation(JMap.class);
		SimplyAttribute[] targetAttributes = toTargetAttributes(jMap.attributes());
		
		String get = null;
		String set = null;
		JMapAccessor jMapAccessor = Annotation.getFieldAccessors(clazz,field);
		if(!isNull(jMapAccessor)){
			get = jMapAccessor.get();
			set = jMapAccessor.set();
		}
		
		return toXmlAttribute(field.getName(),new Value(jMap.value()),get,set,targetAttributes,jMap.classes());
	}
	
	/**
	 * This method transforms a Attribute given in input, into a XmlAttribute.
	 * @param attribute an Attribute to transform in XmlAttribute
	 * @return an Attribute converted to XmlAttribute
	 */
	public static XmlAttribute toXmlAttribute(Attribute attribute){
		return toXmlAttribute(attribute.getName(),attribute.getValue(),attribute.getGet(),attribute.getSet(),attribute.getAttributes(),attribute.getClasses());
	}
	
	/**
	 * Shared method. Starting from general parameters returns an instance of XmlAttribute.
	 * @param name name of the mapped field
	 * @param value name of target field
	 * @param get get method name
	 * @param set set method name
	 * @param attributes target fields
	 * @param classes list of target classes
	 * @return a XmlAttribute instance
	 */
	private static XmlAttribute toXmlAttribute(String name, Value value, String get, String set, SimplyAttribute[] attributes, Class[] classes){
		
		XmlAttribute xmlAttribute = new XmlAttribute();
		
		xmlAttribute.name = name;
		xmlAttribute.get = get;
		xmlAttribute.set = set;
		
		if(!isNull(value)){
			String targetName = value.getName();
			if(!isNull(targetName) && (!isEmpty(targetName) || DEFAULT_FIELD_VALUE.equals(targetName)) )
				xmlAttribute.value = new XmlTargetAttribute(getValue(targetName,name));
		}

		if(!isEmpty(attributes)){
			xmlAttribute.attributes = new ArrayList();
			for (SimplyAttribute attribute : attributes)
				xmlAttribute.attributes.add(new XmlTargetAttribute(getValue(attribute.getName(),name),attribute.getGet(), attribute.getSet()));
		}

		if(!isEmpty(classes)){
			xmlAttribute.classes = new ArrayList();
			for (Class clazz : classes) 
				xmlAttribute.classes.add(new XmlTargetClass(clazz.getName()));
		}
		
		return xmlAttribute;
	}
	
	/**
	 * This method compare the name of the target field with the DEFAULT_FIELD_VALUE, 
	 * if are equals, the name of mapped field will be returned,
	 * otherwise name of target field will be returned.
	 * 
	 * @param value value of the configuration
	 * @param name name of the configured field
	 * @return the name of target field
	 * 
	 * @see Constants#DEFAULT_FIELD_VALUE
	 */
	private static String getValue(final String value,final String name){
		if(value == null) return null;
		return value.equals(DEFAULT_FIELD_VALUE)?name:value;
	}
	
	private static String[] trim(String[] array){
		for (int i = 0; i < array.length; i++)array[i] = array[i].trim();
		return array;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy