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

jadex.xml.bean.JavaWriter Maven / Gradle / Ivy

package jadex.xml.bean;


import java.io.OutputStream;
import java.math.BigInteger;
import java.net.InetAddress;
import java.net.URI;
import java.net.URL;
import java.security.cert.Certificate;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Currency;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.LogRecord;

import jadex.commons.Base64;
import jadex.commons.MethodInfo;
import jadex.commons.SReflect;
import jadex.commons.Tuple;
import jadex.commons.Tuple2;
import jadex.commons.Tuple3;
import jadex.commons.collection.LRU;
import jadex.commons.collection.MultiCollection;
import jadex.commons.transformation.IObjectStringConverter;
import jadex.commons.transformation.traverser.SStackTraceElementHelper;
import jadex.xml.AccessInfo;
import jadex.xml.AttributeConverter;
import jadex.xml.AttributeInfo;
import jadex.xml.IAttributeConverter;
import jadex.xml.MappingInfo;
import jadex.xml.ObjectInfo;
import jadex.xml.SubobjectInfo;
import jadex.xml.TypeInfo;
import jadex.xml.XMLInfo;
import jadex.xml.stax.QName;
import jadex.xml.writer.AWriter;
import jadex.xml.writer.IObjectWriterHandler;
import jadex.xml.writer.XMLWriterFactory;


/**
 * Java specific reader that supports collection classes and arrays.
 */
public class JavaWriter
{
	//-------- attributes --------
	
	/** The static writer instance. */
	protected static volatile AWriter writer;
	
	/** The object handler. */
	protected static volatile IObjectWriterHandler handler;
	
	
	//-------- constructors --------
	
	/**
	 *  Create a new reader.
	 */
	public JavaWriter()
	{
	}
	
	//-------- methods --------
	
	/**
	 *  Join sets of typeinfos.
	 *  @param typeinfos The user specific type infos. 
	 *  @return The joined type infos.
	 */
	public static Set joinTypeInfos(Set typeinfos)
	{
		Set ret = getTypeInfos();
		if(typeinfos!=null)
			ret.addAll(typeinfos);
		return ret;
	}
	
	/**
	 *  Get the java type infos.
	 *  
	 *  Supported types:
	 *  
	 *  - java.util.Map
	 *  - jadex.commons.collection.MultiCollection
	 *  - java.util.List
	 *  - java.util.Set
	 *  - Array
	 *  - java.util.Color
	 *  - java.util.Date
	 *  - java.util.Calendar
	 *  - java.util.Currency
	 *  - java.lang.Class
	 *  - java.net.URL
	 *  - java.logging.Level
	 *  - java.logging.LogRecord
	 *  - java.net.InetAddress
	 *  - java.awt.image.RenderedImage
	 *  - java.lang.String
	 *  - java.lang.Boolean
	 *	- java.lang.Integer
	 *	- java.lang.Double
	 *	- java.lang.Float
	 *	- java.lang.Long
	 *	- java.lang.Short
	 *	- java.lang.Byte
	 *	- java.lang.Character
	 *	- java.lang.enum
	 *	- boolean/Boolean Array
	 *	- int/Integer Array
	 *	- double/Double Array
	 *	- float/Float array
	 *	- long/Long array
	 *	- short/Short Array
	 *	- byte/Byte Array
	 *	- java.lang.Character
	 *	- jadex.commons.Tuple
	 *	- jadex.commons.Tuple2
	 *  - jadex.commons.Tuple3
	 *  - java.util.UUID
	 *  - java.lang.Throwable
	 */
	public static Set getTypeInfos()
	{
		Set typeinfos = new HashSet();
		
		try
		{
			// jadex.commons.collection.LRU
			TypeInfo ti_lru = new TypeInfo(null, new ObjectInfo(LRU.class),
				new MappingInfo(null,
				new AttributeInfo[]{
				new AttributeInfo(new AccessInfo("maxEntries", null))
				},
				new SubobjectInfo[]{
				new SubobjectInfo(new AccessInfo("cleaner")),
				new SubobjectInfo(new AccessInfo("entries", null, null, null,
				new BeanAccessInfo(null, Map.class.getMethod("entrySet", new Class[0]))), null, true)
			}));
			typeinfos.add(ti_lru);
			
			// java.util.Map
			TypeInfo ti_map = new TypeInfo(null, new ObjectInfo(Map.class),
				new MappingInfo(null, new SubobjectInfo[]{
				new SubobjectInfo(new AccessInfo("entries", null, null, null,
				new BeanAccessInfo(null, Map.class.getMethod("entrySet", new Class[0]))), null, true)
			}));
			typeinfos.add(ti_map);
			
			// Cannot let xmltag be null, because class name then contains $ which is not allowed in a tag
			// Note: XMLinfo is necessary because it cannot be written as 'Map$Entry'
			TypeInfo ti_mapentry = new TypeInfo(new XMLInfo("entry"),
				new ObjectInfo(Map.Entry.class), new MappingInfo(null, new SubobjectInfo[]{
				new SubobjectInfo(new AccessInfo("key", null, null, null,  
				new BeanAccessInfo(null, Map.Entry.class.getMethod("getKey", new Class[0])))),
				new SubobjectInfo(new AccessInfo("value", null, null, null, 
				new BeanAccessInfo(null, Map.Entry.class.getMethod("getValue", new Class[0]))))
			}));
			typeinfos.add(ti_mapentry);
			
			// jadex.commons.collection.MultiCollection
			TypeInfo ti_mc = new TypeInfo(null, new ObjectInfo(MultiCollection.class),
				new MappingInfo(null, new SubobjectInfo[]{
				new SubobjectInfo(new AccessInfo("entries", null, null, null,
				new BeanAccessInfo(null, Map.class.getMethod("entrySet", new Class[0]))), null, true)
			}));
			typeinfos.add(ti_mc);
			
			// java.util.List
			TypeInfo ti_list = new TypeInfo(null, new ObjectInfo(List.class), new MappingInfo(null,
				new SubobjectInfo[]{
				new SubobjectInfo(new AccessInfo("entries", AccessInfo.THIS), null, true)
			}));
			typeinfos.add(ti_list);
			
			// java.util.Set
			TypeInfo ti_set = new TypeInfo(null, new ObjectInfo(Set.class), new MappingInfo(null,
				new SubobjectInfo[]{
				new SubobjectInfo(new AccessInfo("entries", AccessInfo.THIS), null, true)
			}));
			typeinfos.add(ti_set);
			
			// jadex.commons.MethodInfo	// Hack!!! also use parameterTypes for backwards compatibility.
			TypeInfo ti_mi = new TypeInfo(null, new ObjectInfo(MethodInfo.class), 
			new MappingInfo(null, null, null, null, new SubobjectInfo[]{
				//new SubobjectInfo(new AccessInfo("parameterTypes", "parameterTypes"), null, false),
				new SubobjectInfo(new AccessInfo("parameterTypeInfos", "parameterTypeInfos"), null, false)
			}, true, null, null));
					
//					new AttributeInfo[]{
//					new AttributeInfo(new AccessInfo("parameterTypes", "parameterTypes")),
//					new AttributeInfo(new AccessInfo("parameterTypeInfos", "parameterTypeInfos"))},
//					null
//				));
			typeinfos.add(ti_mi);
			
			// Array
			TypeInfo ti_array = new TypeInfo(null, new ObjectInfo(Object[].class),
				new MappingInfo(null, new SubobjectInfo[]{
				new SubobjectInfo(new AccessInfo("entries", AccessInfo.THIS), null, true)
			}));
			typeinfos.add(ti_array);
			
			// java.util.UnmodifyableSet
			// java.util.UnmodifyableList
//			TypeInfo ti_unlist = new TypeInfo(null, new ObjectInfo(Collections.UnmodifiableList.class), new MappingInfo(null,
//				new SubobjectInfo[]{
//				new SubobjectInfo(new AccessInfo("entries", AccessInfo.THIS), null, true)
//			}));
//			typeinfos.add(ti_unlist);
			// java.util.UnmodifyableMap
			
		
			
			// java.util.Date
			// Ignores several redundant bean attributes for performance reasons.
			TypeInfo ti_date = new TypeInfo(null, new ObjectInfo(Date.class), 
				new MappingInfo(null, new AttributeInfo[]{
				new AttributeInfo(new AccessInfo("time", null)),
				new AttributeInfo(new AccessInfo("hours", null, AccessInfo.IGNORE_READWRITE)),
				new AttributeInfo(new AccessInfo("minutes", null, AccessInfo.IGNORE_READWRITE)),
				new AttributeInfo(new AccessInfo("seconds", null, AccessInfo.IGNORE_READWRITE)),
				new AttributeInfo(new AccessInfo("month", null, AccessInfo.IGNORE_READWRITE)),
				new AttributeInfo(new AccessInfo("year", null, AccessInfo.IGNORE_READWRITE)),
				new AttributeInfo(new AccessInfo("date", null, AccessInfo.IGNORE_READWRITE))},
				null
			));
			typeinfos.add(ti_date);
			
			// java.util.Calendar
			// Ignores several redundant bean attributes for performance reasons.
			IObjectStringConverter cconv = new IObjectStringConverter()
			{
				public String convertObject(Object val, Object context)
				{
					String	ret	= val.getClass().getName();
					return ret;
				}
			};
			IObjectStringConverter c2conv = new IObjectStringConverter()
			{
				public String convertObject(Object val, Object context)
				{
					String	ret	= ""+((Date)val).getTime();
					return ret;
				}
			};
			TypeInfo ti_calendar = new TypeInfo(new XMLInfo(new QName("typeinfo:java.util", "Calendar")), new ObjectInfo(Calendar.class), 
				new MappingInfo(null, new AttributeInfo[]{
				new AttributeInfo(new AccessInfo("time", null), new AttributeConverter(null, c2conv)),
				new AttributeInfo(new AccessInfo("classname", AccessInfo.THIS), new AttributeConverter(null, cconv))},
//				new AttributeInfo(new AccessInfo("hours", null, AccessInfo.IGNORE_READWRITE)),
//				new AttributeInfo(new AccessInfo("minutes", null, AccessInfo.IGNORE_READWRITE)),
//				new AttributeInfo(new AccessInfo("seconds", null, AccessInfo.IGNORE_READWRITE)),
//				new AttributeInfo(new AccessInfo("month", null, AccessInfo.IGNORE_READWRITE)),
//				new AttributeInfo(new AccessInfo("year", null, AccessInfo.IGNORE_READWRITE)),
//				new AttributeInfo(new AccessInfo("date", null, AccessInfo.IGNORE_READWRITE))},
				null
			));
			typeinfos.add(ti_calendar);

			// java.util.Currency
			// Ignores several redundant bean attributes for performance reasons.
			TypeInfo ti_currency = new TypeInfo(new XMLInfo(new QName("typeinfo:java.util", "Currency")), new ObjectInfo(Currency.class), 
				new MappingInfo(null, new AttributeInfo[]{
				new AttributeInfo(new AccessInfo("currencyCode", null))},
				null
			));
			typeinfos.add(ti_currency);

			// java.text.SimpleDateFormat
			// Pattern managed with applyPattern(String) and String toPattern() grrrr.
			TypeInfo ti_simpledateformat = new TypeInfo(new XMLInfo(new QName("typeinfo:java.text", "SimpleDateFormat")), new ObjectInfo(SimpleDateFormat.class), 
				new MappingInfo(null, null, null, new AttributeInfo[]{
				new AttributeInfo(new AccessInfo("pattern", null, null, null,
					new BeanAccessInfo(SimpleDateFormat.class.getMethod("applyPattern", String.class),
						SimpleDateFormat.class.getMethod("toPattern"))))},
				null, false, null, null
			));
			typeinfos.add(ti_simpledateformat);

			// java.sql.Timestamp
			// Ignores several redundant bean attributes for performance reasons.
			TypeInfo ti_timestamp = new TypeInfo(null, new ObjectInfo(Timestamp.class), 
				new MappingInfo(null, new AttributeInfo[]{
				new AttributeInfo(new AccessInfo("time", null)),
				new AttributeInfo(new AccessInfo("hours", null, AccessInfo.IGNORE_READWRITE)),
				new AttributeInfo(new AccessInfo("minutes", null, AccessInfo.IGNORE_READWRITE)),
				new AttributeInfo(new AccessInfo("seconds", null, AccessInfo.IGNORE_READWRITE)),
				new AttributeInfo(new AccessInfo("month", null, AccessInfo.IGNORE_READWRITE)),
				new AttributeInfo(new AccessInfo("year", null, AccessInfo.IGNORE_READWRITE)),
				new AttributeInfo(new AccessInfo("date", null, AccessInfo.IGNORE_READWRITE))},
				null
			));
			typeinfos.add(ti_timestamp);
			
			// java.lang.Class
			IObjectStringConverter clconv = new IObjectStringConverter()
			{
				public String convertObject(Object val, Object context)
				{
//					String	ret	= ""+((Class)val).getCanonicalName();
					// Todo: SReflect doesn not work for some case!? (Lars)
					String	ret	= SReflect.getClassName((Class)val);
					return ret;
				}
			};
			TypeInfo ti_class = new TypeInfo(null, new ObjectInfo(Class.class), new MappingInfo(null, new AttributeInfo[]{
				new AttributeInfo(new AccessInfo("classname", AccessInfo.THIS), new AttributeConverter(null, clconv))},
				null
			));
			typeinfos.add(ti_class);
			
			// java.net.URL
			TypeInfo ti_url = new TypeInfo(null, new ObjectInfo(URL.class), 
				new MappingInfo(null, new AttributeInfo[]{
				new AttributeInfo(new AccessInfo("protocol", null)),
				new AttributeInfo(new AccessInfo("host", null)),
				new AttributeInfo(new AccessInfo("port", null)),
				new AttributeInfo(new AccessInfo("file", null))},
				null
			));
			typeinfos.add(ti_url);
			
			// java.net.URL
			TypeInfo ti_uri = new TypeInfo(null, new ObjectInfo(URI.class), 
				new MappingInfo(null, new AttributeInfo[]{
				new AttributeInfo(new AccessInfo("uri", AccessInfo.THIS), new IAttributeConverter()
				{
					public String convertObject(Object val, Object context)
					{
						return val.toString();
					}
					
					public Object convertString(String val, Object context) throws Exception
					{
						return new URI(val);
					}
				})},
				null
			));
			typeinfos.add(ti_uri);
			
			// java.logging.Level
			TypeInfo ti_level = new TypeInfo(null, new ObjectInfo(Level.class), 
				new MappingInfo(null, new AttributeInfo[]{
				new AttributeInfo(new AccessInfo("name", null))},
//				new AttributeInfo(new AccessInfo("value", null, null, null, 
//					new BeanAccessInfo(null, Level.class.getMethod("intValue", new Class[0])))),
//				new AttributeInfo(new AccessInfo("resourceBundleName", null))},
				null
			));
			typeinfos.add(ti_level);
			
			// java.logging.LogRecord
			TypeInfo ti_record = new TypeInfo(null, new ObjectInfo(LogRecord.class), 
				new MappingInfo(null, new AttributeInfo[]{
				new AttributeInfo(new AccessInfo("level", null), new AttributeConverter(null, new IObjectStringConverter()
				{
					public String convertObject(Object val, Object context)
					{
						return ((Level)val).getName();
					}
				})),
				new AttributeInfo(new AccessInfo("level", null)),
				new AttributeInfo(new AccessInfo("message", null))},
				null
			));
			typeinfos.add(ti_record);
			
			// java.net.InetAddress
			// The following hack ensures that all subclasses of InetAdress will be stored using the same tag
			// todo: make this more easily possible
			TypeInfo ti_inetaddr = new TypeInfo(new XMLInfo(new QName("typeinfo:java.net", "InetAddress")), new ObjectInfo(InetAddress.class), 
				new MappingInfo(null, new AttributeInfo[]{
				new AttributeInfo(new AccessInfo("hostAddress", null))},
				null
			));
			typeinfos.add(ti_inetaddr);
			
			// byte/Byte Array
			IObjectStringConverter bytesconv = new IObjectStringConverter()
			{
				public String convertObject(Object val, Object context)
				{
					byte[] bytes = Base64.encode((byte[])val);
					return new String(bytes);
				}
			};
			
			// java.security.Certificate
			TypeInfo ti_cert = new TypeInfo(new XMLInfo(new QName("typeinfo:java.security.cert", "Certificate")), new ObjectInfo(Certificate.class), 
				new MappingInfo(null, new AttributeInfo[]{
				new AttributeInfo(new AccessInfo("data", "encoded"), new AttributeConverter(null, bytesconv)),
				new AttributeInfo(new AccessInfo("type", null))},
				null
			));
			typeinfos.add(ti_cert);
						
			// java.lang.String
//			TypeInfo ti_string = new TypeInfo(null, new ObjectInfo(String.class), new MappingInfo(null, new AttributeInfo[]{
//				new AttributeInfo(new AccessInfo("content", AccessInfo.THIS))}));
			TypeInfo ti_string = new TypeInfo(null, new ObjectInfo(String.class), new MappingInfo(null, null,
				new AttributeInfo(new AccessInfo((String)null, AccessInfo.THIS))));
			typeinfos.add(ti_string);
			
			// java.lang.Boolean
			TypeInfo ti_boolean = new TypeInfo(null, new ObjectInfo(Boolean.class), new MappingInfo(null, new AttributeInfo[]{
				new AttributeInfo(new AccessInfo("content", AccessInfo.THIS))}));
			typeinfos.add(ti_boolean);
			
			// java.lang.Integer
			TypeInfo ti_integer = new TypeInfo(null, new ObjectInfo(Integer.class), new MappingInfo(null, new AttributeInfo[]{
				new AttributeInfo(new AccessInfo("content", AccessInfo.THIS))}));
			typeinfos.add(ti_integer);
			
			// java.lang.Double
			TypeInfo ti_double = new TypeInfo(null, new ObjectInfo(Double.class), new MappingInfo(null, new AttributeInfo[]{
				new AttributeInfo(new AccessInfo("content", AccessInfo.THIS))}));
			typeinfos.add(ti_double);
			
			// java.lang.Float
			TypeInfo ti_float = new TypeInfo(null, new ObjectInfo(Float.class), new MappingInfo(null, new AttributeInfo[]{
				new AttributeInfo(new AccessInfo("content", AccessInfo.THIS))}));
			typeinfos.add(ti_float);
			
			// java.lang.Long
			TypeInfo ti_long = new TypeInfo(null, new ObjectInfo(Long.class), new MappingInfo(null, new AttributeInfo[]{
				new AttributeInfo(new AccessInfo("content", AccessInfo.THIS))}));
			typeinfos.add(ti_long);
			
			// java.lang.Short
			TypeInfo ti_short = new TypeInfo(null, new ObjectInfo(Short.class), new MappingInfo(null, new AttributeInfo[]{
				new AttributeInfo(new AccessInfo("content", AccessInfo.THIS))}));
			typeinfos.add(ti_short);
			
			// java.lang.Byte
			IObjectStringConverter byteconv = new IObjectStringConverter()
			{
				public String convertObject(Object val, Object context)
				{
					return new String(Base64.encode(new byte[]{((Byte)val).byteValue()}));
				}
			};
			TypeInfo ti_byte = new TypeInfo(null, new ObjectInfo(Byte.class), new MappingInfo(null, new AttributeInfo[]{
				new AttributeInfo(new AccessInfo("content", AccessInfo.THIS), new AttributeConverter(null, byteconv))}));
			typeinfos.add(ti_byte);
			
			// java.lang.Character
			TypeInfo ti_character = new TypeInfo(null, new ObjectInfo(Character.class), new MappingInfo(null, new AttributeInfo[]{
				new AttributeInfo(new AccessInfo("content", AccessInfo.THIS))}));
			typeinfos.add(ti_character);
			
			// java.lang.enum
			IObjectStringConverter enumconv = new IObjectStringConverter()
			{
				public String convertObject(Object val, Object context)
				{
					Enum en = (Enum)val;
					String clazz = SReflect.getClassName(val.getClass());
					String name = en.name();
					return clazz+"="+name;
				}
			};
			TypeInfo ti_enum = new TypeInfo(new XMLInfo(new QName("typeinfo:java.lang", "Enum")), new ObjectInfo(Enum.class), new MappingInfo(null, new AttributeInfo[]{
				new AttributeInfo(new AccessInfo("content", AccessInfo.THIS), new AttributeConverter(null, enumconv))}));
			typeinfos.add(ti_enum);
			
			// Shortcut notations for simple array types
			
			// boolean/Boolean Array
			IObjectStringConverter booleanconv = new IObjectStringConverter()
			{
				public String convertObject(Object val, Object context)
				{
					boolean[] data = (boolean[])val;
					StringBuilder bul = new StringBuilder();
					for(int i=0; i




© 2015 - 2025 Weber Informatics LLC | Privacy Policy