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

com.googlecode.jmapper.RelationalJMapper 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

The 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;

import java.io.IOException;
import java.lang.reflect.Field;
import java.net.MalformedURLException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.googlecode.jmapper.annotations.Annotation;
import com.googlecode.jmapper.annotations.JGlobalMap;
import com.googlecode.jmapper.annotations.JMap;
import com.googlecode.jmapper.api.IRelationalJMapper;
import com.googlecode.jmapper.api.JMapperAPI;
import com.googlecode.jmapper.api.enums.MappingType;
import com.googlecode.jmapper.api.enums.NullPointerControl;
import com.googlecode.jmapper.config.Error;
import com.googlecode.jmapper.config.JmapperLog;
import com.googlecode.jmapper.enums.ChooseConfig;
import com.googlecode.jmapper.exceptions.ClassNotMappedException;
import com.googlecode.jmapper.exceptions.MappingErrorException;
import com.googlecode.jmapper.xml.Attribute;
import com.googlecode.jmapper.xml.Global;
import com.googlecode.jmapper.xml.SimplyAttribute;
import com.googlecode.jmapper.xml.XML;

import static com.googlecode.jmapper.util.ClassesManager.*;
import static com.googlecode.jmapper.util.GeneralUtility.*;

/**
 * RelationalJMapper takes as input one configured Class.
* For configured Class, we mean a Class that contains fields configured with annotation or XML.
* It is mandatory that all fields have defined classes.
* For example: *

 * class Destination {
 * 
 *  @JMap(  attributes={"field1Class1","field1Class2","field1Class3"}, 
 *   	  classes={Class1.class,Class2.class,Class3.class})
 *	 private String field1;
 *  @JMap(  attributes={"field2Class1","field2Class2","field2Class3"}, 
 *   	  classes={Class1.class,Class2.class,Class3.class})
 *	 private String field2;
 *  @JMap(  attributes={"field3Class1","field3Class2","field3Class3"}, 
 *   	  classes={Class1.class,Class2.class,Class3.class})
 *	 private String field3;
 *  
 *  // getter and setter
 * }
 * 
* then invoke the methods manyToOne or oneToMany.

* With manyToOne method, the mapped classes are the source and the configured Class is the destination.
* manyToOne example: *

 *         AnnotatedClass manyToOne = null;
 *	Class1 class1 = new Class1("field1Class1", "field2Class1", "field3Class1");
 *	Class2 class2 = new Class2("field1Class2", "field2Class2", "field3Class2");
 *	Class3 class3 = new Class3("field1Class3", "field2Class3", "field3Class3");
 *		
 *	RelationalJMapper<AnnotatedClass> rm = new RelationalJMapper<AnnotatedClass>(AnnotatedClass.class);
 *		
 *	manyToOne = rm.manyToOne(class1);
 *	manyToOne = rm.manyToOne(class2);
 *	manyToOne = rm.manyToOne(class3);
 *	
* With oneToMany method, the mapped classes are the destination and the configured Class is the source.
* oneToMany example: *

 *         AnnotatedClass annotatedClass = new AnnotatedClass("field1", "field2", "field3");
 *		
 *	RelationalJMapper<AnnotatedClass> rm = new RelationalJMapper<AnnotatedClass>(AnnotatedClass.class);
 *		
 *	Class1 class1 = rm.setDestinationClass(Class1.class).oneToMany(annotatedClass);
 *	Class2 class2 = rm.setDestinationClass(Class2.class).oneToMany(annotatedClass);
 *	Class3 class3 = rm.setDestinationClass(Class3.class).oneToMany(annotatedClass);
 *  
* For more information see {@link RelationalJMapper#manyToOne manyToOne} and {@link RelationalJMapper#oneToMany oneToMany} Methods
* * @author Alessandro Vurro * * @param Type of Configured Class */ @SuppressWarnings({"rawtypes","unchecked"}) public final class RelationalJMapper implements IRelationalJMapper{ /** Configured Class*/ private Class configuredClass; /** map that has the target class names as keys and relative JMapper as values */ private final HashMap relationalOneToManyMapper = new HashMap(); /** map that has the target class names as keys and relative JMapper as values */ private final HashMap relationalManyToOneMapper = new HashMap();; /** * Takes in input only the annotated Class * @param configuredClass configured class */ public RelationalJMapper(final Class configuredClass){ this.configuredClass = configuredClass; try{ init(); }catch(ClassNotMappedException e){ JmapperLog.error(e); }catch(MappingErrorException e){ JmapperLog.error(e); } } /** * Takes in input the configured Class and the configuration in API format. * @param configuredClass configured class * @param jmapperAPI the configuration */ public RelationalJMapper(final Class configuredClass, JMapperAPI jmapperAPI){ this(configuredClass, jmapperAPI.toXStream().toString()); } /** * Takes in input only the configured Class and the xml mapping path or the xml as String format. * @param configuredClass configured class * @param xmlPath XML path or xml as String */ public RelationalJMapper(final Class configuredClass, String xmlPath){ this.configuredClass = configuredClass; try { init(xmlPath); } catch (MalformedURLException e) { JmapperLog.error(e); } catch (IOException e) { JmapperLog.error(e); }catch(ClassNotMappedException e){ JmapperLog.error(e); }catch(MappingErrorException e){ JmapperLog.error(e); } } /** * This method initializes relational maps starting from XML. * @param xmlPath xml path * @throws MalformedURLException * @throws IOException */ private void init(String xmlPath) throws MalformedURLException, IOException{ XML xml = new XML(true, xmlPath); if(!xml.isInheritedMapped(configuredClass)) Error.classNotMapped(configuredClass); for (Class classe :getClasses(xml)){ relationalManyToOneMapper.put(classe.getName(), new JMapper(configuredClass, classe,ChooseConfig.DESTINATION, xmlPath)); relationalOneToManyMapper.put(classe.getName(), new JMapper(classe, configuredClass,ChooseConfig.SOURCE, xmlPath)); } } /** * Returns all Target Classes contained in the XML. * @param xml xml to analyze * @return target classes */ private Set> getClasses(XML xml){ HashSet> result = new HashSet>(); // in case of override only the last global configuration must be analyzed Global global = null; for (Class clazz : getAllsuperClasses(configuredClass)) { // 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)){ addClasses(global.getClasses(),result); if(global.getExcluded()!=null) for (Attribute attribute : xml.loadAttributes().get(clazz.getName())) for (String fieldName : global.getExcluded()) if(attribute.getName().equals(fieldName)) addClasses(attribute.getClasses(),result,attribute.getName()); } } List attributes = xml.loadAttributes().get(clazz.getName()); if(!isNull(attributes)) for (Attribute attribute : attributes) if( isNull(global) || isPresent(global.getExcluded(), attribute.getName()) || ( !isEmpty(global.getAttributes()) && !isPresent(global.getAttributes(), new SimplyAttribute(attribute.getName())) ) ) addClasses(attribute.getClasses(),result,attribute.getName()); } return result; } /** * This method initializes relational maps */ private void init(){ if(!Annotation.isInheritedMapped(configuredClass)) Error.classNotMapped(configuredClass); for (Class classe :getClasses()){ relationalManyToOneMapper.put(classe.getName(), new JMapper(configuredClass, classe,ChooseConfig.DESTINATION)); relationalOneToManyMapper.put(classe.getName(), new JMapper(classe, configuredClass,ChooseConfig.SOURCE)); } } /** * Returns all Target Classes * @return a List of Target Classes */ private Set> getClasses() { HashSet> result = new HashSet>(); // in case of override only the last global configuration must be analyzed JGlobalMap jGlobalMap = null; for (Class clazz : getAllsuperClasses(configuredClass)) { // only if global configuration is null will be searched global configuration on super classes if(isNull(jGlobalMap)){ jGlobalMap = clazz.getAnnotation(JGlobalMap.class); //if the field configuration is defined in the global map if(!isNull(jGlobalMap)){ addClasses(jGlobalMap.classes(),result); if(!isNull(jGlobalMap.excluded())) for (Field field : getListOfFields(configuredClass)){ JMap jMap = field.getAnnotation(JMap.class); if(!isNull(jMap)) for (String fieldName : jGlobalMap.excluded()) if(field.getName().equals(fieldName)) addClasses(jMap.classes(),result,field.getName()); } return result; } } } for (Field field : getListOfFields(configuredClass)){ JMap jMap = field.getAnnotation(JMap.class); if(!isNull(jMap)) addClasses(jMap.classes(),result,field.getName()); } return result; } /** * Adds to the result parameter all classes that aren't present in it * @param classes classes to control * @param result List to enrich * @param fieldName name of file, only for control purpose */ private void addClasses(Class[] classes, HashSet> result, String fieldName){ if(classes == null || classes.length==0) Error.classesAbsent(fieldName, configuredClass); for (Class classe : classes) result.add(classe); } /** * Adds to the result parameter all classes that aren't present in it * @param classes classes to control * @param result List to enrich */ private void addClasses(Class[] classes, HashSet> result){ if(isNull(classes) || classes.length==0) Error.globalClassesAbsent(configuredClass); for (Class classe : classes) result.add(classe); } /** * Returns a new instance of Class given as input, managing also the exception. * @param exception exception to handle * @param clazz class to instantiate * @return a new instance of Class given as input */ private I logAndReturnNull(Exception exception){ JmapperLog.error(exception); return null; } /** * This method verifies that the destinationClass exists. * @param exception exception to handle * @param clazz class to check * @return a new instance of Class given as input */ private I destinationClassControl(Exception exception, Class clazz){ try{ if(clazz == null)throw new IllegalArgumentException("it's mandatory define the destination class"); }catch (Exception e) {JmapperLog.error(e);return null;} return logAndReturnNull(exception); } /** * Returns the desired JMapper instance. * @param map the map of relationships * @param source key of the map * @return the instance of JMapper */ private JMapper getJMapper(HashMap map,Object source){ Class sourceClass = source instanceof Class?((Class)source):source.getClass(); JMapper jMapper = map.get(sourceClass.getName()); if(jMapper == null) Error.classNotMapped(source, configuredClass); return jMapper; } /** * This method returns a new instance of Configured Class with this setting: * * * * * * * * *
NullPointerControlSOURCE
MappingType of DestinationALL_FIELDS
MappingType of SourceALL_FIELDS
* @param source instance of Target Class type that contains the data * @return new instance of Configured Class * @see NullPointerControl * @see MappingType */ public T manyToOne(final S source) { try{ return this.getJMapper(relationalManyToOneMapper,source).getDestination(source); } catch (Exception e) { return logAndReturnNull(e);} } /** * This method returns a new instance of Configured Class with this setting: * * * * * * * * *
NullPointerControlNOT_ANY
MappingType of DestinationALL_FIELDS
MappingType of SourceALL_FIELDS
* @param source instance of Target Class type that contains the data * @return new instance of Configured Class * @see NullPointerControl * @see MappingType */ public T manyToOneWithoutControl(final S source) { try{ return this.getJMapper(relationalManyToOneMapper,source).getDestinationWithoutControl(source); } catch (Exception e) { return logAndReturnNull(e); } } /** * This Method returns the configured instance given in input enriched with data contained in source given in input
* with this setting: * * * * * * * * *
NullPointerControlALL
MappingType of DestinationALL_FIELDS
MappingType of SourceALL_FIELDS
* @param destination instance of Configured Class type to enrich * @param source instance of Target Class type that contains the data * @return destination enriched * @see NullPointerControl * @see MappingType */ public T manyToOne(T destination,final S source) { try{ return this.getJMapper(relationalManyToOneMapper,source).getDestination(destination,source); } catch (Exception e) { return logAndReturnNull(e); } } /** * This Method returns the configured instance given in input enriched with data contained in source given in input
* with this setting: * * * * * * * * *
NullPointerControlNOT_ANY
MappingType of DestinationALL_FIELDS
MappingType of SourceALL_FIELDS
* @param destination instance of Configured Class type to enrich * @param source instance of Target Class type that contains the data * @return destination enriched * @see NullPointerControl * @see MappingType */ public T manyToOneWithoutControl(T destination,final S source) { try{ return this.getJMapper(relationalManyToOneMapper,source).getDestinationWithoutControl(destination,source); } catch (Exception e) { return logAndReturnNull(e); } } /** * This method returns a new instance of Configured Class with this setting: * * * * * * * * *
NullPointerControlSOURCE
MappingType of DestinationALL_FIELDS
MappingType of SourcemtSource
* @param source instance of Target Class type that contains the data * @param mtSource type of mapping of source instance * @return new instance of Configured Class * @see NullPointerControl * @see MappingType */ public T manyToOne(final S source,final MappingType mtSource) { try{ return this.getJMapper(relationalManyToOneMapper,source).getDestination(source,mtSource); } catch (Exception e) { return logAndReturnNull(e); } } /** * This method returns a new instance of Configured Class with this setting: * * * * * * * * *
NullPointerControlnullPointerControl
MappingType of DestinationALL_FIELDS
MappingType of SourcemtSource
* @param source instance of Target Class type that contains the data * @param nullPointerControl type of null pointer control * @param mtSource type of mapping of source instance * @return new instance of Configured Class * @see NullPointerControl * @see MappingType */ public T manyToOne(final S source,final NullPointerControl nullPointerControl,final MappingType mtSource) { try{ return this.getJMapper(relationalManyToOneMapper,source).getDestination(source,nullPointerControl,mtSource); } catch (Exception e) { return logAndReturnNull(e); } } /** * This Method returns the configured instance given in input enriched with data contained in source given in input
* with this setting: * * * * * * * * *
NullPointerControlALL
MappingType of DestinationmtDestination
MappingType of SourcemtSource
* @param destination instance of Configured Class type to enrich * @param source instance of Target Class type that contains the data * @param mtDestination type of mapping of destination instance * @param mtSource type of mapping of source instance * @return destination enriched * @see NullPointerControl * @see MappingType */ public T manyToOne(T destination,final S source,final MappingType mtDestination,final MappingType mtSource) { try{ return this.getJMapper(relationalManyToOneMapper,source).getDestination(destination, source, mtDestination,mtSource); } catch (Exception e) { return logAndReturnNull(e); } } /** * This Method returns the configured instance given in input enriched with data contained in source given in input
* with this setting: * * * * * * * * *
NullPointerControlnullPointerControl
MappingType of DestinationmtDestination
MappingType of SourcemtSource
* @param destination instance of Configured Class type to enrich * @param source instance of Target Class type that contains the data * @param nullPointerControl type of null pointer control * @param mtDestination type of mapping of destination instance * @param mtSource type of mapping of source instance * @return destination enriched * @see NullPointerControl * @see MappingType */ public T manyToOne(T destination,final S source,final NullPointerControl nullPointerControl,final MappingType mtDestination,final MappingType mtSource) { try{ return this.getJMapper(relationalManyToOneMapper,source).getDestination(destination, source, nullPointerControl, mtDestination, mtSource); } catch (Exception e) { return logAndReturnNull(e); } } /** * This method returns a new instance of Target Class with this setting: * * * * * * * * *
NullPointerControlSOURCE
MappingType of DestinationALL_FIELDS
MappingType of SourceALL_FIELDS
* @param destinationClass class to create * @param source instance of Configured Class that contains the data * @return new instance of Target Class * @see NullPointerControl * @see MappingType */ public D oneToMany(Class destinationClass, final T source) { try{ return this.getJMapper(relationalOneToManyMapper,destinationClass).getDestination(source); } catch (Exception e) { return (D) this.destinationClassControl(e,destinationClass); } } /** * This method returns a new instance of Target Class with this setting: * * * * * * * * *
NullPointerControlNOT_ANY
MappingType of DestinationALL_FIELDS
MappingType of SourceALL_FIELDS
* @param source instance of Configured Class that contains the data * @return new instance of Target Class * @see NullPointerControl * @see MappingType */ public D oneToManyWithoutControl(Class destinationClass, final T source) { try{ return this.getJMapper(relationalOneToManyMapper,destinationClass).getDestinationWithoutControl(source); } catch (Exception e) { return (D) this.destinationClassControl(e,destinationClass); } } /** * This Method returns the destination given in input enriched with data contained in source given in input
* with this setting: * * * * * * * * *
NullPointerControlALL
MappingType of DestinationALL_FIELDS
MappingType of SourceALL_FIELDS
* @param destination instance of Target Class to enrich * @param source instance of Configured Class that contains the data * @return destination enriched * @see NullPointerControl * @see MappingType */ public D oneToMany(D destination,final T source) { try{ return this.getJMapper(relationalOneToManyMapper,destination.getClass()).getDestination(destination,source); } catch (Exception e) { return this.logAndReturnNull(e); } } /** * This Method returns the destination given in input enriched with data contained in source given in input
* with this setting: * * * * * * * * *
NullPointerControlNOT_ANY
MappingType of DestinationALL_FIELDS
MappingType of SourceALL_FIELDS
* @param destination instance of Target Class to enrich * @param source instance of Configured Class that contains the data * @return destination enriched * @see NullPointerControl * @see MappingType */ public D oneToManyWithoutControl(D destination,final T source) { try{ return this.getJMapper(relationalOneToManyMapper,destination.getClass()).getDestinationWithoutControl(destination,source); } catch (Exception e) { return this.logAndReturnNull(e); } } /** * This method returns a new instance of Target Class with this setting: * * * * * * * * *
NullPointerControlSOURCE
MappingType of DestinationALL_FIELDS
MappingType of SourcemtSource
* @param destinationClass class to create * @param source instance of Configured Class that contains the data * @param mtSource type of mapping of source instance * @return new instance of Target Class * @see NullPointerControl * @see MappingType */ public D oneToMany(Class destinationClass, final T source,final MappingType mtSource) { try{ return this.getJMapper(relationalOneToManyMapper,destinationClass).getDestination(source,mtSource); } catch (Exception e) { return (D) this.destinationClassControl(e,destinationClass); } } /** * This method returns a new instance of Target Class with this setting: * * * * * * * * *
NullPointerControlnullPointerControl
MappingType of DestinationALL_FIELDS
MappingType of SourcemtSource
* @param source instance of Configured Class that contains the data * @param nullPointerControl type of control * @param mtSource type of mapping of source instance * @return new instance of Target Class * @see NullPointerControl * @see MappingType */ public D oneToMany(Class destinationClass, final T source,final NullPointerControl nullPointerControl,final MappingType mtSource) { try{ return this.getJMapper(relationalOneToManyMapper,destinationClass).getDestination(source,nullPointerControl,mtSource); } catch (Exception e) { return (D) this.destinationClassControl(e,destinationClass); } } /** * This Method returns the destination given in input enriched with data contained in source given in input
* with this setting: * * * * * * * * *
NullPointerControlALL
MappingType of DestinationmtDestination
MappingType of SourcemtSource
* @param destination instance of Target Class to enrich * @param source instance of Configured Class that contains the data * @param mtDestination type of mapping of destination instance * @param mtSource type of mapping of source instance * @return destination enriched * @see NullPointerControl * @see MappingType */ public D oneToMany(D destination,final T source,final MappingType mtDestination,final MappingType mtSource) { try{ return this.getJMapper(relationalOneToManyMapper,destination.getClass()).getDestination(destination, source, mtDestination,mtSource); } catch (Exception e) { return this.logAndReturnNull(e); } } /** * This Method returns the destination given in input enriched with data contained in source given in input
* with this setting: * * * * * * * * *
NullPointerControlnullPointerControl
MappingType of DestinationmtDestination
MappingType of SourcemtSource
* @param destination instance of Target Class to enrich * @param source instance of Configured Class that contains the data * @param nullPointerControl type of null pointer control * @param mtDestination type of mapping of destination instance * @param mtSource type of mapping of source instance * @return destination enriched * @see NullPointerControl * @see MappingType */ public D oneToMany(D destination,final T source,final NullPointerControl nullPointerControl,final MappingType mtDestination,final MappingType mtSource) { try{ return this.getJMapper(relationalOneToManyMapper,destination.getClass()).getDestination(destination, source, nullPointerControl, mtDestination, mtSource);} catch (Exception e) { return this.logAndReturnNull(e); } } }