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

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

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

import com.sun.jersey.api.client.ClientResponse;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
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.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.basic.filter.ResourceId;
import org.opengis.cite.iso19142.util.XMLUtils;
import org.opengis.cite.iso19142.util.ServiceMetadataUtils;
import org.opengis.cite.iso19142.util.TestSuiteLogger;
import org.opengis.cite.iso19142.util.WFSMessage;
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.Node;
import org.w3c.dom.NodeList;

/**
 * Tests the response to a Transaction request that includes one or more insert
 * actions.
 * 
 * @see "ISO 19142:2010, cl. 15.2.4: Insert action"
 */
public class InsertTests extends TransactionFixture {

    private Map createdFeatures = new HashMap();

    /**
     * Restores the WFS data store to its previous state by deleting all
     * features that were successfully inserted by test methods in this class.
     */
    @AfterClass
    public void deleteInsertedFeatures() {
        if (createdFeatures.isEmpty()) {
            return;
        }
        Document rspEntity = this.wfsClient.deleteFeatures(createdFeatures, ProtocolBinding.ANY);
        String xpath = String.format("//wfs:totalDeleted = '%d'", createdFeatures.size());
        Boolean result;
        try {
            result = (Boolean) XMLUtils.evaluateXPath(rspEntity, xpath, null, XPathConstants.BOOLEAN);
        } catch (XPathExpressionException xpe) {
            throw new RuntimeException(xpe);
        }
        if (!result) {
            String msg = String.format("%s: Failed to remove all new features:\n %s \n%s", getClass().getName(),
                    this.createdFeatures, XMLUtils.writeNodeToString(rspEntity));
            TestSuiteLogger.log(Level.WARNING, msg);
        }
        this.createdFeatures.clear();
    }

    /**
     * [{@code Test}] Submits a Transaction request to insert a feature instance
     * of a type supported by the SUT. The test is run for all supported
     * Transaction request bindings and feature types. The response entity
     * (wfs:TransactionResponse) must be schema-valid and contain the
     * wfs:InsertResults element.
     * 
     * @param binding
     *            A supported message binding.
     * @param featureType
     *            A QName representing the qualified name of some feature type.
     * 
     * @see "ISO 19142:2010, cl. 15.3.3: TransactionSummary element"
     * @see "ISO 19142:2010, cl. 15.3.4: InsertResults element"
     */
    @Test(description = "See ISO 19142: 15.2.4, 15.3.4", dataProvider = "binding+availFeatureType")
    public void insertSupportedFeature(ProtocolBinding binding, QName featureType) {
        Node feature = createFeatureInstance(featureType);
        WFSMessage.addInsertStatement(this.reqEntity, feature);
        URI endpoint = ServiceMetadataUtils.getOperationEndpoint(this.wfsMetadata, WFS2.TRANSACTION, binding);
        ClientResponse rsp = this.wfsClient.submitRequest(new DOMSource(this.reqEntity), binding, endpoint);
        this.rspEntity = rsp.getEntity(Document.class);
        Assert.assertEquals(rsp.getStatus(), ClientResponse.Status.OK.getStatusCode(),
                ErrorMessage.get(ErrorMessageKeys.UNEXPECTED_STATUS));
        ETSAssert.assertXPath("//wfs:TransactionResponse/wfs:InsertResults", this.rspEntity, null);
        List newFeatureIDs = extractFeatureIdentifiers(this.rspEntity, WFS2.Transaction.INSERT);
        String rid = newFeatureIDs.get(0).getRid();
        createdFeatures.put(rid, featureType);
        ETSAssert.assertFeatureAvailability(rid, true, this.wfsClient);
    }

    /**
     * [{@code Test}] Submits a Transaction request to insert a feature instance
     * of a type not recognized by the SUT. An ExceptionReport (with status code
     * 400) containing the exception code {@code InvalidValue} is expected in
     * response.
     * 
     * @see "ISO 19142:2010, Table 3:  WFS exception codes"
     */
    @Test(description = "See ISO 19142: 7.5, 15.4")
    public void insertInvalidFeature() {
        try {
            this.reqEntity = docBuilder.parse(getClass().getResourceAsStream("InsertUnrecognizedFeature.xml"));
        } catch (Exception e) {
            throw new RuntimeException("Failed to parse InsertUnrecognizedFeature.xml from classpath", e);
        }
        ProtocolBinding binding = wfsClient.getAnyTransactionBinding();
        URI endpoint = ServiceMetadataUtils.getOperationEndpoint(this.wfsMetadata, WFS2.TRANSACTION, binding);
        ClientResponse rsp = wfsClient.submitRequest(new DOMSource(this.reqEntity), binding, endpoint);
        Assert.assertEquals(rsp.getStatus(), ClientResponse.Status.BAD_REQUEST.getStatusCode(),
                ErrorMessage.get(ErrorMessageKeys.UNEXPECTED_STATUS));
        this.rspEntity = rsp.getEntity(Document.class);
        String xpath = "//ows:Exception[@exceptionCode = 'InvalidValue']";
        ETSAssert.assertXPath(xpath, this.rspEntity.getDocumentElement(), null);
    }

    /**
     * Extracts a list of resource identifiers for features that were affected
     * by a successful transaction request. The identifiers are found using this
     * XPath expression: "//{wfs:ActionResultsType}/wfs:Feature/fes:ResourceId",
     * where {@literal wfs:ActionResultsType} denotes an element of this type.
     * 
     * @param entity
     *            A Document representing a successful transaction response
     *            entity (wfs:TransactionResponse).
     * @param action
     *            The transaction results of interest.
     * @return A List containing zero or more feature identifiers.
     */
    public static List extractFeatureIdentifiers(Document entity, WFS2.Transaction action) {
        List idList = new ArrayList<>();
        String xpath = String.format("//wfs:%sResults/wfs:Feature/fes:ResourceId", action.toString());
        Map nsBindings = new HashMap();
        nsBindings.put(Namespaces.WFS, "wfs");
        nsBindings.put(Namespaces.FES, "fes");
        try {
            NodeList idNodes = XMLUtils.evaluateXPath(entity, xpath, nsBindings);
            for (int i = 0; i < idNodes.getLength(); i++) {
                Element idElem = (Element) idNodes.item(i);
                ResourceId id = new ResourceId(idElem.getAttribute("rid"));
                if (!idElem.getAttribute("previousRid").isEmpty()) {
                    id.setPreviousRid(idElem.getAttribute("previousRid"));
                }
                if (!idElem.getAttribute("version").isEmpty()) {
                    id.setVersion(idElem.getAttribute("version"));
                }
                idList.add(id);
            }
        } catch (XPathExpressionException e) {
            throw new RuntimeException(e);
        }
        return idList;
    }

    /**
     * Creates a new representation of a feature instance. First, an attempt is
     * made to retrieve a feature representation from the SUT; if this fails or
     * no instances exist then one is generated using an application schema
     * (Note: this facility is not yet implemented). The gml:id attribute is
     * modified and a new gml:identifier is added.
     * 
     * @param featureType
     *            A QName representing the qualified name of some feature type.
     * @return A Node (Element) node representing a feature instance.
     */
    Node createFeatureInstance(QName featureType) {
        Document entity = wfsClient.getFeatureByType(featureType, 1, null);
        NodeList features = entity.getElementsByTagNameNS(featureType.getNamespaceURI(), featureType.getLocalPart());
        if (features.getLength() == 0) {
            // TODO: try generating minimal instance from schema
            throw new NullPointerException("Unable to obtain feature instance of type " + featureType);
        }
        Element feature = (Element) features.item(0);
        feature.setAttributeNS(Namespaces.GML, "gml:id", "id-" + System.currentTimeMillis());
        insertRandomIdentifier(feature);
        return feature.cloneNode(true);
    }

    /**
     * Inserts a user-assigned gml:identifier element having a random UUID
     * value. An existing identifier is replaced.
     * 
     * @param feature
     *            An Element node representing a GML feature.
     * @return The UUID that was assigned to the feature instance.
     */
    public static UUID insertRandomIdentifier(Element feature) {
        QName propName = new QName(Namespaces.GML, "identifier");
        Element identifier = XMLUtils.createElement(propName);
        identifier.setAttribute("codeSpace", "http://cite.opengeospatial.org/");
        UUID uuid = UUID.randomUUID();
        identifier.setTextContent(uuid.toString());
        WFSMessage.insertGMLProperty(feature, identifier);
        return uuid;
    }

    /**
     * Adds a gml:name element to the given feature representation. The first
     * name will be replaced if one or more are already present.
     * 
     * @param feature
     *            An Element node representing a GML feature.
     * @return The name that was assigned to the feature instance.
     */
    public static String addRandomName(Element feature) {
        QName gmlName = new QName(Namespaces.GML, "name");
        Element name = XMLUtils.createElement(gmlName);
        name.setAttribute("codeSpace", "http://cite.opengeospatial.org/");
        String value = UUID.randomUUID().toString().replaceAll("-", "");
        name.setTextContent(value.toString());
        WFSMessage.insertGMLProperty(feature, name);
        return value;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy