Revision: 5109 http://sourceforge.net/p/jump-pilot/code/5109 Author: michaudm Date: 2016-10-26 21:18:12 +0000 (Wed, 26 Oct 2016) Log Message: ----------- SimpleQuery : spatial queries are now very fast (use of spatial indexes) + use of generics and code cleaning
Modified Paths: -------------- core/trunk/ChangeLog core/trunk/src/com/vividsolutions/jump/workbench/model/LayerManager.java core/trunk/src/org/openjump/core/ui/plugin/queries/Condition.java core/trunk/src/org/openjump/core/ui/plugin/queries/QueryDialog.java core/trunk/src/org/openjump/core/ui/plugin/queries/SimpleQueryPlugIn.java Modified: core/trunk/ChangeLog =================================================================== --- core/trunk/ChangeLog 2016-10-26 19:26:49 UTC (rev 5108) +++ core/trunk/ChangeLog 2016-10-26 21:18:12 UTC (rev 5109) @@ -3,6 +3,9 @@ # 2. make sure that lines break at 80 chars for constricted display situations #<-------------------------------- 80 chars ----------------------------------># +2016-10-26 mmichaud <m.michael.mich...@orange.fr> + * SimpleQuery : spatial queries are now very fast (use of spatial indexes) + 2016-10-25 mmichaud <m.michael.mich...@orange.fr> * Add ViewManager extension (v0.3.4) in OpenJUMP PLUS version Modified: core/trunk/src/com/vividsolutions/jump/workbench/model/LayerManager.java =================================================================== --- core/trunk/src/com/vividsolutions/jump/workbench/model/LayerManager.java 2016-10-26 19:26:49 UTC (rev 5108) +++ core/trunk/src/com/vividsolutions/jump/workbench/model/LayerManager.java 2016-10-26 21:18:12 UTC (rev 5109) @@ -32,7 +32,6 @@ package com.vividsolutions.jump.workbench.model; import java.awt.Color; -import java.awt.geom.Line2D; import java.lang.ref.WeakReference; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; @@ -45,8 +44,6 @@ import org.openjump.core.rasterimage.RasterImageLayer; import com.vividsolutions.jts.geom.Envelope; -import com.vividsolutions.jts.io.ParseException; -import com.vividsolutions.jts.io.WKTReader; import com.vividsolutions.jts.util.Assert; import com.vividsolutions.jump.coordsys.CoordinateSystem; import com.vividsolutions.jump.coordsys.Reprojector; Modified: core/trunk/src/org/openjump/core/ui/plugin/queries/Condition.java =================================================================== --- core/trunk/src/org/openjump/core/ui/plugin/queries/Condition.java 2016-10-26 19:26:49 UTC (rev 5108) +++ core/trunk/src/org/openjump/core/ui/plugin/queries/Condition.java 2016-10-26 21:18:12 UTC (rev 5109) @@ -1,7 +1,9 @@ package org.openjump.core.ui.plugin.queries; +import com.vividsolutions.jts.geom.Envelope; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.GeometryCollection; +import com.vividsolutions.jts.index.strtree.STRtree; import com.vividsolutions.jump.feature.Feature; import com.vividsolutions.jump.feature.FeatureCollection; import com.vividsolutions.jump.util.FlexibleDateParser; @@ -16,7 +18,9 @@ /** * Condition * @author Michael MICHAUD - * @version 0.3.0 + * @version 0.4.0 + * version 0.4.0 (2016-10-26) + * big optimization for spatial queries * version 0.3.0 (2013-06-28) * add relate operator * version 0.2.3 (2012-03-05) @@ -45,11 +49,12 @@ private static final FlexibleDateParser FLEXIBLE_DATE_PARSER = new FlexibleDateParser(); - QueryDialog query; - Function ft; - Operator op; - Pattern pattern; // only used for match & find functions - PlugInContext context; + private QueryDialog query; + private Function ft; + private Operator op; + private Pattern pattern; // only used for match & find functions + private PlugInContext context; + private Map<String,STRtree> spatialIndices; public Condition(QueryDialog query, PlugInContext context) { this.query = query; @@ -61,6 +66,7 @@ else pattern = Pattern.compile((String)query.valueCB.getSelectedValue(), Pattern.CASE_INSENSITIVE); } + if (op.type == 'G') spatialIndices = new HashMap<>(); this.context = context; } @@ -72,7 +78,7 @@ } public boolean test(Feature feature) throws Exception { - Object o = null; + Object o; if(query.attributeType=='G') { o = feature.getGeometry(); if(ft.type=='G') return test(gfunction((Geometry)o)); @@ -121,7 +127,7 @@ } private boolean test(boolean b) throws Exception { - boolean value = query.valueCB.getSelectedIndex()==0?true:false; + boolean value = query.valueCB.getSelectedIndex()==0; if (b==value && op==Operator.BEQ) return true; else if (b!=value && op==Operator.BNE) return true; else return false; @@ -192,7 +198,9 @@ // System.out.println("position de la valeur selectionnee : " + pos); // pos 1 = selected features case if (pos == QueryDialog.SELECTION) { - for (Iterator it = query.selection.iterator() ; it.hasNext() ;) { + // [mmichaud 2016] optimization with spatial index + Collection candidates = candidates(g, "$SELECTION", query.selection); + for (Iterator it = candidates.iterator() ; it.hasNext() ;) { Geometry p = (Geometry)it.next(); if (op==Operator.INTER && g.intersects(p)) return true; else if (op==Operator.CONTA && g.contains(p)) return true; @@ -213,7 +221,9 @@ Layer[] ll = context.getLayerNamePanel().getSelectedLayers(); for (int i = 0 ; i < ll.length ; i++) { FeatureCollection fc = ll[i].getFeatureCollectionWrapper(); - for (Iterator it = fc.iterator() ; it.hasNext() ;) { + // [mmichaud 2016] optimization with spatial index + Collection candidates = candidates(g, ll[i].getName(), fc); + for (Iterator it = candidates.iterator() ; it.hasNext() ;) { Geometry p = ((Feature)it.next()).getGeometry(); if (op==Operator.INTER && g.intersects(p)) return true; else if (op==Operator.CONTA && g.contains(p)) return true; @@ -235,7 +245,9 @@ List ll = context.getLayerManager().getLayers(); for (int i = 0 ; i < ll.size() ; i++) { FeatureCollection fc = ((Layer)ll.get(i)).getFeatureCollectionWrapper(); - for (Iterator it = fc.iterator() ; it.hasNext() ;) { + // [mmichaud 2016] optimization with spatial index + Collection candidates = candidates(g, ((Layer)ll.get(i)).getName(), fc); + for (Iterator it = candidates.iterator() ; it.hasNext() ;) { Geometry p = ((Feature)it.next()).getGeometry(); if (op==Operator.INTER && g.intersects(p)) return true; else if (op==Operator.CONTA && g.contains(p)) return true; @@ -255,7 +267,9 @@ else { Layer layer = context.getLayerManager().getLayer((String)query.valueCB.getSelectedValue()); FeatureCollection fc = layer.getFeatureCollectionWrapper(); - for (Iterator it = fc.iterator() ; it.hasNext() ;) { + // [mmichaud 2016] optimization with spatial index + Collection candidates = candidates(g, layer.getName(), fc); + for (Iterator it = candidates.iterator() ; it.hasNext() ;) { Geometry p = ((Feature)it.next()).getGeometry(); if (op==Operator.INTER && g.intersects(p)) return true; else if (op==Operator.CONTA && g.contains(p)) return true; @@ -273,6 +287,56 @@ } return false; } + + private STRtree createIndex(Collection geometries) { + STRtree index = new STRtree(); + for (Object geometry : geometries) { + index.insert(((Geometry)geometry).getEnvelopeInternal(), geometry); + } + return index; + } + + private STRtree createIndex(FeatureCollection fc) { + STRtree index = new STRtree(); + for (Feature f : fc.getFeatures()) { + index.insert(f.getGeometry().getEnvelopeInternal(), f); + } + return index; + } + + private Collection candidates(Geometry g, String collectionName, Collection collection) { + if (collection.size() > 256 && + Arrays.asList(Operator.INTER, Operator.CONTA, Operator.WITHI, Operator.WSTRI, + Operator.WDIST, Operator.TOUCH, Operator.CROSS, Operator.OVERL).contains(op)) { + STRtree index = spatialIndices.get(collectionName); + if (index == null) { + index = createIndex(collection); + spatialIndices.put(collectionName, index); + } + Envelope e = g.getEnvelopeInternal(); + if (op == Operator.WDIST) e.expandBy(Double.parseDouble(op.arg.toString())); + return index.query(e); + } else { + return collection; + } + } + + private Collection candidates(Geometry g, String collectionName, FeatureCollection collection) { + if (collection.size() > 256 && + Arrays.asList(Operator.INTER, Operator.CONTA, Operator.WITHI, Operator.WSTRI, + Operator.WDIST, Operator.TOUCH, Operator.CROSS, Operator.OVERL).contains(op)) { + STRtree index = spatialIndices.get(collectionName); + if (index == null) { + index = createIndex(collection); + spatialIndices.put(collectionName, index); + } + Envelope e = g.getEnvelopeInternal(); + if (op == Operator.WDIST) e.expandBy(Double.parseDouble(op.arg.toString())); + return index.query(e); + } else { + return collection.getFeatures(); + } + } //************************************************************************** // apply functions @@ -296,7 +360,6 @@ } private Geometry gfunction(Geometry g) { - //System.out.println("geometric function"); if (ft==Function.GNOF) return g; else if (ft==Function.CENT) return g.getInteriorPoint(); else if (ft==Function.BUFF) return g.buffer(ft.arg); @@ -304,7 +367,6 @@ } private Date dfunction(Date d) { - //System.out.println("date function"); if (ft==Function.DNOF) return d; else if (ft==Function.DDAY || ft==Function.DYEA) { Calendar cal = new GregorianCalendar(); Modified: core/trunk/src/org/openjump/core/ui/plugin/queries/QueryDialog.java =================================================================== --- core/trunk/src/org/openjump/core/ui/plugin/queries/QueryDialog.java 2016-10-26 19:26:49 UTC (rev 5108) +++ core/trunk/src/org/openjump/core/ui/plugin/queries/QueryDialog.java 2016-10-26 21:18:12 UTC (rev 5109) @@ -10,12 +10,8 @@ import com.vividsolutions.jump.util.CollectionMap; import com.vividsolutions.jump.workbench.model.*; import com.vividsolutions.jump.workbench.plugin.PlugInContext; -import com.vividsolutions.jump.workbench.ui.FeatureSelection; -import com.vividsolutions.jump.workbench.ui.InfoFrame; -import com.vividsolutions.jump.workbench.ui.LayerNameRenderer; -import com.vividsolutions.jump.workbench.ui.TaskFrame; +import com.vividsolutions.jump.workbench.ui.*; -import javax.management.RuntimeErrorException; import javax.swing.*; import javax.swing.border.Border; import java.awt.*; @@ -23,8 +19,6 @@ import java.text.SimpleDateFormat; import java.util.*; import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -45,15 +39,15 @@ public static final int ALL_LAYERS = 0; public static final int SELECTION = 1; public static final int SELECTED_LAYERS = 2; + + private static final SimpleDateFormat DATE_FORMATTER = new SimpleDateFormat(); - public static final SimpleDateFormat DATE_FORMATTER = new SimpleDateFormat(); - private PlugInContext context; // List of layers to search - List layers = new ArrayList(); + List<Layer> layers = new ArrayList<>(); // List of available attributes - Set attributes = new TreeSet(); + Set<String> attributes = new TreeSet<>(); // Selected attribute name String attribute; // Selected attribute type @@ -65,14 +59,14 @@ // Selected value String value; // Map attributes with lists of available values read in the fc - Map enumerations = new HashMap(); + private Map enumerations = new HashMap(); // Flag indicating a query is running - static boolean runningQuery = false; - static boolean cancelQuery = false; + private static boolean runningQuery = false; + private static boolean cancelQuery = false; // selected features initialized in execute query if "select" option is true - Collection selection; - + Collection selection; + BCheckBox charFilter; BCheckBox caseSensitive; BCheckBox numFilter; @@ -82,21 +76,21 @@ BCheckBox display; BCheckBox select; BCheckBox create; - + BComboBox layerCB; BComboBox attributeCB; BComboBox functionCB; BComboBox operatorCB; BComboBox valueCB; - BLabel comments; - BLabel progressBarTitle; - BProgressBar progressBar; + private BLabel comments; + private BLabel progressBarTitle; + private BProgressBar progressBar; - BButton okButton; - BButton refreshButton; - BButton cancelButton; - BButton stopButton; + private BButton okButton; + private BButton refreshButton; + private BButton cancelButton; + private BButton stopButton; /** @@ -115,7 +109,7 @@ /** * User Interface Initialization */ - protected void initUI(PlugInContext context) { + private void initUI(PlugInContext context) { // LAYOUT DEFINITIONS LayoutInfo centerNone6 = new LayoutInfo(LayoutInfo.CENTER, LayoutInfo.NONE, @@ -306,9 +300,9 @@ southPanel.add(refreshButton, 3, 0); southPanel.add(stopButton, 4, 0); - dialogContainer.add(northPanel, dialogContainer.NORTH); - dialogContainer.add(centerPanel, dialogContainer.CENTER); - dialogContainer.add(southPanel, dialogContainer.SOUTH); + dialogContainer.add(northPanel, BorderContainer.NORTH); + dialogContainer.add(centerPanel, BorderContainer.CENTER); + dialogContainer.add(southPanel, BorderContainer.SOUTH); // added on 2007-08-22 to synchronize the UI with layerNamePanel changes context.getLayerManager().addLayerListener(new LayerListener() { @@ -330,7 +324,7 @@ BButton getCancelButton() {return cancelButton;} - void initVariables() { + private void initVariables() { runningQuery = false; cancelQuery = false; progressBarTitle.setText(""); @@ -351,9 +345,8 @@ layerCB.add(I18N.get("org.openjump.core.ui.plugin.queries.SimpleQuery.selection")); layerCB.add(I18N.get("org.openjump.core.ui.plugin.queries.SimpleQuery.selected-layers")); - List layers = context.getLayerManager().getLayers(); - for (int i = 0 ; i < layers.size() ; i++) { - Layer layer = (Layer)layers.get(i); + List<Layer> layers = context.getLayerManager().getLayers(); + for (Layer layer : layers) { layerCB.add(layer); } ((javax.swing.JComboBox)layerCB.getComponent()).setRenderer(layerListCellRenderer); @@ -398,8 +391,7 @@ } // selected layer else { - //layers.add(context.getLayerManager().getLayer((String)layerCB.getSelectedValue())); - layers.add(layerCB.getSelectedValue()); + layers.add((Layer)layerCB.getSelectedValue()); } attributes.addAll(authorizedAttributes(layers)); attributeCB.setContents(attributes); @@ -418,16 +410,15 @@ else return false; } - private Set authorizedAttributes(List layers) { + private Set<String> authorizedAttributes(List<Layer> layers) { // set of authorized Attributes - Set set = new TreeSet(); + Set<String> set = new TreeSet<>(); // map of enumerations enumerations = new HashMap(); // Geometry is processed separetely in order to always have it first if (geoFilter.getState()) set.add(" (GEOMETRY)"); attribute = ""; - for (int i = 0 ; i < layers.size() ; i++) { - Layer layer = (Layer)layers.get(i); + for (Layer layer : layers) { FeatureSchema fs = layer.getFeatureCollectionWrapper().getFeatureSchema(); for (int j = 0 ; j < fs.getAttributeCount() ; j++) { String att = fs.getAttributeName(j); @@ -457,13 +448,13 @@ private void booFilterChanged() { layerChanged(); } - - public void attributeChanged() { + + private void attributeChanged() { String att = (String)attributeCB.getSelectedValue(); attribute = att.substring(0, att.lastIndexOf(' ')); String attType = att.substring(att.lastIndexOf('(')+1, att.lastIndexOf(')')); - char newat = 'S'; + char newat; if (attType.equals("INTEGER")) newat = 'N'; else if (attType.equals("LONG")) newat = 'N'; else if (attType.equals("DATE")) newat = 'D'; @@ -471,7 +462,7 @@ else if (attType.equals("STRING")) newat = 'S'; else if (attType.equals("GEOMETRY")) newat = 'G'; else if (attType.equals("BOOLEAN")) newat = 'B'; - else; + else newat = 'S';; // No type change if (newat==attributeType) { if (newat=='S') updateValues(); @@ -508,10 +499,10 @@ } } - public void functionChanged() { + private void functionChanged() { // if function is edited to change the parameter value by hand (buffer), // functionCB.getSelectedValue() class changes from Function to String - String ft = functionCB.getSelectedValue().toString(); + //String ft = functionCB.getSelectedValue().toString(); try { if (functionCB.getSelectedValue() instanceof Function) { Function newfunction = (Function)functionCB.getSelectedValue(); @@ -551,7 +542,7 @@ } } } catch(Exception e) { - context.getWorkbenchFrame().toMessage(e); + context.getWorkbenchFrame().warnUser(WorkbenchFrame.toMessage(e)); } } @@ -576,9 +567,8 @@ } } - public boolean operatorChanged() { - //Operator newop = (Operator)operatorCB.getSelectedValue(); - String newopstring = operatorCB.getSelectedValue().toString(); + private boolean operatorChanged() { + try { if (operatorCB.getSelectedValue() instanceof Operator) { Operator newop = (Operator)operatorCB.getSelectedValue(); @@ -637,7 +627,7 @@ } } catch(Exception e) { - context.getWorkbenchFrame().toMessage(e); + context.getWorkbenchFrame().warnUser(WorkbenchFrame.toMessage(e)); return false; } return true; @@ -690,29 +680,28 @@ value = (String)valueCB.getSelectedValue(); } - private List availableTargets() { - List list = new ArrayList(); + private List<String> availableTargets() { + List<String> list = new ArrayList<>(); list.add(I18N.get("org.openjump.core.ui.plugin.queries.SimpleQuery.all-layers")); list.add(I18N.get("org.openjump.core.ui.plugin.queries.SimpleQuery.selection")); list.add(I18N.get("org.openjump.core.ui.plugin.queries.SimpleQuery.selected-layers")); - List layers = context.getLayerManager().getLayers(); - for (int i = 0 ; i < layers.size() ; i++) { - list.add(((Layer)layers.get(i)).getName()); + for (Layer layer : context.getLayerManager().getLayers()) { + list.add(layer.getName()); } return list; } - + + // attribute must be f type String private Set availableStrings(String attribute, int maxsize) { - Set set = new TreeSet(); + Set<String> set = new TreeSet<>(); set.add(""); - for (int i = 0 ; i < layers.size() ; i++) { - FeatureCollection fc = ((Layer)layers.get(i)).getFeatureCollectionWrapper(); + for (Layer layer : layers) { + FeatureCollection fc = layer.getFeatureCollectionWrapper(); if (!fc.getFeatureSchema().hasAttribute(attribute)) continue; Iterator it = fc.iterator(); while (it.hasNext() && set.size()<maxsize) { Feature f = (Feature)it.next(); - Object val = f.getAttribute(attribute); - if (val != null) set.add(val); + set.add(f.getString(attribute)); } } return set; @@ -732,14 +721,14 @@ } } else {return;} - charFilter.setState(new Boolean(prop.getProperty("org.openjump.core.ui.plugin.queries.SimpleQuery.string")).booleanValue()); - caseSensitive.setState(new Boolean(prop.getProperty("org.openjump.core.ui.plugin.queries.SimpleQuery.case-sensitive")).booleanValue()); - numFilter.setState(new Boolean(prop.getProperty("org.openjump.core.ui.plugin.queries.SimpleQuery.numeric")).booleanValue()); - geoFilter.setState(new Boolean(prop.getProperty("org.openjump.core.ui.plugin.queries.SimpleQuery.geometric")).booleanValue()); + charFilter.setState(Boolean.parseBoolean(prop.getProperty("org.openjump.core.ui.plugin.queries.SimpleQuery.string"))); + caseSensitive.setState(Boolean.parseBoolean(prop.getProperty("org.openjump.core.ui.plugin.queries.SimpleQuery.case-sensitive"))); + numFilter.setState(Boolean.parseBoolean(prop.getProperty("org.openjump.core.ui.plugin.queries.SimpleQuery.numeric"))); + geoFilter.setState(Boolean.parseBoolean(prop.getProperty("org.openjump.core.ui.plugin.queries.SimpleQuery.geometric"))); - display.setState(new Boolean(prop.getProperty("org.openjump.core.ui.plugin.queries.SimpleQuery.display-the-table")).booleanValue()); - select.setState(new Boolean(prop.getProperty("org.openjump.core.ui.plugin.queries.SimpleQuery.select-the-result")).booleanValue()); - create.setState(new Boolean(prop.getProperty("org.openjump.core.ui.plugin.queries.SimpleQuery.create-a-new-layer")).booleanValue()); + display.setState(Boolean.parseBoolean(prop.getProperty("org.openjump.core.ui.plugin.queries.SimpleQuery.display-the-table"))); + select.setState(Boolean.parseBoolean(prop.getProperty("org.openjump.core.ui.plugin.queries.SimpleQuery.select-the-result"))); + create.setState(Boolean.parseBoolean(prop.getProperty("org.openjump.core.ui.plugin.queries.SimpleQuery.create-a-new-layer"))); initComboBoxes(); @@ -833,9 +822,6 @@ File f = bfc.getSelectedFile(); prop.store(new FileOutputStream(f), "Query file for Sqi4jump"); } - catch(FileNotFoundException e) { - context.getWorkbenchFrame().warnUser(e.getMessage()); - } catch(IOException e) { context.getWorkbenchFrame().warnUser(e.getMessage()); } @@ -844,12 +830,12 @@ } - void executeQuery() { + private void executeQuery() { final QueryDialog queryDialog = this; // dirty patch to avoid executing query if the operator combobox is in an invalid state // some operators are editable. If the user enter an invalid operator parameter, and then // click execute, the new user edited operator is evaluated before execution - // @TODO improve semantic of operatorChange retrun value + // @TODO improve semantic of operatorChange return value if (!operatorChanged()) return; Runnable runnable = new Runnable() { public void run() { @@ -875,20 +861,19 @@ // srcFeaturesMap keys are layers to query // srcFeaturesMap values are collection of features to query - CollectionMap srcFeaturesMap = new CollectionMap(); + CollectionMap<Layer,Feature> srcFeaturesMap = new CollectionMap<>(); int total = 0; // total number of objects to scan int featuresfound = 0; if (layerCB.getSelectedIndex() == SELECTION) { - for (Iterator it = selectedFeatures.getLayersWithSelectedItems().iterator() ; it.hasNext() ; ) { - Layer layer = (Layer)it.next(); + for (Layer layer : selectedFeatures.getLayersWithSelectedItems()) { srcFeaturesMap.put(layer, selectedFeatures.getFeaturesWithSelectedItems(layer)); } total = srcFeaturesMap.size(); } else { - for (int i = 0 ; i < layers.size() ; i++) { - total += ((Layer)layers.get(i)).getFeatureCollectionWrapper().size(); + for (Layer layer : layers) { + total += layer.getFeatureCollectionWrapper().size(); } } @@ -904,15 +889,13 @@ // initialization for infoframe InfoFrame info = null; if(display.getState()) { - info = new InfoFrame(context.getWorkbenchContext(), - (LayerManagerProxy)context, + info = new InfoFrame(context.getWorkbenchContext(), context, (TaskFrame)context.getWorkbenchFrame().getActiveInternalFrame()); } // Loop on the requested layers int count = 0; - for (int i = 0 ; i < layers.size() ; i++) { - Layer layer = (Layer)layers.get(i); + for (Layer layer : layers) { FeatureCollection fc = layer.getFeatureCollectionWrapper(); // When the user choose all layers, some attributes are not @@ -920,10 +903,10 @@ if(attributeType!='G' && !fc.getFeatureSchema().hasAttribute(attribute)) continue; //monitor.report(layer.getName()); - Collection features = null; + Collection<Feature> features; // case 1 : query only selected features if (layerCB.getSelectedIndex()==1) { - features = (Collection)srcFeaturesMap.get(layer); + features = srcFeaturesMap.get(layer); } // other cases : query the whole layer else { @@ -941,21 +924,20 @@ FeatureCollection dataset = new FeatureDataset(fc.getFeatureSchema()); // initialize a new list for the new selection - List<Feature> okFeatures = new ArrayList<Feature>(); + List<Feature> okFeatures = new ArrayList<>(); int mod = 1; if (total > 1000) mod = 10; if (total > 33000) mod = 100; if (total > 1000000) mod = 1000; try { - for (Iterator it = features.iterator() ; it.hasNext() ; ) { + for (Feature feature : features) { count++; if (count%mod==0) { progressBar.setProgressText(""+count+"/"+total); progressBar.setValue(count); } - Feature f = (BasicFeature)it.next(); - if (condition.test(f)) { - okFeatures.add(f); + if (condition.test(feature)) { + okFeatures.add(feature); featuresfound++; } Thread.yield(); @@ -970,15 +952,14 @@ if (cancelQuery) break; if (okFeatures.size()==0) continue; - - // + if(select.getState()) { selectedFeatures.selectItems(layer, okFeatures); } if(create.getState()) { for (Feature f : okFeatures) { - dataset.add((Feature)f.clone()); + dataset.add(f.clone()); } String outputLayerName = layer.getName() + "_"; if (attributeType != 'G') { Modified: core/trunk/src/org/openjump/core/ui/plugin/queries/SimpleQueryPlugIn.java =================================================================== --- core/trunk/src/org/openjump/core/ui/plugin/queries/SimpleQueryPlugIn.java 2016-10-26 19:26:49 UTC (rev 5108) +++ core/trunk/src/org/openjump/core/ui/plugin/queries/SimpleQueryPlugIn.java 2016-10-26 21:18:12 UTC (rev 5109) @@ -1,7 +1,6 @@ package org.openjump.core.ui.plugin.queries; import com.vividsolutions.jump.I18N; -import com.vividsolutions.jump.workbench.WorkbenchContext; import com.vividsolutions.jump.workbench.plugin.AbstractPlugIn; import com.vividsolutions.jump.workbench.plugin.EnableCheck; import com.vividsolutions.jump.workbench.plugin.EnableCheckFactory; @@ -24,8 +23,9 @@ * @version 0.2 (16 Oct 2005) */ public class SimpleQueryPlugIn extends AbstractPlugIn { - static QueryDialog queryDialog; + private static QueryDialog queryDialog; + public void initialize(PlugInContext context) throws Exception { context.getFeatureInstaller().addMainMenuPlugin (this, ------------------------------------------------------------------------------ The Command Line: Reinvented for Modern Developers Did the resurgence of CLI tooling catch you by surprise? Reconnect with the command line and become more productive. Learn the new .NET and ASP.NET CLI. Get your free copy! http://sdm.link/telerik _______________________________________________ Jump-pilot-devel mailing list Jump-pilot-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/jump-pilot-devel