/* * Copyright (c) 2015 Data Harmonisation Panel * * All rights reserved. This program and the accompanying materials are made * available under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the License, * or (at your option) any later version. * * You should have received a copy of the GNU Lesser General Public License * along with this distribution. If not, see <http://www.gnu.org/licenses/>. * * Contributors: * Data Harmonisation Panel <http://www.dhpanel.eu> */ package eu.esdihumboldt.hale.io.wfs.file; import java.util.Date; import java.util.List; import javax.xml.namespace.QName; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamWriter; import org.apache.xmlbeans.XmlDateTime; import eu.esdihumboldt.hale.common.core.io.IOProviderConfigurationException; import eu.esdihumboldt.hale.common.core.io.Value; import eu.esdihumboldt.hale.common.core.io.report.IOReporter; import eu.esdihumboldt.hale.common.core.io.supplier.LocatableURI; import eu.esdihumboldt.hale.common.instance.model.Instance; import eu.esdihumboldt.hale.common.instance.model.InstanceCollection; import eu.esdihumboldt.hale.common.instance.model.ResourceIterator; import eu.esdihumboldt.hale.common.schema.model.TypeDefinition; import eu.esdihumboldt.hale.io.gml.geometry.GMLConstants; import eu.esdihumboldt.hale.io.gml.writer.GmlInstanceWriter; import eu.esdihumboldt.hale.io.gml.writer.internal.GmlWriterUtil; import eu.esdihumboldt.hale.io.wfs.WFSConstants; import eu.esdihumboldt.hale.io.wfs.WFSVersion; import eu.esdihumboldt.hale.io.wfs.WFSWriter; import eu.esdihumboldt.hale.io.xsd.model.XmlElement; import eu.esdihumboldt.hale.io.xsd.model.XmlIndex; import eu.esdihumboldt.hale.io.xsd.reader.internal.SubstitutionGroupProperty; /** * Write GML features as a WFS FeatureCollection. * * @author Simon Templer */ @SuppressWarnings("restriction") public class WFSFeatureCollectionWriter extends GmlInstanceWriter implements WFSWriter, WFSConstants { /** * Parameter to skip counting instances. */ public static final String PARAM_SKIP_COUNT = "skipFeatureCount"; @Override public void validate() throws IOProviderConfigurationException { super.validate(); if (getWFSVersion() == null) { fail("A WFS version must be provided"); } } @Override protected XmlElement findDefaultContainter(XmlIndex targetIndex, IOReporter reporter) { WFSVersion version = getWFSVersion(); if (version != null) { XmlElement result = createFeatureCollectionElement(version, targetIndex); if (result != null) { return result; } } throw new IllegalStateException("Unable to write to WFS FeatureCollection"); } private XmlElement createFeatureCollectionElement(WFSVersion version, XmlIndex targetIndex) { String wfsNs = version.wfsNamespace; XmlElement memberElement = null; switch (version) { case V1_1_0: memberElement = targetIndex.getElements() .get(new QName(GMLConstants.NS_GML, "_Feature")); break; case V2_0_0: case V2_0_2: for (XmlElement element : targetIndex.getElements().values()) { if (element.getName().getLocalPart().equals("AbstractFeature") && element.getName() .getNamespaceURI().startsWith(GMLConstants.GML_NAMESPACE_CORE)) { memberElement = element; break; } } break; } if (memberElement == null) { throw new IllegalStateException( "Unable to identify member types for feature collection"); } addValidationSchema(version.wfsNamespace, new LocatableURI(version.schemaLocation), "wfs"); List<XmlElement> memberElements = SubstitutionGroupProperty .collectSubstitutions(memberElement.getName(), memberElement.getType()); TypeDefinition fcType = WFSSchemaHelper.createFeatureCollectionType(version, memberElements); return new XmlElement(new QName(wfsNs, "FeatureCollection"), fcType, null); } @Override protected void writeAdditionalElements(XMLStreamWriter writer, TypeDefinition containerDefinition, IOReporter reporter) throws XMLStreamException { // write additional needed attributes for WFS 2.0 boolean requiresCount = requiresCount(); boolean skipCount = getParameter(PARAM_SKIP_COUNT).as(Boolean.class, false); if (requiresCount) { String countString = null; InstanceCollection source = getInstances(); if (source.hasSize()) { // no iteration needed countString = String.valueOf(source.size()); } else if (!skipCount) { // count features int count = 0; // need to iterate collection to determine size try (ResourceIterator<Instance> it = source.iterator()) { while (it.hasNext()) { Instance candidate = it.next(); if (GmlWriterUtil.isFeatureType(candidate.getDefinition())) { count++; } } } countString = String.valueOf(count); } // numberMatched if (countString != null) { writer.writeAttribute("numberMatched", countString); } else { writer.writeAttribute("numberMatched", "unknown"); } // numberReturned if (countString != null) { writer.writeAttribute("numberReturned", countString); } else { writer.writeAttribute("numberReturned", "0"); } // timestamp XmlDateTime result = XmlDateTime.Factory.newInstance(); result.setDateValue(new Date()); writer.writeAttribute("timeStamp", result.getStringValue()); } super.writeAdditionalElements(writer, containerDefinition, reporter); } private boolean requiresCount() { WFSVersion version = getWFSVersion(); if (version != null) { switch (version) { case V2_0_0: case V2_0_2: return true; case V1_1_0: default: return false; } } else { return false; } } @Override public void setWFSVersion(WFSVersion version) { setParameter(PARAM_WFS_VERSION, Value.of(version.versionString)); } @Override public WFSVersion getWFSVersion() { String versionString = getParameter(PARAM_WFS_VERSION).as(String.class); if (versionString == null) { return null; } else return WFSVersion.fromString(versionString, null); } @Override public boolean isPassthrough() { boolean requiresCount = requiresCount(); boolean skipCount = getParameter(PARAM_SKIP_COUNT).as(Boolean.class, false); return !requiresCount || skipCount; } }