de.tsl2.nano.bean.def.Extension Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of tsl2.nano.descriptor Show documentation
Show all versions of tsl2.nano.descriptor Show documentation
TSL2 Framework Descriptor (currency-handling, generic formatter, descriptors for beans, collections, actions and values)
/*
* File: $HeadURL$
* Id : $Id$
*
* created by: Tom
* created on: 01.03.2014
*
* Copyright: (c) Thomas Schneider 2014, all rights reserved
*/
package de.tsl2.nano.bean.def;
import java.io.Serializable;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Set;
import org.simpleframework.xml.Attribute;
import org.simpleframework.xml.ElementMap;
import org.simpleframework.xml.Transient;
import org.simpleframework.xml.core.Commit;
import de.tsl2.nano.bean.BeanUtil;
import de.tsl2.nano.core.cls.BeanClass;
import de.tsl2.nano.core.cls.PrivateAccessor;
import de.tsl2.nano.util.operation.IConverter;
/**
* Workaround for de-/serializings through simple-xml. while you must know the type of your deserializing root element,
* it is not possible, to load any class-extensions.
*
* This class can be used as member of your base-class. after deserializing you can create the desired extension
* instance through informations of this extension-instance.
*
* USE:
*
*
* - mark all extending members with annotation {@link Transient} (not with javas keyword 'transient')
* - on serialization of your extension class, call {@link #Extension(Object)} in your method annotated with {@link Commit}.
* {AT}Persist
* protected void initSerialization() {
* extension = new Extension(this);
* if (extension.isEmpty())
* extension = null;
* }
* - on de-serialization, call {@link #to(Object)} getting the desired instance.
*
*
* @author Tom
* @version $Revision$
*/
public class Extension implements Serializable, IConverter {
/** serialVersionUID */
private static final long serialVersionUID = -3429339914632368033L;
/**
* while there are problems on simple-xml serializing an own extension of hashmap, we use it only as member-variable
*/
@ElementMap(entry = "member", attribute = true, inline = true, required = false, empty = true, keyType = String.class, key = "name")
private LinkedHashMap members;
/** only used to check type by generics */
protected transient Class baseClass;
/** extension class - has to have a default constructor */
@Attribute
protected Class declaringClass;
/**
* constructor
*/
protected Extension() {
super();
}
/**
* constructor
*
* @param baseClass
* @param declaringClass
*/
protected Extension(Class baseClass, Class declaringClass) {
super();
this.baseClass = baseClass;
this.declaringClass = declaringClass;
}
/**
* evaluates the given instance and stores all found members, having the Annotation {@link Transient} but is
* implementing {@link Serializable}.
*
* @param extInstance instance to prepare for serialization
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public Extension(EXT extInstance) {
declaringClass = (Class) extInstance.getClass();
PrivateAccessor extAcc = new PrivateAccessor(extInstance);
List members = extAcc.memberNames(Transient.class);
Object value;
for (String m : members) {
value = extAcc.member(m);
if (value != null && Serializable.class.isAssignableFrom(value.getClass())) {
members().put(m, value);
}
}
}
private final LinkedHashMap members() {
if (members == null) {
members = new LinkedHashMap();
}
return members;
}
/**
* @return Returns the declaringClass.
*/
protected Class getDeclaringClass() {
return declaringClass;
}
@Override
public BASE from(EXT toValue) {
throw new UnsupportedOperationException();
}
@Override
public EXT to(BASE fromValue) {
EXT ext = BeanClass.createInstance(declaringClass);
PrivateAccessor extAcc = new PrivateAccessor(ext);
BeanUtil.copy(fromValue, ext);
Set keys = members().keySet();
for (String member : keys) {
extAcc.set(member, members().get(member));
}
//TODO: eval the right method name having annotation 'Commit'.
extAcc.call("initDeserialization", Void.class);
return ext;
}
public boolean isEmpty() {
return members().isEmpty();
}
}