/***************************************************
*
* cismet GmbH, Saarbruecken, Germany
*
* ... and it just works.
*
****************************************************/
package de.cismet.cids.search;
import org.apache.log4j.Logger;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.Namespace;
import org.jdom.input.SAXBuilder;
import org.openide.util.NbBundle;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import javax.swing.SwingWorker;
import de.cismet.cismap.commons.features.DefaultFeatureCollection;
import de.cismet.cismap.commons.features.Feature;
import de.cismet.cismap.commons.features.FeatureWithId;
import de.cismet.cismap.commons.featureservice.AbstractFeatureService;
import de.cismet.cismap.commons.featureservice.FeatureServiceUtilities;
import de.cismet.cismap.commons.featureservice.WebFeatureService;
import de.cismet.cismap.commons.featureservice.factory.AbstractFeatureFactory;
import de.cismet.cismap.commons.featureservice.factory.FeatureFactory;
import de.cismet.cismap.commons.gui.MappingComponent;
import de.cismet.cismap.commons.gui.piccolo.PFeature;
import de.cismet.cismap.commons.gui.piccolo.eventlistener.SelectionListener;
import de.cismet.cismap.commons.interaction.CismapBroker;
import de.cismet.commons.concurrency.CismetExecutors;
/**
* DOCUMENT ME!
*
* @author therter
* @version $Revision$, $Date$
*/
@org.openide.util.lookup.ServiceProvider(service = QuerySearchMethod.class)
public class SelectQuerySearchMethod implements QuerySearchMethod {
//~ Static fields/initializers ---------------------------------------------
private static final Logger LOG = Logger.getLogger(SelectQuerySearchMethod.class);
//~ Instance fields --------------------------------------------------------
private QuerySearch querySearch;
private boolean searching = false;
private SearchAndSelectThread searchThread;
private Object lastLayer;
//~ Methods ----------------------------------------------------------------
@Override
public void setQuerySearch(final QuerySearch querySearch) {
this.querySearch = querySearch;
}
@Override
public void actionPerformed(final Object layer, final String query) {
if (LOG.isInfoEnabled()) {
LOG.info((searching ? "Cancel" : "Search") + " button was clicked.");
}
if (searching) {
if (searchThread != null) {
if (lastLayer instanceof AbstractFeatureService) {
final FeatureFactory ff = ((AbstractFeatureService)lastLayer).getFeatureFactory();
if (ff instanceof AbstractFeatureFactory) {
((AbstractFeatureFactory)ff).waitUntilInterruptedIsAllowed();
}
}
searchThread.cancel(true);
}
} else {
lastLayer = layer;
searchThread = new SearchAndSelectThread(layer, query);
CismetExecutors.newSingleThreadExecutor().submit(searchThread);
searching = true;
querySearch.setControlsAccordingToState(searching);
}
}
@Override
public String toString() {
return NbBundle.getMessage(SearchQuerySearchMethod.class, "SelectQuerySearchMethod.toString");
}
//~ Inner Classes ----------------------------------------------------------
/**
* DOCUMENT ME!
*
* @version $Revision$, $Date$
*/
private class SearchAndSelectThread extends SwingWorker<List<FeatureWithId>, Void> {
//~ Instance fields ----------------------------------------------------
private Object layer;
private String query;
//~ Constructors -------------------------------------------------------
/**
* Creates a new SearchAndSelectThread object.
*
* @param layer DOCUMENT ME!
* @param query DOCUMENT ME!
*/
public SearchAndSelectThread(final Object layer, final String query) {
this.layer = layer;
this.query = query;
}
//~ Methods ------------------------------------------------------------
@Override
protected List<FeatureWithId> doInBackground() throws Exception {
List<FeatureWithId> features = null;
if (layer instanceof WebFeatureService) {
final WebFeatureService wfs = (WebFeatureService)layer;
try {
final Element e = (Element)wfs.getQueryElement().clone();
final Element queryElement = e.getChild(
"Query",
Namespace.getNamespace("wfs", "http://www.opengis.net/wfs"));
queryElement.removeChild("Filter", Namespace.getNamespace("ogc", "http://www.opengis.net/ogc"));
final Element filterElement = new Element(
"Filter",
Namespace.getNamespace("ogc", "http://www.opengis.net/ogc"));
final SAXBuilder builder = new SAXBuilder();
final Document d = builder.build(new StringReader(query));
filterElement.addContent((Element)d.getRootElement().clone());
queryElement.addContent(0, filterElement);
features = wfs.getFeatureFactory()
.createFeatures(FeatureServiceUtilities.elementToString(e),
CismapBroker.getInstance().getMappingComponent().getCurrentBoundingBox(),
null,
0,
0,
null);
} catch (Exception ex) {
LOG.error("Error while retrieving features", ex);
}
} else if (layer instanceof AbstractFeatureService) {
final AbstractFeatureService fs = (AbstractFeatureService)layer;
features = fs.getFeatureFactory()
.createFeatures(
query,
CismapBroker.getInstance().getMappingComponent().getCurrentBoundingBox(),
null,
0,
0,
null);
}
return features;
}
@Override
protected void done() {
try {
final List<FeatureWithId> features = get();
if (isCancelled()) {
return;
}
if ((features != null) && (layer instanceof AbstractFeatureService)) {
final AbstractFeatureService service = (AbstractFeatureService)layer;
final List<Feature> toBeSelected = new ArrayList<Feature>();
final List<Feature> toBeUnselected = new ArrayList<Feature>();
for (final Object featureObject : service.getPNode().getChildrenReference()) {
final PFeature feature = (PFeature)featureObject;
final FeatureWithId featureWithId = (FeatureWithId)feature.getFeature();
if (isCancelled()) {
return;
}
if (isFeatureInList(featureWithId, features)) {
if (!feature.isSelected()) {
feature.setSelected(true);
final SelectionListener sl = (SelectionListener)CismapBroker.getInstance()
.getMappingComponent()
.getInputEventListener()
.get(MappingComponent.SELECT);
sl.addSelectedFeature(feature);
toBeSelected.add(feature.getFeature());
}
} else {
if (feature.isSelected()) {
feature.setSelected(false);
final SelectionListener sl = (SelectionListener)CismapBroker.getInstance()
.getMappingComponent()
.getInputEventListener()
.get(MappingComponent.SELECT);
sl.removeSelectedFeature(feature);
toBeUnselected.add(feature.getFeature());
}
}
}
((DefaultFeatureCollection)CismapBroker.getInstance().getMappingComponent().getFeatureCollection())
.addToSelection(toBeSelected);
((DefaultFeatureCollection)CismapBroker.getInstance().getMappingComponent().getFeatureCollection())
.unselect(toBeUnselected);
}
} catch (Exception e) {
LOG.error("Error while selecting features", e);
}
searching = false;
querySearch.setControlsAccordingToState(searching);
}
/**
* DOCUMENT ME!
*
* @param f DOCUMENT ME!
* @param list DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
private boolean isFeatureInList(final FeatureWithId f, final List<FeatureWithId> list) {
for (final FeatureWithId tmp : list) {
if (tmp.getId() == f.getId()) {
return true;
}
}
return false;
}
}
}