/* (c) 2014 Open Source Geospatial Foundation - all rights reserved * (c) 2001 - 2013 OpenPlans * This code is licensed under the GPL 2.0 license, available at the root * application directory. */ package org.geoserver.wfs.xml; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import javax.xml.namespace.QName; import net.opengis.wfs.PropertyType; import org.eclipse.xsd.XSDElementDeclaration; import org.eclipse.xsd.XSDFactory; import org.eclipse.xsd.XSDParticle; import org.eclipse.xsd.XSDTypeDefinition; import org.geotools.xml.PropertyExtractor; import org.geotools.xml.SchemaIndex; import org.geotools.xml.Schemas; import org.opengis.feature.type.Name; /** * Extracts properties from an instance of {@link PropertyType}. * <p> * In a sense this class retypes {@link PropertyType#getValue()} to a new xml * type so that the encoder can encode it properly. * </p> * @author Justin Deoliveira, The Open Planning Project, jdeolive@openplans.org * */ public class PropertyTypePropertyExtractor implements PropertyExtractor { /** * index for looking up xml types */ SchemaIndex index; public PropertyTypePropertyExtractor(SchemaIndex index) { this.index = index; } public boolean canHandle(Object object) { return object instanceof PropertyType; } public List properties(Object object, XSDElementDeclaration element) { PropertyType property = (PropertyType) object; List properties = new ArrayList(2); //the Name particle we can use as is properties.add(new Object[] { Schemas.getChildElementParticle(element.getType(), "Name", false), property.getName() }); //the Value particle we must retype //first guess its type QName newTypeName = guessValueType(property.getValue()); XSDTypeDefinition type = (newTypeName != null) ? index.getTypeDefinition(newTypeName) : null; if (type != null) { //create a new particle based on the new type XSDElementDeclaration value = XSDFactory.eINSTANCE.createXSDElementDeclaration(); value.setName("Value"); value.setTypeDefinition(type); XSDParticle particle = XSDFactory.eINSTANCE.createXSDParticle(); particle.setMinOccurs(1); particle.setMaxOccurs(1); particle.setContent(value); properties.add(new Object[] { particle, property.getValue() }); } else { //coudl not determine new type, just fall back to xs:anyType Object[] p = new Object[] { Schemas.getChildElementParticle(element.getType(), "Value", false), property.getValue() }; properties.add(p); } return properties; } private QName guessValueType(Object value) { Class clazz = value.getClass(); List profiles = Arrays.asList(new Object[] { new XSProfile(), new GML3Profile() }); for (Iterator it = profiles.iterator(); it.hasNext();) { TypeMappingProfile profile = (TypeMappingProfile) it.next(); Name name = profile.name(clazz); if (name != null) { return new QName(name.getNamespaceURI(), name.getLocalPart()); } } return null; } }