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

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




© 2015 - 2024 Weber Informatics LLC | Privacy Policy