Package org.geowebcache.service.wmts

Source Code of org.geowebcache.service.wmts.WMTSGetCapabilities

/**
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  You should have received a copy of the GNU Lesser General Public License
*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*
* @author Arne Kepp, OpenGeo, Copyright 2009
*
*/
package org.geowebcache.service.wmts;

import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.geowebcache.config.meta.ServiceContact;
import org.geowebcache.config.meta.ServiceInformation;
import org.geowebcache.config.meta.ServiceProvider;
import org.geowebcache.conveyor.Conveyor.CacheResult;
import org.geowebcache.filter.parameters.ParameterFilter;
import org.geowebcache.grid.Grid;
import org.geowebcache.grid.GridSet;
import org.geowebcache.grid.GridSetBroker;
import org.geowebcache.grid.GridSubset;
import org.geowebcache.grid.SRS;
import org.geowebcache.io.XMLBuilder;
import org.geowebcache.layer.TileLayer;
import org.geowebcache.layer.TileLayerDispatcher;
import org.geowebcache.layer.meta.LayerMetaInformation;
import org.geowebcache.mime.MimeType;
import org.geowebcache.stats.RuntimeStats;
import org.geowebcache.util.ServletUtils;
import org.geowebcache.util.URLMangler;

public class WMTSGetCapabilities {
   
    private static Log log = LogFactory.getLog(WMTSGetCapabilities.class);
   
    private TileLayerDispatcher tld;
   
    private GridSetBroker gsb;
   
    private String baseUrl;
   
    protected WMTSGetCapabilities(TileLayerDispatcher tld, GridSetBroker gsb, HttpServletRequest servReq, String baseUrl,
            String contextPath, URLMangler urlMangler) {
        this.tld = tld;
        this.gsb = gsb;

        String forcedBaseUrl = ServletUtils.stringFromMap(servReq.getParameterMap(), servReq.getCharacterEncoding(), "base_url");

        if(forcedBaseUrl!=null) {
            this.baseUrl = forcedBaseUrl;
        } else {
            this.baseUrl = urlMangler.buildURL(baseUrl, contextPath, WMTSService.SERVICE_PATH);
        }
       
    }
   
    protected void writeResponse(HttpServletResponse response, RuntimeStats stats) {
        final Charset encoding = StandardCharsets.UTF_8;
        byte[] data = generateGetCapabilities(encoding).getBytes(encoding);
       
        response.setStatus(HttpServletResponse.SC_OK);
        response.setContentType("application/vnd.ogc.wms_xml");
        response.setCharacterEncoding(encoding.name());
        response.setContentLength(data.length);
        response.setHeader("content-disposition", "inline;filename=wmts-getcapabilities.xml");
       
        stats.log(data.length, CacheResult.OTHER);
       
        try {
            OutputStream os = response.getOutputStream();
            os.write(data);
            os.flush();
        } catch (IOException ioe) {
            log.debug("Caught IOException" + ioe.getMessage());
        }
    }

    private String generateGetCapabilities(Charset encoding) {
        StringBuilder str = new StringBuilder();
        XMLBuilder xml = new XMLBuilder(str);
       
        try {
            xml.header("1.0", encoding);
            xml.indentElement("Capabilities");
            xml.attribute("xmlns", "http://www.opengis.net/wmts/1.0");
            xml.attribute("xmlns:ows", "http://www.opengis.net/ows/1.1");
            xml.attribute("xmlns:xlink", "http://www.w3.org/1999/xlink");
            xml.attribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
            xml.attribute("xmlns:gml", "http://www.opengis.net/gml");
            xml.attribute("xsi:schemaLocation", "http://www.opengis.net/wmts/1.0 http://schemas.opengis.net/wmts/1.0/wmtsGetCapabilities_response.xsd");
            xml.attribute("version", "1.0.0");
            // There were some contradictions in the draft schema, haven't checked whether they've fixed those
            //str.append("xsi:schemaLocation=\"http://www.opengis.net/wmts/1.0 http://geowebcache.org/schema/opengis/wmts/1.0.0/wmtsGetCapabilities_response.xsd\"\n");
           
            serviceIdentification(xml);
            serviceProvider(xml);
            operationsMetadata(xml);
            contents(xml);
            xml.indentElement("ServiceMetadataURL")
                .attribute("xlink:href", baseUrl+"?REQUEST=getcapabilities&VERSION=1.0.0")
                .endElement();
           
            xml.endElement("Capabilities");
           
            return str.toString();
        } catch (IOException e) {
            // Should not happen as StringBuilder doesn't throw
            throw new IllegalStateException(e);
        }
    }

    private void serviceIdentification(XMLBuilder xml) throws IOException {
        ServiceInformation servInfo = tld.getServiceInformation();
       
        xml.indentElement("ows:ServiceIdentification");
       
        if (servInfo != null) {
            appendTag(xml, "ows:Title", servInfo.getTitle(), "Web Map Tile Service - GeoWebCache");
            appendTag(xml, "ows:Abstract", servInfo.getDescription(), null);
           
            if (servInfo != null && servInfo.getKeywords() != null) {
                xml.indentElement("ows:Keywords");
                Iterator<String> keywordIter = servInfo.getKeywords().iterator();
                while(keywordIter.hasNext()) {
                    appendTag(xml, "ows:Keyword", keywordIter.next(), null);
                }
                xml.endElement();
            }
        } else {
            xml.simpleElement("ows:Title","Web Map Tile Service - GeoWebCache", true);
        }
        xml.simpleElement("ows:ServiceType","OGC WMTS", true);
        xml.simpleElement("ows:ServiceTypeVersion","1.0.0", true);
       
        if (servInfo != null) {
            appendTag(xml, "ows:Fees", servInfo.getFees(), null);
            appendTag(xml, "ows:AccessConstraints", servInfo.getAccessConstraints(), null);
        }

        xml.endElement("ows:ServiceIdentification");
    }
   
    private void serviceProvider(XMLBuilder xml) throws IOException {
        ServiceInformation servInfo = tld.getServiceInformation();
        ServiceProvider servProv = null;
        if(servInfo != null) {
            servProv = servInfo.getServiceProvider();
        }
        xml.indentElement("ows:ServiceProvider");
       
        if(servProv != null) {
            appendTag(xml, "ows:ProviderName", servProv.getProviderName(), null);
           
            if(servProv.getProviderSite() != null) {
                xml.indentElement("ows:ProviderSite").attribute("xlink:href", servProv.getProviderSite()).endElement();
            }
           
            ServiceContact servCont = servProv.getServiceContact();
            if(servCont != null) {
                xml.indentElement("ows:ServiceContact");
                appendTag(xml, "ows:IndividualName", servCont.getIndividualName(), null);
                appendTag(xml, "ows:PositionName", servCont.getPositionName(), null);
                xml.indentElement("ows:ContactInfo");
               
                if(servCont.getPhoneNumber() != null || servCont.getFaxNumber() != null) {
                    xml.indentElement("ows:Phone");
                    appendTag(xml, "ows:Voice", servCont.getPhoneNumber(), null);
                    appendTag(xml, "ows:Facsimile", servCont.getFaxNumber(), null);
                    xml.endElement();
                }
               
                xml.indentElement("ows:Address");
                appendTag(xml, "ows:DeliveryPoint", servCont.getAddressStreet(), null);
                appendTag(xml, "ows:City", servCont.getAddressCity(), null);
                appendTag(xml, "ows:AdministrativeArea", servCont.getAddressAdministrativeArea(), null);
                appendTag(xml, "ows:PostalCode", servCont.getAddressPostalCode(), null);
                appendTag(xml, "ows:Country", servCont.getAddressCountry(), null);
                appendTag(xml, "ows:ElectronicMailAddress", servCont.getAddressEmail(), null);
                xml.endElement("ows:Address");
               
                xml.endElement();
                xml.endElement();
            }
        } else {
            appendTag(xml, "ows:ProviderName", baseUrl, null);
            xml.indentElement("ows:ProviderSite").attribute("xlink:href", baseUrl).endElement();
            xml.indentElement("ows:ServiceContact");
            appendTag(xml, "ows:IndividualName", "GeoWebCache User", null);
            xml.endElement();
        }
           
        xml.endElement("ows:ServiceProvider");
    }
   
    private void operationsMetadata(XMLBuilder xml) throws IOException {
        xml.indentElement("ows:OperationsMetadata");
        operation(xml, "GetCapabilities", baseUrl);
        operation(xml, "GetTile", baseUrl);
        operation(xml, "GetFeatureInfo", baseUrl);
        xml.endElement("ows:OperationsMetadata");
    }
       
     private void operation(XMLBuilder xml, String operationName, String baseUrl) throws IOException {
        xml.indentElement("ows:Operation").attribute("name", operationName);
        xml.indentElement("ows:DCP");
        xml.indentElement("ows:HTTP");
        xml.indentElement("ows:Get").attribute("xlink:href", baseUrl+"?");
        xml.indentElement("ows:Constraint").attribute("name", "GetEncoding");
        xml.indentElement("ows:AllowedValues");
        xml.simpleElement("ows:Value", "KVP", true);
        xml.endElement();
        xml.endElement();
        xml.endElement();
        xml.endElement();
        xml.endElement();
        xml.endElement("ows:Operation");
     }
    
     private void contents(XMLBuilder xml) throws IOException {
         xml.indentElement("Contents");
         Iterable<TileLayer> iter = tld.getLayerList();
        for (TileLayer layer : iter) {
            if (!layer.isEnabled()) {
                continue;
            }
            layer(xml, layer, baseUrl);
        }
        
        for (GridSet gset : gsb.getGridSets()) {
            tileMatrixSet(xml, gset);
        }
        
         xml.endElement("Contents");
     }
    
     private void layer(XMLBuilder xml, TileLayer layer, String baseurl) throws IOException {
        xml.indentElement("Layer");
        LayerMetaInformation layerMeta = layer.getMetaInformation();

        if (layerMeta == null) {
            appendTag(xml, "ows:Title", layer.getName(), null);
        } else {
            appendTag(xml, "ows:Title", layerMeta.getTitle(), null);
            appendTag(xml, "ows:Abstract", layerMeta.getDescription(), null);
        }

        layerWGS84BoundingBox(xml, layer);
        appendTag(xml, "ows:Identifier", layer.getName(), null);
       
        // We need the filters for styles and dimensions
        List<ParameterFilter> filters = layer.getParameterFilters();
       
        layerStyles(xml, layer, filters);
       
        layerFormats(xml, layer);
       
        layerInfoFormats(xml, layer);
       
        if(filters != null) {
            layerDimensions(xml, layer, filters);
        }
       
        layerGridSubSets(xml, layer);
        // TODO REST
        // str.append("    <ResourceURL format=\"image/png\" resourceType=\"tile\" template=\"http://www.maps.cat/wmts/BlueMarbleNextGeneration/default/BigWorldPixel/{TileMatrix}/{TileRow}/{TileCol}.png\"/>\n");
        xml.endElement("Layer");
    }
    
    private void layerWGS84BoundingBox(XMLBuilder xml, TileLayer layer) throws IOException {
        GridSubset subset = layer.getGridSubsetForSRS(SRS.getEPSG4326());
        if(subset != null) {
            double[] coords = subset.getOriginalExtent().getCoords();
            xml.indentElement("ows:WGS84BoundingBox");
            xml.simpleElement("ows:LowerCorner", coords[0]+" "+coords[1], true);
            xml.simpleElement("ows:UpperCorner", coords[2]+" "+coords[3], true);
            xml.endElement("ows:WGS84BoundingBox");  
        }
     }
    
     private void layerStyles(XMLBuilder xml, TileLayer layer, List<ParameterFilter> filters) throws IOException {
         String defStyle = layer.getStyles();
         if(filters == null) {
             xml.indentElement("Style");
             xml.attribute("isDefault", "true");
             if(defStyle == null) {
                 xml.simpleElement("ows:Identifier", "", true);
             } else {
                 xml.simpleElement("ows:Identifier", "TileLayer.encodeDimensionValue(defStyle)", true);
             }
             xml.endElement("Style");
         } else {
             ParameterFilter stylesFilter = null;
             Iterator<ParameterFilter> iter = filters.iterator();
             while(stylesFilter == null && iter.hasNext()) {
                 ParameterFilter filter = iter.next();
                 if(filter.getKey().equalsIgnoreCase("STYLES")) {
                     stylesFilter = filter;
                 }
             }
            
             List<String> legalStyles=null;
             if(stylesFilter != null) legalStyles = stylesFilter.getLegalValues();
            
             if(legalStyles!=null && !legalStyles.isEmpty()) {
                 // There's a style filter listing at least one value
                 String defVal = stylesFilter.getDefaultValue();
                 if(defVal == null) {
                     if(defStyle != null) {
                         defVal = defStyle;
                     } else {
                         defVal = "";
                     }
                 }
                
                 for(String value:legalStyles) {
                     xml.indentElement("Style");
                     if(value.equals(defVal)) {
                         xml.attribute("isDefault", "true");
                     }
                     xml.simpleElement("ows:Identifier", TileLayer.encodeDimensionValue(value), true);
                     xml.endElement();
                 }
             } else {
                // Couldn't get a list of styles so just say there's a default.
                xml.indentElement("Style");
                xml.attribute("isDefault", "true");
                xml.simpleElement("ows:Identifier", "", true);
                xml.endElement();
             }
         }
     }
    
     private void layerFormats(XMLBuilder xml, TileLayer layer) throws IOException {
         Iterator<MimeType> mimeIter = layer.getMimeTypes().iterator();
        
         while(mimeIter.hasNext()){
             xml.simpleElement("Format", mimeIter.next().getFormat(), true);
         }
     }
    
     private void layerInfoFormats(XMLBuilder xml, TileLayer layer) throws IOException {
         if (layer.isQueryable()) {
             Iterator<MimeType> mimeIter = layer.getInfoMimeTypes().iterator();
           while (mimeIter.hasNext()) {
             xml.simpleElement("InfoFormat", mimeIter.next().getFormat(), true);
           }
         }
     }
    
     private void layerDimensions(XMLBuilder xml, TileLayer layer, List<ParameterFilter> filters) throws IOException {
        
         Iterator<ParameterFilter> iter = filters.iterator();
        
         while(iter.hasNext()) {
             ParameterFilter filter = iter.next();
            
             if(! filter.getKey().equalsIgnoreCase("STYLES")) {
                 List<String> values = filter.getLegalValues();
            
                 if(values != null) {
                     dimensionDescription(xml, filter, values);
                 }
             }
         }
     }
        
     private void dimensionDescription(XMLBuilder xml, ParameterFilter filter, List<String> values) throws IOException {
         xml.startElement("Dimension");
         xml.simpleElement("Identifier", filter.getKey(), false);
         String defaultStr = TileLayer.encodeDimensionValue(filter.getDefaultValue());
         xml.simpleElement("Default", defaultStr, false);
        
         Iterator<String> iter = values.iterator();
         while(iter.hasNext()) {
             String value = TileLayer.encodeDimensionValue(iter.next());
             xml.simpleElement("Value", value, false);
         }
         xml.endElement("Dimension");
     }
    
     
     private void layerGridSubSets(XMLBuilder xml, TileLayer layer) throws IOException {

        for (String gridSetId : layer.getGridSubsets()) {
            GridSubset gridSubset = layer.getGridSubset(gridSetId);
        
             xml.indentElement("TileMatrixSetLink");
             xml.simpleElement("TileMatrixSet", gridSubset.getName(), true);
            
             if (! gridSubset.fullGridSetCoverage()) {
                String[] levelNames = gridSubset.getGridNames();
                long[][] wmtsLimits = gridSubset.getWMTSCoverages();

                xml.indentElement("TileMatrixSetLimits");
                for (int i = 0; i < levelNames.length; i++) {
                    xml.indentElement("TileMatrixLimits");
                    xml.simpleElement("TileMatrix", levelNames[i], true);
                    xml.simpleElement("MinTileRow", Long.toString(wmtsLimits[i][1]), true);
                    xml.simpleElement("MaxTileRow", Long.toString(wmtsLimits[i][3]), true);
                    xml.simpleElement("MinTileCol", Long.toString(wmtsLimits[i][0]), true);
                    xml.simpleElement("MaxTileCol", Long.toString(wmtsLimits[i][2]), true);
                    xml.endElement();
                }
                xml.endElement();
            }
            xml.endElement("TileMatrixSetLink");
         }
     }
    
     private void tileMatrixSet(XMLBuilder xml, GridSet gridSet) throws IOException {
         xml.indentElement("TileMatrixSet");
         xml.simpleElement("ows:Identifier", gridSet.getName(), true);
         // If the following is not good enough, please get in touch and we will try to fix it :)
         xml.simpleElement("ows:SupportedCRS", "urn:ogc:def:crs:EPSG::"+gridSet.getSrs().getNumber(), true);
         // TODO detect these str.append("    <WellKnownScaleSet>urn:ogc:def:wkss:GlobalCRS84Pixel</WellKnownScaleSet>\n");
         Grid[] grids = gridSet.getGridLevels();
         for(int i=0; i<grids.length; i++) {
             double[] tlCoordinates = gridSet.getOrderedTopLeftCorner(i);
             tileMatrix(xml, grids[i], tlCoordinates, gridSet.getTileWidth(), gridSet.getTileHeight(), gridSet.isScaleWarning());
         }
         xml.endElement("TileMatrixSet");
     }
    
     private void tileMatrix(XMLBuilder xml, Grid grid, double[] tlCoordinates, int tileWidth, int tileHeight, boolean scaleWarning) throws IOException {
         xml.indentElement("TileMatrix");
         if(scaleWarning) {
             xml.simpleElement("ows:Abstract", "The grid was not well-defined, the scale therefore assumes 1m per map unit.", true);
         }
         xml.simpleElement("ows:Identifier", grid.getName(), true);
         xml.simpleElement("ScaleDenominator", Double.toString(grid.getScaleDenominator()), true);
         xml.indentElement("TopLeftCorner")
             .text(Double.toString(tlCoordinates[0]))
             .text(" ")
             .text(Double.toString(tlCoordinates[1]))
             .endElement();
         xml.simpleElement("TileWidth", Integer.toString(tileWidth), true);
         xml.simpleElement("TileHeight", Integer.toString(tileHeight), true);
         xml.simpleElement("MatrixWidth", Long.toString(grid.getNumTilesWide()), true);
         xml.simpleElement("MatrixHeight", Long.toString(grid.getNumTilesHigh()), true);
         xml.endElement("TileMatrix");
     }
    
     private void appendTag(XMLBuilder xml, String tagName, String value, String defaultValue) throws IOException {
         if(value == null) {
             if(defaultValue == null) return;
             else value = defaultValue;
         }
         xml.simpleElement(tagName, value, true);
     }
}
TOP

Related Classes of org.geowebcache.service.wmts.WMTSGetCapabilities

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.