/* (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.csw.response; import java.util.Collection; import java.util.List; import net.opengis.cat.csw20.RequestBaseType; import org.geoserver.csw.records.CSWRecordDescriptor; import org.geoserver.csw.records.GenericRecordBuilder; import org.geoserver.platform.ServiceException; import org.geotools.geometry.jts.ReferencedEnvelope; import org.geotools.referencing.CRS; import org.geotools.xml.transform.Translator; import org.opengis.feature.ComplexAttribute; import org.opengis.feature.Feature; import org.opengis.feature.Property; import org.opengis.feature.type.AttributeDescriptor; import org.opengis.feature.type.Name; import org.xml.sax.ContentHandler; import org.xml.sax.helpers.AttributesImpl; /** * Encodes a FeatureCollection containing {@link CSWRecordDescriptor#RECORD} features into the specified * XML according to the chosen profile, brief, summary or full * * * @author Andrea Aime - GeoSolutions */ public class CSWRecordTransformer extends AbstractRecordTransformer { static final String CSW_ROOT_LOCATION = "http://schemas.opengis.net/csw/2.0.2/"; private static final AttributeDescriptor DC_TITLE = CSWRecordDescriptor.getDescriptor("title"); public CSWRecordTransformer(RequestBaseType request, boolean canonicalSchemaLocation) { super(request, canonicalSchemaLocation, CSWRecordDescriptor.NAMESPACES); } @Override public Translator createTranslator(ContentHandler handler) { return new CSWRecordTranslator(handler); } @Override public boolean canHandleRespose(CSWRecordsResult response) { return true; } class CSWRecordTranslator extends AbstractRecordTranslator { public CSWRecordTranslator(ContentHandler handler) { super(handler); } public void encode(CSWRecordsResult response, Feature f) { String element = "csw:" + getRecordElement(response); start(element); List<Name> elements = getElements(response); // encode all elements besides bbox if(elements != null && ! element.isEmpty()) { // brief and summary have a specific order for (Name name : elements) { Collection<Property> properties = f.getProperties(name); if(properties != null && !properties.isEmpty()) { for (Property p : properties) { encodeProperty(f, p); } } else if(DC_TITLE.getName().equals(name)) { // dc:title is mandatory even if we don't have a value for it element("dc:title", null); } } } else { // csw:Record has freeform order for (Property p : f.getProperties()) { if (elements == null || elements.contains(p.getName())) { encodeProperty(f, p); } } } // encode the bbox if present if(elements == null || elements.contains(CSWRecordDescriptor.RECORD_BBOX_NAME)) { Property bboxes = f.getProperty(CSWRecordDescriptor.RECORD_BBOX_NAME); if(bboxes != null) { // grab the original bounding boxes from the user data (the geometry is an aggregate) List<ReferencedEnvelope> originalBoxes = (List<ReferencedEnvelope>) bboxes .getUserData().get(GenericRecordBuilder.ORIGINAL_BBOXES); for (ReferencedEnvelope re : originalBoxes) { try { ReferencedEnvelope wgs84re = re.transform( CRS.decode(CSWRecordDescriptor.DEFAULT_CRS_NAME), true); String minx = String.valueOf(wgs84re.getMinX()); String miny = String.valueOf(wgs84re.getMinY()); String maxx = String.valueOf(wgs84re.getMaxX()); String maxy = String.valueOf(wgs84re.getMaxY()); AttributesImpl attributes = new AttributesImpl(); addAttribute(attributes, "crs", CSWRecordDescriptor.DEFAULT_CRS_NAME); start("ows:BoundingBox", attributes); element("ows:LowerCorner", minx + " " + miny); element("ows:UpperCorner", maxx + " " + maxy); end("ows:BoundingBox"); } catch (Exception e) { throw new ServiceException("Failed to encode the current record: " + f, e); } } } } end(element); } private void encodeProperty(Feature f, Property p) { if (p.getType() == CSWRecordDescriptor.SIMPLE_LITERAL) { encodeSimpleLiteral(p); } else if (CSWRecordDescriptor.RECORD_BBOX_NAME.equals(p.getName())) { // skip it for the moment, it is constrained to be last } else { throw new IllegalArgumentException("Don't know how to encode property " + p + " in record " + f); } } private void encodeSimpleLiteral(Property p) { ComplexAttribute sl = (ComplexAttribute) p; String scheme = sl.getProperty("scheme") == null ? null : (String) sl.getProperty("scheme").getValue(); String value = sl.getProperty("value") == null? "" : (String) sl.getProperty("value").getValue(); Name dn = p.getDescriptor().getName(); String name = dn.getLocalPart(); String prefix = CSWRecordDescriptor.NAMESPACES.getPrefix(dn.getNamespaceURI()); if (scheme == null) { element(prefix + ":" + name, value); } else { AttributesImpl attributes = new AttributesImpl(); addAttribute(attributes, "scheme", scheme); element(prefix + ":" + name, value, attributes); } } private String getRecordElement(CSWRecordsResult response) { switch (response.getElementSet()) { case BRIEF: return "BriefRecord"; case SUMMARY: return "SummaryRecord"; default: return "Record"; } } private List<Name> getElements(CSWRecordsResult response) { switch (response.getElementSet()) { case BRIEF: return CSWRecordDescriptor.BRIEF_ELEMENTS; case SUMMARY: return CSWRecordDescriptor.SUMMARY_ELEMENTS; default: return null; } } } }