自己实现的XML和Entity映射工具XmlHandler

公司不允许随便下载第三方jar包,但是公司lib库中的jar又非常老,更新需要申请,很多时候都是自己去写一些工具类,这次遇到xml处理的一些程序,于是自己写了一个工具类。这个比较粗糙,属于Test版本。

实体类注解@XmlEntity:

package com.cugxw.utils;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author cugxw
 * @date 2012-10-11
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface XmlEntity {
	/**
	 * Map namespace name of the XML.<br>
	 * If this value is "$Default$", the namespace name will be class namespace name.<br>
	 * If class namespace is unnamed, the XML namespace will be null. <br>
	 */
	String namespace() default "$Default$";
	
	/**
	 * Map root name of the XML.<br>
	 * If this value is "$Default$", the XML root name will be simple class name.<br>
	 */
	String name() default "$Default$";
	
	/**
	 * Map prefix of the elements.<br>
	 * If this value is "$Default$", all elements of the XML will have no prefix string.<br>
	 */
	String xmlPrefix() default "$Default$";
}

 实体类field注解@XmlField

package com.cugxw.utils;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author cugxw
 * @date 2012-10-11
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface XmlField {
	/**
	 * Map the element name of the XML.
	 * If this value is "$Default$", the elements' name of the XML will be class field name.
	 */
	String name() default "$Default$";
}

 Xml处理类,包含toXML和fromXML方法:

package com.cugxw.utils;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.QName;

@SuppressWarnings("unchecked")
public class XmlHandler {
	
	//Registed entity name 
	private  Map regClassMap;
	
	//Entity path, default src root directory.
	private boolean useXmlAnnotation = false;
	
	public XmlHandler()
	{
		this.regClassMap = new HashMap();
		this.registClass(null);
	}
	
	public XmlHandler(String entityPath)
	{
		this.regClassMap = new HashMap();
		this.registClass(entityPath);
	}
	
	public XmlHandler(String entityPath, boolean useXmlAnnotation)
	{
		this.regClassMap = new HashMap();
		this.useXmlAnnotation = useXmlAnnotation;
		this.registClass(entityPath);
	}
	
	/**
	 * Get all loaded classes, return them.
	 * @return
	 * @throws SecurityException
	 * @throws NoSuchFieldException
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 */
	private List getLoadedClass() throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
		ClassLoader curClassLoader = Thread.currentThread().getContextClassLoader();
		Class loaderClass = curClassLoader.getClass();
		
		/* Find all loaded classes in classloader */
		while (!loaderClass.equals(ClassLoader.class)) {
			loaderClass = loaderClass.getSuperclass();
		}
		
		/* Get the access to read private field */
		Field loaderField = loaderClass.getDeclaredField("classes");
		loaderField.setAccessible(true);
		
		return (List) loaderField.get(curClassLoader);
	}
	
	private String getXmlEntityName(Class<Object> clazz) {
		Object obj = clazz.getAnnotation(XmlEntity.class);
		if (obj == null) {
			return null;
		}
		return clazz.getAnnotation(XmlEntity.class).name();
	}
	
	public void registClassName(Class clazz) {
		String className = clazz.getName();
		if (this.useXmlAnnotation) {
			String xmlEntityName = getXmlEntityName(clazz);
			if (xmlEntityName != null && !"".equals(xmlEntityName)) {
				this.regClassMap.put(clazz.getSimpleName(), 
						className);
				System.out.println(className);
			}
		} else {
			this.regClassMap.put(clazz.getSimpleName(), 
					className);
			System.out.println(className);
		}
	}
	
	/**
	 * Regist all loaded classes, put them into a map.
	 * @param regPath
	 */
	public void registClass(String regPath) {
		try {
			List classList = this.getLoadedClass();
			int count = classList.size();
			for(int i=0; i<count; i++) {
				Object clazz = classList.get(i);
				String className = ((Class)clazz).getName();
				if (regPath == null || "".equals(regPath)) {
					this.registClassName((Class)clazz);
				} else {
					if (className.startsWith(regPath)) {
						this.registClassName((Class)clazz);
					}
				}
			}
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * Get field value from one object by field name 
	 * @param fieldName
	 * @param obj
	 * @return field value of the object;
	 */
	private Object getFieldValueByName(String fieldName, Object obj) throws Exception 
	{    
		String firstLetter = fieldName.substring(0, 1).toUpperCase();    
		String getter = "get" + firstLetter + fieldName.substring(1);    
		Method method = obj.getClass().getMethod(getter, new Class[] {});    
		Object value = method.invoke(obj, new Object[] {});
		return value;
	}  
	
	/**
	 * A sub task of addition sub element by calling recursion method
	 * @param pElement
	 * @param subElementName
	 * @param prefix
	 * @param textValue
	 * @return sub element
	 */
	private  Element addSubElement(Element pElement, String subElementName, 
			String prefix, String textValue)
	{
		QName qname = QName.get(subElementName);
		if(prefix != null && !"".equals(prefix))
		{
			qname = QName.get(prefix + ":" + subElementName);
		}
		Element node = pElement.addElement(qname);
		if(textValue != null && !"".equals(textValue))
		{
			node.setText(this.nullToStr(textValue));
		}
		return node;
	}
	
	private String getXmlFieldName(Field field) {
		String xmlFieldName = null;
		if (this.useXmlAnnotation) {
			XmlField xmlField = field.getAnnotation(XmlField.class);
			if (xmlField != null) {
				if (!"$Default$".equals(xmlField.name())) {
					xmlFieldName = xmlField.name();
					return xmlFieldName;
				}
			}
		}
		xmlFieldName = field.getName();
		return xmlFieldName;
	}
	
	/**
	 * A sub task of create sub xml by Recursion method
	 * @param element
	 * @param prefix
	 * @param obj
	 */
	private void createSubXml(Element element, String prefix, Object obj) throws Exception
	{
		if(obj == null)
		{
			return;
		}
		Class objClass = obj.getClass();
		Field[] fields = objClass.getDeclaredFields();
		for(int i=0; i<fields.length; i++)
		{
			String fieldName = fields[i].getName();
			String xmlFieldName = getXmlFieldName(fields[i]);
			Object fieldVal = this.getFieldValueByName(fieldName, obj);
			String fieldClassName = fields[i].getType().getSimpleName();
			if(fieldClassName == null || "".equals(fieldClassName)
					|| this.regClassMap == null)
			{
				continue;
			}
			
			String classFullName = (String) this.regClassMap.get(fieldClassName);
			if(classFullName != null && !"".equals(classFullName))
			{
				Element subElement = this.addSubElement(element, xmlFieldName, prefix, null);
				this.createSubXml(subElement, prefix, fieldVal);
			}
			else if(fieldVal != null && ("List".equals(fieldClassName) || "ArrayList".equals(fieldClassName)))
			{
				/* When sub class in a list object */
				Element subElement = this.addSubElement(element, xmlFieldName, prefix, null);
				Collection collection = (Collection) fieldVal;
				for(Object aVal : collection)
				{
					Element grandSubEle = this.addSubElement(subElement, aVal.getClass().getSimpleName(), prefix, null);
					this.createSubXml(grandSubEle, prefix, aVal);
				}
			}
			else if(fieldVal != null && ("Set".equals(fieldClassName) || "HashSet".equals(fieldClassName)))
			{
				/* When sub class in a set object */
				Element subElement = this.addSubElement(element, xmlFieldName, prefix, null);
				Set set = (Set)fieldVal;
				Iterator it = set.iterator();
				while(it.hasNext())
				{
					Object aVal = it.next();
					Element grandSubEle = this.addSubElement(subElement, aVal.getClass().getSimpleName(), prefix, null);
					this.createSubXml(grandSubEle, prefix, aVal);
				}
			}
			else if(fieldVal != null)
			{
				this.addSubElement(element, xmlFieldName, prefix, this.nullToStr(fieldVal));
			}
		}
	}
	
	/**
	 * Get QName by entity object
	 * @param obj entity object
	 * @return QName
	 */
	private QName getQName(Object obj) {
		QName qname = null;
		String namespace = null;
		String prefix = null;
		if (this.useXmlAnnotation) {
			XmlEntity xmlEntity = obj.getClass().getAnnotation(XmlEntity.class);
			if (xmlEntity != null) {
				String elementName = obj.getClass().getSimpleName();
				if (!"$Default$".equals(xmlEntity.name())) {
					elementName = xmlEntity.name();
				}
				if (!"$Default$".equals(xmlEntity.namespace())) {
					namespace = xmlEntity.namespace();
				}
				if (!"$Default$".equals(xmlEntity.xmlPrefix())) {
					prefix = xmlEntity.xmlPrefix();
				}
				qname = QName.get(elementName, prefix, namespace);
				return qname;
			}
		}
		QName.get(obj.getClass().getSimpleName());
		return qname;
	}
	
	/**
	 * Get xml data from an entity
	 * @param obj
	 * @param namespace
	 * @param prefix
	 * @return string data
	 */
	public String toXml(Object obj) throws Exception
	{
		if(obj != null)
		{
			QName qname = this.getQName(obj);
			Element root = DocumentHelper.createElement(qname);
			
			String prefix = qname.getNamespacePrefix();
			if ("".equals(prefix)) {
				prefix = null;
			}
			
			this.createSubXml(root, prefix, obj);
		
			Document document = DocumentHelper.createDocument(root);
			return document.asXML();
		}
		return null;
	}
	
	/**
	 * A sub work of parse sub xml via Recursion method
	 * @param obj
	 * @param element
	 */
	private void parseSubXml(Object obj, Element element)
	{
		/* The object and element must not be null */
		if(obj == null || element == null)
		{
			return;
		}
		
		/* Get the all declared fields */
		Field[] fields = obj.getClass().getDeclaredFields();
		
		if(fields != null)
		{
			for(int i=0; i<fields.length; i++)
			{
				/* Get the field information */
				Field aField = fields[i];
				Class fieldClass = aField.getType();
				String fieldClassName = fieldClass.getSimpleName();
				String xmlFieldName = this.getXmlFieldName(aField);
				
				if(this.regClassMap == null)
				{
					continue;
				}
				
				/* Get class name from registed class map if the class is registered */
				String classFullName = (String) this.regClassMap.get(fieldClass.getSimpleName());
				Element subEle = element.element(xmlFieldName);
				
				// Make the field be accessible
				fields[i].setAccessible(true);
				
				Object value = null;
				
				if(classFullName != null && !"".equals(classFullName))
				{
					/* Create an object of this sub class if it's a class which is registered */
					try {
						value = fieldClass.newInstance();
					} catch (InstantiationException e) {
						e.printStackTrace();
						return;
					} catch (IllegalAccessException e) {
						e.printStackTrace();
						return;
					}
					
					this.parseSubXml(value, subEle);
					
				}
				else if(subEle != null && ("List".equals(fieldClassName) || "ArrayList".equals(fieldClassName)))
				{
					/* When sub class in a list object */
					List objList = new ArrayList();
					List<Element> eleList = subEle.elements();
					for(Element aEle : eleList)
					{
						if(aEle != null)
						{
							String fullPath = (String) this.regClassMap.get(aEle.getName());
							Object aVal = null;
							try {
								aVal = Class.forName(fullPath).newInstance();
							} catch (InstantiationException e) {
								e.printStackTrace();
								return;
							} catch (IllegalAccessException e) {
								e.printStackTrace();
								return;
							} catch (ClassNotFoundException e) {
								e.printStackTrace();
								return;
							}
							this.parseSubXml(aVal, aEle);
							objList.add(aVal);
						}
					}
					value = objList;
				}
				else if(subEle != null && ("Set".equals(fieldClassName) || "HashSet".equals(fieldClassName)))
				{
					/* When sub class in a set object */
					Set objSet = new HashSet();
					List<Element> eleList = subEle.elements();
					for(Element aEle : eleList)
					{
						if(aEle != null)
						{
							String fullPath = (String) this.regClassMap.get(aEle.getName());
							Object aVal = null;
							try {
								aVal = Class.forName(fullPath).newInstance();
							} catch (InstantiationException e) {
								e.printStackTrace();
								return;
							} catch (IllegalAccessException e) {
								e.printStackTrace();
								return;
							} catch (ClassNotFoundException e) {
								e.printStackTrace();
								return;
							}
							this.parseSubXml(aVal, aEle);
							objSet.add(aVal);
						}
					}
					value = objSet;
				}
				else if(subEle != null)
				{
					// Get the common value if it's not a class which is registered
					value = subEle.getText();
				}
				
				/*set the fields' value*/
				if(value != null && !"".equals(value))
				{
					try {
						fields[i].set(obj, value);
					} catch (IllegalArgumentException e) {
						e.printStackTrace();
						return;
					} catch (IllegalAccessException e) {
						e.printStackTrace();
						return;
					}
				}
			}
		}
	}
	
	/**
	 * Get a entity object from xml
	 * @param entityClass
	 * @param xml
	 * @return a entity object
	 * @throws DocumentException 
	 */
	public Object fromXml(Class entityClass, String xml) throws Exception
	{
		/* Create a new object of the entity */
		Object resObj = null;
		
		/* Get the root of the xml */
		Document document = null;
		Element root = null;
		document = DocumentHelper.parseText(xml);
		root = document.getRootElement();
		
		if(entityClass != null)
		{
			String xmlEntityName = this.getXmlEntityName(entityClass);
			if(!xmlEntityName.equals(root.getName()))
			{
				return null;
			}
			
			/* Parse the XML */
			resObj = entityClass.newInstance();
			this.parseSubXml(resObj, root);
		}

		return resObj;
	}
	
	/**
	 * May be,we need to converse null to blank String
	 * @param obj
	 * @return string
	 */
	private String nullToStr(Object obj)
	{
		if(obj == null)
		{
			return "";
		}
		return obj.toString();
	}
	
	public boolean isUseXmlAnnotation() {
		return useXmlAnnotation;
	}

	public void setUseXmlAnnotation(boolean useXmlAnnotation) {
		this.useXmlAnnotation = useXmlAnnotation;
	}
	
	public void showRegMap() {
		Set mSet = this.regClassMap.keySet();
		for (Object clazzName : mSet) {
			System.out.println(clazzName);
		}
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值