if (prefix != null
&& prefix.equals(BXML_PREFIX)) {
// The element represents a BXML operation
if (element == null) {
throw new SerializationException("Invalid root element.");
}
if (localName.equals(INCLUDE_TAG)) {
elementType = Element.Type.INCLUDE;
} else if (localName.equals(SCRIPT_TAG)) {
elementType = Element.Type.SCRIPT;
} else if (localName.equals(DEFINE_TAG)) {
elementType = Element.Type.DEFINE;
} else if (localName.equals(REFERENCE_TAG)) {
elementType = Element.Type.REFERENCE;
} else {
throw new SerializationException("Invalid element.");
}
name = "<" + prefix + ":" + localName + ">";
} else {
if (Character.isUpperCase(localName.charAt(0))) {
int i = localName.indexOf('.');
if (i != -1
&& Character.isLowerCase(localName.charAt(i + 1))) {
// The element represents an attached property
elementType = Element.Type.WRITABLE_PROPERTY;
name = localName.substring(i + 1);
String propertyClassName = namespaceURI + "." + localName.substring(0, i);
try {
propertyClass = Class.forName(propertyClassName);
} catch (ClassNotFoundException exception) {
throw new SerializationException(exception);
}
} else {
// The element represents a typed object
if (namespaceURI == null) {
throw new SerializationException("No XML namespace specified for "
+ localName + " tag.");
}
elementType = Element.Type.INSTANCE;
name = "<" + ((prefix == null) ? "" : prefix + ":") + localName + ">";
String className = namespaceURI + "." + localName.replace('.', '$');
try {
Class<?> type = Class.forName(className);
value = newTypedObject(type);
} catch (ClassNotFoundException exception) {
throw new SerializationException(exception);
} catch (InstantiationException exception) {
throw new SerializationException(exception);
} catch (IllegalAccessException exception) {
throw new SerializationException(exception);
}
}
} else {
// The element represents a property
if (prefix != null) {
throw new SerializationException("Property elements cannot have a namespace prefix.");
}
if (element.value instanceof Dictionary<?, ?>) {
elementType = Element.Type.WRITABLE_PROPERTY;
} else {
BeanAdapter beanAdapter = new BeanAdapter(element.value);
if (beanAdapter.isReadOnly(localName)) {
Class<?> propertyType = beanAdapter.getType(localName);
if (propertyType == null) {
throw new SerializationException("\"" + localName
+ "\" is not a valid property of element "
+ element.name + ".");
}
if (ListenerList.class.isAssignableFrom(propertyType)) {
elementType = Element.Type.LISTENER_LIST_PROPERTY;
} else {
elementType = Element.Type.READ_ONLY_PROPERTY;
value = beanAdapter.get(localName);
assert (value != null) : "Read-only properties cannot be null.";
}
} else {
elementType = Element.Type.WRITABLE_PROPERTY;
}
}
name = localName;
}
}
// Create the element and process the attributes
element = new Element(element, elementType, name, propertyClass, value);
processAttributes();
if (elementType == Element.Type.INCLUDE) {
// Load the include
if (!element.properties.containsKey(INCLUDE_SRC_ATTRIBUTE)) {
throw new SerializationException(INCLUDE_SRC_ATTRIBUTE
+ " attribute is required for " + BXML_PREFIX + ":" + INCLUDE_TAG
+ " tag.");
}
String src = element.properties.get(INCLUDE_SRC_ATTRIBUTE);
Resources resources = this.resources;
if (element.properties.containsKey(INCLUDE_RESOURCES_ATTRIBUTE)) {
resources = new Resources(resources,
element.properties.get(INCLUDE_RESOURCES_ATTRIBUTE));
}
String mimeType = null;
if (element.properties.containsKey(INCLUDE_MIME_TYPE_ATTRIBUTE)) {
mimeType = element.properties.get(INCLUDE_MIME_TYPE_ATTRIBUTE);
}
if (mimeType == null) {
// Get the file extension
int i = src.lastIndexOf(".");
if (i != -1) {
String extension = src.substring(i + 1);
mimeType = fileExtensions.get(extension);
}
}
if (mimeType == null) {
throw new SerializationException("Cannot determine MIME type of include \""
+ src + "\".");
}
boolean inline = false;
if (element.properties.containsKey(INCLUDE_INLINE_ATTRIBUTE)) {
inline = Boolean.parseBoolean(element.properties.get(INCLUDE_INLINE_ATTRIBUTE));
}
// Determine an appropriate serializer to use for the include
Class<? extends Serializer<?>> serializerClass = mimeTypes.get(mimeType);
if (serializerClass == null) {
throw new SerializationException("No serializer associated with MIME type "
+ mimeType + ".");
}
Serializer<?> serializer;
try {
serializer = newIncludeSerializer(serializerClass);
} catch (InstantiationException exception) {
throw new SerializationException(exception);
} catch (IllegalAccessException exception) {
throw new SerializationException(exception);
}
// Determine location from src attribute
URL location;
if (src.charAt(0) == '/') {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
location = classLoader.getResource(src.substring(1));
} else {
location = new URL(this.location, src);
}
// Set optional resolution properties
if (serializer instanceof Resolvable) {
Resolvable resolvable = (Resolvable)serializer;
if (inline) {
resolvable.setNamespace(namespace);
}
resolvable.setLocation(location);
resolvable.setResources(resources);
}
// Read the object
InputStream inputStream = new BufferedInputStream(location.openStream());
try {
element.value = serializer.readObject(inputStream);
} finally {
inputStream.close();
}
} else if (element.type == Element.Type.REFERENCE) {
// Dereference the value
if (!element.properties.containsKey(REFERENCE_ID_ATTRIBUTE)) {
throw new SerializationException(REFERENCE_ID_ATTRIBUTE
+ " attribute is required for " + BXML_PREFIX + ":" + REFERENCE_TAG
+ " tag.");
}
String id = element.properties.get(REFERENCE_ID_ATTRIBUTE);
if (!namespace.containsKey(id)) {
throw new SerializationException("A value with ID \"" + id + "\" does not exist.");
}
element.value = namespace.get(id);
}