/*
* @(#)DefaultDOMFactory.java
*
* Copyright (c) 1996-2010 The authors and contributors of JHotDraw.
* You may not use, copy or modify this file, except in compliance with the
* accompanying license terms.
*/
package org.jhotdraw.xml;
import java.util.*;
/**
* {@code DefaultDOMFactory} can be used to serialize DOMStorable objects in a
* DOM with the use of a mapping between Java class names and DOM element names.
*
* @author Werner Randelshofer.
* @version $Id$
*/
public class DefaultDOMFactory extends JavaPrimitivesDOMFactory {
private static final HashMap<Class<?>, String> classToNameMap = new HashMap<Class<?>, String>();
private static final HashMap<String, Object> nameToPrototypeMap = new HashMap<String, Object>();
private static final HashMap<Class<?>, String> enumClassToNameMap = new HashMap<Class<?>, String>();
private static final HashMap<String, Class<?>> nameToEnumClassMap = new HashMap<String, Class<?>>();
@SuppressWarnings("rawtypes")
private static final HashMap<Enum, String> enumToValueMap = new HashMap<Enum, String>();
@SuppressWarnings("rawtypes")
private static final HashMap<String, Set<Enum>> valueToEnumMap = new HashMap<String, Set<Enum>>();
/**
* Creates a new instance.
*/
public DefaultDOMFactory() {
}
/**
* Adds a DOMStorable class to the DOMFactory.
*/
public void addStorableClass(String name, Class<?> c) {
nameToPrototypeMap.put(name, c);
classToNameMap.put(c, name);
}
/**
* Adds a DOMStorable prototype to the DOMFactory.
*/
public void addStorable(String name, DOMStorable prototype) {
nameToPrototypeMap.put(name, prototype);
classToNameMap.put(prototype.getClass(), name);
}
/**
* Adds an Enum class to the DOMFactory.
*/
public void addEnumClass(String name, Class<?> c) {
enumClassToNameMap.put(c, name);
nameToEnumClassMap.put(name, c);
}
/**
* Adds an Enum value to the DOMFactory.
*/
@SuppressWarnings("rawtypes")
public <T extends Enum<T>> void addEnum(String value, Enum<T> e) {
enumToValueMap.put(e, value);
Set<Enum> enums;
if (valueToEnumMap.containsKey(value)) {
enums = valueToEnumMap.get(value);
} else {
enums = new HashSet<Enum>();
valueToEnumMap.put(value, enums);
}
enums.add(e);
}
/**
* Creates a DOMStorable object.
*/
@Override
public Object create(String name) {
Object o = nameToPrototypeMap.get(name);
if (o == null) {
throw new IllegalArgumentException("Storable name not known to factory: " + name);
}
if (o instanceof Class<?>) {
try {
return ((Class<?>) o).newInstance();
} catch (Exception e) {
IllegalArgumentException error = new IllegalArgumentException("Storable class not instantiable by factory: " + name);
error.initCause(e);
throw error;
}
} else {
try {
return o.getClass().getMethod("clone", (Class<?>[]) null).
invoke(o, (Object[]) null);
} catch (Exception e) {
IllegalArgumentException error = new IllegalArgumentException("Storable prototype not cloneable by factory. Name: " + name);
error.initCause(e);
throw error;
}
}
}
@Override
public String getName(Object o) {
String name = (o == null) ? null : classToNameMap.get(o.getClass());
if (name == null) {
name = super.getName(o);
}
if (name == null) {
throw new IllegalArgumentException("Storable class not known to factory. Storable class:" + o.getClass() + " Factory:" + this.getClass());
}
return name;
}
@SuppressWarnings("rawtypes")
@Override
protected String getEnumName(Enum e) {
String name = enumClassToNameMap.get(e.getClass());
if (name == null) {
throw new IllegalArgumentException("Enum class not known to factory:" + e.getClass());
}
return name;
}
@SuppressWarnings("rawtypes")
@Override
protected String getEnumValue(Enum e) {
return (enumToValueMap.containsKey(e)) ? enumToValueMap.get(e) : e.toString();
}
@SuppressWarnings({"unchecked","rawtypes"})
@Override
protected <T extends Enum<T>> Enum<T> createEnum(String name, String value) {
Class<T> enumClass = (Class<T>) nameToEnumClassMap.get(name);
if (enumClass == null) {
throw new IllegalArgumentException("Enum name not known to factory:" + name);
}
Set<Enum> enums = valueToEnumMap.get(value);
if (enums == null) {
return Enum.valueOf(enumClass, value);
}
for (Enum e : enums) {
if (e.getClass() == enumClass) {
return e;
}
}
throw new IllegalArgumentException("Enum value not known to factory:" + value);
}
}