001: /* uDig - User Friendly Desktop Internet GIS client
002: * http://udig.refractions.net
003: * (C) 2004, Refractions Research Inc.
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation;
008: * version 2.1 of the License.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: */
015: package net.refractions.udig.tools.edit.behaviour;
016:
017: import java.util.ArrayList;
018: import java.util.Collections;
019: import java.util.List;
020: import java.util.Map;
021: import java.util.Set;
022: import java.util.Map.Entry;
023:
024: import net.refractions.udig.core.IBlockingProvider;
025: import net.refractions.udig.core.StaticBlockingProvider;
026: import net.refractions.udig.project.ILayer;
027: import net.refractions.udig.project.command.UndoableComposite;
028: import net.refractions.udig.project.command.UndoableMapCommand;
029: import net.refractions.udig.project.command.factory.EditCommandFactory;
030: import net.refractions.udig.project.command.provider.FIDFeatureProvider;
031: import net.refractions.udig.project.internal.commands.edit.DeleteFeatureCommand;
032: import net.refractions.udig.project.render.displayAdapter.IMapDisplay;
033: import net.refractions.udig.project.ui.IAnimation;
034: import net.refractions.udig.project.ui.commands.DrawCommandFactory;
035: import net.refractions.udig.tool.edit.internal.Messages;
036: import net.refractions.udig.tools.edit.Behaviour;
037: import net.refractions.udig.tools.edit.EditPlugin;
038: import net.refractions.udig.tools.edit.EditState;
039: import net.refractions.udig.tools.edit.EditToolHandler;
040: import net.refractions.udig.tools.edit.animation.GeometryOperationAnimation;
041: import net.refractions.udig.tools.edit.commands.AddVertexCommand;
042: import net.refractions.udig.tools.edit.commands.CreateAndSetNewFeature;
043: import net.refractions.udig.tools.edit.commands.CreateOrSetFeatureCommand;
044: import net.refractions.udig.tools.edit.commands.SetEditGeomChangedStateCommand;
045: import net.refractions.udig.tools.edit.commands.SetEditStateCommand;
046: import net.refractions.udig.tools.edit.support.EditGeom;
047: import net.refractions.udig.tools.edit.support.EditGeomPathIterator;
048: import net.refractions.udig.tools.edit.support.GeometryCreationUtil;
049: import net.refractions.udig.tools.edit.support.IsBusyStateProvider;
050: import net.refractions.udig.tools.edit.support.PrimitiveShape;
051: import net.refractions.udig.tools.edit.support.ShapeType;
052:
053: import org.geotools.feature.Feature;
054: import org.geotools.feature.IllegalAttributeException;
055:
056: import com.vividsolutions.jts.geom.Geometry;
057: import com.vividsolutions.jts.geom.LineString;
058: import com.vividsolutions.jts.geom.LinearRing;
059: import com.vividsolutions.jts.geom.MultiLineString;
060: import com.vividsolutions.jts.geom.MultiPoint;
061: import com.vividsolutions.jts.geom.MultiPolygon;
062: import com.vividsolutions.jts.geom.Point;
063: import com.vividsolutions.jts.geom.Polygon;
064:
065: /**
066: * Creates a geometry from the currentGeom in the {@link EditToolHandler}.
067: * <p>
068: * Requirements:
069: * <ul>
070: * <li>handler.getCurrentGeom() != null</li>
071: * <li>EditManager has a edit feature and a edit layer</li>
072: * <li>Geometry can be assigned to feature's geometry</li>
073: * </ul>
074: * </p>
075: * <p>
076: * Action:
077: * <ul>
078: * <li>Creates a geometry of the indicated type.</li>
079: * <li>Set the edit feature's default geometry to be the created geometry if it is not null</li>
080: * <li>Also writes the changes to other geoms in the blackboard. The type created for those depends
081: * on the what the ShapeType of those geometries are.</li>
082: * </ul>
083: * </p>
084: *
085: * @author jones
086: * @since 1.1.0
087: */
088: public class WriteChangesBehaviour implements Behaviour {
089:
090: private final Class<? extends Geometry> geomToCreate;
091: private boolean updateBlackboard = true;
092:
093: /**
094: * @param geomToCreate must be polygon, point, multipoint, linestring or linearring
095: */
096: public WriteChangesBehaviour(Class<? extends Geometry> geomToCreate) {
097: if (geomToCreate != Polygon.class
098: && geomToCreate != Point.class
099: && geomToCreate != LineString.class
100: && geomToCreate != LinearRing.class)
101: throw new IllegalArgumentException(
102: "Must be one of Polygon, Point, LineString, MultiPoint or LinearRing"); //$NON-NLS-1$
103:
104: this .geomToCreate = geomToCreate;
105: }
106:
107: public boolean isValid(EditToolHandler handler) {
108: EditGeom currentGeom = handler.getCurrentGeom();
109:
110: boolean currentGeomNotNull = currentGeom != null;
111: return currentGeomNotNull
112: && typeCanBeAssignedToLayer(handler.getEditLayer()
113: .getSchema().getDefaultGeometry().getType());
114: }
115:
116: /**
117: * @param type
118: * @return
119: */
120: @SuppressWarnings("unchecked")
121: private boolean typeCanBeAssignedToLayer(Class type) {
122: if (type.isAssignableFrom(geomToCreate))
123: return true;
124: if (geomToCreate == Polygon.class
125: && type.isAssignableFrom(MultiPolygon.class)) {
126: return true;
127: } else if (geomToCreate == LinearRing.class
128: && type.isAssignableFrom(MultiLineString.class)) {
129: return true;
130: } else if (geomToCreate == LineString.class
131: && type.isAssignableFrom(MultiLineString.class)) {
132: return true;
133: } else if (geomToCreate == Point.class
134: && type.isAssignableFrom(MultiPoint.class)) {
135: return true;
136: }
137: return false;
138: }
139:
140: @SuppressWarnings({"deprecation","unchecked"})
141: public UndoableMapCommand getCommand(EditToolHandler handler) {
142: if (!isValid(handler))
143: throw new IllegalArgumentException(
144: "Not in a valid state for this to run"); //$NON-NLS-1$
145: Map<String, GeometryCreationUtil.Bag> idToGeom = GeometryCreationUtil
146: .createAllGeoms(handler.getCurrentGeom(), geomToCreate,
147: handler.getEditLayer().getSchema()
148: .getDefaultGeometry());
149:
150: EditState oldState = handler.getCurrentState();
151:
152: IMapDisplay display = handler.getContext().getMapDisplay();
153: DrawCommandFactory drawfactory = handler.getContext()
154: .getDrawFactory();
155: List<UndoableMapCommand> commands = new ArrayList<UndoableMapCommand>();
156: commands.add(new SetEditStateCommand(handler,
157: EditState.COMMITTING));
158:
159: ILayer layer = handler.getEditLayer();
160: EditCommandFactory editFactory = handler.getContext()
161: .getEditFactory();
162: Set<Entry<String, GeometryCreationUtil.Bag>> entries = idToGeom
163: .entrySet();
164: for (Entry<String, GeometryCreationUtil.Bag> entry : entries) {
165: EditGeom editGeom = entry.getValue().geom;
166: List<Geometry> geoms = entry.getValue().jts;
167:
168: Geometry geom = GeometryCreationUtil
169: .ceateGeometryCollection(geoms, layer.getSchema()
170: .getDefaultGeometry().getType());
171:
172: if (geom == null) {
173: IBlockingProvider<ILayer> layerProvider = new StaticBlockingProvider<ILayer>(
174: layer);
175: return new DeleteFeatureCommand(new FIDFeatureProvider(
176: entry.getKey(), layerProvider), layerProvider);
177: }
178:
179: if (updateBlackboard)
180: updateBlackboardGeometry(handler, editGeom, geom,
181: commands);
182:
183: GeometryOperationAnimation animation = new GeometryOperationAnimation(
184: EditGeomPathIterator.getPathIterator(editGeom)
185: .toShape(),
186: new IsBusyStateProvider(handler));
187:
188: commands.add(drawfactory.createStartAnimationCommand(
189: display, Collections
190: .singletonList((IAnimation) animation)));
191:
192: if (editGeom == handler.getCurrentGeom()) {
193: if (handler.getContext().getEditManager()
194: .getEditFeature() == null) {
195: int i = layer.getSchema().getAttributeCount();
196:
197: Feature feature;
198: try {
199: feature = layer.getSchema().create(
200: new Object[i]);
201: feature.setDefaultGeometry(geom);
202: } catch (IllegalAttributeException e) {
203: throw (RuntimeException) new RuntimeException()
204: .initCause(e);
205: }
206: commands.add(new CreateAndSetNewFeature(handler
207: .getCurrentGeom(), feature, layer));
208: } else {
209: // not creating it so don't need to set it.
210: commands.add(editFactory
211: .createSetGeometryCommand(geom));
212: }
213: } else {
214: commands.add(new CreateOrSetFeatureCommand(editGeom
215: .getFeatureIDRef().get(), layer, geom));
216:
217: }
218: commands.add(new SetEditGeomChangedStateCommand(editGeom,
219: false));
220: commands.add(drawfactory.createStopAnimationCommand(
221: display, Collections
222: .singletonList((IAnimation) animation)));
223: }
224:
225: UndoableComposite composite = new UndoableComposite(commands);
226: composite.setName(Messages.WriteChangesBehaviour_commandName);
227: composite.getFinalizerCommands().add(
228: new SetEditStateCommand(handler, EditState.MODIFYING));
229:
230: handler.setCurrentState(oldState);
231:
232: return composite;
233: }
234:
235: private void updateBlackboardGeometry(EditToolHandler handler,
236: EditGeom editGeom, Geometry geom,
237: List<UndoableMapCommand> commands) {
238: if (handler.getCurrentGeom() == editGeom) {
239: if (Polygon.class.isAssignableFrom(geomToCreate)) {
240: for (PrimitiveShape shape : editGeom) {
241: if (shape.getNumPoints() > 0
242: && !shape
243: .getPoint(0)
244: .equals(
245: shape
246: .getPoint(shape
247: .getNumPoints() - 1)))
248: commands.add(new AddVertexCommand(handler,
249: editGeom.getEditBlackboard(), shape
250: .getPoint(0)));
251: }
252: }
253: } else {
254: if (editGeom.getShapeType() == ShapeType.POLYGON
255: || (editGeom.getShapeType() == ShapeType.UNKNOWN && Polygon.class
256: .isAssignableFrom(geomToCreate))) {
257: for (PrimitiveShape shape : editGeom) {
258: if (shape.getNumPoints() > 0
259: && !shape
260: .getPoint(0)
261: .equals(
262: shape
263: .getPoint(shape
264: .getNumPoints() - 1)))
265: commands.add(new AddVertexCommand(handler,
266: editGeom.getEditBlackboard(), shape
267: .getPoint(0)));
268: }
269: }
270: }
271: }
272:
273: public void handleError(EditToolHandler handler, Throwable error,
274: UndoableMapCommand command) {
275: EditPlugin.log("", error); //$NON-NLS-1$
276: }
277:
278: /**
279: * @param updateBlackboard The updateBlackboard to set.
280: */
281: public void setUpdateBlackboard(boolean updateBlackboard) {
282: this.updateBlackboard = updateBlackboard;
283: }
284: }
|