All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opengis.cite.iso19142.transaction.Update Maven / Gradle / Ivy

There is a newer version: 2.0-r18
Show newest version
package org.opengis.cite.iso19142.transaction;

import java.math.BigDecimal;
import java.net.URI;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;

import javax.xml.namespace.QName;
import javax.xml.transform.dom.DOMSource;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;

import org.apache.xerces.xs.StringList;
import org.apache.xerces.xs.XSComplexTypeDefinition;
import org.apache.xerces.xs.XSConstants;
import org.apache.xerces.xs.XSElementDeclaration;
import org.apache.xerces.xs.XSSimpleTypeDefinition;
import org.apache.xerces.xs.XSTypeDefinition;
import org.opengis.cite.iso19142.ETSAssert;
import org.opengis.cite.iso19142.ErrorMessage;
import org.opengis.cite.iso19142.ErrorMessageKeys;
import org.opengis.cite.iso19142.Namespaces;
import org.opengis.cite.iso19142.ProtocolBinding;
import org.opengis.cite.iso19142.WFS2;
import org.opengis.cite.iso19142.util.AppSchemaUtils;
import org.opengis.cite.iso19142.util.ServiceMetadataUtils;
import org.opengis.cite.iso19142.util.TestSuiteLogger;
import org.opengis.cite.iso19142.util.WFSMessage;
import org.opengis.cite.iso19142.util.XMLUtils;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import com.sun.jersey.api.client.ClientResponse;

/**
 * Tests the response to a Transaction request that includes one or more update
 * actions. If the WFS supports feature versioning, then the wfs:UpdateResults
 * element must be present (to convey the new identifiers); however, this is not
 * currently checked.
 * 
 * @see "ISO 19142:2010, cl. 15.2.5: Update action"
 */
public class Update extends TransactionFixture {

    /** List containing original representations of modified features */
    private List modifiedFeatures = new ArrayList();

    /**
     * Attempts to restore the WFS data store to its previous state by replacing
     * all modified features with their original representations. If this does
     * not succeed a log message (WARNING) is written to the test suite logger.
     */
    @AfterClass
    public void restoreModifiedFeatures() {
        if (modifiedFeatures.isEmpty()) {
            return;
        }
        Document req = WFSMessage.createRequestEntity(WFS2.TRANSACTION, this.wfsVersion);
        WFSMessage.addReplaceStatements(req, modifiedFeatures);
        ClientResponse rsp = wfsClient.submitRequest(req, ProtocolBinding.ANY);
        Document rspEntity = rsp.getEntity(Document.class);
        String expr = String.format("//wfs:totalReplaced = '%d'", modifiedFeatures.size());
        Boolean result;
        try {
            result = (Boolean) XMLUtils.evaluateXPath(rspEntity, expr, null, XPathConstants.BOOLEAN);
        } catch (XPathExpressionException xpe) {
            throw new RuntimeException(xpe);
        }
        if (!result) {
            String msg = String.format("%s: Failed to replace modified features.\n%s", getClass().getName(),
                    XMLUtils.writeNodeToString(rspEntity));
            TestSuiteLogger.log(Level.WARNING, msg);
        }
    }

    /**
     * [{@code Test}] Submits a Transaction request to update the first name
     * (gml:name[1]) of an existing feature instance. The test is run for all
     * supported transaction bindings and available feature types. The response
     * entity (wfs:TransactionResponse) must be schema-valid.
     * 
     * 

* Sources *

*
    *
  • ISO 19142:2010, cl. 15.3.3: TransactionSummary element
  • *
  • ISO 19142:2010, cl. 15.3.5: UpdateResults element
  • *
* * @param binding * A supported transaction request binding. * @param featureType * A QName representing the name of some feature type for which * data are available. */ @Test(description = "See ISO 19142: 15.3.3, 15.3.5", dataProvider = "binding+availFeatureType") public void updateGMLName(ProtocolBinding binding, QName featureType) { Document doc = wfsClient.getFeatureByType(featureType, 1, null); NodeList features = doc.getElementsByTagNameNS(featureType.getNamespaceURI(), featureType.getLocalPart()); Element originalFeature = (Element) features.item(0); String gmlId = originalFeature.getAttributeNS(Namespaces.GML, "id"); Map properties = new HashMap(); String newName = "Pellentesque Arcu Lorem"; properties.put("gml:name[1]", newName); this.rspEntity = wfsClient.updateFeature(this.reqEntity, gmlId, featureType, properties, binding); if (this.rspEntity.getDocumentElement().getLocalName().equals(WFS2.TRANSACTION_RSP)) { modifiedFeatures.add(originalFeature); } this.rspEntity = wfsClient.invokeStoredQuery(WFS2.QRY_GET_FEATURE_BY_ID, Collections.singletonMap("id", gmlId)); Element feature = this.rspEntity.getDocumentElement(); ETSAssert.assertQualifiedName(feature, featureType); XSElementDeclaration gmlName = this.model.getElementDeclaration("name", Namespaces.GML); ETSAssert.assertSimpleProperties(feature, Collections.singletonMap(gmlName, newName), null); } /** * [{@code Test}] Submits a Transaction request to update a property * (gml:boundedBy) with an invalid value (kml:Point). An ExceptionReport * (with status code 400) containing the exception code {@code InvalidValue} * is expected in response. * *

* Sources *

*
    *
  • ISO 19142:2010, 15.2.5.2.1: Property element
  • *
  • ISO 19142:2010, Table 3: WFS exception codes
  • *
* */ @Test(description = "See ISO 19142: 7.5, 15.2.5.2.1") public void updateBoundedByWithKMLPoint() { try { this.reqEntity = docBuilder.parse(getClass().getResourceAsStream("UpdateInvalidFeatureProperty.xml")); } catch (Exception e) { throw new RuntimeException("Failed to parse XML resource from classpath", e); } Element update = (Element) this.reqEntity.getElementsByTagNameNS(Namespaces.WFS, WFS2.UPDATE).item(0); WFSMessage.setTypeName(update, featureTypes.get(0)); ProtocolBinding binding = wfsClient.getAnyTransactionBinding(); URI endpoint = ServiceMetadataUtils.getOperationEndpoint(this.wfsMetadata, WFS2.TRANSACTION, binding); ClientResponse rsp = wfsClient.submitRequest(new DOMSource(this.reqEntity), binding, endpoint); this.rspEntity = rsp.getEntity(Document.class); Assert.assertEquals(rsp.getStatus(), ClientResponse.Status.BAD_REQUEST.getStatusCode(), ErrorMessage.get(ErrorMessageKeys.UNEXPECTED_STATUS)); String xpath = "//ows:Exception[@exceptionCode = 'InvalidValue']"; ETSAssert.assertXPath(xpath, this.rspEntity.getDocumentElement(), null); } /** * [{@code Test}] Submits a request to update a simple property value, one * that is based on a built-in XML Schema datatype (including enumerated * types). The test is run for all supported transaction bindings and * available feature types. * *

* Sources *

*
    *
  • ISO 19142:2010, cl. 15.3.3: TransactionSummary element
  • *
  • ISO 19142:2010, cl. 15.3.5: UpdateResults element
  • *
* * @param binding * A supported message binding. * @param featureType * A QName representing the name of some feature type for which * data are available. */ @Test(description = "See ISO 19142: 15.3.3, 15.3.5", dataProvider = "binding+availFeatureType") public void updateSimplePropertyValue(ProtocolBinding binding, QName featureType) { List simpleProps = AppSchemaUtils.getSimpleFeatureProperties(this.model, featureType); // position iterator at end of list so previous() returns last item ListIterator propItr = simpleProps.listIterator(simpleProps.size()); XSElementDeclaration prop = propItr.previous(); Set identifiers = this.dataSampler.selectRandomFeatureIdentifiers(featureType, 1); String featureId = identifiers.iterator().next(); QName propName = new QName(prop.getNamespace(), prop.getName(), "tns"); List propValues = this.dataSampler.getSimplePropertyValues(featureType, propName, featureId); String newVal = newPropertyValue(prop, propValues); WFSMessage.addNamespaceBinding(this.reqEntity, propName); Map properties = new HashMap(); properties.put(propName.getPrefix() + ":" + propName.getLocalPart() + "[1]", newVal); this.rspEntity = wfsClient.updateFeature(this.reqEntity, featureId, featureType, properties, binding); if (this.rspEntity.getDocumentElement().getLocalName().equals(WFS2.TRANSACTION_RSP)) { modifiedFeatures.add(this.dataSampler.getFeatureById(featureId)); } this.rspEntity = wfsClient.invokeStoredQuery(WFS2.QRY_GET_FEATURE_BY_ID, Collections.singletonMap("id", featureId)); Element feature = this.rspEntity.getDocumentElement(); ETSAssert.assertQualifiedName(feature, featureType); ETSAssert.assertSimpleProperties(feature, Collections.singletonMap(prop, newVal), Collections.singletonMap(propName.getNamespaceURI(), propName.getPrefix())); } /** * Returns a new property value that conforms to the applicable simple type * definition. If the type contains an enumeration facet, the new value will * be one that does not occur in the original feature instance. * *

* The following XML Schema data types are recognized: *

*
    *
  • xsd:string
  • *
  • xsd:dateTime
  • *
  • xsd:date
  • *
  • xsd:float
  • *
  • xsd:double
  • *
  • xsd:decimal
  • *
  • xsd:integer
  • *
  • xsd:anyURI
  • *
  • xsd:boolean
  • *
* * @param prop * A property (element) declaration. * @param propValues * A List of known property values (may be empty). * @return A String representing the new property value. */ String newPropertyValue(XSElementDeclaration prop, List propValues) { XSSimpleTypeDefinition propType; if (prop.getTypeDefinition().getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE) { propType = (XSSimpleTypeDefinition) prop.getTypeDefinition(); } else { XSComplexTypeDefinition complexType = (XSComplexTypeDefinition) prop.getTypeDefinition(); propType = complexType.getSimpleType(); } // empty StringList if not an enumerated data type StringList enums = propType.getLexicalEnumeration(); for (int i = 0; i < enums.getLength(); i++) { if (!propValues.contains(enums.item(i))) { return enums.item(i); } } String newValue = null; switch (propType.getBuiltInKind()) { case XSConstants.STRING_DT: newValue = "TEST_VALUE"; break; case XSConstants.DATETIME_DT: ZonedDateTime utcNow = ZonedDateTime.now(ZoneId.of("Z")); newValue = utcNow.format(DateTimeFormatter.ISO_INSTANT); break; case XSConstants.DATE_DT: LocalDate localDate = LocalDate.now(ZoneId.of("Z")); newValue = localDate.toString(); break; case XSConstants.FLOAT_DT: Float fVal = Float.valueOf(propValues.get(0)); newValue = Float.toString(fVal / 2); break; case XSConstants.DOUBLE_DT: Double dVal = Double.valueOf(propValues.get(0)); newValue = Double.toString(dVal / 2); break; case XSConstants.DECIMAL_DT: BigDecimal decimalVal = new BigDecimal(propValues.get(0)); newValue = decimalVal.movePointLeft(1).toString(); break; case XSConstants.INTEGER_DT: int intVal = Integer.parseInt(propValues.get(0)); newValue = Integer.toString(intVal + 1); break; case XSConstants.ANYURI_DT: newValue = "http://example.org/test"; break; case XSConstants.BOOLEAN_DT: String boolVal = propValues.get(0); boolean oldValue = (boolVal.equals("true") || boolVal.equals("1")) ? true : false; newValue = new Boolean(!oldValue).toString(); break; default: newValue = "UNSUPPORTED_DATATYPE"; } return newValue; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy