com.att.rosetta.JaxInfo Maven / Gradle / Ivy
The newest version!
/*******************************************************************************
* Copyright (c) 2016 AT&T Intellectual Property. All rights reserved.
*******************************************************************************/
package com.att.rosetta;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSchema;
import javax.xml.bind.annotation.XmlType;
import javax.xml.datatype.XMLGregorianCalendar;
public class JaxInfo {
private static final String DEFAULT = "##default";
public static final int DATA = 0;
public static final int ARRAY = 1;
public static final int OBJECT = 2;
public final String name;
public final Class> clss;
public Map extensions; // Classes, which might be found at runtime, that extend this class. Lazy Instantiation
public final JaxInfo[] members;
public final boolean isArray;
public final boolean isString;
public final boolean required;
public final boolean nillable;
public String ns;
public boolean isObject() {return members!=null;}
private JaxInfo(String n, String ns, Class> c, JaxInfo[] members, boolean string, boolean array, boolean required, boolean nillable) {
name = n;
this.ns = ns;
clss = c;
this.members = members;
this.isString = string;
isArray = array;
this.required = required;
this.nillable = nillable;
extensions = null;
}
public int getType() {
if(isArray)return ARRAY;
else if(members!=null)return OBJECT;
return DATA;
}
public JaxInfo getDerived(String derivedName) {
JaxInfo derived;
// Lazy Instantiation
if(extensions == null) {
extensions = new HashMap();
derived = null;
} else {
derived = extensions.get(derivedName);
}
if(derived == null) {
//TODO for the moment, Classes are in same package
Package pkg = clss.getPackage();
try {
Class> dc = getClass().getClassLoader().loadClass(pkg.getName()+'.'+Character.toUpperCase(derivedName.charAt(0))+derivedName.substring(1));
derived = JaxInfo.build(dc, this); // Use this JAXInfo's name so the tags are correct
extensions.put(derivedName, derived);
} catch (Exception e) {
e.printStackTrace();
}
}
return derived;
}
public static JaxInfo get(JaxInfo[] fields, String name) {
for(JaxInfo f : fields) {
if(name.equals(f.name)) return f;
}
return null;
}
/**
* Build up JAXB Information (recursively)
*
* @param cls
* @param rootNns
* @return
* @throws SecurityException
* @throws NoSuchFieldException
* @throws ClassNotFoundException
* @throws ParseException
*/
public static JaxInfo build(Class> cls, JaxInfo parent) throws NoSuchFieldException, ClassNotFoundException, ParseException {
return new JaxInfo(parent.name,parent.ns, cls,buildFields(cls,parent.ns),parent.isString, parent.isArray,parent.required,parent.nillable);
}
/**
* Build up JAXB Information (recursively)
*
* @param cls
* @param rootNns
* @return
* @throws SecurityException
* @throws NoSuchFieldException
* @throws ClassNotFoundException
* @throws ParseException
*/
public static JaxInfo build(Class> cls, String ... rootNns) throws SecurityException, NoSuchFieldException, ClassNotFoundException, ParseException {
String defaultNS;
if(rootNns.length>0 && rootNns[0]!=null) {
defaultNS = rootNns[0];
} else {
Package pkg = cls.getPackage();
XmlSchema xs = pkg.getAnnotation(XmlSchema.class);
defaultNS = xs==null?"":xs.namespace();
}
String name;
if(rootNns.length>1) {
name = rootNns[1];
} else {
XmlRootElement xre = cls.getAnnotation(XmlRootElement.class);
if(xre!=null) {
name = xre.name();
} else {
XmlType xt = cls.getAnnotation(XmlType.class);
if(xt!=null) {
name=xt.name();
} else {
throw new ParseException("Need a JAXB Object with XmlRootElement, or stipulate in parms");
}
}
}
return new JaxInfo(name,defaultNS, cls,buildFields(cls,defaultNS),false,false,false,false);
}
// Build up the name and members of this particular class
// This is recursive, if a member is a JAXB Object as well.
private static JaxInfo[] buildFields(Class> clazz, String defaultNS) throws SecurityException, NoSuchFieldException, ClassNotFoundException {
ArrayList fields = null; // allow for lazy instantiation, because many structures won't have XmlType
Class> cls = clazz;
// Build up Method names from JAXB Annotations
XmlType xt;
while((xt = cls.getAnnotation(XmlType.class))!=null) {
if(fields==null)fields = new ArrayList();
for(String field : xt.propOrder()) {
if("".equals(field)) break; // odd bug. "" returned when no fields exist, rather than empty array
Field rf = cls.getDeclaredField(field);
Class> ft = rf.getType();
boolean required = false;
boolean nillable = false;
String xmlName = field;
String namespace = defaultNS;
XmlElement xe = rf.getAnnotation(XmlElement.class);
if(xe!=null) {
xmlName=xe.name();
required = xe.required();
nillable = false;
if(DEFAULT.equals(xmlName)) {
xmlName = field;
}
namespace = xe.namespace();
if(DEFAULT.equals(namespace)) {
namespace = defaultNS;
}
}
// If object is a List, then it is possible multiple, per XML/JAXB evaluation
if(ft.isAssignableFrom(List.class)) {
Type t = rf.getGenericType();
String classname = t.toString();
int start = classname.indexOf('<');
int end = classname.indexOf('>');
Class> genClass = Class.forName(classname.substring(start+1, end));
xe = genClass.getAnnotation(XmlElement.class);
if(xe!=null && !DEFAULT.equals(xe.namespace())) {
namespace = xe.namespace();
}
// add recursed recursed member, marked as array
fields.add(new JaxInfo(xmlName,namespace,genClass,buildFields(genClass,namespace), genClass.equals(String.class),true,required,nillable));
} else {
boolean isString = ft.equals(String.class) || ft.equals(XMLGregorianCalendar.class);
// add recursed member
fields.add(new JaxInfo(xmlName,namespace,ft,buildFields(ft,namespace),isString,false,required,nillable));
}
}
cls = cls.getSuperclass();
};
if(fields!=null) {
JaxInfo[] rv = new JaxInfo[fields.size()];
fields.toArray(rv);
return rv;
} else {
return null;
}
}
public StringBuilder dump(StringBuilder sb, int idx) {
for(int i=0;i