//$Header$ /*---------------- FILE HEADER ------------------------------------------ This file is part of deegree. Copyright (C) 2001-2006 by: EXSE, Department of Geography, University of Bonn http://www.giub.uni-bonn.de/deegree/ lat/lon GmbH http://www.lat-lon.de This library 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 2.1 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Contact: Andreas Poth lat/lon GmbH Aennchenstr. 19 53177 Bonn Germany E-Mail: poth@lat-lon.de Prof. Dr. Klaus Greve Department of Geography University of Bonn Meckenheimer Allee 166 53115 Bonn Germany E-Mail: greve@giub.uni-bonn.de ---------------------------------------------------------------------------*/ package org.deegree.portal.portlet.modules.map.actions.portlets; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import org.apache.jetspeed.portal.Portlet; import org.apache.jetspeed.portal.PortletException; import org.deegree.datatypes.QualifiedName; import org.deegree.framework.log.ILogger; import org.deegree.framework.log.LoggerFactory; import org.deegree.framework.util.StringTools; import org.deegree.model.spatialschema.Envelope; import org.deegree.model.spatialschema.GeometryFactory; import org.deegree.model.spatialschema.Point; import org.deegree.portal.PortalException; import org.deegree.portal.context.ContextException; import org.deegree.portal.context.DefaultMapModelAccess; import org.deegree.portal.context.Layer; import org.deegree.portal.context.LayerList; import org.deegree.portal.context.MapModelAccess; import org.deegree.portal.context.Server; import org.deegree.portal.context.ViewContext; import org.deegree.portal.portlet.modules.actions.AbstractPortletPerform; import org.deegree.portal.portlet.modules.actions.IGeoPortalPortletPerform; /** * * * @version $Revision$ * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a> * @author last edited by: $Author$ * * @version 1.0. $Revision$, $Date$ * * @since 2.0 */ public class MapWindowPortletPerform extends IGeoPortalPortletPerform { private static final ILogger LOG = LoggerFactory.getLogger( MapWindowPortletPerform.class ); // init parameter of the portlet static String INIT_INITAL_GETMAP = "initialGETMAP"; static String INIT_PANBUTTONS = "panButtons"; static String INIT_HOMEBBOX = "homeBoundingBox"; static String INIT_SCALEMAPTOPORTLETSIZE = "scaleMapToPortletSize"; static String INIT_FEATUREINFOTARGETPORTLET = "featureInfoTargetPortlet"; // known request parameter static String PARAM_WIDTH = "WIDTH"; static String PARAM_HEIGHT = "HEIGHT"; static String PARAM_CLICKPOINT = "CLICKPOINT"; static String PARAM_MAPPOINT = "MAPPOINT"; static String PARAM_FACTOR = "FACTOR"; static String PARAM_PANDIRECTION = "DIRECTIONCODE"; static String PARAM_CURRENTFILAYER = "CURRENTFILAYER"; // session attributes static String SESSION_HISTORY = "HISTORY"; static String SESSION_HISTORYPOSITION = "HISTORYPOSITION"; /** * private constructor * @param request * @param portlet */ MapWindowPortletPerform(HttpServletRequest request, Portlet portlet, ServletContext sc) { super( request, portlet, sc ); } @Override public void buildNormalContext() throws PortalException { super.buildNormalContext(); init(); setBoundingBoxFromBBOXParam(); setMapWindowAttributes(); } /** * initializes the portlet by reading the assigned map context and storing * it into the users session * @throws PortletException */ private void init() { List<Envelope> history = (List<Envelope>)request.getSession().getAttribute( SESSION_HISTORY ); if ( history == null ) { history = new ArrayList( 1000 ); request.getSession().setAttribute( SESSION_HISTORY, history ); request.getSession().setAttribute( SESSION_HISTORYPOSITION, 0 ); } } /** * writes the passed values into the attributes of the passed * @see HttpServletRequest to be read by the JSP page assigned to * the iGeoPortal:MapWindowPortlet * */ private void setAttributes(ArrayList panButtons) { request.setAttribute( "PANBUTTONS", panButtons ); request.setAttribute( "PORTLETID", portlet.getID() ); request.setAttribute( "FEATUREINFOTARGETPORTLET", getInitParam( INIT_FEATUREINFOTARGETPORTLET ) ); } /** * sets all request attributes required by a map from the passed ViewContext * @param vc */ private void setMapWindowAttributes() { String tmp = getInitParam( INIT_PANBUTTONS ); ArrayList pB = new ArrayList(20); if ( tmp != null ) { String[] panButtons = StringTools.toArray( tmp, ",;", true ); List list = Arrays.asList( panButtons ); pB.addAll( list ); } setAttributes( pB ); } /** * sets a new bounding box of the map read from the the request object * passed when initialized an instance of <code>MapWindowPortletPerfom</code> */ void setHomeBoundingbox() { Envelope env = (Envelope)request.getSession().getAttribute( AbstractPortletPerform.SESSION_HOME ); setBoundingBox( env ); } /** * sets a new size of the map read from the request * @throws PortalException */ void setMapSize() throws PortalException { String tmp = (String)parameter.get( PARAM_WIDTH ); if ( tmp == null ) { throw new PortalException( "request does not contain a WIDTH parameter!" ); } int width = Integer.parseInt( tmp ); tmp = request.getParameter( PARAM_HEIGHT ); if ( tmp == null ) { throw new PortalException( "request does not contain a HEIGHT parameter!" ); } int height = Integer.parseInt( tmp ); ViewContext vc = getCurrentViewContext( portlet.getID() ); MapModelAccess mma = new DefaultMapModelAccess( vc ); vc = mma.setMapSize( width, height ); // if the request contains a BBOX parameter the current bounding box // will be updated too setBoundingBox( (String)parameter.get( PARAM_BBOX ) ); setCurrentMapContext( vc, portlet.getID() ); } /** * zooms the current map by a factor and recenters it to the point the * user has clicked to. * * @throws PortalException * @throws ContextException */ void zoom() throws PortalException, ContextException { ViewContext vc = getCurrentViewContext( portlet.getID() ); MapModelAccess mma = new DefaultMapModelAccess( vc ); String tmp = (String)parameter.get( PARAM_FACTOR ); if ( tmp == null ) { throw new PortalException( "FACTOR must be set for zoom operation!" ); } double factor = Double.parseDouble( tmp ); tmp = (String)parameter.get( PARAM_CLICKPOINT ); if ( tmp != null ) { // zoom by pixel coordinates double coords[] = StringTools.toArrayDouble( tmp, "," ); java.awt.Point point = new java.awt.Point( (int)coords[0], (int)coords[1] ); vc = mma.zoom( point, factor ); } else { // zoom by map coordinates tmp = (String)parameter.get( PARAM_MAPPOINT ); if ( tmp == null ) { throw new PortalException( "at least a CLICKPOINT or a MAPPOINT " + "must be defined for zoom operation!" ); } double coords[] = StringTools.toArrayDouble( tmp, "," ); Point point = GeometryFactory.createPoint( coords[0], coords[1], null ); vc = mma.zoom( point, factor ); } setCurrentMapContext( vc, portlet.getID() ); } /** * pan the map with a set factor to one of eight possible directions * * @throws PortalException * @throws ContextException */ void pan() throws PortalException, ContextException { String tmp = (String)parameter.get( PARAM_FACTOR ); if ( tmp == null ) { throw new PortalException( "FACTOR must be set for pan operation!" ); } double factor = Double.parseDouble( tmp ); tmp = (String)parameter.get( PARAM_PANDIRECTION ); if ( tmp == null ) { throw new PortalException( "DIRECTION must be set for pan operation!" ); } boolean isnumber = true; try { Double.parseDouble( tmp ); } catch ( Exception e ) { isnumber = false; } ViewContext vc = getCurrentViewContext( portlet.getID() ); MapModelAccess mma = new DefaultMapModelAccess( vc ); if ( isnumber ) { // use value as direction in degree vc = mma.pan( Double.parseDouble( tmp ), factor ); } else { int dir = 0; if ( tmp.equals( "N" ) ) { dir = MapModelAccess.PAN_NORTH; } else if ( tmp.equals( "NW" ) ) { dir = MapModelAccess.PAN_NORTHWEST; } else if ( tmp.equals( "NE" ) ) { dir = MapModelAccess.PAN_NORTHEAST; } else if ( tmp.equals( "W" ) ) { dir = MapModelAccess.PAN_WEST; } else if ( tmp.equals( "E" ) ) { dir = MapModelAccess.PAN_EAST; } else if ( tmp.equals( "SW" ) ) { dir = MapModelAccess.PAN_SOUTHWEST; } else if ( tmp.equals( "S" ) ) { dir = MapModelAccess.PAN_SOUTH; } else if ( tmp.equals( "SE" ) ) { dir = MapModelAccess.PAN_SOUTHEAST; } else { throw new PortalException( "unknown pan direction: " + tmp ); } vc = mma.pan( dir, factor ); } setCurrentMapContext( vc, portlet.getID() ); } /** * recenters the current map to the point the user has clicked to * @throws PortalException * @throws ContextException */ void recenter() throws PortalException, ContextException { ViewContext vc = getCurrentViewContext( portlet.getID() ); MapModelAccess mma = new DefaultMapModelAccess( vc ); String tmp = (String)parameter.get( PARAM_CLICKPOINT ); if ( tmp != null ) { // zoom by pixel coordinates double coords[] = StringTools.toArrayDouble( tmp, "," ); java.awt.Point point = new java.awt.Point( (int)coords[0], (int)coords[1] ); vc = mma.recenterMap( point ); } else { // zoom by map coordinates tmp = (String)parameter.get( PARAM_MAPPOINT ); if ( tmp == null ) { throw new PortalException( "at least a CLICKPOINT or a MAPPOINT " + "must be defined for zoom operation!" ); } double coords[] = StringTools.toArrayDouble( tmp, "," ); Point point = GeometryFactory.createPoint( coords[0], coords[1], null ); vc = mma.recenterMap( point ); } setCurrentMapContext( vc, portlet.getID() ); } /** * sets the name of the the layers that are activated for feature * info requests in the uses WMC */ void setCurrentFILayer() { String tmp = (String)parameter.get( PARAM_CURRENTFILAYER ); String[] fiLayer = StringTools.toArray( tmp, ",", false ); if ( fiLayer != null ) { List list = Arrays.asList( fiLayer ); list = new ArrayList( list ); ViewContext vc = getCurrentViewContext( portlet.getID() ); LayerList layerList = vc.getLayerList(); Layer[] layers = layerList.getLayers(); for (int i = 0; i < layers.length; i++) { try { if ( list.contains( layers[i].getName() ) ) { layers[i].getExtension().setSelectedForQuery( true ); } else { layers[i].getExtension().setSelectedForQuery( false ); } } catch ( Exception e ) { // TODO: handle exception LOG.logError( e.getMessage(), e ); } } } } /** * moves the layer passed through by the HTTP request up for one position * * @throws PortalException */ void moveUp() throws PortalException { ViewContext vc = getCurrentViewContext( portlet.getID() ); String tmp = (String)parameter.get( PARAM_LAYER ); String[] s = StringTools.toArray( tmp, "|", false ); LOG.logDebug( StringTools.concat( 150, "moving layer: ", s[0], " map model: ", portlet.getID(), " down" ) ); MapModelAccess mma = new DefaultMapModelAccess( vc ); try { vc = mma.swapLayers( new QualifiedName( s[0] ), new URL( s[1] ), "OGC:WMS", true ); } catch ( MalformedURLException e ) { throw new PortalException( "no valid URL", e ); } setCurrentMapContext( vc, portlet.getID() ); } /** * moves the layer passed through by the HTTP request down for one position * * @throws PortalException */ void moveDown() throws PortalException { ; ViewContext vc = getCurrentViewContext( portlet.getID() ); String tmp = (String)parameter.get( PARAM_LAYER ); String[] s = StringTools.toArray( tmp, "|", false ); LOG.logDebug( StringTools.concat( 150, "moving layer: ", s[0], " map model: ", portlet.getID(), " down" ) ); MapModelAccess mma = new DefaultMapModelAccess( vc ); try { vc = mma.swapLayers( new QualifiedName( s[0] ), new URL( s[1] ), "OGC:WMS", false ); } catch ( MalformedURLException e ) { throw new PortalException( "no valid URL", e ); } setCurrentMapContext( vc, portlet.getID() ); } /** * move the map view (just bounding box) to the next entry in the history */ void doHistoryforward() { List<Envelope> history = (List<Envelope>)request.getSession().getAttribute( SESSION_HISTORY ); int p = (Integer)request.getSession().getAttribute( SESSION_HISTORYPOSITION ); LOG.logDebug( "stepping forward in hinstory to position: " + (p+1) ); if ( p < history.size() - 1) { Envelope env = history.get( ++p ); setBoundingBox( env ); request.getSession().setAttribute( SESSION_HISTORYPOSITION, p ); } } /** * move the map view (just bounding box) to the previous entry in the history */ void doHistorybackward() { List<Envelope> history = (List<Envelope>)request.getSession().getAttribute( SESSION_HISTORY ); int p = (Integer)request.getSession().getAttribute( SESSION_HISTORYPOSITION ); LOG.logDebug( "stepping backward in hinstory to position: " + (p-1) ); if ( p > 0 ) { Envelope env = history.get( --p ); setBoundingBox( env ); request.getSession().setAttribute( SESSION_HISTORYPOSITION, p ); } } /** * adds a new OWS to one of the WMC available a MapWindow * TODO */ void doAddows() { System.out.println( parameter ); ViewContext vc = getCurrentViewContext( portlet.getID() ); Layer layer = vc.getLayerList().getLayers()[0]; parameter.get( "FORMAT" ); // TODO } /** * removes an OWS from a MapWindow * */ void doRemoveows() { System.out.println( parameter ); String title = (String)parameter.get( "TITLE" ); ViewContext vc = getCurrentViewContext( portlet.getID() ); Layer[] layers = vc.getLayerList().getLayers(); for ( int i = 0; i < layers.length; i++ ) { Server server = layers[i].getServer(); if ( server.getTitle().equals( title ) ) { vc.getLayerList().removeLayer( layers[i].getName() ); } } } } /* ******************************************************************** Changes to this class. What the people have been up to: $Log$ Revision 1.27 2006/10/12 15:46:19 poth adaption required to avoid allocating larger amounts of memory for each user session when using several WMC documents Revision 1.26 2006/08/29 19:54:13 poth footer corrected Revision 1.25 2006/07/06 11:41:49 poth bug fix - moving layer up/down using more than on map context Revision 1.24 2006/07/06 09:59:04 poth bug fix - settig correct ID of current map context using more than one WMC (SelectWMCPortlet) Revision 1.23 2006/06/09 07:25:05 poth *** empty log message *** Revision 1.22 2006/06/08 11:33:30 poth *** empty log message *** Revision 1.21 2006/06/07 12:19:38 poth *** empty log message *** Revision 1.20 2006/06/06 19:49:25 poth handling of mapmodel changed - it now will be available for each MapWindowPortlet through the session Revision 1.19 2006/05/13 16:53:52 poth *** empty log message *** Revision 1.18 2006/05/12 14:36:28 poth *** empty log message *** Revision 1.17 2006/04/06 20:25:21 poth *** empty log message *** Revision 1.16 2006/03/30 21:20:23 poth *** empty log message *** Revision 1.15 2006/03/22 13:22:14 poth *** empty log message *** Revision 1.14 2006/03/04 20:36:18 poth *** empty log message *** Revision 1.13 2006/02/28 08:47:38 poth *** empty log message *** Revision 1.12 2006/02/27 21:58:57 poth *** empty log message *** Revision 1.11 2006/02/20 09:28:15 poth *** empty log message *** Revision 1.10 2006/02/14 16:05:05 poth *** empty log message *** Revision 1.9 2006/02/13 14:13:05 poth *** empty log message *** Revision 1.8 2006/02/10 12:14:08 poth *** empty log message *** Revision 1.7 2006/02/10 11:48:50 poth *** empty log message *** Revision 1.6 2006/02/07 19:52:44 poth *** empty log message *** Revision 1.5 2006/02/07 17:10:18 poth *** empty log message *** Revision 1.4 2006/02/07 07:58:56 poth history function implemented Revision 1.3 2006/02/06 21:46:19 poth *** empty log message *** Revision 1.2 2006/02/05 20:33:09 poth *** empty log message *** Revision 1.1 2006/02/05 09:30:11 poth *** empty log message *** Revision 1.10 2006/01/09 07:47:09 ap *** empty log message *** ********************************************************************** */