/* Spatial Operations & Editing Tools for uDig
*
* Axios Engineering under a funding contract with:
* Diputación Foral de Gipuzkoa, Ordenación Territorial
*
* http://b5m.gipuzkoa.net
* http://www.axios.es
*
* (C) 2006, Diputación Foral de Gipuzkoa, Ordenación Territorial (DFG-OT).
* DFG-OT agrees to licence under Lesser General Public License (LGPL).
*
* 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; version 2.1 of the License.
*
* 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.
*/
package es.axios.udig.spatialoperations.ui.taskmanager;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.text.MessageFormat;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import net.refractions.udig.catalog.IGeoResource;
import net.refractions.udig.project.ILayer;
import net.refractions.udig.project.IMap;
import org.eclipse.core.runtime.IProgressMonitor;
import org.geotools.data.FeatureStore;
import org.geotools.data.simple.SimpleFeatureStore;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.SchemaException;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.filter.Filter;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import com.vividsolutions.jts.geom.Geometry;
import es.axios.geotools.util.FeatureTypeUnionBuilder;
import es.axios.udig.spatialoperations.internal.i18n.Messages;
import es.axios.udig.spatialoperations.internal.parameters.IIntersectInExistentLayerParameters;
import es.axios.udig.spatialoperations.internal.parameters.IIntersectInNewLayerParameters;
import es.axios.udig.spatialoperations.internal.parameters.IIntersectParameters;
import es.axios.udig.spatialoperations.tasks.IIntersectTask;
import es.axios.udig.spatialoperations.tasks.SpatialOperationException;
import es.axios.udig.spatialoperations.tasks.SpatialOperationFactory;
import es.axios.udig.ui.commons.mediator.AppGISMediator;
import es.axios.udig.ui.commons.util.LayerUtil;
import es.axios.udig.ui.commons.util.MapUtil;
/**
* Monitoring the intersect operation.
*
* @author Aritz Davila (www.axios.es)
* @author Mauricio Pazos (www.axios.es)
*/
final class IntersectMonitor extends SOTaskMonitor<FeatureStore<SimpleFeatureType, SimpleFeature>> {
private Future<FeatureStore<SimpleFeatureType, SimpleFeature>> future;
private IIntersectParameters params;
private ILayer targetLayer = null;
private ILayer secondLayer = null;
private ILayer firstLayer = null;
private boolean isCreatingNewLayer;
private FeatureTypeUnionBuilder featureUnionBuilder;
/**
* New instance of {@link IntersectMonitor}. Client must use
* {@link #newInstance(IIntersectParameters)}.
*
* @param params
*/
private IntersectMonitor(final IIntersectParameters params) {
assert params != null;
this.params = params;
}
/**
* New instance of {@link IntersectMonitor}.
*
* @param params
* @return
*/
public static ISOTaskMonitor newInstance(IIntersectParameters params) {
return new IntersectMonitor(params);
}
@Override
protected void deliveryResult(Future<FeatureStore<SimpleFeatureType, SimpleFeature>> future, ILayer target)
throws InterruptedException {
presentFeaturesOnTargetLayer(target);
}
@Override
protected String getBeginMessage() {
final String msg = MessageFormat.format(Messages.IntersectProcess_intersectin_with, this.firstLayer.getName(),
this.secondLayer.getName());
return msg;
}
@Override
protected String getCancelMessage() {
return Messages.IntersectProcess_canceled;
}
@Override
protected String getDoneMessage() {
return Messages.IntersectProcess_successful;
}
@Override
protected Future<FeatureStore<SimpleFeatureType, SimpleFeature>> getFuture() {
return this.future;
}
@Override
protected IMap getMap() {
IMap map = this.firstLayer.getMap();
assert map != null;
return map;
}
@Override
protected ILayer getTarget() {
return this.targetLayer;
}
@Override
protected void initTaskMonitor(IProgressMonitor progress) throws InvocationTargetException {
this.firstLayer = params.getFirstLayer();
assert this.firstLayer != null;
this.secondLayer = params.getSecondLayer();
assert this.secondLayer != null;
Filter filterInFirstLayer = params.getFilterInFirstLayer();
assert filterInFirstLayer != null;
Filter filterInSecondLayer = params.getFilterInSecondLayer();
assert filterInSecondLayer != null;
FeatureCollection<SimpleFeatureType, SimpleFeature> featuresInFirstLayer, featuresInSecondLayer;
try {
featuresInFirstLayer = LayerUtil.getSelectedFeatures(this.firstLayer, filterInFirstLayer);
assert featuresInFirstLayer != null;
featuresInSecondLayer = LayerUtil.getSelectedFeatures(this.secondLayer, filterInSecondLayer);
assert featuresInSecondLayer != null;
SimpleFeatureStore targetStore = getTargetStore(this.params, progress);
// Traverses the first layer doing the intersection of each feature
// in first layer
// with each feature in second layer.
// gets the crs of map
final CoordinateReferenceSystem firstLayerCrs = params.getFirstCRS();
final CoordinateReferenceSystem mapCrs = MapUtil.getCRS(getMap());
final CoordinateReferenceSystem secondLayerCrs = params.getSecondCRS();
IIntersectTask task = SpatialOperationFactory.createIntersect(targetStore, featuresInFirstLayer,
featuresInSecondLayer, firstLayerCrs, mapCrs, isCreatingNewLayer, featureUnionBuilder,
secondLayerCrs);
ExecutorService executor = Executors.newCachedThreadPool();
this.future = executor.submit(task);
progress.worked(1);
} catch (IOException e) {
throw makeInitializeExcepion(progress, e);
} catch (SpatialOperationException e) {
throw makeInitializeExcepion(progress, e);
}
}
private SimpleFeatureStore getTargetStore( IIntersectParameters params,
IProgressMonitor progress)
throws IOException, SpatialOperationException {
SimpleFeatureStore targetStore;
if (params instanceof IIntersectInExistentLayerParameters) {
this.targetLayer = ((IIntersectInExistentLayerParameters) params).getTargetLayer();
targetStore = getFeatureStore(targetLayer);
this.isCreatingNewLayer = false;
} else {
final String targetName = ((IIntersectInNewLayerParameters) params).getTargetName();
final Class<? extends Geometry> geomClass = ((IIntersectInNewLayerParameters) params)
.getTargetGeometryClass();
final CoordinateReferenceSystem crs = MapUtil.getCRS(getMap());
SimpleFeatureType type = buildTargetFeatureType(this.firstLayer.getSchema(), this.secondLayer.getSchema(),
targetName, geomClass, crs);
IGeoResource targetGeoResource = AppGISMediator.createTempGeoResource(type);
assert targetGeoResource != null;
targetStore = (SimpleFeatureStore) targetGeoResource.resolve(FeatureStore.class, progress);
this.targetLayer = addLayerToMap(getMap(), targetGeoResource);
this.isCreatingNewLayer = true;
}
return targetStore;
}
private SimpleFeatureType buildTargetFeatureType( final SimpleFeatureType firstType,
final SimpleFeatureType secondType,
final String layerName,
final Class<? extends Geometry> geometryClass,
final CoordinateReferenceSystem crs)
throws SpatialOperationException {
try {
this.featureUnionBuilder = new FeatureTypeUnionBuilder(layerName);
featureUnionBuilder.add(firstType).add(secondType).setGeometryClass("geometry", geometryClass, crs); //$NON-NLS-1$
SimpleFeatureType newFeatureType = featureUnionBuilder.getFeatureType();
return newFeatureType;
} catch (SchemaException e) {
throw new SpatialOperationException(e);
}
}
}