001: package org.geotools.xml;
002:
003: import java.lang.reflect.Method;
004: import java.util.Iterator;
005:
006: import javax.xml.namespace.QName;
007:
008: import org.eclipse.emf.ecore.EFactory;
009: import org.eclipse.emf.ecore.EObject;
010:
011: /**
012: * Base class for complex bindings which map to an EMF model class.
013: * <p>
014: * Provides implementations for:
015: * <ul>
016: * <li>{@link ComplexBinding#getProperty(Object, QName)}.
017: * </ul>
018: * </p>
019: * @author Justin Deoliveira, The Open Planning Project, jdeolive@openplans.org
020: *
021: */
022: public abstract class AbstractComplexEMFBinding extends
023: AbstractComplexBinding {
024:
025: /**
026: * Factory used to create model objects
027: */
028: EFactory factory;
029:
030: /**
031: * Default constructor.
032: * <p>
033: * Creatign the binding with this constructor will force it to perform a
034: * noop in the {@link #parse(ElementInstance, Node, Object)} method.
035: * </p>
036: */
037: public AbstractComplexEMFBinding() {
038: }
039:
040: /**
041: * Constructs the binding with an efactory.
042: *
043: * @param factory Factory used to create model objects.
044: */
045: public AbstractComplexEMFBinding(EFactory factory) {
046: this .factory = factory;
047: }
048:
049: /**
050: * Dynamically tries to determine the type of the object using emf naming
051: * conventions and the name returned by {@link Binding#getTarget()}.
052: * <p>
053: * This implementation is a heuristic and is not guarenteed to work. Subclasses
054: * may override to provide the type explicity.
055: * </p>
056: */
057: public Class getType() {
058: //try to build up a class name
059: String pkg = factory.getClass().getPackage().getName();
060: if (pkg.endsWith(".impl")) {
061: pkg = pkg.substring(0, pkg.length() - 5);
062: }
063:
064: String className = getTarget().getLocalPart();
065: try {
066: return Class.forName(pkg + "." + className);
067: } catch (ClassNotFoundException e) {
068:
069: //do an underscore check
070: if (className.startsWith("_")) {
071: className = className.substring(1) + "Type";
072: }
073:
074: try {
075: return Class.forName(pkg + "." + className);
076: } catch (ClassNotFoundException e1) {
077: //try appending a Type
078: }
079: }
080:
081: return null;
082: }
083:
084: /**
085: * Uses EMF reflection to create an instance of the EMF model object this
086: * binding maps to. The properties of the resulting object are set using
087: * the the contents of <param>node</param>
088: */
089: public Object parse(ElementInstance instance, Node node,
090: Object value) throws Exception {
091: //does this binding actually map to an eObject?
092: if (EObject.class.isAssignableFrom(getType())
093: && factory != null) {
094: //yes, try and use the factory to dynamically create a new instance
095:
096: //get the classname
097: String className = getType().getName();
098: int index = className.lastIndexOf('.');
099: if (index != -1) {
100: className = className.substring(index + 1);
101: }
102:
103: //find the proper create method
104: Method create = factory.getClass().getMethod(
105: "create" + className, null);
106: if (create == null) {
107: //no dice
108: return value;
109: }
110:
111: //create the instance
112: EObject eObject = (EObject) create.invoke(factory, null);
113:
114: //reflectivley set the properties of it
115: for (Iterator c = node.getChildren().iterator(); c
116: .hasNext();) {
117: Node child = (Node) c.next();
118: String property = child.getComponent().getName();
119:
120: if (EMFUtils.has(eObject, property)) {
121: if (EMFUtils.isCollection(eObject, property)) {
122: EMFUtils.add(eObject, property, child
123: .getValue());
124: } else {
125: EMFUtils.set(eObject, property, child
126: .getValue());
127: }
128: }
129: }
130:
131: return eObject;
132: }
133:
134: //could not do it, just return whatever was passed in
135: return value;
136: }
137:
138: /**
139: * Uses EMF reflection dynamically return the property with the specified
140: * name.
141: */
142: public Object getProperty(Object object, QName name)
143: throws Exception {
144:
145: if (object instanceof EObject) {
146: EObject eObject = (EObject) object;
147: if (EMFUtils.has(eObject, name.getLocalPart())) {
148: return EMFUtils.get(eObject, name.getLocalPart());
149: }
150: }
151:
152: return null;
153: }
154:
155: }
|