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

org.opengis.cite.iso19142.versioning.VersioningTests Maven / Gradle / Ivy

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

import static org.testng.Assert.*;

import java.net.URI;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.xml.namespace.QName;
import javax.xml.transform.dom.DOMSource;

import org.opengis.cite.iso19142.BaseFixture;
import org.opengis.cite.iso19142.ETSAssert;
import org.opengis.cite.iso19142.ErrorMessage;
import org.opengis.cite.iso19142.ErrorMessageKeys;
import org.opengis.cite.iso19142.FES2;
import org.opengis.cite.iso19142.Namespaces;
import org.opengis.cite.iso19142.ProtocolBinding;
import org.opengis.cite.iso19142.SuiteAttribute;
import org.opengis.cite.iso19142.WFS2;
import org.opengis.cite.iso19142.basic.filter.ResourceId;
import org.opengis.cite.iso19142.transaction.InsertTests;
import org.opengis.cite.iso19142.util.DataSampler;
import org.opengis.cite.iso19142.util.Randomizer;
import org.opengis.cite.iso19142.util.ServiceMetadataUtils;
import org.opengis.cite.iso19142.util.WFSMessage;
import org.opengis.cite.iso19142.util.XMLUtils;
import org.testng.Assert;
import org.testng.ITestContext;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

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

/**
 * Provides test methods that verify the behavior of the IUT with respect to
 * creating and navigating feature versions.
 */
public class VersioningTests extends BaseFixture {

    private DataSampler dataSampler;
    private Map modifiedFeatures = new HashMap();

    @BeforeClass
    public void getDataSamplerFromContext(ITestContext testContext) {
        Object obj = testContext.getSuite().getAttribute(SuiteAttribute.SAMPLER.getName());
        if (null != obj) {
            this.dataSampler = DataSampler.class.cast(obj);
        }
    }

    @AfterClass
    public void deleteModifiedFeatures() {
        if (modifiedFeatures.isEmpty()) {
            return;
        }
        Document rspEntity = this.wfsClient.deleteFeatures(this.modifiedFeatures, ProtocolBinding.ANY);
        Element totalDeleted = (Element) rspEntity.getElementsByTagNameNS(Namespaces.WFS, WFS2.TOTAL_DEL).item(0);
        if (null == totalDeleted || Integer.parseInt(totalDeleted.getTextContent().trim()) != modifiedFeatures.size()) {
            Logger.getLogger(getClass().getName()).log(Level.WARNING,
                    String.format("Failed to delete all new features: %s \n%s", this.modifiedFeatures,
                            XMLUtils.writeNodeToString(rspEntity)));
        }
        this.modifiedFeatures.clear();
    }

    /**
     * [{@code Test}] Submits a request to insert a feature. The response is
     * expected to contain a single fes:ResourceId element with
     * version="1" and the previousRid attribute NOT
     * set. A subsequent query to retrieve the LAST version shall reveal that
     * its state is "valid".
     */
    @Test(description = "See OGC 09-025: 11.3.3.2, 15.3.4; OGC 09-026: 7.11.2")
    public void firstVersionHasNoPredecessor() {
        this.reqEntity = WFSMessage.createRequestEntity(WFS2.TRANSACTION, this.wfsVersion);
        Element feature = this.dataSampler.randomlySelectFeatureInstance();
        QName typeName = new QName(feature.getNamespaceURI(), feature.getLocalName());
        feature.setAttributeNS(Namespaces.GML, "id", "id-" + System.currentTimeMillis());
        InsertTests.insertRandomIdentifier(feature);
        WFSMessage.addInsertStatement(this.reqEntity, feature);
        URI endpoint = ServiceMetadataUtils.getOperationEndpoint(this.wfsMetadata, WFS2.TRANSACTION,
                ProtocolBinding.POST);
        ClientResponse rsp = this.wfsClient.submitRequest(new DOMSource(this.reqEntity), ProtocolBinding.POST,
                endpoint);
        this.rspEntity = rsp.getEntity(Document.class);
        Assert.assertEquals(rsp.getStatus(), ClientResponse.Status.OK.getStatusCode(),
                ErrorMessage.get(ErrorMessageKeys.UNEXPECTED_STATUS));
        List newFeatureIDs = InsertTests.extractFeatureIdentifiers(this.rspEntity, WFS2.Transaction.INSERT);
        assertEquals(newFeatureIDs.size(), 1,
                "Unexpected number of fes:ResourceId elements in response entity (InsertResults).");
        ResourceId id = newFeatureIDs.get(0);
        this.modifiedFeatures.put(id.getRid(), typeName);
        assertNotNull(id.getVersion(), String.format("ResourceId is missing version designator (rid=%s)", id.getRid()));
        assertEquals(id.getVersion(), "1", "Unexpected designator for first version.");
        assertNull(id.getPreviousRid(), String.format("New feature has previousRid (rid=%s)", id.getRid()));
        ResourceId qryId = new ResourceId(id.getRid());
        // get LAST version and check that state attribute is "valid"
        qryId.setVersion(FES2.VersionAction.LAST.name());
        rsp = this.wfsClient.GetFeatureVersion(qryId, typeName);
        this.rspEntity = rsp.getEntity(Document.class);
        int numReturned = Integer.parseInt(this.rspEntity.getDocumentElement().getAttribute("numberReturned"));
        assertEquals(numReturned, 1, ErrorMessage.get(ErrorMessageKeys.NUM_RETURNED));
        feature = (Element) this.rspEntity.getElementsByTagNameNS(typeName.getNamespaceURI(), typeName.getLocalPart())
                .item(0);
        Element member = (Element) feature.getParentNode();
        assertEquals(member.getAttribute("state"), WFS2.VersionState.VALID.toString(),
                ErrorMessage.get(ErrorMessageKeys.VERSION_STATE));
    }

    /**
     * [{@code Test}] Submits a request to update a feature property (gml:name).
     * The response is expected to contain a single fes:ResourceId element with
     * the previousRid attribute set. A subsequent query to
     * retrieve the PREVIOUS version shall reveal that its state is
     * "superseded".
     */
    @Test(description = "See OGC 09-025: 15.3.5")
    public void updatedVersionHasSupersededPredecessor() {
        this.reqEntity = WFSMessage.createRequestEntity(WFS2.TRANSACTION, this.wfsVersion);
        Element feature = this.dataSampler.randomlySelectFeatureInstance();
        QName typeName = new QName(feature.getNamespaceURI(), feature.getLocalName());
        String oldId = feature.getAttributeNS(Namespaces.GML, "id");
        Map properties = new HashMap();
        String newName = Randomizer.generateWords(2);
        properties.put("gml:name[1]", newName);
        this.rspEntity = wfsClient.updateFeature(this.reqEntity, oldId, typeName, properties, ProtocolBinding.POST);
        List updatedIDs = InsertTests.extractFeatureIdentifiers(this.rspEntity, WFS2.Transaction.UPDATE);
        assertEquals(updatedIDs.size(), 1,
                "Unexpected number of fes:ResourceId elements in response entity (UpdateResults).");
        ResourceId id = updatedIDs.get(0);
        this.modifiedFeatures.put(id.getRid(), typeName);
        assertNotNull(id.getPreviousRid(),
                String.format("Updated feature is missing previousRid (rid=%s)", id.getRid()));
        // get PREVIOUS version and check that state attribute is "superseded"
        ResourceId qryId = new ResourceId(id.getPreviousRid());
        ClientResponse rsp = this.wfsClient.GetFeatureVersion(qryId, typeName);
        this.rspEntity = rsp.getEntity(Document.class);
        int numReturned = Integer.parseInt(this.rspEntity.getDocumentElement().getAttribute("numberReturned"));
        assertEquals(numReturned, 1, ErrorMessage.get(ErrorMessageKeys.NUM_RETURNED));
        feature = (Element) this.rspEntity.getElementsByTagNameNS(typeName.getNamespaceURI(), typeName.getLocalPart())
                .item(0);
        Element member = (Element) feature.getParentNode();
        assertEquals(member.getAttribute("state"), WFS2.VersionState.SUPERSEDED.toString(),
                ErrorMessage.get(ErrorMessageKeys.VERSION_STATE));
    }

    /**
     * [{@code Test}] Submits a request to update a superseded version (whose
     * state is NOT "valid"). An exception report is expected in response; it
     * must contain the error code OperationProcessingFailed and
     * refer to the update handle.
     * 
     * TODO: Enable this when expected behavior is clarified.
     */
    @Test(description = "See OGC 09-025: Table 3, 15.4", enabled = false)
    public void updateSupersededVersion() {
        this.reqEntity = WFSMessage.createRequestEntity(WFS2.TRANSACTION, this.wfsVersion);
        Element feature = this.dataSampler.randomlySelectFeatureInstance();
        QName typeName = new QName(feature.getNamespaceURI(), feature.getLocalName());
        String oldId = feature.getAttributeNS(Namespaces.GML, "id");
        Map properties = new HashMap();
        String newName = Randomizer.generateWords(2);
        properties.put("gml:name[1]", newName);
        this.rspEntity = this.wfsClient.updateFeature(this.reqEntity, oldId, typeName, properties,
                ProtocolBinding.POST);
        List updatedIDs = InsertTests.extractFeatureIdentifiers(this.rspEntity, WFS2.Transaction.UPDATE);
        assertEquals(updatedIDs.size(), 1,
                "Unexpected number of fes:ResourceId elements in response entity (UpdateResults).");
        ResourceId id = updatedIDs.get(0);
        this.modifiedFeatures.put(id.getRid(), typeName);
        assertFalse(id.getRid().equals(id.getPreviousRid()),
                String.format("The rid and previousRid values should not match. ", id));
        // resubmit update request against previous revision
        this.rspEntity = this.wfsClient.updateFeature(this.reqEntity, oldId, typeName, properties,
                ProtocolBinding.POST);
        ETSAssert.assertExceptionReport(this.rspEntity, "OperationProcessingFailed", "Update");
    }

    /**
     * [{@code Test}] Submits a request to replace a feature version. The
     * response is expected to contain a single fes:ResourceId element with the
     * previousRid attribute set. A subsequent query to retrieve
     * the NEXT version shall produce an empty response.
     */
    @Test(description = "See OGC 09-025: 15.3.6")
    public void replacementVersionHasNoSuccessor() {
        this.reqEntity = WFSMessage.createRequestEntity(WFS2.TRANSACTION, this.wfsVersion);
        Element feature = this.dataSampler.randomlySelectFeatureInstance();
        QName typeName = new QName(feature.getNamespaceURI(), feature.getLocalName());
        InsertTests.insertRandomIdentifier(feature);
        InsertTests.addRandomName(feature);
        WFSMessage.addReplaceStatements(this.reqEntity, Collections.singletonList(feature));
        URI endpoint = ServiceMetadataUtils.getOperationEndpoint(this.wfsMetadata, WFS2.TRANSACTION,
                ProtocolBinding.POST);
        ClientResponse rsp = this.wfsClient.submitRequest(new DOMSource(this.reqEntity), ProtocolBinding.POST,
                endpoint);
        this.rspEntity = rsp.getEntity(Document.class);
        Assert.assertEquals(rsp.getStatus(), ClientResponse.Status.OK.getStatusCode(),
                ErrorMessage.get(ErrorMessageKeys.UNEXPECTED_STATUS));
        List newFeatureIDs = InsertTests.extractFeatureIdentifiers(this.rspEntity,
                WFS2.Transaction.REPLACE);
        assertEquals(newFeatureIDs.size(), 1,
                "Unexpected number of fes:ResourceId elements in response entity (ReplaceResults).");
        ResourceId id = newFeatureIDs.get(0);
        this.modifiedFeatures.put(id.getRid(), typeName);
        assertNotNull(id.getPreviousRid(),
                String.format("Replacement feature is missing previousRid (rid=%s)", id.getRid()));
        // get NEXT version and check that it doesn't exist
        ResourceId qryId = new ResourceId(id.getRid());
        qryId.setVersion(FES2.VersionAction.NEXT.name());
        rsp = this.wfsClient.GetFeatureVersion(qryId, typeName);
        this.rspEntity = rsp.getEntity(Document.class);
        int numMatched = Integer.parseInt(this.rspEntity.getDocumentElement().getAttribute("numberMatched"));
        assertEquals(numMatched, 0, ErrorMessage.get(ErrorMessageKeys.NUM_MATCHED));
    }

    /**
     * [{@code Test}] Submits a request to delete a feature. The response is
     * expected to report totalDeleted = 1. A subsequent query to retrieve the
     * LAST version shall reveal that its state is "retired".
     */
    @Test(description = "See OGC 09-025: 15.2.7.1")
    public void deletedFeatureIsRetired() {
        this.reqEntity = WFSMessage.createRequestEntity(WFS2.TRANSACTION, this.wfsVersion);
        Element feature = this.dataSampler.randomlySelectFeatureInstance();
        String gmlId = feature.getAttributeNS(Namespaces.GML, "id");
        QName typeName = new QName(feature.getNamespaceURI(), feature.getLocalName());
        ClientResponse rsp = wfsClient.deleteFeature(this.reqEntity, gmlId, typeName);
        this.rspEntity = rsp.getEntity(Document.class);
        assertEquals(rsp.getStatus(), ClientResponse.Status.OK.getStatusCode(),
                ErrorMessage.get(ErrorMessageKeys.UNEXPECTED_STATUS));
        int totalDeleted = Integer.parseInt(
                this.rspEntity.getElementsByTagNameNS(Namespaces.WFS, WFS2.TOTAL_DEL).item(0).getTextContent());
        assertEquals(totalDeleted, 1, ErrorMessage.format(ErrorMessageKeys.UNEXPECTED_VALUE, WFS2.TOTAL_DEL));
        // get LAST version and check that state attribute is "superseded"
        ResourceId qryId = new ResourceId(gmlId);
        qryId.setVersion(FES2.VersionAction.LAST.name());
        rsp = this.wfsClient.GetFeatureVersion(qryId, typeName);
        this.rspEntity = rsp.getEntity(Document.class);
        int numReturned = Integer.parseInt(this.rspEntity.getDocumentElement().getAttribute("numberReturned"));
        assertEquals(numReturned, 1, ErrorMessage.get(ErrorMessageKeys.NUM_RETURNED));
        feature = (Element) this.rspEntity.getElementsByTagNameNS(typeName.getNamespaceURI(), typeName.getLocalPart())
                .item(0);
        Element member = (Element) feature.getParentNode();
        assertEquals(member.getAttribute("state"), WFS2.VersionState.RETIRED.toString(),
                ErrorMessage.get(ErrorMessageKeys.VERSION_STATE));
        // attempt to restore deleted feature
        Document doc = this.wfsClient.insert(Collections.singletonList(feature), ProtocolBinding.POST);
        int totalInserted = Integer
                .parseInt(doc.getElementsByTagNameNS(Namespaces.WFS, WFS2.TOTAL_INS).item(0).getTextContent());
        if (totalInserted != 1) {
            Logger.getLogger(getClass().getName()).log(Level.WARNING,
                    String.format("Failed to restore deleted feature with id = %s", gmlId));
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy