001: package org.geotools.xml.impl;
002:
003: import java.util.ArrayList;
004: import java.util.Collection;
005: import java.util.HashMap;
006: import java.util.Iterator;
007: import java.util.List;
008: import java.util.Map;
009:
010: import javax.xml.namespace.QName;
011:
012: import org.apache.commons.collections.MultiHashMap;
013: import org.apache.commons.collections.MultiMap;
014: import org.eclipse.xsd.XSDElementDeclaration;
015: import org.eclipse.xsd.XSDFactory;
016: import org.eclipse.xsd.XSDParticle;
017: import org.geotools.xml.Encoder;
018: import org.geotools.xml.PropertyExtractor;
019: import org.geotools.xml.Schemas;
020: import org.picocontainer.MutablePicoContainer;
021:
022: /**
023: * Uses {@link org.geotools.xml.ComplexBinding#getProperty(Object, QName)} to obtain
024: * properties from the objecet being encoded.
025: *
026: * @author Justin Deoliveira, The Open Planning Project
027: *
028: */
029: public class BindingPropertyExtractor implements PropertyExtractor {
030:
031: Encoder encoder;
032: MutablePicoContainer context;
033:
034: public BindingPropertyExtractor(Encoder encoder,
035: MutablePicoContainer context) {
036: this .encoder = encoder;
037: this .context = context;
038: }
039:
040: public boolean canHandle(Object object) {
041: return true;
042: }
043:
044: public void setContext(MutablePicoContainer context) {
045: this .context = context;
046: }
047:
048: public List properties(Object object, XSDElementDeclaration element) {
049:
050: List properties = new ArrayList();
051:
052: //first get all the properties that can be infered from teh schema
053: List children = encoder.getSchemaIndex()
054: .getChildElementParticles(element);
055:
056: O: for (Iterator itr = children.iterator(); itr.hasNext();) {
057: XSDParticle particle = (XSDParticle) itr.next();
058: XSDElementDeclaration child = (XSDElementDeclaration) particle
059: .getContent();
060: if (child.isElementDeclarationReference()) {
061: child = child.getResolvedElementDeclaration();
062: }
063:
064: //get the object(s) for this element
065: GetPropertyExecutor executor = new GetPropertyExecutor(
066: object, child);
067:
068: encoder.getBindingWalker().walk(element, executor, context);
069:
070: if (executor.getChildObject() != null) {
071: properties.add(new Object[] { particle,
072: executor.getChildObject() });
073: }
074: }
075:
076: //second, get the properties which cannot be infereed from the schema
077: GetPropertiesExecutor executor = new GetPropertiesExecutor(
078: object);
079: encoder.getBindingWalker().walk(element, executor, context);
080:
081: if (!executor.getProperties().isEmpty()) {
082: //group into a map of name, list
083: MultiHashMap map = new MultiHashMap();
084: for (Iterator p = executor.getProperties().iterator(); p
085: .hasNext();) {
086: Object[] property = (Object[]) p.next();
087: map.put(property[0], property[1]);
088: }
089:
090: //turn each map entry into a particle
091: HashMap particles = new HashMap();
092: for (Iterator e = map.entrySet().iterator(); e.hasNext();) {
093: Map.Entry entry = (Map.Entry) e.next();
094: QName name = (QName) entry.getKey();
095: Collection values = (Collection) entry.getValue();
096:
097: //find hte element
098: XSDElementDeclaration elementDecl = encoder
099: .getSchemaIndex().getElementDeclaration(name);
100: if (elementDecl == null) {
101: //TODO: resolving like this will return an element no
102: // matter what, modifying the underlying schema, this might
103: // be dangerous. What we shold do is force the schema to
104: // resolve all of it simports when the encoder starts
105: elementDecl = encoder.getSchema()
106: .resolveElementDeclaration(
107: name.getNamespaceURI(),
108: name.getLocalPart());
109: }
110:
111: //wrap it in a particle
112: XSDParticle particle = XSDFactory.eINSTANCE
113: .createXSDParticle();
114: particle.setContent(elementDecl);
115:
116: if (values.size() > 1) {
117: //make a multi property
118: particle.setMaxOccurs(-1);
119: } else {
120: //single property
121: particle.setMaxOccurs(1);
122: }
123:
124: particles.put(name, particle);
125: }
126:
127: //process the particles in order in which we got the properties
128: for (Iterator p = executor.getProperties().iterator(); p
129: .hasNext();) {
130: Object[] property = (Object[]) p.next();
131: QName name = (QName) property[0];
132:
133: XSDParticle particle = (XSDParticle) particles
134: .get(name);
135: if (particle == null) {
136: continue; //already processed, must be a multi property
137: }
138:
139: Collection values = (Collection) map.get(name);
140: if (values.size() > 1) {
141: //add as is, the encoder will unwrap
142: properties.add(new Object[] { particle, values });
143: } else {
144: //unwrap it
145: properties.add(new Object[] { particle,
146: values.iterator().next() });
147: }
148:
149: //done with this particle
150: particles.remove(name);
151: }
152:
153: }
154:
155: return properties;
156: }
157:
158: }
|