Package org.locationtech.udig.tool.info.internal

Source Code of org.locationtech.udig.tool.info.internal.WMSDescribeLayer

/*
*    uDig - User Friendly Desktop Internet GIS client
*    http://udig.refractions.net
*    (C) 2012, Refractions Research Inc.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* (http://www.eclipse.org/legal/epl-v10.html), and the Refractions BSD
* License v1.0 (http://udig.refractions.net/files/bsd3-v10.html).
*/
package org.locationtech.udig.tool.info.internal;

import java.awt.Point;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.locationtech.udig.project.ILayer;
import org.locationtech.udig.project.IMap;
import org.locationtech.udig.project.render.ICompositeRenderContext;
import org.locationtech.udig.project.render.IRenderContext;
import org.locationtech.udig.render.internal.wms.basic.BasicWMSRenderer2;
import org.locationtech.udig.style.wms.WMSStyleContent;
import org.locationtech.udig.tool.info.InfoPlugin;
import org.locationtech.udig.tool.info.LayerPointInfo;

import org.eclipse.core.runtime.IProgressMonitor;
import org.geotools.data.ows.Layer;
import org.geotools.data.ows.StyleImpl;
import org.geotools.data.wms.WebMapServer;
import org.geotools.data.wms.request.GetFeatureInfoRequest;
import org.geotools.data.wms.request.GetMapRequest;
import org.geotools.data.wms.response.GetFeatureInfoResponse;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.referencing.CRS;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.opengis.metadata.Identifier;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.NoSuchAuthorityCodeException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.xml.sax.SAXException;

import com.vividsolutions.jts.geom.Envelope;

public class WMSDescribeLayer {
   
    /** Figures out the mapping from wms layers to udig layers */
    private Map<Layer, ILayer> getLayerMap( ICompositeRenderContext composite, IProgressMonitor monitor ) throws IOException {
        Map<Layer, ILayer> mapping=new HashMap<Layer, ILayer>();
        for( IRenderContext context: composite.getContexts() ) {
            ILayer layer = context.getLayer();
            if( context.getLayer().isVisible()
                //&& layer.isApplicable("information" )
                ) {               
                Layer wmslayer = layer.getResource( Layer.class, monitor );
                mapping.put( wmslayer, layer );
            }
        }
        return mapping;
    }
   
    public WebMapServer getWMS( ICompositeRenderContext context, IProgressMonitor monitor ) throws IOException {
        return context.getLayer().getResource(WebMapServer.class, monitor );
    }
   
    /** Get list of applicable wms layers from composite */
    private List<Layer> getLayerList(ICompositeRenderContext composite) throws IOException {
        List<Layer> layers = new ArrayList<Layer>();
        for( IRenderContext context: composite.getContexts()) {
            ILayer layer = context.getLayer();
            if( layer.isVisible()
                // && layer.isApplicable("information")
                    ) {
                Layer wmslayer = layer.getResource( org.geotools.data.ows.Layer.class, null );               
                layers.add( wmslayer );
            }           
        }   
        return layers;
    }
   
    /**
     * Implementation is forgiving codes must be in uppercase etc ...
     *
     * @param crs CoordinateReferenceSystem
     * @param codes Set of valid vodes
     *
     * @return Code common to both or null
     */
    private static String commonCode( CoordinateReferenceSystem crs, Set<String> codes ) {       
        // First pass based on string identity
        //
        Set<String> crsCodes = new HashSet<String>();       
        for( Identifier id : crs.getIdentifiers() ) {
            String code = id.toString();
            if( codes.contains( code ) ) return code;
            crsCodes.add( code );
        }
        // Second pass based on CoordinateReferenceSystem equality
        for( String code : codes ) {
            try {              
                CoordinateReferenceSystem check = CRS.decode( code );
                if( crs.equals( check )) {
                    // note we are trusting the code of the matched crs
                    // (because if the id provided by crs worked we would
                    // not get this far
                    //
                    return check.getIdentifiers().iterator().next().getCode();
                }               
            } catch (NoSuchAuthorityCodeException e) {
                // could not understand code
            } catch (FactoryException e) {
                // could not understand code               
            }
        }
        // last pass do the power set lookup based on id
        //
        for( String code : codes ) {
            try {              
                CoordinateReferenceSystem check = CRS.decode( code );
                for( Identifier checkId : check.getIdentifiers() ) {
                    String checkCode = checkId.toString();
                    if( crsCodes.contains( checkCode ) ) {
                        return code;
                    }                   
                }               
            } catch (NoSuchAuthorityCodeException e) {
                // could not understand code
            } catch (FactoryException e) {
                // could not understand code
            }
        }       
        return null;
    }
   
    @SuppressWarnings("unchecked")
    public static List<LayerPointInfo> info( ILayer layer, ReferencedEnvelope bbox ) throws IOException {
        LayerPointInfo info = info2( layer, bbox );
        if( info == null ) return Collections.EMPTY_LIST;
       
        return Collections.singletonList( info );       
    }
   
    /**
     * Aquire info for the provided bbox
     *
     * @param layer Must be associated with a wms layer
     * @param bbox
     * @return LayerPointInfo object or null if information is unavailable.
     * @throws IOException
     * @throws IOException if Response could not be understood
     *
     * TODO: possible problem with client side reprojection - may need to
     * properly reproject the center point that was clicked on
     *
     * TODO: this requires some testing
     */
    public static LayerPointInfo info2( ILayer layer, ReferencedEnvelope query ) throws IOException {       

    Envelope reprojected = null;
    IMap map = layer.getMap();
        try {
            reprojected = query.transform(map.getViewportModel().getCRS(), true);
        } catch (Exception e) {
            InfoPlugin.log("", e); //$NON-NLS-1$
            return null;
        }
        Point centre = map.getViewportModel().worldToPixel(reprojected.centre());

        Envelope sanebbox = map.getViewportModel().getBounds();
        ReferencedEnvelope bbox = new ReferencedEnvelope(sanebbox, query.getCoordinateReferenceSystem());
   
      Layer wmslayer;
        wmslayer = layer.getResource( Layer.class, null );
       
        if( wmslayer == null ) {
            throw new IllegalArgumentException("Provided layer is not a WMS layer" ); //$NON-NLS-1$
        }
        if( !wmslayer.isQueryable() ){
            return null;
        }
        // TODO: Fix wmslayer so we can ask who its "source" is.
        final WebMapServer wms = layer.getResource( WebMapServer.class, null );       
        if( wms == null ) {
            throw new IllegalArgumentException("Provided layer cannot resolve to a wms" ); //$NON-NLS-1$
        }
        String desiredFormat = desiredInfoFormat( wms );               
        if( desiredFormat == null ){
            return null;
        }
        GetMapRequest getmap = wms.createGetMapRequest();       
        String code = BasicWMSRenderer2.findRequestCRS(
                Collections.singletonList( wmslayer ), map.getViewportModel().getCRS(), map );

        getmap.setBBox( bbox );
        String srs = CRS.toSRS(bbox.getCoordinateReferenceSystem() );
        //getmap.setSRS( code != null ? code : srs );
       
        getmap.setProperty( GetMapRequest.LAYERS, wmslayer.getName() );
        int width = map.getRenderManager().getMapDisplay().getWidth();
        int height = map.getRenderManager().getMapDisplay().getHeight();
        getmap.setDimensions(width, height);
        //getmap.setSRS(code);
       
        List<String> formats = wms.getCapabilities().getRequest().getGetMap().getFormats();
        if (formats.contains("image/png")) { //$NON-NLS-1$
            getmap.setProperty(GetMapRequest.FORMAT, "image/png"); //$NON-NLS-1$
        } else if (formats.contains("image/gif")) { //$NON-NLS-1$
            getmap.setProperty(GetMapRequest.FORMAT, "image/gif"); //$NON-NLS-1$
        } else if (formats.contains("image/jpeg")) { //$NON-NLS-1$
            getmap.setProperty(GetMapRequest.FORMAT, "image/jpeg"); //$NON-NLS-1$
        } else if (formats.contains("image/bmp")) { //$NON-NLS-1$
            getmap.setProperty(GetMapRequest.FORMAT, "image/bmp"); //$NON-NLS-1$
        }
       
        StyleImpl wmsStyle = (StyleImpl) layer.getStyleBlackboard().get(WMSStyleContent.WMSSTYLE);
        if (wmsStyle != null) {
            getmap.setProperty(GetMapRequest.STYLES, wmsStyle.getName());
        }
        else {
            // supply an empty String as per UDIG-1507
            getmap.setProperty(GetMapRequest.STYLES, "");
        }
       
        final GetFeatureInfoRequest request = wms.createGetFeatureInfoRequest( getmap );                      
        request.setInfoFormat( desiredFormat );
        request.setQueryPoint( centre.x, centre.y );               
        request.setQueryLayers( Collections.singleton( wmslayer ) );
               
        LayerPointInfo info = new LayerPointInfo( layer ){
                   
            private GetFeatureInfoResponse response;
            /** Lazy request */
                   
            protected GetFeatureInfoResponse getResponse() throws IOException {
                if (this.response == null) {
                    try {
                        System.out.println(request.getFinalURL());
                        this.response = wms.issueRequest( request );
                    } catch (SAXException e) {
                        throw new IOException(
                                "Unable to parse the returned response from the server. Reason unknown."); //$NON-NLS-1$
                    }
                }
                return this.response;
            }
            public URL getRequestURL() {
                return request.getFinalURL();
            }
            /** Only acquire the value if needed */
            public String getMimeType() {
                try {
                    return getResponse().getContentType();
                } catch (IOException e) {
                    return null; // unavailable
                }
            }
            /** Only acquire the value if needed */
            public Object acquireValue() throws IOException {
                // final String CONTENT_TYPE = response.getContentType();
                // if ("text/plain".equals( CONTENT_TYPE ) ||
                // "text/html".equals( CONTENT_TYPE )) {
                String result = ""; //$NON-NLS-1$
                InputStream input = getResponse().getInputStream();
                BufferedReader reader = new BufferedReader(new InputStreamReader(input));
                String line = null;
                while( (line = reader.readLine()) != null ) {
                    result = result + line;
                }
                reader.close();
                input.close();
                return result;
                // } else if ( LayerPointInfo.GML.equals( CONTENT_TYPE ) ) {
                // // parse w/ GML parser from WFS !
                // return Collections.singletonList(new LayerPointInfo( getContext().getLayer() ) {
                // protected Object acquireValue() {
                // return null; // should perform lazy parsing here
                // }
                // public String getMimeType() {
                // return LayerPointInfo.GML;
                // }
                // });
                // }
                // else {
                // return Collections.EMPTY_LIST;
                // }
            }
        };
        return info;
    }

    /**
     * This assumes the same formats are available for all layers? Hope that is a good assumption.
     *
     * @param wms
     * @return MIME type of prefered content, or null if we can't get our info on
     */
    private static String desiredInfoFormat( WebMapServer wms ) {
        List formats  =
            wms.getCapabilities().getRequest().getGetFeatureInfo().getFormats();
       
        String desiredFormat;
     
        if (formats.contains("text/html")) { //$NON-NLS-1$
            desiredFormat = "text/html"; //$NON-NLS-1$
        } else if (formats.contains("text/plain")) { //$NON-NLS-1$
            desiredFormat = "text/plain"; //$NON-NLS-1$
        } else if (formats.contains(LayerPointInfo.GML)) {
            desiredFormat = LayerPointInfo.GML;
        } else {
            desiredFormat = null;
        }
        return desiredFormat;
    }
}
TOP

Related Classes of org.locationtech.udig.tool.info.internal.WMSDescribeLayer

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.