// Apply instance attributes
Dictionary<String, Object> dictionary;
if (element.value instanceof Dictionary<?, ?>) {
dictionary = (Dictionary<String, Object>)element.value;
} else {
dictionary = new BeanAdapter(element.value);
}
for (Attribute attribute : instancePropertyAttributes) {
dictionary.put(attribute.localName, resolve(attribute.value));
}
// If the element's parent is a sequence or a listener list, add
// the element value to it
if (element.parent != null) {
if (element.parent.value instanceof Sequence<?>) {
Sequence<Object> sequence = (Sequence<Object>)element.parent.value;
sequence.add(element.value);
} else {
if (element.parent.value instanceof ListenerList<?>) {
ListenerList<Object> listenerList = (ListenerList<Object>)element.parent.value;
listenerList.add(element.value);
}
}
}
// Apply static attributes
if (element.value instanceof Dictionary<?, ?>) {
if (staticPropertyAttributes.getLength() > 0) {
throw new SerializationException("Static setters are only supported"
+ " for typed objects.");
}
} else {
for (Attribute attribute : staticPropertyAttributes) {
// Determine the type of the attribute
String propertyClassName = attribute.namespaceURI + "."
+ attribute.localName.substring(0, attribute.localName.lastIndexOf("."));
Class<?> propertyClass = null;
try {
propertyClass = Class.forName(propertyClassName);
} catch (ClassNotFoundException exception) {
throw new SerializationException(exception);
}
if (propertyClass.isInterface()) {
// The attribute represents an event listener
String listenerClassName = propertyClassName.substring(propertyClassName.lastIndexOf('.') + 1);
String getListenerListMethodName = "get" + Character.toUpperCase(listenerClassName.charAt(0))
+ listenerClassName.substring(1) + "s";
// Get the listener list
Method getListenerListMethod;
try {
Class<?> type = element.value.getClass();
getListenerListMethod = type.getMethod(getListenerListMethodName);
} catch (NoSuchMethodException exception) {
throw new SerializationException(exception);
}
Object listenerList;
try {
listenerList = getListenerListMethod.invoke(element.value);
} catch (InvocationTargetException exception) {
throw new SerializationException(exception);
} catch (IllegalAccessException exception) {
throw new SerializationException(exception);
}
// Create an invocation handler for this listener
ScriptEngine scriptEngine = scriptEngineManager.getEngineByName(language);
AttributeInvocationHandler handler =
new AttributeInvocationHandler(scriptEngine,
attribute.localName.substring(attribute.localName.lastIndexOf(".") + 1),
attribute.value);
Object listener = Proxy.newProxyInstance(ThreadUtilities.getClassLoader(),
new Class<?>[]{propertyClass}, handler);
// Add the listener
Class<?> listenerListClass = listenerList.getClass();
Method addMethod;
try {
addMethod = listenerListClass.getMethod("add", Object.class);
} catch (NoSuchMethodException exception) {
throw new RuntimeException(exception);
}
try {
addMethod.invoke(listenerList, listener);
} catch (IllegalAccessException exception) {
throw new SerializationException(exception);
} catch (InvocationTargetException exception) {
throw new SerializationException(exception);
}
} else {
// The attribute reprsents a static setter
Object value = resolve(attribute.value);
Class<?> objectType = element.value.getClass();
String propertyName = attribute.localName.substring(attribute.localName.lastIndexOf(".") + 1);
propertyName = Character.toUpperCase(propertyName.charAt(0)) +
propertyName.substring(1);
Method setterMethod = null;
if (value != null) {
setterMethod = getStaticSetterMethod(propertyClass, propertyName,
objectType, value.getClass());
}
if (setterMethod == null) {
Method getterMethod = getStaticGetterMethod(propertyClass, propertyName, objectType);
if (getterMethod != null) {
Class<?> propertyType = getterMethod.getReturnType();
setterMethod = getStaticSetterMethod(propertyClass, propertyName,
objectType, propertyType);
if (value instanceof String) {
value = BeanAdapter.coerce((String)value, propertyType);
}
}
}
if (setterMethod == null) {
throw new SerializationException(attribute.localName + " is not valid static property.");
}
// Invoke the setter
try {
setterMethod.invoke(null, element.value, value);
} catch (Exception exception) {
throw new SerializationException(exception);
}
}
}
}
// If the parent element is a writable property, set this as its
// value; it will be applied later in the parent's closing tag
if (element.parent != null
&& element.parent.type == Element.Type.WRITABLE_PROPERTY) {
element.parent.value = element.value;
}
break;
}
case READ_ONLY_PROPERTY: {
if (element.value instanceof Dictionary<?, ?>) {
// Process attributes looking for instance property setters
for (Attribute attribute : element.attributes) {
if (Character.isUpperCase(attribute.localName.charAt(0))) {
throw new SerializationException("Static setters are not supported"
+ " for read-only properties.");
}
Dictionary<String, Object> dictionary =
(Dictionary<String, Object>)element.value;
dictionary.put(attribute.localName, resolve(attribute.value));
}
}
break;
}
case WRITABLE_PROPERTY: {
BeanAdapter beanAdapter = new BeanAdapter(element.parent.value);
beanAdapter.put(localName, element.value);
break;
}
case SCRIPT: {
// Process attributes looking for src and language