Package org.vfny.geoserver.wfs.responses

Source Code of org.vfny.geoserver.wfs.responses.WFSCapsTransformer

/* Copyright (c) 2001, 2003 TOPP - www.openplans.org.  All rights reserved.
* This code is licensed under the GPL 2.0 license, availible at the root
* application directory.
*/
package org.vfny.geoserver.wfs.responses;

import java.io.IOException;
import java.net.URL;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.logging.Logger;

import org.geotools.factory.FactoryFinder;
import org.geotools.filter.FunctionExpression;
import org.geotools.xml.transform.TransformerBase;
import org.geotools.xml.transform.Translator;
import org.vfny.geoserver.Request;
import org.vfny.geoserver.global.FeatureTypeInfo;
import org.vfny.geoserver.global.NameSpaceInfo;
import org.vfny.geoserver.global.WFS;
import org.vfny.geoserver.global.dto.WFSDTO;
import org.vfny.geoserver.util.requests.CapabilitiesRequest;
import org.vfny.geoserver.wfs.FeatureResponseDelegateProducerSpi;
import org.xml.sax.ContentHandler;
import org.xml.sax.helpers.AttributesImpl;

import com.vividsolutions.jts.geom.Envelope;


/**
* Based on the <code>org.geotools.xml.transform</code> framework, does the job
* of encoding a WFS 1.0 Capabilities document.
*
* @author Gabriel Roldan, Axios Engineering
* @author Chris Holmes
* @version $Id
*/
public class WFSCapsTransformer extends TransformerBase {
    /** DOCUMENT ME! */
    private static final Logger LOGGER = Logger.getLogger(WFSCapsTransformer.class.getPackage()
                                                                                  .getName());

    /** DOCUMENT ME! */
    private static final String HTTP_GET = "Get";

    /** DOCUMENT ME! */
    private static final String HTTP_POST = "Post";

    /** DOCUMENT ME! */
    protected static final String WFS_URI = "http://www.opengis.net/wfs";

    /** DOCUMENT ME! */
    protected static final String CUR_VERSION = "1.0.0";

    /** DOCUMENT ME! */
    protected static final String XSI_PREFIX = "xsi";

    /** DOCUMENT ME! */
    protected static final String XSI_URI = "http://www.w3.org/2001/XMLSchema-instance";

    /** DOCUMENT ME! */
    protected Request request;

    /**
     * Creates a new WFSCapsTransformer object.
     */
    public WFSCapsTransformer() {
        super();
        setNamespaceDeclarationEnabled(false);
    }

    /**
     * DOCUMENT ME!
     *
     * @param handler DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    public Translator createTranslator(ContentHandler handler) {
        return new WFSCapsTranslator(handler);
    }

    /**
     * DOCUMENT ME!
     *
     * @author Gabriel Roldan, Axios Engineering
     * @version $Id
     */
    private static class WFSCapsTranslator extends TranslatorSupport {
        /** DOCUMENT ME!  */
        private static final String EPSG = "EPSG:";

        /** DOCUMENT ME! */
        private CapabilitiesRequest request;

        /**
         * Creates a new WFSCapsTranslator object.
         *
         * @param handler DOCUMENT ME!
         */
        public WFSCapsTranslator(ContentHandler handler) {
            super(handler, null, null);
        }

        /**
         * Encode the object.
         *
         * @param o The Object to encode.
         *
         * @throws IllegalArgumentException if the Object is not encodeable.
         */
        public void encode(Object o) throws IllegalArgumentException {
            if (!(o instanceof CapabilitiesRequest)) {
                throw new IllegalArgumentException(
                    "Not a CapabilitiesRequest: " + o);
            }

            this.request = (CapabilitiesRequest) o;

            AttributesImpl attributes = new AttributesImpl();
            attributes.addAttribute("", "version", "version", "", CUR_VERSION);

            attributes.addAttribute("", "xmlns", "xmlns", "", WFS_URI);

            NameSpaceInfo[] namespaces = request.getWFS().getData()
                                                .getNameSpaces();

            for (int i = 0; i < namespaces.length; i++) {
                String prefixDef = "xmlns:" + namespaces[i].getPrefix();
                String uri = namespaces[i].getUri();
                attributes.addAttribute("", prefixDef, prefixDef, "", uri);
            }

            attributes.addAttribute("", "xmlns:ogc", "xmlns:ogc", "",
                "http://www.opengis.net/ogc");

            String prefixDef = "xmlns:" + XSI_PREFIX;
            attributes.addAttribute("", prefixDef, prefixDef, "", XSI_URI);

            String locationAtt = XSI_PREFIX + ":schemaLocation";
            String locationDef = WFS_URI + " " + request.getSchemaBaseUrl()
                + "wfs/1.0.0/" + "WFS-capabilities.xsd"; //djb: this was pointing to the wrong location
            attributes.addAttribute("", locationAtt, locationAtt, "",
                locationDef);

            start("WFS_Capabilities", attributes);

            handleService();
            handleCapability();
            handleFeatureTypes();
            handleFilterCapabilities();

            end("WFS_Capabilities");
        }

        /**
         * DOCUMENT ME!
         */
        private void handleService() {
            WFS wfs = request.getWFS();
            start("Service");
            element("Name", wfs.getName());
            element("Title", wfs.getTitle());
            element("Abstract", wfs.getAbstract());

            List kwlist = wfs.getKeywords();
            handleKeywords(kwlist);

            URL or = wfs.getOnlineResource();
            element("OnlineResource", (or == null) ? "" : or.toExternalForm());
            element("Fees", wfs.getFees());
            element("AccessConstraints", wfs.getAccessConstraints());
            end("Service");
        }

        /**
         * DOCUMENT ME!
         *
         * @param kwlist
         */
        private void handleKeywords(List kwlist) {
            StringBuffer kwds = new StringBuffer();

            for (Iterator it = kwlist.iterator(); it.hasNext();) {
                kwds.append(String.valueOf(it.next()));

                if (it.hasNext()) {
                    kwds.append(", ");
                }
            }

            element("Keywords", kwds.toString());
        }

        /**
         * DOCUMENT ME!
         */
        private void handleCapability() {
            WFS config = request.getWFS();

            start("Capability");
            start("Request");
            handleGetCapabilities();
            handleDescribeFT();
            handleGetFeature();

    if (config.getServiceLevel() >= WFSDTO.TRANSACTIONAL) {
                handleTransaction();
            }

    if (config.getServiceLevel() == WFSDTO.COMPLETE) {
                handleLock();
                handleFeatureWithLock();
            }

            end("Request");
            end("Capability");
        }

        /**
         * DOCUMENT ME!
         */
        private void handleGetCapabilities() {
            String capName = "GetCapabilities";
            start(capName);
            handleDcpType(capName, HTTP_GET);
            handleDcpType(capName, HTTP_POST);
            end(capName);
        }

        /**
         * DOCUMENT ME!
         */
        private void handleDescribeFT() {
            String capName = "DescribeFeatureType";
            start(capName);
            start("SchemaDescriptionLanguage");
            element("XMLSCHEMA", null);
            end("SchemaDescriptionLanguage");

            handleDcpType(capName, HTTP_GET);
            handleDcpType(capName, HTTP_POST);
            end(capName);
        }

        /**
         * DOCUMENT ME!
         */
        private void handleGetFeature() {
            String capName = "GetFeature";
            start(capName);

            String resultFormat = "ResultFormat";
            start(resultFormat);
           
            //DJB: okay, I'm adding all the supported formats
            //     we probably need a "strict cite" conformance option
            //     somewhere in the config files. (default = not scrict)
            //     Strict meaning only have "GML2" in here.
            //     Alternatively, we could have options for "supported output formats"
            //     in the config and people could check off the extras they want
            //     to allow.
           
           //  element("GML2", null); // old implementation
           
            FeatureResponseDelegateProducerSpi spi;

          //DJB: (see above comment, this fixes it0
          //      WFS config now has a "citeConformanceHacks" boolean in it.
          //      true --> only publish GML2 in caps file
          //      false -> publish all
            WFS config = request.getWFS();
            boolean onlyGML2 = config.getCiteConformanceHacks();
           
            if (onlyGML2)
            {
              element("GML2",null);
            }
            else
          {
              //FULL MONTY
              Iterator spi_it = FactoryFinder.factories(FeatureResponseDelegateProducerSpi.class);
              while (spi_it.hasNext())
              {
                  spi = (FeatureResponseDelegateProducerSpi) spi_it.next();
                  Set formats = spi.getSupportedFormats();
                  Iterator it =formats.iterator();
                  while (it.hasNext())
                  {
                    String format = (String) it.next();
                    element( format, null);
                  }
              }
          }

            //So cite does not even like this.  Which is really lame, since it
            //validates according to our definition for now, and because the cite
            //tests have a bunch of other valid types (perhaps from galdos?).
            //So I think perhaps we should just have it as a capability that
            //is not advertised in the capabilities section for now.  And we
            //should try to get the cite team to add it to their section. ch
            //element("GML2-GZIP", null);
            end(resultFormat);

            handleDcpType(capName, HTTP_GET);
            handleDcpType(capName, HTTP_POST);
            end(capName);
        }

        /**
         * DOCUMENT ME!
         */
        private void handleTransaction() {
            String capName = "Transaction";
            start(capName);
            handleDcpType(capName, HTTP_GET);
            handleDcpType(capName, HTTP_POST);
            end(capName);
        }

        /**
         * DOCUMENT ME!
         */
        private void handleLock() {
            String capName = "LockFeature";
            start(capName);
            handleDcpType(capName, HTTP_GET);
            handleDcpType(capName, HTTP_POST);
            end(capName);
        }

        /**
         * DOCUMENT ME!
         */
        private void handleFeatureWithLock() {
            String capName = "GetFeatureWithLock";
            start(capName);
            start("ResultFormat");
            element("GML2", null);
            end("ResultFormat");
            handleDcpType(capName, HTTP_GET);
            handleDcpType(capName, HTTP_POST);
            end(capName);
        }

        /**
         * Encodes a <code>DCPType</code> fragment for HTTP GET and POST
         * methods.
         *
         * @param capabilityName the URL of the onlineresource for HTTP GET
         *        method requests
         * @param httpMethod the URL of the onlineresource for HTTP POST method
         *        requests
         */
        private void handleDcpType(String capabilityName, String httpMethod) {
            String baseUrl = request.getBaseUrl() + "wfs";
            String url = null;

            if (request.isDispatchedRequest()) {
                url = baseUrl + "?";
            } else {
                url = baseUrl + "/" + capabilityName + "?";
            }

            start("DCPType");
            start("HTTP");

            AttributesImpl atts = new AttributesImpl();
            atts.addAttribute("", "onlineResource", "onlineResource", "", url);
            element(httpMethod, null, atts);

            end("HTTP");
            end("DCPType");
        }

        /**
         * DOCUMENT ME!
         */
        private void handleFeatureTypes() {
            WFS wfs = request.getWFS();

            if (!wfs.isEnabled()) {
                // should we return anything if we are disabled?
            }

            start("FeatureTypeList");
            start("Operations");

            if ((wfs.getServiceLevel() | WFSDTO.SERVICE_BASIC) != 0) {
                element("Query", null);
            }

            if ((wfs.getServiceLevel() | WFSDTO.SERVICE_INSERT) != 0) {
                element("Insert", null);
            }

            if ((wfs.getServiceLevel() | WFSDTO.SERVICE_UPDATE) != 0) {
                element("Update", null);
            }

            if ((wfs.getServiceLevel() | WFSDTO.SERVICE_DELETE) != 0) {
                element("Delete", null);
            }

            if ((wfs.getServiceLevel() | WFSDTO.SERVICE_LOCKING) != 0) {
                element("Lock", null);
            }

            end("Operations");

            Collection featureTypes = wfs.getData().getFeatureTypeInfos()
                                         .values();
            FeatureTypeInfo ftype;

            for (Iterator it = featureTypes.iterator(); it.hasNext();) {
                ftype = (FeatureTypeInfo) it.next();

                //can't handle ones that aren't enabled.
                //and they shouldn't be handled, as they won't function.
                if (ftype.isEnabled()) {
                    handleFeatureType(ftype);
                }
            }

            end("FeatureTypeList");
        }

        /**
         * Default handle of a FeatureTypeInfo content that writes the
         * latLongBBox as well as the GlobalBasic's parameters
         *
         * @param ftype The FeatureType configuration to report capabilities
         *        on.
         *
         * @throws RuntimeException For any errors.
         */
        protected void handleFeatureType(FeatureTypeInfo ftype) {
            start("FeatureType");

            Envelope bbox = null;

            try {
                bbox = ftype.getLatLongBoundingBox();
            } catch (IOException ex) {
                throw new RuntimeException("Can't obtain latLongBBox of "
                    + ftype.getName() + ": " + ex.getMessage(), ex);
            }

            element("Name", ftype.getName());
            element("Title", ftype.getTitle());
            element("Abstract", ftype.getAbstract());
            handleKeywords(ftype.getKeywords());

            /**
             * @task REVISIT: should getSRS() return the full URL?
             */
            element("SRS", EPSG + ftype.getSRS());

            String minx = String.valueOf(bbox.getMinX());
            String miny = String.valueOf(bbox.getMinY());
            String maxx = String.valueOf(bbox.getMaxX());
            String maxy = String.valueOf(bbox.getMaxY());

            AttributesImpl bboxAtts = new AttributesImpl();
            bboxAtts.addAttribute("", "minx", "minx", "", minx);
            bboxAtts.addAttribute("", "miny", "miny", "", miny);
            bboxAtts.addAttribute("", "maxx", "maxx", "", maxx);
            bboxAtts.addAttribute("", "maxy", "maxy", "", maxy);

            element("LatLongBoundingBox", null, bboxAtts);

            end("FeatureType");
        }

        /**
         * DOCUMENT ME!
         */
        private void handleFilterCapabilities() {
            String ogc = "ogc:";

            //REVISIT: for now I"m just prepending ogc onto the name element.
            //Is the proper way to only do that for the qname?  I guess it
            //would only really matter if we're going to be producing capabilities
            //documents that aren't qualified, and I don't see any reason to
            //do that.
            start(ogc + "Filter_Capabilities");
            start(ogc + "Spatial_Capabilities");
            start(ogc + "Spatial_Operators");
            element(ogc + "Disjoint", null);
            element(ogc + "Equals", null);
            element(ogc + "DWithin", null);
            element(ogc + "Beyond", null);
            element(ogc + "Intersect", null);
            element(ogc + "Touches", null);
            element(ogc + "Crosses", null);
            element(ogc + "Within", null);
            element(ogc + "Contains", null);
            element(ogc + "Overlaps", null);
            element(ogc + "BBOX", null);
            end(ogc + "Spatial_Operators");
            end(ogc + "Spatial_Capabilities");

            start(ogc + "Scalar_Capabilities");
            element(ogc + "Logical_Operators", null);
            start(ogc + "Comparison_Operators");
            element(ogc + "Simple_Comparisons", null);
            element(ogc + "Between", null);
            element(ogc + "Like", null);
            element(ogc + "NullCheck", null);
            end(ogc + "Comparison_Operators");
            start(ogc + "Arithmetic_Operators");
            element(ogc + "Simple_Arithmetic", null);
           
            handleFunctions(ogc)//djb: list functions
           
            end(ogc + "Arithmetic_Operators");
            end(ogc + "Scalar_Capabilities");
            end(ogc + "Filter_Capabilities");
        }
       
        public  void handleFunctions(String prefix)
        {
           start(prefix +"Functions");
           start(prefix +"Function_Names");
           java.util.Iterator it = org.geotools.factory.FactoryFinder.factories(FunctionExpression.class);
             //Sort them up for easier visual inspection
           SortedSet sortedFunctions = new TreeSet(new Comparator(){
                 public int compare(Object o1, Object o2){
                        String n1 = ((FunctionExpression) o1).getName();
                        String n2 = ((FunctionExpression) o2).getName();
                        return n1.toLowerCase().compareTo(n2.toLowerCase());
                 }
             });
             while it.hasNext()   )
             {
              sortedFunctions.add(it.next());
             }
            
             //write them now that functions are sorted by name
             FunctionExpression exp = null;
             it = sortedFunctions.iterator();
             while it.hasNext()   )
             {
                 FunctionExpression fe = (FunctionExpression) it.next();
                 String funName = fe.getName();
                 int    funNArgs= fe.getArgCount();
                
                 AttributesImpl atts = new AttributesImpl();
                 atts.addAttribute("", "nArgs", "nArgs", "", funNArgs+"");
                
                 element(prefix +"Function_Name",funName,atts);             
             }
            
             end(prefix +"Function_Names");
             end(prefix +"Functions");
        }
       
    }
   
}
TOP

Related Classes of org.vfny.geoserver.wfs.responses.WFSCapsTransformer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.