//$HeadURL$ /*---------------------------------------------------------------------------- This file is part of deegree, http://deegree.org/ Copyright (C) 2001-2009 by: - Department of Geography, University of Bonn - and - lat/lon GmbH - 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 information: lat/lon GmbH Aennchenstr. 19, 53177 Bonn Germany http://lat-lon.de/ Department of Geography, University of Bonn Prof. Dr. Klaus Greve Postfach 1147, 53001 Bonn Germany http://www.geographie.uni-bonn.de/deegree/ e-mail: info@deegree.org ----------------------------------------------------------------------------*/ package org.deegree.igeo.modules; import java.awt.Container; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.UUID; import org.deegree.framework.log.ILogger; import org.deegree.framework.log.LoggerFactory; import org.deegree.framework.util.GeometryUtils; import org.deegree.framework.util.Pair; import org.deegree.igeo.ApplicationContainer; import org.deegree.igeo.commands.UnselectFeaturesCommand; import org.deegree.igeo.commands.digitize.CuttingPolygonHoleCommand; import org.deegree.igeo.commands.digitize.GroupFeatureCommand; import org.deegree.igeo.commands.digitize.InsertFeatureCommand; import org.deegree.igeo.commands.digitize.MoveFeatureCommand; import org.deegree.igeo.commands.digitize.UngroupFeatureCommand; import org.deegree.igeo.commands.digitize.UniteGeometriesCommand; import org.deegree.igeo.dataadapter.DataAccessAdapter; import org.deegree.igeo.dataadapter.FeatureAdapter; import org.deegree.igeo.i18n.Messages; import org.deegree.igeo.mapmodel.Layer; import org.deegree.igeo.mapmodel.MapModel; import org.deegree.igeo.state.mapstate.EditState; import org.deegree.igeo.state.mapstate.MapTool; import org.deegree.igeo.state.mapstate.ToolState; import org.deegree.igeo.views.DialogFactory; import org.deegree.kernel.Command; import org.deegree.kernel.CommandList; import org.deegree.model.feature.Feature; import org.deegree.model.feature.FeatureCollection; import org.deegree.model.feature.FeatureFactory; import org.deegree.model.feature.FeatureProperty; import org.deegree.model.feature.schema.GeometryPropertyType; import org.deegree.model.feature.schema.PropertyType; import org.deegree.model.spatialschema.Curve; import org.deegree.model.spatialschema.GeometryFactory; import org.deegree.model.spatialschema.MultiCurve; import org.deegree.model.spatialschema.MultiPoint; import org.deegree.model.spatialschema.MultiSurface; import org.deegree.model.spatialschema.Point; import org.deegree.model.spatialschema.Surface; /** * Class containing methods for handling actions triggerd by {@link DigitizerModule} * * @author <a href="mailto:name@deegree.org">Andreas Poth</a> * @author last edited by: $Author$ * * @version $Revision$, $Date$ */ public class DigitizeActionHandler { private static ILogger LOG = LoggerFactory.getLogger( DigitizeActionHandler.class ); private ApplicationContainer<Container> appContainer; private DigitizerModule<Container> owner; /** * * @param owner */ DigitizeActionHandler( DigitizerModule<Container> owner ) { this.appContainer = owner.appContainer; this.owner = owner; } /** * * @param selection * action layer(s) are selected for * @return {@link Layer} */ private Layer getSelectedLayer( String selection ) { MapModel mm = appContainer.getMapModel( null ); List<Layer> layList = mm.getLayersSelectedForAction( selection ); if ( layList.size() > 0 ) { return layList.get( 0 ); } return null; } /** * deletes selected features * */ protected void deleteFeature() { Layer layer = getSelectedLayer( MapModel.SELECTION_EDITING ); List<DataAccessAdapter> dataAccess = layer.getDataAccess(); DefaultMapModule<?> mapModule = owner.getAssignedMapModule(); ToolState ts = mapModule.getMapTool().getState(); setDeleteFeatureState(); // In this case a feature or a number of features has been changed. Because all // changes will be done to a copy of a feature to underlying data access layer // must be updated explicitly. EditState es = (EditState) mapModule.getMapTool().getState(); try { Command command = es.createCommand( dataAccess.get( 0 ), layer.getSelectedFeatures() ); appContainer.getCommandProcessor().executeSychronously( command, true ); } catch ( Exception e ) { LOG.logError( e.getMessage(), e ); DialogFactory.openWarningDialog( appContainer.getViewPlatform(), null, Messages.getMessage( Locale.getDefault(), "$MD10289", e.getMessage() ), Messages.getMessage( Locale.getDefault(), "$MD10290" ) ); } // reset previous state mapModule.getMapTool().setState( ts ); layer.unselectAllFeatures(); owner.getDigitizerPanel().resetAll(); owner.getEditFeature().setFeature( layer, FeatureFactory.createFeatureCollection( "ID_", 1 ) ); } /** * * @param parameter * values contains IDs of features to be deleted */ protected void deleteFeature( Map<String, Object> parameter ) { Layer layer = getSelectedLayer( MapModel.SELECTION_EDITING ); List<DataAccessAdapter> dataAccess = layer.getDataAccess(); FeatureCollection fc = FeatureFactory.createFeatureCollection( "UUID_" + UUID.randomUUID().toString(), parameter.size() ); Iterator<Object> iter = parameter.values().iterator(); while ( iter.hasNext() ) { String id = (String) iter.next(); Feature feature = ( (FeatureAdapter) dataAccess.get( 0 ) ).getFeatureCollection().getFeature( id ); fc.add( feature ); } DefaultMapModule<?> mapModule = owner.getAssignedMapModule(); ToolState ts = mapModule.getMapTool().getState(); setDeleteFeatureState(); // In this case a feature or a number of features has been changed. Because all // changes will be done to a copy of a feature to underlying data access layer // must be updated explicitly. EditState es = (EditState) mapModule.getMapTool().getState(); try { Command command = es.createCommand( dataAccess.get( 0 ), fc ); appContainer.getCommandProcessor().executeSychronously( command, true ); } catch ( Exception e ) { LOG.logError( e.getMessage(), e ); DialogFactory.openWarningDialog( appContainer.getViewPlatform(), null, Messages.getMessage( Locale.getDefault(), "$MD10289", e.getMessage() ), Messages.getMessage( Locale.getDefault(), "$MD10290" ) ); } // reset previous state mapModule.getMapTool().setState( ts ); } /** * Puts the mapModule associated into the DeleteFeatureState. * * @returns the CreateFeatureState object */ private void setDeleteFeatureState() { DefaultMapModule<?> mapModule = owner.getAssignedMapModule(); MapTool<?> mapTool = mapModule.getMapTool(); mapTool.setEditState(); EditState editState = (EditState) mapTool.getState(); editState.setDeleteFeatureState(); } /** * groups selected polygons into a MultiSurface * */ protected void groupPolygons() { groupFeatures( Surface.class, MultiSurface.class ); } /** * groups selected lines into a MultiCurve * */ protected void groupLines() { groupFeatures( Curve.class, MultiCurve.class ); } /** * groups selected points into a MultiPoint * */ protected void groupPoints() { groupFeatures( Point.class, MultiPoint.class ); } private void groupFeatures( Class<?>... classes ) { MapModel mm = appContainer.getMapModel( null ); List<Layer> layList = mm.getLayersSelectedForAction( MapModel.SELECTION_EDITING ); Layer layer = layList.get( 0 ); String fid = owner.getEditFeature().getCurrentFeature().getId(); List<DataAccessAdapter> dataAccess = layer.getDataAccess(); FeatureCollection tmp = layer.getSelectedFeatures(); if ( tmp.size() < 2 ) { DialogFactory.openWarningDialog( appContainer.getViewPlatform(), null, Messages.getMessage( Locale.getDefault(), "$MD10286" ), Messages.getMessage( Locale.getDefault(), "$MD10285" ) ); return; } for ( DataAccessAdapter adapter : dataAccess ) { Command command = new GroupFeatureCommand( adapter, tmp, null, fid, classes ); try { appContainer.getCommandProcessor().executeSychronously( command, true ); } catch ( Exception e ) { LOG.logError( e.getMessage(), e ); DialogFactory.openWarningDialog( appContainer.getViewPlatform(), null, e.getMessage(), Messages.getMessage( Locale.getDefault(), "$MD10285" ) ); } FeatureCollection fc = FeatureFactory.createFeatureCollection( UUID.randomUUID().toString(), 1 ); fc.add( (Feature) command.getResult() ); owner.getEditFeature().setFeature( layer, fc ); owner.getDigitizerPanel().setSelectedFeatures( fc ); owner.getDigitizerPanel().invalidate(); owner.getDigitizerPanel().repaint(); } } /** * ungroups a multi polygon; for each polygon one feature will be created * */ protected void ungroupMultiPolygon() { ungroupFeatures( ); } /** * ungroups a multi curve/linestring; for each curve/linestring one feature will be created * */ protected void ungroupMultiCurve() { ungroupFeatures( ); } /** * ungroups a multi point; for each point one feature will be created * */ protected void ungroupMultiPoint() { ungroupFeatures( ); } private void ungroupFeatures() { MapModel mm = appContainer.getMapModel( null ); List<Layer> layList = mm.getLayersSelectedForAction( MapModel.SELECTION_EDITING ); Layer layer = layList.get( 0 ); List<DataAccessAdapter> dataAccess = layer.getDataAccess(); FeatureCollection tmp = layer.getSelectedFeatures(); if ( tmp.size() != 1 ) { DialogFactory.openWarningDialog( appContainer.getViewPlatform(), null, Messages.getMessage( Locale.getDefault(), "$MD10288" ), Messages.getMessage( Locale.getDefault(), "$MD10287" ) ); return; } for ( DataAccessAdapter adapter : dataAccess ) { Command command = new UngroupFeatureCommand( adapter, tmp.getFeature( 0 ), null ); try { appContainer.getCommandProcessor().executeSychronously( command, true ); } catch ( Exception e ) { LOG.logError( e.getMessage(), e ); DialogFactory.openWarningDialog( appContainer.getViewPlatform(), null, e.getMessage(), Messages.getMessage( Locale.getDefault(), "$MD10285" ) ); } FeatureCollection fc = FeatureFactory.createFeatureCollection( UUID.randomUUID().toString(), 1 ); fc = (FeatureCollection) command.getResult(); owner.getEditFeature().setFeature( layer, fc ); owner.getDigitizerPanel().setSelectedFeatures( fc ); owner.getDigitizerPanel().invalidate(); owner.getDigitizerPanel().repaint(); } } /** * unites two or more polygons into one. The result is one feature having one polygon as geometry. This is the * difference groupXXX where the result will be a MultiGeometry */ protected void uniteGeometries() { MapModel mm = appContainer.getMapModel( null ); List<Layer> layList = mm.getLayersSelectedForAction( MapModel.SELECTION_EDITING ); Layer layer = layList.get( 0 ); String fid = owner.getEditFeature().getCurrentFeature().getId(); List<DataAccessAdapter> dataAccess = layer.getDataAccess(); FeatureCollection tmp = layer.getSelectedFeatures(); if ( tmp.size() < 2 ) { DialogFactory.openWarningDialog( appContainer.getViewPlatform(), null, Messages.getMessage( Locale.getDefault(), "$MD10535" ), Messages.getMessage( Locale.getDefault(), "$MD10536" ) ); return; } for ( DataAccessAdapter adapter : dataAccess ) { Command command1 = new UniteGeometriesCommand( adapter, tmp, null, fid ); Command command2 = new UnselectFeaturesCommand( layer, false ); CommandList command = new CommandList(); command.add( command1 ); command.add( command2 ); try { appContainer.getCommandProcessor().executeSychronously( command, true ); } catch ( Exception e ) { LOG.logError( e.getMessage(), e ); DialogFactory.openWarningDialog( appContainer.getViewPlatform(), null, e.getMessage(), Messages.getMessage( Locale.getDefault(), "$MD10537" ) ); } FeatureCollection fc = FeatureFactory.createFeatureCollection( UUID.randomUUID().toString(), 1 ); fc.add( (Feature) command1.getResult() ); owner.getEditFeature().setFeature( layer, fc ); owner.getDigitizerPanel().invalidate(); owner.getDigitizerPanel().repaint(); } } /** * * @param parameter */ protected void createParallel( Map<String, Object> parameter ) { double distance = ( (Number) parameter.get( "distance" ) ).doubleValue(); Layer layer = appContainer.getMapModel( null ).getLayersSelectedForAction( MapModel.SELECTION_EDITING ).get( 0 ); FeatureCollection fc = layer.getSelectedFeatures(); List<Feature> list = new ArrayList<Feature>( fc.size() * 2 ); Iterator<Feature> iter = fc.iterator(); while ( iter.hasNext() ) { Feature feature = (Feature) iter.next(); if ( (Boolean) parameter.get( "right" ) ) { Feature tmp = createParallelFeature( distance, feature ); if ( tmp != null ) { list.add( tmp ); } } if ( (Boolean) parameter.get( "left" ) ) { Feature tmp = createParallelFeature( -1 * distance, feature ); if ( tmp != null ) { list.add( tmp ); } } } if ( list.size() > 0 ) { Feature[] features = list.toArray( new Feature[list.size()] ); InsertFeatureCommand ifc = new InsertFeatureCommand( layer.getDataAccess().get( 0 ), features ); try { appContainer.getCommandProcessor().executeSychronously( ifc, true ); } catch ( Exception e ) { LOG.logError( e.getMessage(), e ); DialogFactory.openErrorDialog( appContainer.getViewPlatform(), null, Messages.get( "$MD11236" ), Messages.get( "$MD11237" ), e ); } } } private Feature createParallelFeature( double distance, Feature feature ) { try { feature = (Feature) feature.cloneDeep(); FeatureProperty[] geomProps = collectGeometryProperties( feature ); for ( int i = 0; i < geomProps.length; i++ ) { if ( geomProps[i].getValue() instanceof Curve ) { Curve curve = (Curve) geomProps[i].getValue(); geomProps[i].setValue( GeometryUtils.createCurveParallel( distance, curve ) ); feature.setProperty( geomProps[i], i ); } else if ( geomProps[i].getValue() instanceof MultiCurve ) { Curve[] curves = ( (MultiCurve) geomProps[i].getValue() ).getAllCurves(); for ( int j = 0; j < curves.length; j++ ) { curves[j] = GeometryUtils.createCurveParallel( distance, curves[j] ); geomProps[i].setValue( GeometryFactory.createMultiCurve( curves ) ); feature.setProperty( geomProps[i], i ); } } else { LOG.logWarning( "just for curves and multi curves parallels can be computed" ); } } } catch ( Exception e ) { LOG.logError( e.getMessage(), e ); feature = null; DialogFactory.openErrorDialog( appContainer.getViewPlatform(), null, Messages.get( "$MD11262" ), Messages.get( "$MD11263" ), e ); } return feature; } protected FeatureProperty[] collectGeometryProperties( Feature feature ) { List<FeatureProperty> list = new ArrayList<FeatureProperty>( 10 ); PropertyType[] pt = feature.getFeatureType().getProperties(); for ( PropertyType type : pt ) { if ( type instanceof GeometryPropertyType ) { FeatureProperty[] tmp = feature.getProperties( type.getName() ); for ( FeatureProperty property : tmp ) { list.add( property ); } } } return list.toArray( new FeatureProperty[list.size()] ); } /** * move selected objects by defined distance in x- and y-direction * * @param parameter */ @SuppressWarnings("unchecked") public void moveByDistance( Map<String, Object> parameter ) { Pair<Double, Double> pair = (Pair<Double, Double>) parameter.get( "distance" ); double[] d = new double[] { pair.first, pair.second }; Layer layer = appContainer.getMapModel( null ).getLayersSelectedForAction( MapModel.SELECTION_EDITING ).get( 0 ); FeatureCollection fc = layer.getSelectedFeatures(); MoveFeatureCommand command = new MoveFeatureCommand( fc, null, d ); try { appContainer.getCommandProcessor().executeSychronously( command, true ); } catch ( Exception e ) { LOG.logError( e.getMessage(), e ); DialogFactory.openErrorDialog( appContainer.getViewPlatform(), null, Messages.get( "$MD11260" ), Messages.get( "$MD11261", pair.first, pair.second ), e ); } } /** * performs a command for cutting holes into a surface by selecting overlapping surfaces */ public void cutPolygonHole() { Layer layer = getSelectedLayer( MapModel.SELECTION_EDITING ); List<DataAccessAdapter> dataAccess = layer.getDataAccess(); DefaultMapModule<?> mapModule = owner.getAssignedMapModule(); MapTool<?> mapTool = mapModule.getMapTool(); ToolState ts = mapTool.getState(); mapTool.setEditState(); EditState editState = (EditState) mapTool.getState(); editState.setCuttingPolygonHoleState(); EditState es = (EditState) mapModule.getMapTool().getState(); CuttingPolygonHoleCommand command = null; try { command = (CuttingPolygonHoleCommand) es.createCommand( dataAccess.get( 0 ), null ); appContainer.getCommandProcessor().executeSychronously( command, true ); } catch ( Exception e ) { LOG.logError( e.getMessage(), e ); DialogFactory.openWarningDialog( appContainer.getViewPlatform(), null, Messages.getMessage( Locale.getDefault(), "$MD11606", e.getMessage() ), Messages.getMessage( Locale.getDefault(), "$MD11607" ) ); return; } // reset previous state mapModule.getMapTool().setState( ts ); layer.unselectAllFeatures(); owner.getDigitizerPanel().resetAll(); FeatureCollection fc = FeatureFactory.createFeatureCollection( UUID.randomUUID().toString(), new Feature[] { (Feature) command.getResult() } ); owner.getEditFeature().setFeature( layer, fc ); } }