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

com.googlecode.jmapper.xml.XML 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.util.FilesManager.fullPathOf;
import static com.googlecode.jmapper.util.FilesManager.isPath;
import static com.googlecode.jmapper.util.FilesManager.readAtDevelopmentTime;
import static com.googlecode.jmapper.util.FilesManager.readAtRuntime;
import static com.googlecode.jmapper.util.GeneralUtility.*;
import static com.googlecode.jmapper.util.ClassesManager.*;

import java.io.IOException;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.googlecode.jmapper.config.Error;
import com.googlecode.jmapper.config.JmapperLog;
import com.googlecode.jmapper.conversions.explicit.ConversionMethod;
import com.googlecode.jmapper.exceptions.XmlConversionNameException;
import com.googlecode.jmapper.exceptions.XmlConversionParameterException;
import com.googlecode.jmapper.exceptions.XmlConversionTypeException;
import com.googlecode.jmapper.operations.beans.MappedField;
import com.googlecode.jmapper.util.FilesManager;
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.XmlJmapper;

/**
 * XML exposes utility methods for managing the XML file.
 * 
 * @author Alessandro Vurro
 *
 */
public final class XML {

	/**  xml path */
	private String xmlPath;
	/**  xmlJmapper object */
	private XmlJmapper xmlJmapper;
	
	/**
	 * Xml file can be loaded in two ways: at runtime and development time.
	 * @param atRuntime true if xml file must be loaded at runtime, false at development time
	 * @param xmlPath path of xml file
	 * @throws IOException other cases 
	 * @throws MalformedURLException in case of malformed xml path
	 */
	//TODO XML -> bisogna differenziare da Path e contenuto
	// inoltre gli stessi errori si hanno con la configurazione API
	// quindi sarebbe meglio generalizzarli
	public XML(boolean atRuntime, String xmlPath) throws MalformedURLException, IOException{
		if(!isNull(xmlPath)){
			xmlJmapper = atRuntime?readAtRuntime(xmlPath):readAtDevelopmentTime(xmlPath);
			
			if(isPath(xmlPath))
				this.xmlPath = atRuntime?xmlPath:fullPathOf(xmlPath);
			else
				this.xmlPath = "";//TODO XML -> scrivere il messaggio da visualizzare 
		}
		
		if(isNull(xmlJmapper))xmlJmapper = new XmlJmapper();
		if(isNull(xmlJmapper.classes))xmlJmapper.classes = new ArrayList();
	}
	
	/**
	 * Default behavior
	 */
	public XML(){
		xmlJmapper = new XmlJmapper();
		xmlJmapper.classes = new ArrayList();
	}
	
	/**
	 * Returns an XStream version of this XML.
	 * @return xstream bean
	 */
	public XmlJmapper toXStream(){
		return xmlJmapper;
	}
	
	/**
	 * Returns the xml path of this object.
	 * @return xml path
	 */
	public String getXmlPath(){
		return xmlPath;
	}
	
	/**
	 * True if xml path has been defined, false otherwise.
	 * @return true if xml path has been defined, false otherwise
	 */
	public boolean exists(){
		return xmlPath != null;
	}
	
	/**
	 * Setting of xml path.
	 * @param aXmlPath xml path
	 * @return this instance of XML
	 */
	public XML setXmlPath(String aXmlPath){
		xmlPath = aXmlPath;
		return this;
	}
	
	/** @return a Map with class name as key and a the global as value */
	public Map loadGlobals(){
		Map map = new HashMap();
		
		try{	// if xml mapping file isn't empty
				if(!isEmpty(xmlJmapper.classes))
				    for (XmlClass xmlClass : xmlJmapper.classes) 
					   if(xmlClass.global != null)
						   map.put(xmlClass.name, Converter.toGlobal(xmlClass.global));
					   					
		}catch (Exception e) {JmapperLog.error(e);}
		return map;
	}
	
	/** @return a Map with class name as key and a list of Attributes as value */
	public Map> loadAttributes(){
		Map> map = new HashMap>();
		
		try{	// if xml mapping file isn't empty
				if(!isEmpty(xmlJmapper.classes))
					for (XmlClass xmlClass : xmlJmapper.classes) {
					   List attributes = new ArrayList();
					   if(!isEmpty(xmlClass.attributes))
						 for (XmlAttribute xmlAttribute : xmlClass.attributes)
							 attributes.add(Converter.toAttribute(xmlAttribute));
													
					   map.put(xmlClass.name, attributes);
					}
		}catch (Exception e) {JmapperLog.error(e);}
		return map;
	}
	
	/** @return a Map with class name as key and a list of Conversions as value */
	public Map> conversionsLoad(){
		Map> map = new HashMap>();
		
		try{	// if xml mapping file isn't empty
				if(!isEmpty(xmlJmapper.classes))
					for (XmlClass xmlClass : xmlJmapper.classes) {
					   List conversions = new ArrayList();
					   if(!isEmpty(xmlClass.conversions))
						 for (XmlConversion xmlConversion : xmlClass.conversions)
							 try{	 conversions.add(Converter.toConversionMethod(xmlConversion));
							 }catch (XmlConversionNameException e) {
								 Error.xmlConversionNameUndefined(this.xmlPath,xmlClass.name);
							 }catch (XmlConversionTypeException e) {
								 Error.xmlConversionTypeIncorrect(xmlConversion.name,this.xmlPath,xmlClass.name,xmlConversion.type);
							 }catch (XmlConversionParameterException e) {
								 Error.improperUseOfTheParameter(xmlConversion.name,this.xmlPath,xmlClass.name);
							 }
					   // enrich map only if for this class there are conversions
					   if(!conversions.isEmpty())
						   map.put(xmlClass.name, conversions);
					}
		}catch (Exception e) {JmapperLog.error(e);}
		return map;
	}
	
	/**
	 * Returns the conversions method belonging to clazz.
	 * @param clazz class to check
	 * @return the conversion method list
	 */
	public List getConversionMethods (Class clazz){
		List conversions = new ArrayList();
		Map> conversionsMap = this.conversionsLoad();
		for (Class classToCheck : getAllsuperClasses(clazz)){
			List methods = conversionsMap.get(classToCheck.getName());
			if(methods != null)conversions.addAll(methods);
		}
		return conversions;
	}
		
	/**
	 * Returns a list with the classes names presents in xml mapping file.
	 * @return a list with the classes names presents in xml mapping file
	 */
	public List getClasses(){
		List classes = new ArrayList();
		for (XmlClass xmlClass : xmlJmapper.classes) 
			classes.add(xmlClass.name);
		return classes;
	}
	
	/**
	 * Writes the xml mapping file starting from xmlJmapper object.
	 * @return this instance of XML
	 */
	public XML write(){
		try { FilesManager.write(xmlJmapper, xmlPath);
		} catch (IOException e) {JmapperLog.error(e);}
		return this;
	}
	
	/**
	 * This method adds to the xml configuration file, the class given in input.
	 * @param aClass add This Class to Xml Configuration file
	 * @return this instance
	 */
	public XML addAnnotatedClass(Class aClass){
		checksClassAbsence(aClass);
		addClass(aClass);
		return this;
	}
	
	/**
	 * This method adds aClass with the attributes given as input to XML configuration file.
* It's mandatory define at least one attribute. * @param aClass Class to adds * @param attributes attributes of Class * @return this instance */ public XML addClass(Class aClass,Attribute[] attributes){ checksClassAbsence(aClass); XmlClass xmlClass = new XmlClass(); xmlClass.name = aClass.getName(); xmlClass.attributes = new ArrayList(); xmlJmapper.classes.add(xmlClass); addAttributes(aClass, attributes); return this; } /** * This method adds aClass with this global mapping and attributes to XML configuration file.
* It's mandatory define at least one attribute, global is optional instead. * @param aClass Class to adds * @param global global mapping * @return this instance */ public XML addClass(Class aClass, Global global){ checksClassAbsence(aClass); XmlClass xmlClass = new XmlClass(); xmlClass.name = aClass.getName(); xmlJmapper.classes.add(xmlClass); addGlobal(aClass, global); return this; } /** * This method adds aClass with this global mapping and attributes to XML configuration file.
* It's mandatory define at least one attribute, global is optional instead. * @param aClass Class to adds * @param global global mapping * @param attributes attributes of Class * @return this instance */ public XML addClass(Class aClass, Global global, Attribute[] attributes){ XmlClass xmlClass = new XmlClass(); xmlClass.name = aClass.getName(); xmlJmapper.classes.add(xmlClass); if(!isEmpty(attributes)){ xmlClass.attributes = new ArrayList(); addAttributes(aClass, attributes); } if(global != null) addGlobal(aClass, global); return this; } /** * This method remove a specific Class from Xml Configuration File * @param aClass class to delete * @return this instance of XML */ public XML deleteClass(Class aClass){ boolean isRemoved = xmlJmapper.classes.remove(new XmlClass(aClass.getName())); if(!isRemoved)Error.xmlClassInexistent(this.xmlPath,aClass); return this; } /** * This method adds the global to an existing Class. * @param aClass class to edit * @param global global to add * @return this instance of XML */ public XML addGlobal(Class aClass,Global global){ checksGlobalAbsence(aClass); findXmlClass(aClass).global = Converter.toXmlGlobal(global); return this; } /** * This method deletes the global to an existing Class. * @param aClass class to delete * @return this instance of XML */ public XML deleteGlobal(Class aClass){ checksGlobalExistence(aClass); XmlClass xmlClass = findXmlClass(aClass); if(isEmpty(xmlClass.attributes)) deleteClass(aClass); else xmlClass.global = null; return this; } /** * This method adds the attributes to an existing Class. * @param aClass class to which add attributes * @param attributes attributes to add * @return this instance of XML */ public XML addAttributes(Class aClass,Attribute[] attributes){ checksAttributesExistence(aClass,attributes); for (Attribute attribute : attributes) { if(attributeExists(aClass,attribute)) Error.xmlAttributeExistent(this.xmlPath,attribute, aClass); findXmlClass(aClass).attributes.add(Converter.toXmlAttribute(attribute)); } return this; } /** * This method deletes the attributes to an existing Class. * @param aClass class to which delete the attributes * @param attributes attributes to delete * @return this instance of XML */ public XML deleteAttributes(Class aClass,String[] attributes){ checksAttributesExistence(aClass,attributes); if(isEmpty(findXmlClass(aClass).attributes) || findXmlClass(aClass).attributes.size()<=1) Error.xmlWrongMethod(aClass); for (String attributeName : attributes) { XmlAttribute attribute = null; for (XmlAttribute xmlAttribute : findXmlClass(aClass).attributes) if(xmlAttribute.name.equals(attributeName)) attribute = xmlAttribute; if(attribute == null) Error.xmlAttributeInexistent(this.xmlPath,attributeName,aClass); findXmlClass(aClass).attributes.remove(attribute); } return this; } /** * Adds an annotated Class to xmlJmapper structure. * @param aClass Class to convert to XmlClass * @return this instance of XML */ private XML addClass(Class aClass){ xmlJmapper.classes.add(Converter.toXmlClass(aClass)); return this; } /** * Verifies that the global mapping exist in aClass. * @param aClass class to check * @return this intance of XML */ private XML checksGlobalExistence(Class aClass){ if(!classExists(aClass)) Error.xmlClassInexistent(this.xmlPath,aClass); if(findXmlClass(aClass).global==null) Error.xmlGlobalInexistent(aClass); return this; } /** * Verifies that the global mapping exist in aClass. * @param aClass class to check * @return this intance of XML */ private XML checksGlobalAbsence(Class aClass){ if(!classExists(aClass)) Error.xmlClassInexistent(this.xmlPath,aClass); if(findXmlClass(aClass).global!=null) Error.xmlGlobalExistent(aClass); return this; } /** * Verifies that the attributes exist in aClass. * @param aClass Class to check * @param attributes attributes to check * @return this instance of XML */ private XML checksAttributesExistence(Class aClass,Attribute[] attributes){ String[] attributesNames = new String[attributes.length]; for (int i = attributes.length; i --> 0;) attributesNames[i] = attributes[i].getName(); checksAttributesExistence(aClass,attributesNames); return this; } /** * Verifies that the attributes exist in aClass. * @param aClass Class to check * @param attributes list of the names attributes to check. * @return this instance of XML */ private XML checksAttributesExistence(Class aClass,String[] attributes){ if(!classExists(aClass)) Error.xmlClassInexistent(this.xmlPath,aClass); for (String attributeName : attributes) try{ aClass.getDeclaredField(attributeName); } catch (Exception e){ Error.attributeInexistent(attributeName, aClass);} return this; } /** * Throws an exception if the class exist. * @param aClass a Class to check * @return this instance of XML */ private XML checksClassAbsence(Class aClass){ if(classExists(aClass))Error.xmlClassExistent(this.xmlPath,aClass); return this; } /** * verifies that this class exist in Xml Configuration File. * * @param aClass Class to verify * @return this instance */ private boolean classExists(Class aClass) { if(xmlJmapper.classes == null)return false; return findXmlClass(aClass) !=null?true:false; } /** * This method returns true if the attribute exist in the Class given in input, returns false otherwise. * @param aClass Class of the Attribute * @param attribute Attribute to check * @return true if attribute exist, false otherwise */ private boolean attributeExists(Class aClass,Attribute attribute){ if(!classExists(aClass))return false; for (XmlAttribute xmlAttribute : findXmlClass(aClass).attributes) if(xmlAttribute.name.equals(attribute.getName()))return true; return false; } /** * Finds the Class, given in input, in the xml mapping file and returns a XmlClass instance if exist, null otherwise. * @param aClass Class to finds * @return a XmlClass if aClass exist in xml mapping file, null otherwise */ private XmlClass findXmlClass(Class aClass){ for (XmlClass xmlClass : xmlJmapper.classes) if(xmlClass.name.equals(aClass.getName())) return xmlClass; return null; } /** * Returns true if the class is configured in xml (also checking the super classes), false otherwise. * @param classToCheck class to check * @return true if the class is configured in xml, false otherwise */ public boolean isInheritedMapped(Class classToCheck){ for (Class clazz : getAllsuperClasses(classToCheck)) if(isMapped(clazz))return true; return false; } /** * Returns true if the class is configured in xml, false otherwise. * @param classToCheck class to check * @return true if the class is configured in xml, false otherwise */ public boolean isMapped(Class classToCheck){ return !isNull(loadGlobals().get(classToCheck.getName())) || !isEmpty(loadAttributes().get(classToCheck.getName())); } /** * Returns the Attribute relative to the configured field, null otherwise. * @param configuredField field to find * @param configuredClass class of field * @return */ private Attribute getGlobalAttribute(MappedField configuredField, Class configuredClass){ Global global = null; Map globals = loadGlobals(); for (Class clazz : getAllsuperClasses(configuredClass)) { global = globals.get(clazz.getName()); if(!isNull(global))break; } if(!isNull(global) && !isNull(global.getAttributes())) for (SimplyAttribute globalAttribute : global.getAttributes()) { String name = globalAttribute.getName(); if(configuredField.getValue().getName().equals(name)){ String get = globalAttribute.getGet(); String set = globalAttribute.getSet(); if(!isNull(get) || !isNull(set)) return new Attribute(name, null, get, set, null, null); } } return null; } /** * Returns the Attribute relative to the configured field, null otherwise. * @param configuredField field to find * @param configuredClass class of field * @return */ private Attribute getAttribute(MappedField configuredField, Class configuredClass){ // If configuredClass exists in XML configuration file for (Class clazz : getAllsuperClasses(configuredClass)) if (isMapped(clazz)) // loads all configured attributes for (Attribute attribute : 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(configuredField.getValue().getName())) return attribute; } return null; } /** * Enrich configuredField with get and set define in xml configuration. * @param configuredClass class of field * @param configuredField configured field * @return this */ public XML fillMappedField(Class configuredClass, MappedField configuredField) { Attribute attribute = getGlobalAttribute(configuredField, configuredClass); if(isNull(attribute)) attribute = getAttribute(configuredField, configuredClass); if(!isNull(attribute)){ if(isEmpty(configuredField.getMethod())) configuredField.getMethod(attribute.getGet()); if(isEmpty(configuredField.setMethod())) configuredField.setMethod(attribute.getSet()); } return this; } /** * Enrich targetField with get and set define in xml configuration. * @param configuredClass class of field * @param configuredField configured field * @param targetField the opposite field to enrich * @return this */ public XML fillOppositeField(Class configuredClass, MappedField configuredField, MappedField targetField) { Attribute attribute = null; Global global = loadGlobals().get(configuredClass.getName()); if(!isNull(global)){ String value = global.getValue(); if(!isEmpty(value) && value.equals(targetField.getValue().getName())){ String get = global.getGet(); String set = global.getSet(); if(!isNull(get) || !isNull(set)) attribute = new Attribute(null,new Value(global.getValue(),get,set)); } } if(isNull(attribute)) attribute = getAttribute(configuredField, configuredClass); if(!isNull(attribute)){ Value value = attribute.getValue(); // verifies value if(!isNull(value)) if(targetField.getValue().getName().equals(value.getName())){ if(isEmpty(targetField.getMethod())) targetField.getMethod(value.getGet()); if(isEmpty(targetField.setMethod())) targetField.setMethod(value.getSet()); } SimplyAttribute[] attributes = attribute.getAttributes(); // verifies attributes if(!isNull(attributes)) for (SimplyAttribute targetAttribute : attributes) if(targetField.getValue().getName().equals(targetAttribute.getName())){ if(isEmpty(targetField.getMethod())) targetField.getMethod(targetAttribute.getGet()); if(isEmpty(targetField.setMethod())) targetField.setMethod(targetAttribute.getSet()); } } return this; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy