/*************************************************** * * 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 org.deegree.model.feature.Feature; import org.deegree.model.feature.FeatureProgressListener; import org.deegree.model.feature.FeatureProperty; import org.deegree.model.spatialschema.JTSAdapter; import java.util.Vector; import javax.swing.SwingWorker; import de.cismet.cismap.commons.CrsTransformer; import de.cismet.cismap.commons.features.FeatureServiceFeature; import de.cismet.cismap.commons.featureservice.*; /** * Abstract Base class of features factories that make use of the degree framework to read features documents. * * @author Pascal Dihé * @version $Revision$, $Date$ */ public abstract class DegreeFeatureFactory<FT extends FeatureServiceFeature, QT> extends AbstractFeatureFactory<FT, QT> { //~ Instance fields -------------------------------------------------------- protected int geometryIndex; protected Integer featureSrid = null; //~ Constructors ----------------------------------------------------------- /** * Creates a new DegreeFeatureFactory object. */ public DegreeFeatureFactory() { super(); } /** * Creates a new DegreeFeatureFactory object. * * @param dff DOCUMENT ME! */ protected DegreeFeatureFactory(final DegreeFeatureFactory dff) { super(dff); this.geometryIndex = dff.geometryIndex; this.featureSrid = dff.featureSrid; } //~ Methods ---------------------------------------------------------------- /** * Processes a degree feature collection and fills the provided vector with feature service features of custom type * {@code FT}. * * @param workerThread thread that is observed * @param featureCollection collection of degree features to be processed * @param evaluateExpressions featureVector vector of * * @return {@code true} if the operation completed successfully, {@code false} otherwise * * @throws Exception DOCUMENT ME! */ protected Vector<FT> processFeatureCollection(final SwingWorker workerThread, final Feature[] featureCollection, final boolean evaluateExpressions) throws Exception { if (DEBUG) { if (logger.isDebugEnabled()) { logger.debug("SW[" + workerThread + "]: converting " + featureCollection.length + " degree features to FeatureServiceFeatures"); } } final long start = System.currentTimeMillis(); int i = 0; geometryIndex = GeometryHeuristics.findBestGeometryIndex(featureCollection[0]); final Vector<FT> featureVector = new Vector(featureCollection.length); for (final Feature degreeFeature : featureCollection) { // check if canceled ....................................................... if (this.checkCancelled(workerThread, "converting degree features (" + i + ")")) { return featureVector; } // check if canceled ....................................................... // int progress = (int) (((double) featureCollection.length / (double) i) * 100d); // FIXME: use feature.getId() if idExpression is undefined? Feature ID may be a string! // if(DEBUG)logger.debug("Degree Feature ID: '" + degreeFeature.getId() + "'"); final FT featureServiceFeature = this.createFeatureInstance(degreeFeature, i); this.initialiseFeature(featureServiceFeature, degreeFeature, evaluateExpressions, i); featureVector.add(featureServiceFeature); i++; } logger.info("SW[" + workerThread + "]: converting " + featureCollection.length + " degree features took " + (System.currentTimeMillis() - start) + " ms"); return featureVector; } /** * Perform standard initialisation of a newly created feature.<br/> * In gereal, this operation is invokded by the {@code processFeatureCollection} operation. * * @param featureServiceFeature DOCUMENT ME! * @param degreeFeature feature to be initialised * @param evaluateExpressions DOCUMENT ME! * @param index DOCUMENT ME! * * @throws Exception DOCUMENT ME! * * @see #processFeatureCollection(javax.swing.SwingWorker, org.deegree2.model.feature.Feature[], boolean) */ protected void initialiseFeature(final FT featureServiceFeature, final Feature degreeFeature, final boolean evaluateExpressions, final int index) throws Exception { // perform standard initilaisation featureServiceFeature.setLayerProperties(this.getLayerProperties()); // creating geometry if (featureServiceFeature.getGeometry() == null) { try { featureServiceFeature.setGeometry(JTSAdapter.export( degreeFeature.getGeometryPropertyValues()[geometryIndex])); } catch (Exception e) { featureServiceFeature.setGeometry(JTSAdapter.export(degreeFeature.getDefaultGeometryPropertyValue())); } } if ((featureServiceFeature.getGeometry() != null) && (featureSrid != null)) { featureServiceFeature.getGeometry().setSRID(featureSrid); } // adding properties if ((featureServiceFeature.getProperties() == null) || featureServiceFeature.getProperties().isEmpty()) { // set the properties final FeatureProperty[] featureProperties = degreeFeature.getProperties(); // if(DEBUG)if(DEBUG)logger.debug("setting " + featureProperties.length + "properties"); for (final FeatureProperty fp : featureProperties) { // if(DEBUG)if(DEBUG)logger.debug("setting '" + fp.getName().getAsString() + "' = '" + fp.getValue() + // "'"); featureServiceFeature.addProperty(fp.getName().getAsString(), fp.getValue()); } } if (evaluateExpressions) { this.evaluateExpressions(featureServiceFeature, index); } } /** * Creates an instance of the custom FeatureServiceFeature types and may perform a custom initialisation with * properties of the degree feature.<br/> * * @param degreeFeature the degree feature that may be used for custom initialisation * @param index index of the current processing step, can be used for id generation * * @return the newly creates FeatureServiceFeature * * @throws Exception DOCUMENT ME! * * @see #processFeatureCollection(javax.swing.SwingWorker, org.deegree2.model.feature.Feature[], boolean) */ protected abstract FT createFeatureInstance(Feature degreeFeature, int index) throws Exception; //~ Inner Classes ---------------------------------------------------------- /** * FeatureProgressListener used to track parsing progress of documents. * * @version $Revision$, $Date$ */ protected class ParsingProgressListener implements FeatureProgressListener { //~ Instance fields ---------------------------------------------------- private final int progressThreshold; private final int featureCount; private final SwingWorker workerThread; private int currentProgress = 0; //~ Constructors ------------------------------------------------------- /** * Creates a new ParsingProgressListener object. * * @param workerThread DOCUMENT ME! * @param featureCount DOCUMENT ME! * @param progressThreshold DOCUMENT ME! */ public ParsingProgressListener(final SwingWorker workerThread, final int featureCount, final int progressThreshold) { this.progressThreshold = progressThreshold; this.workerThread = workerThread; this.featureCount = featureCount; } //~ Methods ------------------------------------------------------------ /** * DOCUMENT ME! * * @param progress DOCUMENT ME! */ @Override public void featureProgress(final int progress) { if (DEBUG) { if (logger.isDebugEnabled()) { logger.debug("real feature parsing progress: " + progress); } } final int newProgress = (int)((double)progress / (double)featureCount * progressThreshold); if ((workerThread != null) && (newProgress > currentProgress)) { // set to progress to -1 (indeterminate progress bar) currentProgress = (newProgress < progressThreshold) ? newProgress : -1; if (DEBUG) { if (logger.isDebugEnabled()) { logger.debug("SW[" + workerThread + "]: passing progress: " + currentProgress + "%"); } } workerThread.firePropertyChange("progress", currentProgress - 5, currentProgress); } } } }