/***************************************************
*
* cismet GmbH, Saarbruecken, Germany
*
* ... and it just works.
*
****************************************************/
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package de.cismet.cismap.commons.featureservice.factory;
import com.vividsolutions.jts.geom.*;
import org.deegree.io.rtree.HyperBoundingBox;
import org.deegree.io.rtree.HyperPoint;
import org.deegree.io.rtree.RTree;
import org.deegree.io.rtree.RTreeException;
import org.deegree.io.shpapi.ShapeFile;
import org.deegree.io.shpapi.shape_new.ShapeFileReader;
import org.deegree.model.feature.Feature;
import org.deegree.model.feature.FeatureCollection;
import org.deegree.model.feature.schema.FeatureType;
import org.deegree.model.feature.schema.PropertyType;
import org.deegree.model.spatialschema.JTSAdapter;
import org.deegree.style.se.unevaluated.Style;
import org.geotools.referencing.wkt.Parser;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.openide.util.NbBundle;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.net.URI;
import java.nio.charset.Charset;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
import javax.swing.JOptionPane;
import javax.swing.SwingWorker;
import de.cismet.cismap.commons.BoundingBox;
import de.cismet.cismap.commons.Crs;
import de.cismet.cismap.commons.CrsTransformer;
import de.cismet.cismap.commons.exceptions.ShapeFileImportAborted;
import de.cismet.cismap.commons.features.ShapeFeature;
import de.cismet.cismap.commons.features.ShapeInfo;
import de.cismet.cismap.commons.featureservice.AbstractFeatureService;
import de.cismet.cismap.commons.featureservice.FeatureServiceAttribute;
import de.cismet.cismap.commons.featureservice.LayerProperties;
import de.cismet.cismap.commons.featureservice.factory.FeatureFactory.TooManyFeaturesException;
import de.cismet.cismap.commons.interaction.CismapBroker;
import de.cismet.cismap.commons.util.CrsDeterminer;
import static de.cismet.cismap.commons.featureservice.factory.AbstractFeatureFactory.DEBUG;
/**
* DOCUMENT ME!
*
* @author pascal
* @version $Revision$, $Date$
*/
public class ShapeFeatureFactory extends DegreeFeatureFactory<ShapeFeature, String>
implements CachingFeatureFactory<ShapeFeature, String> {
//~ Instance fields --------------------------------------------------------
protected int maxCachedFeatureCount = Integer.MAX_VALUE;
protected URI documentURI;
protected ShapeFile shapeFile;
protected boolean initialised = false;
// private Feature[] tempFeatureCollection;
// private int currentProgress = 0;
protected Vector<FeatureServiceAttribute> featureServiceAttributes;
// private Geometry extend;
private boolean noGeometryRecognised = false;
private boolean errorInGeometryFound = false;
private String shapeCrs = null;
private Crs crs = CismapBroker.getInstance().getSrs();
private org.deegree.model.spatialschema.Envelope envelope;
private FeatureCollection fc = null;
private String filename;
private String geometryType = AbstractFeatureService.UNKNOWN;
//~ Constructors -----------------------------------------------------------
/**
* Creates a new ShapeFeatureFactory object.
*
* @param layerProperties DOCUMENT ME!
* @param documentURL DOCUMENT ME!
* @param maxCachedFeatureCount DOCUMENT ME!
* @param workerThread DOCUMENT ME!
* @param styles DOCUMENT ME!
*
* @throws Exception DOCUMENT ME!
*/
public ShapeFeatureFactory(final LayerProperties layerProperties,
final URI documentURL,
final int maxCachedFeatureCount,
final SwingWorker workerThread,
final Map<String, LinkedList<org.deegree.style.se.unevaluated.Style>> styles) throws Exception {
this(layerProperties, documentURL, maxCachedFeatureCount, workerThread, styles, null);
}
/**
* Creates a new ShapeFeatureFactory object.
*
* @param layerProperties DOCUMENT ME!
* @param documentURL DOCUMENT ME!
* @param maxCachedFeatureCount DOCUMENT ME!
* @param workerThread DOCUMENT ME!
* @param styles DOCUMENT ME!
* @param shapeCrs DOCUMENT ME!
*
* @throws Exception DOCUMENT ME!
*/
public ShapeFeatureFactory(final LayerProperties layerProperties,
final URI documentURL,
final int maxCachedFeatureCount,
final SwingWorker workerThread,
final Map<String, LinkedList<org.deegree.style.se.unevaluated.Style>> styles,
final String shapeCrs) throws Exception {
this.layerProperties = layerProperties;
this.documentURI = documentURL;
this.maxCachedFeatureCount = maxCachedFeatureCount;
this.styles = styles;
this.shapeCrs = shapeCrs;
if (shapeCrs != null) {
this.featureSrid = CrsTransformer.extractSridFromCrs(shapeCrs);
}
try {
this.parseShapeFile(workerThread);
this.initialised = true;
} catch (ShapeFileImportAborted e) {
// this exception will be handled in the ShapeFileFeatureService
throw e;
} catch (Exception ex) {
logger.error("SW[" + workerThread + "]: error parsing shape file", ex);
if (DEBUG && (shapeFile != null)) {
if (logger.isDebugEnabled()) {
logger.debug(shapeFile.getFileMBR());
}
}
this.cleanup();
}
}
/**
* Creates a new ShapeFeatureFactory object.
*
* @param shpff DOCUMENT ME!
*/
protected ShapeFeatureFactory(final ShapeFeatureFactory shpff) {
super(shpff);
this.maxCachedFeatureCount = shpff.maxCachedFeatureCount;
this.documentURI = shpff.documentURI;
this.shapeFile = shpff.shapeFile;
this.featureServiceAttributes = new Vector(shpff.featureServiceAttributes);
this.initialised = shpff.initialised;
this.crs = shpff.crs;
this.shapeCrs = shpff.shapeCrs;
this.fc = shpff.fc;
}
//~ Methods ----------------------------------------------------------------
@Override
protected ShapeFeature createFeatureInstance(final Feature degreeFeature, final int index) throws Exception {
// dummy method
return null;
}
/**
* DOCUMENT ME!
*
* @param degreeFeature DOCUMENT ME!
* @param shapeInfo DOCUMENT ME!
* @param index DOCUMENT ME!
*
* @return DOCUMENT ME!
*
* @throws Exception DOCUMENT ME!
*/
protected ShapeFeature createFeatureInstance(final Feature degreeFeature,
final ShapeInfo shapeInfo,
final int index) throws Exception {
layerName = filename;
final ShapeFeature shapeFeature = new ShapeFeature(shapeInfo, getStyle(filename));
// auto generate Ids!
shapeFeature.setId(index);
return shapeFeature;
}
@Override
protected void initialiseFeature(final ShapeFeature featureServiceFeature,
final Feature degreeFeature,
final boolean evaluateExpressions,
final int index) throws Exception {
// perform standard initialisation
featureServiceFeature.setLayerProperties(this.getLayerProperties());
if (evaluateExpressions) {
this.evaluateExpressions(featureServiceFeature, index);
}
}
/**
* DOCUMENT ME!
*/
protected synchronized void cleanup() {
if (this.shapeFile != null) {
shapeFile.close();
shapeFile = null;
System.gc();
}
}
@Override
public boolean isLazy() {
return false;
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
private Charset getCharsetDefinition() {
Charset cs = null;
String cpgFilename;
File cpgFile;
if (this.documentURI.getPath().endsWith(".shp")) {
cpgFilename = this.documentURI.getPath().substring(0, this.documentURI.getPath().length() - 4);
} else {
cpgFilename = this.documentURI.getPath();
}
cpgFile = new File(cpgFilename + ".cpg");
if (!cpgFile.exists()) {
cpgFile = new File(cpgFilename + ".CPG");
}
try {
if (cpgFile.exists()) {
final BufferedReader br = new BufferedReader(new FileReader(cpgFile));
final String csName = br.readLine();
if (logger.isDebugEnabled()) {
logger.debug("cpg file with charset " + csName + " found");
}
if ((csName != null) && Charset.isSupported(csName)) {
cs = Charset.forName(csName);
} else {
logger.warn("The given charset is not supported. Charset: " + csName);
}
br.close();
} else {
if (logger.isDebugEnabled()) {
logger.debug("No cpg file found.");
}
}
} catch (IOException e) {
logger.error("Error while reading the cpg file.");
}
return cs;
}
/**
* DOCUMENT ME!
*
* @param workerThread DOCUMENT ME!
*
* @throws Exception DOCUMENT ME!
* @throws ShapeFileImportAborted DOCUMENT ME!
*/
protected synchronized void parseShapeFile(final SwingWorker workerThread) throws Exception {
filename = new File(documentURI).getName();
shapeFile = getShapeFile();
envelope = shapeFile.getFileMBR();
if (getShapeCrs() == null) {
setShapeCrs(determineShapeCrs());
if (getShapeCrs() == null) {
throw new ShapeFileImportAborted();
}
featureSrid = CrsTransformer.extractSridFromCrs(getShapeCrs());
}
final Feature degreeFeature = shapeFile.getFeatureByRecNo(1);
final FeatureType type = degreeFeature.getFeatureType();
logger.info("SW[" + workerThread + "]: creating " + type.getProperties().length
+ " featureServiceAttributes from first parsed degree feature");
featureServiceAttributes = new Vector(type.getProperties().length);
for (final PropertyType pt : type.getProperties()) {
featureServiceAttributes.add(
new FeatureServiceAttribute(pt.getName().getAsString(), Integer.toString(pt.getType()), true));
}
// create an index file, if it does not alreay exists
int currentProgress = 0;
int newProgress;
String filename;
if (this.documentURI.getPath().endsWith(".shp")) {
filename = this.documentURI.getPath().substring(0, this.documentURI.getPath().length() - 4);
} else {
filename = this.documentURI.getPath();
}
final ShapeFileReader reader = new ShapeFileReader(filename);
final int shapeType = reader.getShapeType();
if ((shapeType == org.deegree.io.shpapi.shape_new.ShapeFile.MULTIPOINTM)
|| (shapeType == org.deegree.io.shpapi.shape_new.ShapeFile.POLYLINEM)
|| (shapeType == org.deegree.io.shpapi.shape_new.ShapeFile.POLYGONM)
|| (shapeType == org.deegree.io.shpapi.shape_new.ShapeFile.POINTM)
|| (shapeType == org.deegree.io.shpapi.shape_new.ShapeFile.POLYGONZ)
|| (shapeType == org.deegree.io.shpapi.shape_new.ShapeFile.POLYLINEZ)
|| (shapeType == org.deegree.io.shpapi.shape_new.ShapeFile.POINTZ)) {
final org.deegree.io.shpapi.shape_new.ShapeFile shapeFromReader = reader.read();
fc = shapeFromReader.getFeatureCollection();
}
try {
if (!shapeFile.hasRTreeIndex()) {
final int features = shapeFile.getRecordNum();
final RTree rtree = new RTree(2, 11, filename + ".rti");
for (int i = 1; i < (features + 1); i++) {
Feature feature = null;
if (fc != null) {
feature = fc.getFeature(i - 1);
} else {
feature = shapeFile.getFeatureByRecNo(i);
}
final org.deegree.model.spatialschema.Geometry[] geometries = feature.getGeometryPropertyValues();
if (geometries.length == 0) {
if (logger.isDebugEnabled()) {
logger.debug("no geometries at recno" + i);
}
continue;
}
org.deegree.model.spatialschema.Envelope envelope = null;
// TODO: handle geometry=null (allowed in shapefile)
envelope = (feature.getDefaultGeometryPropertyValue()).getEnvelope();
if (envelope == null) { // assume a Point-geometry
if (geometries[0] instanceof org.deegree.model.spatialschema.Point) {
final org.deegree.model.spatialschema.Point pnt = (org.deegree.model.spatialschema.Point)
geometries[0];
envelope = org.deegree.model.spatialschema.GeometryFactory.createEnvelope(pnt.getX(),
pnt.getY(),
pnt.getX(),
pnt.getY(),
null);
}
}
final HyperBoundingBox box = new HyperBoundingBox(
new HyperPoint(envelope.getMin().getAsArray()),
new HyperPoint(envelope.getMax().getAsArray()));
rtree.insert(new Integer(i), box);
// refresh progress bar
newProgress = (int)((double)i / (double)features * 100d);
if ((workerThread != null) && ((newProgress % 5) == 0) && (newProgress > currentProgress)
&& (newProgress >= 5)) {
// set to progress to -1 (indeterminate progress bar)
currentProgress = (newProgress <= 100) ? newProgress : -1;
workerThread.firePropertyChange("progress", currentProgress - 5, currentProgress);
}
}
rtree.close();
}
} catch (final RTreeException e) {
logger.error("The index file cannot be created. The corresponding folder is possibly write protected.", e);
}
determineGeometryType();
initialised = true;
this.cleanup();
}
/**
* Determines the crs of the corresponding prj file.
*
* @return the crs of the corresponding prj file or null, if the initialisation of the shape file should be
* cancelled.
*/
private String determineShapeCrs() {
String prjFilename;
File prjFile;
final Map<Crs, CoordinateReferenceSystem> prjMapping = CrsDeterminer.getKnownCrsMappings();
if ((prjMapping != null) && !prjMapping.isEmpty()) {
// if no mapping file is defined, it will be assumed that the shape file ueses the current crs
if (this.documentURI.getPath().endsWith(".shp")) {
prjFilename = this.documentURI.getPath().substring(0, this.documentURI.getPath().length() - 4);
} else {
prjFilename = this.documentURI.getPath();
}
prjFile = new File(prjFilename + ".prj");
if (!prjFile.exists()) {
prjFile = new File(prjFilename + ".PRJ");
}
try {
if (prjFile.exists()) {
final BufferedReader br = new BufferedReader(new FileReader(prjFile));
String crsDefinition = br.readLine();
br.close();
if (crsDefinition != null) {
final Parser parser = new Parser();
if (logger.isDebugEnabled()) {
logger.debug("prj file with definition: " + crsDefinition + " found");
}
crsDefinition = CrsDeterminer.crsDefinitionAdjustments(crsDefinition);
final CoordinateReferenceSystem crsFromShape = parser.parseCoordinateReferenceSystem(
crsDefinition);
for (final Crs key : prjMapping.keySet()) {
if (CrsDeterminer.isCrsEqual(prjMapping.get(key), crsFromShape)) {
return key.getCode();
}
}
} else {
logger.warn("The prj file is empty.");
}
} else {
if (logger.isDebugEnabled()) {
logger.debug("No prj file found.");
}
}
} catch (IOException e) {
logger.error("Error while reading the prj file.", e);
} catch (ParseException e) {
logger.error("Error while parsing the prj file.", e);
}
if (featureSrid == null) {
// the featureSrid must be set before the getEnvelope method will be called.
featureSrid = CrsTransformer.extractSridFromCrs(CismapBroker.getInstance().getSrs().getCode());
}
final BoundingBox currentBBox = CismapBroker.getInstance()
.getMappingComponent()
.getCurrentBoundingBoxFromCamera();
if (getEnvelope().intersects(currentBBox.getGeometry(featureSrid))) {
return CismapBroker.getInstance().getSrs().getCode();
} else {
// Ask the user, what crs should be used
final List<Crs> crsList = CismapBroker.getInstance().getMappingComponent().getCrsList();
final List<Object> definedMappings = new ArrayList<Object>();
for (final Crs tmpCrs : crsList) {
if (tmpCrs.hasEsriDefinition()) {
definedMappings.add(new CrsWrapper(tmpCrs));
}
}
final Object userAnswer = JOptionPane.showInputDialog(CismapBroker.getInstance().getMappingComponent(),
NbBundle.getMessage(ShapeFeatureFactory.class, "ShapeFeatureFactory.determineShapeCrs.message"),
NbBundle.getMessage(ShapeFeatureFactory.class, "ShapeFeatureFactory.determineShapeCrs.title"),
JOptionPane.OK_CANCEL_OPTION,
null,
definedMappings.toArray(),
definedMappings.get(0));
if (userAnswer instanceof CrsWrapper) {
return ((CrsWrapper)userAnswer).getCrs().getCode();
} else {
return null;
}
}
}
return CismapBroker.getInstance().getSrs().getCode();
}
/**
* DOCUMENT ME!
*/
private void determineGeometryType() {
try {
final ShapeFile persShapeFile = getShapeFile();
final ShapeInfo info = new ShapeInfo(filename, persShapeFile, featureSrid, fc);
final ShapeFeature featureServiceFeature = createFeatureInstance(null, info, 1);
this.initialiseFeature(featureServiceFeature, null, false, 1);
geometryType = featureServiceFeature.getGeometry().getGeometryType();
} catch (Exception e) {
logger.error("Cannot determine the geometry type of a shape file.", e);
}
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*
* @throws IOException DOCUMENT ME!
*/
private ShapeFile getShapeFile() throws IOException {
cleanup();
final Charset cs = getCharsetDefinition();
String filename = null;
if (this.documentURI.getPath().endsWith(".shp")) {
filename = this.documentURI.getPath().substring(0, this.documentURI.getPath().length() - 4);
} else {
filename = this.documentURI.getPath();
}
shapeFile = new ShapeFile(filename, cs);
return shapeFile;
}
@Override
public synchronized void flush() {
logger.warn("flushing cached features");
this.lastCreatedfeatureVector.clear();
this.lastGeom = null;
this.lastQuery = null;
System.gc();
}
/**
* is not used and not usable.
*
* @return DOCUMENT ME!
*/
@Override
public int getMaxCachedFeatureCount() {
try {
return getShapeFile().getRecordNum();
} catch (IOException ex) {
logger.error("Cannot open the shape file", ex);
return 0;
} finally {
cleanup();
}
}
@Override
public void setMaxCachedFeatureCount(final int maxCachedFeatureCount) {
// this.maxCachedFeatureCount = maxCachedFeatureCount;
}
/**
* Get the value of documentURL.
*
* @return the value of documentURL
*/
public URI getDocumentURI() {
return documentURI;
}
/**
* Set the value of documentURL.
*
* @param documentURI new value of documentURL
*/
public synchronized void setDocumentURI(final URI documentURI) {
this.documentURI = documentURI;
try {
parseShapeFile(null);
} catch (Exception e) {
logger.error("Errro while parsing shape file", e);
}
}
@Override
public synchronized List<ShapeFeature> createFeatures(final String query,
final BoundingBox boundingBox,
final SwingWorker workerThread) throws TooManyFeaturesException, Exception {
return createFeatures_internal(query, boundingBox, workerThread, 0, 0, null, true);
}
@Override
public synchronized Vector<FeatureServiceAttribute> createAttributes(final SwingWorker workerThread)
throws TooManyFeaturesException, Exception {
if ((this.featureServiceAttributes == null) || (this.featureServiceAttributes.size() == 0)) {
logger.warn("SW[" + workerThread + "]: Factory not correctly initialised, parsing shape file");
this.parseShapeFile(workerThread);
}
if ((this.featureServiceAttributes == null) || (this.featureServiceAttributes.size() == 0)) {
logger.error("SW[" + workerThread + "]: no attributes could be found in shape file");
throw new Exception("no attributes could be found in shape file '" + this.documentURI + "'");
}
return this.featureServiceAttributes;
}
@Override
protected boolean isGenerateIds() {
return true;
}
// public static void main(String args[])
// {
// BasicConfigurator.configure();
//
// try
// {
// ShapeFeatureFactory shapeFeatureFactory = new ShapeFeatureFactory(new DefaultLayerProperties(), new URL("file:///P:/Street3D/SHAPE/mini.shp"));
// shapeFeatureFactory.logger.setLevel(org.apache.log4j.Level.ALL);
// shapeFeatureFactory.logger.info("OK");
// } catch (Throwable t)
// {
// t.printStackTrace();
// }
// }
@Override
public ShapeFeatureFactory clone() {
return new ShapeFeatureFactory(this);
}
/**
* DOCUMENT ME!
*
* @return the noGeometryRecognised
*/
public boolean isNoGeometryRecognised() {
return noGeometryRecognised;
}
/**
* DOCUMENT ME!
*
* @return the errorInGeometryFound
*/
public boolean isErrorInGeometryFound() {
return errorInGeometryFound;
}
/**
* DOCUMENT ME!
*
* @param crs DOCUMENT ME!
*/
public void setCrs(final Crs crs) {
this.crs = crs;
}
/**
* DOCUMENT ME!
*
* @return the envelope of the currently loaded shape file
*/
public Geometry getEnvelope() {
try {
if (envelope == null) {
envelope = getShapeFile().getFileMBR();
cleanup();
}
final Coordinate[] polyCords = new Coordinate[5];
polyCords[0] = new Coordinate(envelope.getMin().getX(), envelope.getMin().getY());
polyCords[1] = new Coordinate(envelope.getMin().getX(), envelope.getMax().getY());
polyCords[2] = new Coordinate(envelope.getMax().getX(), envelope.getMax().getY());
polyCords[3] = new Coordinate(envelope.getMax().getX(), envelope.getMin().getY());
polyCords[4] = new Coordinate(envelope.getMin().getX(), envelope.getMin().getY());
// The GeometryFactory must use the same srid as the elements in the deegreeFeaturesTree
final GeometryFactory geomFactory = new GeometryFactory(new PrecisionModel(PrecisionModel.FLOATING),
featureSrid);
final Polygon boundingPolygon = geomFactory.createPolygon(geomFactory.createLinearRing(polyCords), null);
return boundingPolygon.getEnvelope();
} catch (Exception e) {
logger.error("Error whie reading Shape file", e);
}
return null;
}
@Override
public int getFeatureCount(final String query, final BoundingBox bb) {
try {
final Coordinate[] polyCords = new Coordinate[5];
polyCords[0] = new Coordinate(bb.getX1(), bb.getY1());
polyCords[1] = new Coordinate(bb.getX1(), bb.getY2());
polyCords[2] = new Coordinate(bb.getX2(), bb.getY2());
polyCords[3] = new Coordinate(bb.getX2(), bb.getY1());
polyCords[4] = new Coordinate(bb.getX1(), bb.getY1());
// The GeometryFactory must use the same srid as the elements in the deegreeFeaturesTree
final GeometryFactory geomFactory = new GeometryFactory(new PrecisionModel(PrecisionModel.FLOATING),
CrsTransformer.extractSridFromCrs(crs.getCode()));
Polygon boundingPolygon = geomFactory.createPolygon(geomFactory.createLinearRing(polyCords), null);
boundingPolygon = (Polygon)CrsTransformer.transformToGivenCrs(boundingPolygon, getShapeCrs());
// List<ShapeFeature> selectedFeatures =
// this.degreeFeaturesTree.query(boundingPolygon.getEnvelopeInternal());
return getShapeFile().getGeoNumbersByRect(JTSAdapter.wrap(boundingPolygon).getEnvelope()).length;
} catch (final Exception e) {
logger.error("Error while determining the feature count", e);
} finally {
cleanup();
}
return 0;
}
@Override
public synchronized List<ShapeFeature> createFeatures(final String query,
final BoundingBox boundingBox,
final SwingWorker workerThread,
final int offset,
final int limit,
final FeatureServiceAttribute[] orderBy) throws TooManyFeaturesException, Exception {
return createFeatures_internal(query, boundingBox, workerThread, offset, limit, orderBy, false);
}
/**
* DOCUMENT ME!
*
* @param query DOCUMENT ME!
* @param boundingBox DOCUMENT ME!
* @param workerThread DOCUMENT ME!
* @param offset DOCUMENT ME!
* @param limit DOCUMENT ME!
* @param orderBy DOCUMENT ME!
* @param saveAsLastCreated DOCUMENT ME!
*
* @return DOCUMENT ME!
*
* @throws TooManyFeaturesException DOCUMENT ME!
* @throws Exception DOCUMENT ME!
*/
private synchronized List<ShapeFeature> createFeatures_internal(final String query,
final BoundingBox boundingBox,
final SwingWorker workerThread,
final int offset,
final int limit,
final FeatureServiceAttribute[] orderBy,
final boolean saveAsLastCreated) throws TooManyFeaturesException, Exception {
try {
if (!this.initialised) {
logger.warn("SW[" + workerThread + "]: Factory not correclty initialised, parsing shape file");
this.parseShapeFile(workerThread);
this.initialised = true;
// check if thread is canceled .........................................
if (this.checkCancelled(workerThread, " initialisation")) {
return null;
}
// check if thread is canceled .........................................
}
List<ShapeFeature> selectedFeatures;
final long start = System.currentTimeMillis();
final Coordinate[] polyCords = new Coordinate[5];
polyCords[0] = new Coordinate(boundingBox.getX1(), boundingBox.getY1());
polyCords[1] = new Coordinate(boundingBox.getX1(), boundingBox.getY2());
polyCords[2] = new Coordinate(boundingBox.getX2(), boundingBox.getY2());
polyCords[3] = new Coordinate(boundingBox.getX2(), boundingBox.getY1());
polyCords[4] = new Coordinate(boundingBox.getX1(), boundingBox.getY1());
// The GeometryFactory must use the same srid as the elements in the deegreeFeaturesTree
final GeometryFactory geomFactory = new GeometryFactory(new PrecisionModel(PrecisionModel.FLOATING),
CrsTransformer.extractSridFromCrs(crs.getCode()));
Polygon boundingPolygon = geomFactory.createPolygon(geomFactory.createLinearRing(polyCords), null);
boundingPolygon = (Polygon)CrsTransformer.transformToGivenCrs(boundingPolygon, getShapeCrs());
if (this.checkCancelled(workerThread, " quering spatial index structure")) {
return null;
}
if (featuresAlreadyInMemory(boundingPolygon, query)) {
selectedFeatures = createFeaturesFromMemory(query, boundingPolygon);
} else {
String filename = null;
if (this.documentURI.getPath().endsWith(".shp")) {
filename = this.documentURI.getPath().substring(0, this.documentURI.getPath().length() - 4);
} else {
filename = this.documentURI.getPath();
}
final ShapeFile persShapeFile = getShapeFile();
shapeFile = null;
final int[] recordNumbers = persShapeFile.getGeoNumbersByRect(JTSAdapter.wrap(boundingPolygon)
.getEnvelope());
if (recordNumbers == null) {
return new Vector<ShapeFeature>();
}
if (this.checkCancelled(workerThread, " quering spatial index structure")) {
return null;
}
selectedFeatures = new ArrayList<ShapeFeature>(recordNumbers.length);
final ShapeInfo info = new ShapeInfo(filename, persShapeFile, featureSrid, fc);
int count = 0;
for (final int record : recordNumbers) {
++count;
ShapeFeature featureServiceFeature;
if (fc != null) {
featureServiceFeature = createFeatureInstance(null, info, record);
this.initialiseFeature(featureServiceFeature, null, false, record);
} else {
featureServiceFeature = createFeatureInstance(null, info, record);
this.initialiseFeature(featureServiceFeature, null, false, record);
}
selectedFeatures.add(featureServiceFeature);
if (saveAsLastCreated && (count > 50000)) {
break;
}
}
}
if (logger.isDebugEnabled()) {
logger.debug("feature crs: " + getShapeCrs() + " features " + selectedFeatures.size()
+ " boundingbox: "
+ boundingPolygon.getEnvelopeInternal());
}
// check if thread is canceled .........................................
if (this.checkCancelled(workerThread, " quering spatial index structure")) {
return null;
}
// check if thread is canceled .........................................
if (logger.isDebugEnabled()) {
logger.debug("SW[" + workerThread + "]: quering spatial index for bounding box took "
+ (System.currentTimeMillis() - start) + " ms");
}
if (selectedFeatures.size() > this.getMaxFeatureCount()) {
throw new TooManyFeaturesException("features in selected area " + selectedFeatures.size()
+ " exceeds max feature count " + this.getMaxFeatureCount());
} else if (selectedFeatures.size() == 0) {
logger.warn("SW[" + workerThread + "]: no features found in selected bounding box");
return null;
}
if ((orderBy != null) && (orderBy.length > 0)) {
sortFeatureList(selectedFeatures, orderBy);
}
if (offset > 0) {
selectedFeatures = selectedFeatures.subList(offset, selectedFeatures.size());
}
if ((limit > 0) && (selectedFeatures.size() > limit)) {
selectedFeatures = selectedFeatures.subList(0, limit);
}
this.reEvaluteExpressions(selectedFeatures, workerThread);
// check if thread is canceled .........................................
if (this.checkCancelled(workerThread, " saving LastCreatedFeatures ")) {
return null;
}
// check if thread is canceled .........................................
if (saveAsLastCreated) {
this.updateLastCreatedFeatures(selectedFeatures, boundingPolygon, query);
}
// set the SLDs for features
final List<Style> style = getStyle(layerName);
if ((style != null) && (selectedFeatures != null)) {
for (final ShapeFeature f : selectedFeatures) {
f.setSLDStyles(style);
}
}
return new Vector<ShapeFeature>(selectedFeatures);
} finally {
cleanup();
}
}
/**
* DOCUMENT ME!
*
* @return the geometryType
*/
public String getGeometryType() {
return geometryType;
}
/**
* DOCUMENT ME!
*
* @return the shapeCrs
*/
public String getShapeCrs() {
return shapeCrs;
}
/**
* DOCUMENT ME!
*
* @param shapeCrs the shapeCrs to set
*/
public void setShapeCrs(final String shapeCrs) {
this.shapeCrs = shapeCrs;
}
//~ Inner Classes ----------------------------------------------------------
/**
* DOCUMENT ME!
*
* @version $Revision$, $Date$
*/
private class CrsWrapper {
//~ Instance fields ----------------------------------------------------
private Crs crs;
//~ Constructors -------------------------------------------------------
/**
* Creates a new CrsWrapper object.
*
* @param crs DOCUMENT ME!
*/
public CrsWrapper(final Crs crs) {
this.crs = crs;
}
//~ Methods ------------------------------------------------------------
@Override
public String toString() {
return crs.getShortname();
}
/**
* DOCUMENT ME!
*
* @return the crs
*/
public Crs getCrs() {
return crs;
}
/**
* DOCUMENT ME!
*
* @param crs the crs to set
*/
public void setCrs(final Crs crs) {
this.crs = crs;
}
}
}