de.ii.xtraplatform.feature.provider.wfs.WFSCapabilitiesParser.java Source code

Java tutorial

Introduction

Here is the source code for de.ii.xtraplatform.feature.provider.wfs.WFSCapabilitiesParser.java

Source

/**
 * Copyright 2017 European Union, interactive instruments GmbH
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */
/**
 * bla
 */
package de.ii.xtraplatform.feature.provider.wfs;

import de.ii.xtraplatform.feature.query.api.FeatureProviderMetadataConsumer;
import de.ii.xtraplatform.ogc.api.OWS;
import de.ii.xtraplatform.ogc.api.XLINK;
import org.apache.http.HttpEntity;
import org.apache.http.util.EntityUtils;
import org.codehaus.staxmate.SMInputFactory;
import org.codehaus.staxmate.in.SMEvent;
import org.codehaus.staxmate.in.SMInputCursor;
import org.xml.sax.InputSource;

import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.io.IOException;
import java.io.InputStream;

/**
 *
 * @author zahnen
 */
public class WFSCapabilitiesParser {

    private final FeatureProviderMetadataConsumer metadataConsumer;
    private final SMInputFactory staxFactory;

    public WFSCapabilitiesParser(FeatureProviderMetadataConsumer metadataConsumer, SMInputFactory staxFactory) {
        this.metadataConsumer = metadataConsumer;
        this.staxFactory = staxFactory;
    }

    public void parse(InputStream inputStream) {
        try {
            InputSource is = new InputSource(inputStream);
            parse(is);
        } catch (Exception ex) {
            // TODO: move to analyzer for XtraProxy
            //LOGGER.error(FrameworkMessages.ERROR_PARSING_WFS_CAPABILITIES);
            //throw new SchemaParseException(FrameworkMessages.ERROR_PARSING_WFS_CAPABILITIES);

            metadataConsumer.analyzeFailed(ex);
        }
    }

    public void parse(InputSource is) {

        SMInputCursor root = null;

        try {
            root = staxFactory.rootElementCursor(is.getByteStream()).advance();

            if (checkForExceptionReport(root)) {
                return;
            }

            parseNamespaces(root);

            metadataConsumer.analyzeVersion(root.getAttrValue(OWS.getWord(OWS.VOCABULARY.VERSION)));

            SMInputCursor capabilitiesChild = root.childElementCursor().advance();

            while (capabilitiesChild.readerAccessible()) {

                switch (OWS.findKey(capabilitiesChild.getLocalName())) {
                case SERVICE_IDENTIFICATION:
                    parseServiceIdentification(capabilitiesChild);
                    break;
                case SERVICE_PROVIDER:
                    parseServiceProvider(capabilitiesChild);
                    break;
                case OPERATIONS_METADATA:
                    parseOperationsMetadata(capabilitiesChild);
                    break;
                case FEATURE_TYPE_LIST:
                    parseFeatureTypeList(capabilitiesChild);
                    break;
                }

                capabilitiesChild = capabilitiesChild.advance();
            }
        } catch (XMLStreamException ex) {
            // TODO: move to analyzer for XtraProxy
            //LOGGER.error(FrameworkMessages.ERROR_PARSING_WFS_CAPABILITIES);
            //throw new ParseError(FrameworkMessages.ERROR_PARSING_WFS_CAPABILITIES);

            metadataConsumer.analyzeFailed(ex);
        } finally {
            if (root != null) {
                try {
                    root.getStreamReader().closeCompletely();
                } catch (XMLStreamException ex) {
                    // ignore
                }
            }
        }
    }

    private void parseNamespaces(SMInputCursor cursor) throws XMLStreamException {
        XMLStreamReader xml = cursor.getStreamReader();

        for (int i = 0; i < xml.getNamespaceCount(); i++) {
            metadataConsumer.analyzeNamespace(xml.getNamespacePrefix(i), xml.getNamespaceURI(i));
        }
    }

    private boolean checkForExceptionReport(SMInputCursor cursor) throws XMLStreamException {

        boolean exceptionFound = false;

        // TODO: make version agnostic
        if (OWS.findKey(cursor.getLocalName()) == OWS.VOCABULARY.EXCEPTION_REPORT) {

            exceptionFound = true;

            SMInputCursor exceptionReportChild = cursor.childElementCursor().advance();

            boolean reportChildFound = false;

            while (exceptionReportChild.readerAccessible()) {

                switch (OWS.findKey(exceptionReportChild.getLocalName())) {
                case EXCEPTION:
                    parseException(exceptionReportChild);
                    reportChildFound = true;
                    break;
                }

                exceptionReportChild = exceptionReportChild.advance();

                // TODO: move to analyzer for XtraProxy
                /*LOGGER.error(FrameworkMessages.EXCEPTION_COMING_FROM_WFS, exceptionCode + " " + exceptionText + "");
                WFSException wfse = new WFSException(FrameworkMessages.EXCEPTION_COMING_FROM_WFS, exceptionText);
                wfse.addDetail(FrameworkMessages.EXCEPTION_COMING_FROM_WFS, exceptionCode);
                throw wfse;
                */
            }

            if (!reportChildFound) {
                metadataConsumer.analyzeFailed("", "");
            }
        }

        return exceptionFound;
    }

    private void parseException(SMInputCursor cursor) throws XMLStreamException {

        String exceptionCode = cursor.getAttrValue(OWS.getWord(OWS.VERSION._1_1_0, OWS.VOCABULARY.EXCEPTION_CODE));

        if (exceptionCode != null) {

            SMInputCursor exceptionChild = cursor.childElementCursor().advance();

            while (exceptionChild.readerAccessible()) {

                switch (OWS.findKey(exceptionChild.getLocalName())) {
                case EXCEPTION_TEXT:
                    metadataConsumer.analyzeFailed(exceptionCode, exceptionChild.collectDescendantText());
                    break;
                }

                exceptionChild = exceptionChild.advance();
            }

        } else {
            exceptionCode = cursor.getAttrValue(OWS.getWord(OWS.VERSION._1_0_0, OWS.VOCABULARY.EXCEPTION_CODE));

            metadataConsumer.analyzeFailed(exceptionCode, cursor.collectDescendantText());
        }

    }

    private void parseServiceIdentification(SMInputCursor cursor) throws XMLStreamException {

        SMInputCursor serviceIdentificationChild = cursor.childElementCursor().advance();

        while (serviceIdentificationChild.readerAccessible()) {

            switch (OWS.findKey(serviceIdentificationChild.getLocalName())) {
            case TITLE:
                metadataConsumer.analyzeTitle(serviceIdentificationChild.collectDescendantText());
                break;
            case ABSTRACT:
                metadataConsumer.analyzeAbstract(serviceIdentificationChild.collectDescendantText());
                break;
            case KEYWORDS:
                parseKeywords("", false, serviceIdentificationChild);
                break;
            case FEES:
                metadataConsumer.analyzeFees(serviceIdentificationChild.collectDescendantText());
                break;
            case ACCESS_CONSTRAINTS:
                metadataConsumer.analyzeAccessConstraints(serviceIdentificationChild.collectDescendantText());
                break;
            case SERVICE_TYPE_VERSION:
                metadataConsumer.analyzeVersion(serviceIdentificationChild.collectDescendantText());
                break;
            }

            serviceIdentificationChild = serviceIdentificationChild.advance();
        }
    }

    private void parseKeywords(String featureTypeName, boolean isFeatureType, SMInputCursor cursor)
            throws XMLStreamException {
        SMInputCursor keywordsChild = cursor.descendantMixedCursor().advance();

        while (keywordsChild.readerAccessible()) {

            if (keywordsChild.getCurrEvent().hasText() && keywordsChild.getCurrEvent() != SMEvent.IGNORABLE_WS) {
                String keywords = keywordsChild.getText().trim();
                if (!keywords.isEmpty()) {
                    if (isFeatureType) {
                        metadataConsumer.analyzeFeatureTypeKeywords(featureTypeName, keywords.split(","));
                    } else {
                        metadataConsumer.analyzeKeywords(keywords.split(","));
                    }
                }
            }

            keywordsChild = keywordsChild.advance();
        }
    }

    private void parseServiceProvider(SMInputCursor cursor) throws XMLStreamException {
        SMInputCursor serviceProviderChild = cursor.childElementCursor().advance();

        while (serviceProviderChild.readerAccessible()) {

            switch (OWS.findKey(serviceProviderChild.getLocalName())) {
            case PROVIDER_NAME:
                metadataConsumer.analyzeProviderName(serviceProviderChild.collectDescendantText());
                break;
            case PROVIDER_SITE:
                metadataConsumer.analyzeProviderSite(serviceProviderChild.collectDescendantText());
                break;
            case SERVICE_CONTACT:
                parseServiceContact(serviceProviderChild);
                break;
            }

            serviceProviderChild = serviceProviderChild.advance();
        }
    }

    private void parseServiceContact(SMInputCursor cursor) throws XMLStreamException {
        SMInputCursor serviceContactChild = cursor.childElementCursor().advance();

        while (serviceContactChild.readerAccessible()) {

            switch (OWS.findKey(serviceContactChild.getLocalName())) {
            case INDIVIDUAL_NAME:
                metadataConsumer.analyzeServiceContactIndividualName(serviceContactChild.collectDescendantText());
                break;
            case ORGANIZATION_NAME:
                metadataConsumer.analyzeServiceContactOrganizationName(serviceContactChild.collectDescendantText());
                break;
            case POSITION_NAME:
                metadataConsumer.analyzeServiceContactPositionName(serviceContactChild.collectDescendantText());
                break;
            case CONTACT_INFO:
                parseContactInfo(serviceContactChild);
                break;
            case ROLE:
                metadataConsumer.analyzeServiceContactRole(serviceContactChild.collectDescendantText());
                break;
            }

            serviceContactChild = serviceContactChild.advance();
        }
    }

    private void parseContactInfo(SMInputCursor cursor) throws XMLStreamException {
        SMInputCursor contactInfoChild = cursor.childElementCursor().advance();

        while (contactInfoChild.readerAccessible()) {

            switch (OWS.findKey(contactInfoChild.getLocalName())) {
            case PHONE:
                parsePhone(contactInfoChild);
                break;
            case ADDRESS:
                parseAddress(contactInfoChild);
                break;
            case ONLINE_RESOURCE:
                metadataConsumer.analyzeServiceContactOnlineResource(contactInfoChild
                        .getAttrValue(XLINK.getNS(XLINK.VERSION.DEFAULT), XLINK.getWord(XLINK.VOCABULARY.HREF)));
                break;
            case HOURS_OF_SERVICE:
                metadataConsumer.analyzeServiceContactHoursOfService(contactInfoChild.collectDescendantText());
                break;
            case CONTACT_INSTRUCTIONS:
                metadataConsumer.analyzeServiceContactInstructions(contactInfoChild.collectDescendantText());
                break;
            }

            contactInfoChild = contactInfoChild.advance();
        }
    }

    private void parsePhone(SMInputCursor cursor) throws XMLStreamException {
        SMInputCursor phoneChild = cursor.childElementCursor().advance();

        while (phoneChild.readerAccessible()) {

            switch (OWS.findKey(phoneChild.getLocalName())) {
            case VOICE:
                metadataConsumer.analyzeServiceContactPhone(phoneChild.collectDescendantText());
                break;
            case FACSIMILE:
                metadataConsumer.analyzeServiceContactFacsimile(phoneChild.collectDescendantText());
                break;
            }

            phoneChild = phoneChild.advance();
        }
    }

    private void parseAddress(SMInputCursor cursor) throws XMLStreamException {
        SMInputCursor addressChild = cursor.childElementCursor().advance();

        while (addressChild.readerAccessible()) {

            switch (OWS.findKey(addressChild.getLocalName())) {
            case DELIVERY_POINT:
                metadataConsumer.analyzeServiceContactDeliveryPoint(addressChild.collectDescendantText());
                break;
            case CITY:
                metadataConsumer.analyzeServiceContactCity(addressChild.collectDescendantText());
                break;
            case ADMINISTRATIVE_AREA:
                metadataConsumer.analyzeServiceContactAdministrativeArea(addressChild.collectDescendantText());
                break;
            case POSTAL_CODE:
                metadataConsumer.analyzeServiceContactPostalCode(addressChild.collectDescendantText());
                break;
            case COUNTRY:
                metadataConsumer.analyzeServiceContactCountry(addressChild.collectDescendantText());
                break;
            case EMAIL:
                metadataConsumer.analyzeServiceContactEmail(addressChild.collectDescendantText());
                break;
            }

            addressChild = addressChild.advance();
        }
    }

    private void parseOperationsMetadata(SMInputCursor cursor) throws XMLStreamException {

        SMInputCursor operationsMetadataChild = cursor.childElementCursor().advance();

        while (operationsMetadataChild.readerAccessible()) {

            switch (OWS.findKey(operationsMetadataChild.getLocalName())) {
            case OPERATION:
                parseOperation(operationsMetadataChild);
                break;
            case PARAMETER:
                parseParameterOrConstraint(OWS.OPERATION.NONE, false, operationsMetadataChild);
                break;
            case CONSTRAINT:
                parseParameterOrConstraint(OWS.OPERATION.NONE, true, operationsMetadataChild);
                break;
            case EXTENDED_CAPABILITIES:
                parseExtendedCapabilities(operationsMetadataChild);
                break;
            }

            operationsMetadataChild = operationsMetadataChild.advance();
        }
    }

    private void parseOperation(SMInputCursor cursor) throws XMLStreamException {

        OWS.OPERATION wfsOperation = OWS.OPERATION
                .fromString(cursor.getAttrValue(OWS.getWord(OWS.VOCABULARY.NAME_ATTRIBUTE)));

        if (wfsOperation == OWS.OPERATION.NONE) {
            wfsOperation = OWS.OPERATION.fromString(cursor.getLocalName());
        }

        if (wfsOperation == OWS.OPERATION.NONE) {
            cursor = cursor.childElementCursor().advance();

            while (cursor.readerAccessible()) {
                if (OWS.OPERATION.fromString(cursor.getLocalName()) != OWS.OPERATION.NONE) {
                    parseOperation(cursor);
                }

                cursor = cursor.advance();
            }

            return;
        }

        if (wfsOperation != OWS.OPERATION.NONE) {

            SMInputCursor operationChild = cursor.childElementCursor().advance();

            while (operationChild.readerAccessible()) {

                switch (OWS.findKey(operationChild.getLocalName())) {
                case DCP:
                    SMInputCursor dcpChild = operationChild.descendantElementCursor().advance();

                    while (dcpChild.readerAccessible()) {
                        if (dcpChild.getCurrEvent() == SMEvent.START_ELEMENT) {
                            switch (OWS.findKey(dcpChild.getLocalName())) {
                            case GET:
                                metadataConsumer.analyzeOperationGetUrl(wfsOperation.toString(),
                                        parseUrl(dcpChild));
                                break;
                            case POST:
                                metadataConsumer.analyzeOperationPostUrl(wfsOperation.toString(),
                                        parseUrl(dcpChild));
                                break;
                            }
                        }
                        dcpChild = dcpChild.advance();
                    }
                    break;
                case PARAMETER:
                    parseParameterOrConstraint(wfsOperation, false, operationChild);
                    break;
                case RESULT_FORMAT:
                    parseResultFormat(wfsOperation, operationChild);
                    break;
                case CONSTRAINT:
                    parseParameterOrConstraint(wfsOperation, true, operationChild);
                    break;
                case METADATA:
                    metadataConsumer.analyzeOperationMetadata(wfsOperation.toString(), operationChild.getAttrValue(
                            XLINK.getNS(XLINK.VERSION.DEFAULT), XLINK.getWord(XLINK.VOCABULARY.HREF)));
                    break;
                }

                operationChild = operationChild.advance();
            }
        }
    }

    private String parseUrl(SMInputCursor cursor) throws XMLStreamException {
        String url = cursor.getAttrValue(XLINK.getNS(XLINK.VERSION.DEFAULT), XLINK.getWord(XLINK.VOCABULARY.HREF));
        if (url == null) {
            url = cursor.getAttrValue(OWS.getWord(OWS.VOCABULARY.ONLINE_RESOURCE_ATTRIBUTE));
        }
        return url;
    }

    private void parseParameterOrConstraint(OWS.OPERATION operation, boolean isConstraint, SMInputCursor cursor)
            throws XMLStreamException {

        OWS.VOCABULARY parameterName = OWS.findKey(cursor.getAttrValue(OWS.getWord(OWS.VOCABULARY.NAME_ATTRIBUTE)));

        if (parameterName != OWS.VOCABULARY.NOT_A_WORD) {

            SMInputCursor parameterChild = cursor.descendantElementCursor().advance();

            while (parameterChild.readerAccessible()) {
                if (parameterChild.getCurrEvent() == SMEvent.START_ELEMENT) {
                    switch (OWS.findKey(parameterChild.getLocalName())) {
                    case VALUE:
                    case DEFAULT_VALUE:
                        if (isConstraint) {
                            metadataConsumer.analyzeOperationConstraint(operation.toString(),
                                    parameterName.toString(), parameterChild.collectDescendantText());
                        } else {
                            metadataConsumer.analyzeOperationParameter(operation.toString(),
                                    parameterName.toString(), parameterChild.collectDescendantText());
                        }
                        break;
                    }
                }

                parameterChild = parameterChild.advance();
            }

        }
    }

    private void parseResultFormat(OWS.OPERATION operation, SMInputCursor cursor) throws XMLStreamException {

        OWS.VOCABULARY parameterName = OWS.findKey(cursor.getLocalName());

        if (parameterName == OWS.VOCABULARY.RESULT_FORMAT) {

            SMInputCursor parameterChild = cursor.childElementCursor().advance();

            while (parameterChild.readerAccessible()) {
                metadataConsumer.analyzeOperationParameter(operation.toString(),
                        OWS.VOCABULARY.OUTPUT_FORMAT.toString(), parameterChild.getLocalName());

                parameterChild = parameterChild.advance();
            }

        }
    }

    private void parseExtendedCapabilities(SMInputCursor cursor) throws XMLStreamException {

        SMInputCursor extendedCapabilitiesChild = cursor.childElementCursor().advance();

        while (extendedCapabilitiesChild.readerAccessible()) {

            switch (OWS.findKey(extendedCapabilitiesChild.getLocalName())) {
            case EXTENDED_CAPABILITIES:
                SMInputCursor extendedCapabilitiesChild2 = extendedCapabilitiesChild.childElementCursor().advance();

                while (extendedCapabilitiesChild2.readerAccessible()) {

                    switch (OWS.findKey(extendedCapabilitiesChild2.getLocalName())) {
                    case INSPIRE_METADATA_URL:
                        SMInputCursor inspireMetadataChild = extendedCapabilitiesChild2.childElementCursor()
                                .advance();

                        while (inspireMetadataChild.readerAccessible()) {

                            switch (OWS.findKey(inspireMetadataChild.getLocalName())) {
                            case INSPIRE_URL:
                                metadataConsumer
                                        .analyzeInspireMetadataUrl(inspireMetadataChild.collectDescendantText());
                                break;
                            }

                            inspireMetadataChild = inspireMetadataChild.advance();
                        }
                        break;
                    }

                    extendedCapabilitiesChild2 = extendedCapabilitiesChild2.advance();
                }
                break;
            }

            extendedCapabilitiesChild = extendedCapabilitiesChild.advance();
        }
    }

    private void parseFeatureTypeList(SMInputCursor cursor) throws XMLStreamException {
        SMInputCursor featureTypeListChild = cursor.childElementCursor().advance();

        while (featureTypeListChild.readerAccessible()) {

            switch (OWS.findKey(featureTypeListChild.getLocalName())) {
            case FEATURE_TYPE:
                parseFeatureType(featureTypeListChild);
                break;
            }

            featureTypeListChild = featureTypeListChild.advance();
        }
    }

    private void parseFeatureType(SMInputCursor cursor) throws XMLStreamException {

        parseNamespaces(cursor);

        SMInputCursor featureTypeChild = cursor.childElementCursor().advance();

        String featureTypeName = null;

        while (featureTypeChild.readerAccessible()) {

            switch (OWS.findKey(featureTypeChild.getLocalName())) {
            case NAME:
                parseNamespaces(featureTypeChild);
                featureTypeName = featureTypeChild.collectDescendantText();
                metadataConsumer.analyzeFeatureType(featureTypeName);
                break;
            case TITLE:
                metadataConsumer.analyzeFeatureTypeTitle(featureTypeName, featureTypeChild.collectDescendantText());
                break;
            case ABSTRACT:
                metadataConsumer.analyzeFeatureTypeAbstract(featureTypeName,
                        featureTypeChild.collectDescendantText());
                break;
            case KEYWORDS:
                parseKeywords(featureTypeName, true, featureTypeChild);
                break;
            case DEFAULT_CRS:
                metadataConsumer.analyzeFeatureTypeDefaultCrs(featureTypeName,
                        featureTypeChild.getElemStringValue());
                break;
            case OTHER_CRS:
                metadataConsumer.analyzeFeatureTypeOtherCrs(featureTypeName, featureTypeChild.getElemStringValue());
                break;
            case WGS84_BOUNDING_BOX:
                parseBoundingBox(featureTypeName, featureTypeChild);
                break;
            case METADATA_URL:
                parseMetadataUrl(featureTypeName, featureTypeChild);
                break;
            }

            featureTypeChild = featureTypeChild.advance();
        }
    }

    private void parseBoundingBox(String featureTypeName, SMInputCursor cursor) throws XMLStreamException {

        String xmin = cursor.getAttrValue(OWS.getWord(OWS.VOCABULARY.MIN_X));
        String ymin = cursor.getAttrValue(OWS.getWord(OWS.VOCABULARY.MIN_Y));
        String xmax = cursor.getAttrValue(OWS.getWord(OWS.VOCABULARY.MAX_X));
        String ymax = cursor.getAttrValue(OWS.getWord(OWS.VOCABULARY.MAX_Y));

        if (xmin == null || ymin == null || xmax == null || ymax == null) {

            SMInputCursor bboxChild = cursor.childElementCursor().advance();

            String[] lowerCorner = null;
            String[] upperCorner = null;

            while (bboxChild.readerAccessible()) {

                switch (OWS.findKey(bboxChild.getLocalName())) {
                case LOWER_CORNER:
                    lowerCorner = bboxChild.getElemStringValue().trim().split(" ");
                    break;
                case UPPER_CORNER:
                    upperCorner = bboxChild.getElemStringValue().trim().split(" ");
                    break;
                }

                bboxChild = bboxChild.advance();
            }

            if (lowerCorner != null && lowerCorner.length == 2 && upperCorner != null && upperCorner.length == 2) {
                xmin = lowerCorner[0];
                ymin = lowerCorner[1];
                xmax = upperCorner[0];
                ymax = upperCorner[1];
            }
        }

        metadataConsumer.analyzeFeatureTypeBoundingBox(featureTypeName, xmin, ymin, xmax, ymax);
    }

    private void parseMetadataUrl(String featureTypeName, SMInputCursor cursor) throws XMLStreamException {

        String url = cursor.getAttrValue(XLINK.getNS(XLINK.VERSION.DEFAULT), XLINK.getWord(XLINK.VOCABULARY.HREF));

        if (url == null) {
            url = cursor.collectDescendantText();
        }

        metadataConsumer.analyzeFeatureTypeMetadataUrl(featureTypeName, url);
    }
}