package org.jcommons.file.xml;
import java.io.File;
import java.io.FileOutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Set;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.jcommons.common.ClassUtils;
import org.jcommons.common.ReflectUtils;
@SuppressWarnings("all")
public class BeanXMLWriter implements XMLWriter {
private boolean isCheckStatck = false;
private boolean isSubNameAuto = false;
private String rootElementName = BeanXMLConstant.ROOT_ELEMENT;
private String beanName = BeanXMLConstant.SUBROOT_ELEMENT;
private File file;
private Collection<?> list;
private Set<String> pool = new HashSet<String>();
private Hashtable<String, Class<?>> classes = new Hashtable<String, Class<?>>();
public void setClass(Class<?> clazz) {
this.setClass(this.beanName, clazz);
}
public void setClass(String key, final Class<?> clazz) {
if (key == null || clazz == null)
return;
if (ClassUtils.isPojo(clazz)) {
Field[] fields = clazz.getDeclaredFields();
for (Field f : fields) {
if (Collection.class.isAssignableFrom(f.getType())) {
ParameterizedType pt = (ParameterizedType) f
.getGenericType();
Type type = pt.getActualTypeArguments()[0];
Class<?> cls = ClassUtils.getPojoClass(type.toString()
.replace("class ", ""));
if (cls == null)
continue;
if (this.isCheckStatck) {
if (pool.contains(cls.getName()))
continue;
pool.add(cls.getName());
}
setClass(f.getName(), cls);
} else {
if (this.isCheckStatck) {
if (pool.contains(f.getType().getName()))
continue;
pool.add(f.getType().getName());
}
setClass(f.getName(), f.getType());
}
}
this.classes.put(key, clazz);
}
}
public void setBeanName(String beanName) {
this.beanName = beanName;
}
public void setRootElementName(String rootElementName) {
this.rootElementName = rootElementName;
}
public void setFile(File file) {
this.file = file;
}
public File getFile() {
return this.file;
}
public void setList(Collection<?> list) {
this.list = list;
}
public Collection<?> getList() {
return this.list;
}
public BeanXMLWriter() {
}
public BeanXMLWriter(File file) {
this.setFile(file);
}
public BeanXMLWriter(File file, Collection<?> list) {
this.setFile(file);
this.setList(list);
}
public BeanXMLWriter(File file, Class<?>... clazzs) {
this.setFile(file);
Collection<Class<?>> list = new ArrayList<Class<?>>();
for (Class<?> c : clazzs) {
list.add(c);
}
this.setList(list);
}
public <T> BeanXMLWriter(File file, T... ts) {
this.setFile(file);
Collection<T> list = new ArrayList<T>();
for (T t : ts) {
if (Collection.class.isAssignableFrom(t.getClass()))
list.addAll((Collection<? extends T>) t);
else
list.add(t);
}
this.setList(list);
}
public <T> BeanXMLWriter(File file, Class<T> clazz) {
this.setFile(file);
Collection<T> list = new ArrayList<T>();
try {
list.add(clazz.newInstance());
this.setList(list);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
public <T> BeanXMLWriter(File file, T t) {
this.setFile(file);
Collection<T> list = new ArrayList<T>();
if (Collection.class.isAssignableFrom(t.getClass()))
list.addAll((Collection<? extends T>) t);
else
list.add(t);
this.setList(list);
}
public String toXml() throws Exception {
return createDoc().asXML();
}
public File write() throws Exception {
Document doc = createDoc();
// 读取文件
FileOutputStream fos = new FileOutputStream(this.file);
// 设置文件编码
OutputFormat format = OutputFormat.createPrettyPrint();
// 创建写文件方法
org.dom4j.io.XMLWriter xmlWriter = new org.dom4j.io.XMLWriter(fos,
format);
// 写入文件
xmlWriter.write(doc);
// 关闭
fos.close();
xmlWriter.close();
return this.file;
}
private Document createDoc() throws Exception {
Document doc = DocumentHelper.createDocument();
if ((this.rootElementName == null || this.rootElementName.trim()
.length() == 0) && this.list.size() == 1) {
String name;
if (this.beanName == null || this.beanName.trim().length() == 0)
name = BeanXMLConstant.SUBROOT_ELEMENT;
else
name = this.beanName;
Element bean = doc.addElement(name);
for (Object t : this.list) {
// 递归
writeRecursion(bean, t);
}
} else {
if (this.rootElementName == null
|| this.rootElementName.trim().length() == 0)
this.rootElementName = BeanXMLConstant.ROOT_ELEMENT;
Element beans = doc.addElement(this.rootElementName);
Element bean;
String sub;
if (this.beanName == null || this.beanName.trim().length() == 0)
sub = BeanXMLConstant.SUBROOT_ELEMENT;
else
sub = this.beanName;
for (Object t : this.list) {
if (this.isSubNameAuto)
bean = beans.addElement(t.getClass().getSimpleName()
.toLowerCase());
else
bean = beans.addElement(sub);
// 递归
writeRecursion(bean, t);
}
}
return doc;
}
private <T> void writeRecursion(final Element bean, T t) throws Exception {
ReflectUtils ru = new ReflectUtils(t);
Field[] fields = ru.getFields();
for (Field f : fields) {
String n = f.getName();
Method m = ru.getGetter(n);
if (m == null)
continue;
if ("clazz".equals(n))
n = "class";
Object obj = m.invoke(t);
Skip skip = f.getAnnotation(Skip.class);
if (skip != null)
continue;
AttrTag attrTag = f.getAnnotation(AttrTag.class);
Readonly readonly = f.getAnnotation(Readonly.class);
if (readonly != null)
continue;
if (ClassUtils.isPojo(f.getType())) {
// 属性为class,进入递归
Class<?> cls = this.classes.get(n);
if (cls == null)
continue;
if (obj == null)
obj = cls.newInstance();
writeRecursion(bean.addElement(n), cls.cast(obj));
} else if (attrTag != null) {
if (obj == null)
obj = "";
bean.addAttribute(n, String.valueOf(obj));
} else if (ClassUtils.isListClass(f)) {
Collection<?> list = (Collection<?>) obj;
Class<?> cls = this.classes.get(n);
if (list.size() == 0 && cls != null)
writeRecursion(bean.addElement(n), cls.newInstance());
else
for (Iterator<?> it = list.iterator(); it.hasNext();)
writeRecursion(bean.addElement(n), it.next());
} else if (ClassUtils.isListString(f)) {
Collection<?> list = (Collection<?>) obj;
for (Iterator<?> it = list.iterator(); it.hasNext();) {
Object v2 = it.next();
if (v2 == null)
v2 = "";
bean.addElement(n).addText(String.valueOf(v2));
}
} else {
if (obj == null)
obj = "";
bean.addElement(n).addText(String.valueOf(obj));
}
}
}
public boolean isSubNameAuto() {
return isSubNameAuto;
}
public void setSubNameAuto(boolean isSubNameAuto) {
this.isSubNameAuto = isSubNameAuto;
}
public void setCheckStatck(boolean isCheckStatck) {
this.isCheckStatck = isCheckStatck;
}
}