bboxdb-tools/src/main/java/org/bboxdb/tools/gui/views/query/QueryWindow.java
/*******************************************************************************
*
* Copyright (C) 2015-2022 the BBoxDB project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*******************************************************************************/
package org.bboxdb.tools.gui.views.query;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
import org.bboxdb.commons.InputParseException;
import org.bboxdb.commons.MathUtil;
import org.bboxdb.commons.math.Hyperrectangle;
import org.bboxdb.misc.BBoxDBException;
import org.bboxdb.network.client.BBoxDBCluster;
import org.bboxdb.network.client.future.client.JoinedTupleListFuture;
import org.bboxdb.network.client.future.client.TupleListFuture;
import org.bboxdb.query.ContinuousQueryPlan;
import org.bboxdb.query.QueryPlanBuilder;
import org.bboxdb.query.filter.UserDefinedFilterDefinition;
import org.bboxdb.query.filter.UserDefinedGeoJsonSpatialFilter;
import org.bboxdb.query.filter.UserDefinedGeoJsonSpatialFilterStrict;
import org.bboxdb.storage.entity.MultiTuple;
import org.bboxdb.storage.entity.Tuple;
import org.bboxdb.tools.gui.GuiModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Stopwatch;
import com.jgoodies.forms.builder.PanelBuilder;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;
public class QueryWindow {
/**
* The query types
*/
private static final String QUERY_NONE = "---";
private static final String QUERY_RANGE = "Range query";
private static final String QUERY_JOIN = "Spatial join";
private static final String QUERY_RANGE_CONTINUOUS = "Continuous range query";
private static final String QUERY_JOIN_CONTINUOUS = "Continuous spatial join";
/**
* The predefined queries
*/
private static final String QUERY_PREDEFINED_NONE = "----";
private static final String QUERY_PREDEFINED_STATIC_ROADS = "Roads (Static)";
private static final String QUERY_PREDEFINED_STATIC_FOREST = "Forest (Static)";
private static final String QUERY_PREDEFINED_AIRCRAFT = "Aircraft";
private static final String QUERY_PREDEFINED_BUS = "Buses";
private static final String QUERY_PREDEFINED_BUS_ROAD = "Buses joined with Road";
private static final String QUERY_PREDEFINED_BUS_ELIZABETH = "Buses on Elizabeth Street";
private static final String QUERY_PREDEFINED_BUS_BRIDGE = "Buses on a Bridge";
private static final String QUERY_PREDEFINED_BUS_FOREST_BBOX = "Buses joined with Forest (bbox)";
private static final String QUERY_PREDEFINED_BUS_FOREST_RELAXTED = "Buses joined with Forest (relaxed)";
private static final String QUERY_PREDEFINED_BUS_FOREST_STRICT = "Buses joined with Forest (strict)";
private static final String QUERY_PREDEFINED_STATIC_ROAD_VALUE = "Road with value";
private static final String QUERY_PREDEFINED_STATIC_ROAD_FOREST_JOIN = "Road joined with Forest";
/**
* The main frame
*/
private JFrame mainframe;
/**
* The gui model
*/
private final GuiModel guimodel;
/**
* Selected range latitude begin
*/
private String selectedLatBegin = "-90";
/**
* Selected range latitude end
*/
private String selectedLatEnd = "90";
/**
* Selected range longitude begin
*/
private String selectedLongBegin = "-180";
/**
* Selected range longitude end
*/
private String selectedLongEnd = "180";
/**
* The data to draw
*/
private final ElementOverlayPainter painter;
/**
* The color names for the dropdowns
*/
private final static String[] COLOR_NAMES = new String[] {"Red", "Green",
"Blue", "Yellow", "Orange", "Pink"};
/**
* The color values
*/
private final static Color[] COLOR_VALUES = new Color[] {Color.RED, Color.GREEN,
Color.BLUE, Color.YELLOW, Color.ORANGE, Color.PINK};
/**
* True / False names
*/
private final static String[] BOOL_NAMES = new String[] {"Enabled", "Disabled"};
/**
* True / False values
*/
private final static Boolean[] BOOL_VALUES = new Boolean[] {true, false};
/**
* The predefined query values
*/
private final static String[] PREDEFINED_QUERIES = new String[] {QUERY_PREDEFINED_NONE,
QUERY_PREDEFINED_STATIC_ROADS, QUERY_PREDEFINED_STATIC_FOREST,
QUERY_PREDEFINED_AIRCRAFT, QUERY_PREDEFINED_BUS, QUERY_PREDEFINED_BUS_ROAD,
QUERY_PREDEFINED_BUS_ELIZABETH, QUERY_PREDEFINED_BUS_BRIDGE, QUERY_PREDEFINED_BUS_FOREST_BBOX,
QUERY_PREDEFINED_BUS_FOREST_RELAXTED, QUERY_PREDEFINED_BUS_FOREST_STRICT,
QUERY_PREDEFINED_STATIC_ROAD_VALUE, QUERY_PREDEFINED_STATIC_ROAD_FOREST_JOIN};
/**
* The created background threads
*/
private List<Thread> backgroundThreads;
/**
* The logger
*/
private final static Logger logger = LoggerFactory.getLogger(QueryWindow.class);
public QueryWindow(final GuiModel guimodel, final ElementOverlayPainter painter,
final List<Thread> backgroundThreads) {
this.guimodel = guimodel;
this.painter = painter;
this.backgroundThreads = backgroundThreads;
}
public void show() {
this.mainframe = new JFrame("BBoxDB - Execute query");
final PanelBuilder builder = buildDialog();
mainframe.add(builder.getPanel());
mainframe.pack();
mainframe.setLocationRelativeTo(null);
mainframe.setVisible(true);
}
private PanelBuilder buildDialog() {
final FormLayout layout = new FormLayout(
"right:pref, 3dlu, 120dlu, 10dlu, right:pref, 3dlu, 100dlu", // columns
"p, 3dlu, p, 3dlu, p, 3dlu, p, 3dlu, p, 3dlu, p, 3dlu, p, 3dlu, p, 3dlu, p, 3dlu, p, 9dlu, p"); // rows
final PanelBuilder builder = new PanelBuilder(layout);
builder.setDefaultDialogBorder();
final List<String> allTables = guimodel.getAllTables();
final String[] allTableArray = allTables.toArray(new String[0]);
final CellConstraints cc = new CellConstraints();
builder.addSeparator("Query", cc.xyw(1, 1, 3));
builder.addLabel("Type", cc.xy (1, 3));
final String[] queries = new String[] {QUERY_NONE, QUERY_RANGE, QUERY_JOIN,
QUERY_RANGE_CONTINUOUS, QUERY_JOIN_CONTINUOUS};
final JComboBox<String> queryTypeBox = new JComboBox<>(queries);
builder.add(queryTypeBox, cc.xy (3, 3));
builder.addLabel("Table 1", cc.xy (1, 5));
final JComboBox<String> table1Field = new JComboBox<>(allTableArray);
table1Field.setEnabled(false);
builder.add(table1Field, cc.xy (3, 5));
builder.addLabel("Color for table 1", cc.xy (1, 7));
final JComboBox<String> table1ColorField = new JComboBox<>(COLOR_NAMES);
table1ColorField.setSelectedItem(COLOR_NAMES[0]);
table1ColorField.setEnabled(false);
builder.add(table1ColorField, cc.xy (3, 7));
builder.addLabel("Table 2", cc.xy (1, 9));
final JComboBox<String> table2Field = new JComboBox<>(allTableArray);
table2Field.setEnabled(false);
builder.add(table2Field, cc.xy (3, 9));
builder.addLabel("Color for table 2", cc.xy (1, 11));
final JComboBox<String> table2ColorField = new JComboBox<>(COLOR_NAMES);
table2ColorField.setSelectedItem(COLOR_NAMES[2]);
table2ColorField.setEnabled(false);
builder.add(table2ColorField, cc.xy (3, 11));
builder.addLabel("Receive watermarks", cc.xy (1, 13));
final JComboBox<String> receiveWatermarksField = new JComboBox<>(BOOL_NAMES);
receiveWatermarksField.setEnabled(false);
builder.add(receiveWatermarksField, cc.xy (3, 13));
builder.addLabel("Receive invalidations", cc.xy (1, 15));
final JComboBox<String> receiveInvalidationsField = new JComboBox<>(BOOL_NAMES);
receiveInvalidationsField.setEnabled(false);
builder.add(receiveInvalidationsField, cc.xy (3, 15));
builder.addSeparator("Predefined Queries", cc.xyw(1, 17, 3));
builder.addLabel("Query", cc.xy (1, 19));
final JComboBox<String> predefinedQueriesBox = new JComboBox<>(PREDEFINED_QUERIES);
predefinedQueriesBox.setSelectedItem(PREDEFINED_QUERIES[0]);
predefinedQueriesBox.setEnabled(true);
builder.add(predefinedQueriesBox, cc.xy (3, 19));
builder.addSeparator("Parameter", cc.xyw(5, 1, 3));
builder.addLabel("Longitude begin", cc.xy (5, 3));
final JTextField longBegin = new JTextField();
longBegin.setText(selectedLongBegin);
builder.add(longBegin, cc.xy (7, 3));
builder.addLabel("Longitude end", cc.xy (5, 5));
final JTextField longEnd = new JTextField();
longEnd.setText(selectedLongEnd);
builder.add(longEnd, cc.xy (7, 5));
builder.addLabel("Latitude begin", cc.xy (5, 7));
final JTextField latBegin = new JTextField();
latBegin.setText(selectedLatBegin);
builder.add(latBegin, cc.xy (7, 7));
builder.addLabel("Latitude end", cc.xy (5, 9));
final JTextField latEnd = new JTextField();
latEnd.setText(selectedLatEnd);
builder.add(latEnd, cc.xy (7, 9));
builder.addLabel("UDF Name", cc.xy (5, 11));
final JTextField udfNameField = new JTextField();
builder.add(udfNameField, cc.xy (7, 11));
builder.addLabel("UDF Value", cc.xy (5, 13));
final JTextField udfValueField = new JTextField();
builder.add(udfValueField, cc.xy (7, 13));
// Close
final JButton closeButton = new JButton();
closeButton.setText("Close");
closeButton.addActionListener((e) -> {
mainframe.dispose();
});
final Action executeAction = getExecuteAction(queryTypeBox,
table1Field, table1ColorField, table2Field, table2ColorField,
longBegin, longEnd, latBegin, latEnd, udfNameField, udfValueField,
receiveWatermarksField, receiveInvalidationsField);
final JButton executeButton = new JButton(executeAction);
executeButton.setText("Execute");
executeButton.setEnabled(false);
addActionListener(queryTypeBox, predefinedQueriesBox,
table1Field, table1ColorField, table2Field,
table2ColorField, executeButton, udfNameField, udfValueField,
receiveWatermarksField, receiveInvalidationsField);
builder.add(closeButton, cc.xy(5, 21));
builder.add(executeButton, cc.xy(7, 21));
return builder;
}
/**
* Add the drop down action listener
* @param queryTypeBox
* @param table1Field
* @param table2Field
* @param executeButton
*/
private void addActionListener(final JComboBox<String> queryTypeBox, final JComboBox<String> predefinedQueriesBox,
final JComboBox<String> table1Field, final JComboBox<String> table1ColorField,
final JComboBox<String> table2Field, final JComboBox<String> table2ColorField,
final JButton executeButton, final JTextField udfNameField, final JTextField udfValueField,
final JComboBox<String> receiveWatermarksField, final JComboBox<String> receiveInvalidationsField) {
// The predefined queries
predefinedQueriesBox.addActionListener(l -> {
final String selectedPredefinedQuery = predefinedQueriesBox.getSelectedItem().toString();
switch(selectedPredefinedQuery) {
case QUERY_PREDEFINED_NONE:
udfNameField.setText("");
udfValueField.setText("");
queryTypeBox.setSelectedItem(QUERY_RANGE);
break;
case QUERY_PREDEFINED_STATIC_ROADS:
udfNameField.setText("");
udfValueField.setText("");
table1Field.setSelectedItem("osmgroup_roads");
table1ColorField.setSelectedItem("Blue");
queryTypeBox.setSelectedItem(QUERY_RANGE);
executeButton.setEnabled(true);
table1Field.setEnabled(true);
table1ColorField.setEnabled(true);
table2Field.setEnabled(false);
table2ColorField.setEnabled(false);
receiveWatermarksField.setEnabled(false);
receiveInvalidationsField.setEnabled(false);
break;
case QUERY_PREDEFINED_STATIC_ROAD_VALUE:
udfNameField.setText(UserDefinedGeoJsonSpatialFilter.class.getCanonicalName());
udfValueField.setText("lanes:4");
table1Field.setSelectedItem("osmgroup_roads");
table1ColorField.setSelectedItem("Blue");
queryTypeBox.setSelectedItem(QUERY_RANGE);
executeButton.setEnabled(true);
table1Field.setEnabled(true);
table1ColorField.setEnabled(true);
table2Field.setEnabled(false);
table2ColorField.setEnabled(false);
receiveWatermarksField.setEnabled(false);
receiveInvalidationsField.setEnabled(false);
break;
case QUERY_PREDEFINED_STATIC_ROAD_FOREST_JOIN:
udfNameField.setText(UserDefinedGeoJsonSpatialFilter.class.getCanonicalName());
udfValueField.setText("");
table1Field.setSelectedItem("osmgroup_roads");
table2Field.setSelectedItem("osmgroup_forests");
table1ColorField.setSelectedItem("Blue");
table2ColorField.setSelectedItem("Green");
queryTypeBox.setSelectedItem(QUERY_JOIN);
executeButton.setEnabled(true);
table1Field.setEnabled(true);
table1ColorField.setEnabled(true);
table2Field.setEnabled(true);
table2ColorField.setEnabled(true);
receiveWatermarksField.setEnabled(false);
receiveInvalidationsField.setEnabled(false);
break;
case QUERY_PREDEFINED_STATIC_FOREST:
udfNameField.setText("");
udfValueField.setText("");
table1Field.setSelectedItem("osmgroup_forests");
table1ColorField.setSelectedItem("Green");
queryTypeBox.setSelectedItem(QUERY_RANGE);
executeButton.setEnabled(true);
table1Field.setEnabled(true);
table1ColorField.setEnabled(true);
table2Field.setEnabled(false);
table2ColorField.setEnabled(false);
receiveWatermarksField.setEnabled(false);
receiveInvalidationsField.setEnabled(false);
break;
case QUERY_PREDEFINED_AIRCRAFT:
udfNameField.setText("");
udfValueField.setText("");
table1Field.setSelectedItem("osmgroup_adsb");
queryTypeBox.setSelectedItem(QUERY_RANGE_CONTINUOUS);
executeButton.setEnabled(true);
table1Field.setEnabled(true);
table1ColorField.setEnabled(true);
table2Field.setEnabled(false);
table2ColorField.setEnabled(false);
receiveWatermarksField.setEnabled(true);
receiveInvalidationsField.setEnabled(true);
break;
case QUERY_PREDEFINED_BUS:
udfNameField.setText("");
udfValueField.setText("");
table1Field.setSelectedItem("osmgroup_buses");
queryTypeBox.setSelectedItem(QUERY_RANGE_CONTINUOUS);
executeButton.setEnabled(true);
table1Field.setEnabled(true);
table1ColorField.setEnabled(true);
table2Field.setEnabled(false);
table2ColorField.setEnabled(false);
table2ColorField.setSelectedItem("Blue");
receiveWatermarksField.setEnabled(true);
receiveInvalidationsField.setEnabled(true);
break;
case QUERY_PREDEFINED_BUS_ROAD:
udfNameField.setText(UserDefinedGeoJsonSpatialFilter.class.getCanonicalName());
udfValueField.setText("");
table1Field.setSelectedItem("osmgroup_buses");
table2Field.setSelectedItem("osmgroup_roads");
queryTypeBox.setSelectedItem(QUERY_JOIN_CONTINUOUS);
executeButton.setEnabled(true);
table1Field.setEnabled(true);
table1ColorField.setEnabled(true);
table2Field.setEnabled(true);
table2ColorField.setEnabled(true);
table2ColorField.setSelectedItem("Blue");
receiveWatermarksField.setEnabled(true);
receiveInvalidationsField.setEnabled(true);
break;
case QUERY_PREDEFINED_BUS_ELIZABETH:
udfNameField.setText(UserDefinedGeoJsonSpatialFilter.class.getCanonicalName());
udfValueField.setText("name:Elizabeth Street");
table1Field.setSelectedItem("osmgroup_buses");
table2Field.setSelectedItem("osmgroup_roads");
queryTypeBox.setSelectedItem(QUERY_JOIN_CONTINUOUS);
executeButton.setEnabled(true);
table1Field.setEnabled(true);
table1ColorField.setEnabled(true);
table2Field.setEnabled(true);
table2ColorField.setEnabled(true);
table2ColorField.setSelectedItem("Blue");
receiveWatermarksField.setEnabled(true);
receiveInvalidationsField.setEnabled(true);
break;
case QUERY_PREDEFINED_BUS_BRIDGE:
udfNameField.setText(UserDefinedGeoJsonSpatialFilter.class.getCanonicalName());
udfValueField.setText("bridge:yes");
table1Field.setSelectedItem("osmgroup_buses");
table2Field.setSelectedItem("osmgroup_roads");
queryTypeBox.setSelectedItem(QUERY_JOIN_CONTINUOUS);
executeButton.setEnabled(true);
table1Field.setEnabled(true);
table1ColorField.setEnabled(true);
table2Field.setEnabled(true);
table2ColorField.setEnabled(true);
table2ColorField.setSelectedItem("Blue");
receiveWatermarksField.setEnabled(true);
receiveInvalidationsField.setEnabled(true);
break;
case QUERY_PREDEFINED_BUS_FOREST_BBOX:
udfNameField.setText("");
udfValueField.setText("");
table1Field.setSelectedItem("osmgroup_buses");
table2Field.setSelectedItem("osmgroup_forests");
queryTypeBox.setSelectedItem(QUERY_JOIN_CONTINUOUS);
executeButton.setEnabled(true);
table1Field.setEnabled(true);
table1ColorField.setEnabled(true);
table2Field.setEnabled(true);
table2ColorField.setEnabled(true);
table2ColorField.setSelectedItem("Green");
receiveWatermarksField.setEnabled(true);
receiveInvalidationsField.setEnabled(true);
break;
case QUERY_PREDEFINED_BUS_FOREST_RELAXTED:
udfNameField.setText(UserDefinedGeoJsonSpatialFilter.class.getCanonicalName());
udfValueField.setText("");
table1Field.setSelectedItem("osmgroup_buses");
table2Field.setSelectedItem("osmgroup_forests");
queryTypeBox.setSelectedItem(QUERY_JOIN_CONTINUOUS);
executeButton.setEnabled(true);
table1Field.setEnabled(true);
table1ColorField.setEnabled(true);
table2Field.setEnabled(true);
table2ColorField.setEnabled(true);
table2ColorField.setSelectedItem("Green");
receiveWatermarksField.setEnabled(true);
receiveInvalidationsField.setEnabled(true);
break;
case QUERY_PREDEFINED_BUS_FOREST_STRICT:
udfNameField.setText(UserDefinedGeoJsonSpatialFilterStrict.class.getCanonicalName());
udfValueField.setText("");
table1Field.setSelectedItem("osmgroup_buses");
table2Field.setSelectedItem("osmgroup_forests");
queryTypeBox.setSelectedItem(QUERY_JOIN_CONTINUOUS);
executeButton.setEnabled(true);
table1Field.setEnabled(true);
table1ColorField.setEnabled(true);
table2Field.setEnabled(true);
table2ColorField.setEnabled(true);
table2ColorField.setSelectedItem("Green");
receiveWatermarksField.setEnabled(true);
receiveInvalidationsField.setEnabled(true);
break;
default:
logger.error("Unknown selection: " + selectedPredefinedQuery);
}
});
// The normal queries
queryTypeBox.addActionListener(l -> {
// Are predefined queries in control?
if(! predefinedQueriesBox.getSelectedItem().toString().equals(QUERY_PREDEFINED_NONE)) {
return;
}
final String selectedQuery = queryTypeBox.getSelectedItem().toString();
switch (selectedQuery) {
case QUERY_RANGE:
table1Field.setEnabled(true);
table1ColorField.setEnabled(true);
table2Field.setEnabled(false);
table2ColorField.setEnabled(false);
executeButton.setEnabled(true);
udfNameField.setText("");
udfValueField.setText("");
receiveWatermarksField.setEnabled(false);
receiveInvalidationsField.setEnabled(false);
break;
case QUERY_RANGE_CONTINUOUS:
table1Field.setEnabled(true);
table1ColorField.setEnabled(true);
table2Field.setEnabled(false);
table2ColorField.setEnabled(false);
executeButton.setEnabled(true);
udfNameField.setText("");
udfValueField.setText("");
receiveWatermarksField.setEnabled(true);
receiveInvalidationsField.setEnabled(true);
break;
case QUERY_JOIN:
table1Field.setEnabled(true);
table1ColorField.setEnabled(true);
table2Field.setEnabled(true);
table2ColorField.setEnabled(true);
executeButton.setEnabled(true);
udfNameField.setText("");
udfValueField.setText("");
receiveWatermarksField.setEnabled(false);
receiveInvalidationsField.setEnabled(false);
break;
case QUERY_JOIN_CONTINUOUS:
table1Field.setEnabled(true);
table1ColorField.setEnabled(true);
table2Field.setEnabled(true);
table2ColorField.setEnabled(true);
executeButton.setEnabled(true);
udfNameField.setText("");
udfValueField.setText("");
receiveWatermarksField.setEnabled(true);
receiveInvalidationsField.setEnabled(true);
break;
default:
table1Field.setEnabled(false);
table1ColorField.setEnabled(false);
table2Field.setEnabled(false);
table1ColorField.setEnabled(false);
executeButton.setEnabled(false);
udfNameField.setText("");
udfValueField.setText("");
break;
}
});
}
/**
* Get the execute action
* @param valueField
* @param filterField
* @param rangeField
* @param table2Field
* @param table1Field
* @param queryTypeBox
* @return
*/
private Action getExecuteAction(final JComboBox<String> queryTypeBox,
final JComboBox<String> table1Field, final JComboBox<String> color1Box,
final JComboBox<String> table2Field, final JComboBox<String> color2Box,
final JTextField longBegin, final JTextField longEnd, final JTextField latBegin,
final JTextField latEnd, final JTextField filterField, final JTextField valueField,
final JComboBox<String> receiveWatermarksField, final JComboBox<String> receiveInvalidationsField) {
final AbstractAction ececuteAction = new AbstractAction() {
/**
*
*/
private static final long serialVersionUID = 6307940821474247538L;
@Override
public void actionPerformed(final ActionEvent e) {
try {
final String queryType = queryTypeBox.getSelectedItem().toString();
final String table1 = table1Field.getSelectedItem().toString();
final String table2 = table2Field.getSelectedItem().toString();
final String filter = filterField.getText();
final String value = valueField.getText();
final double longBeginDouble = MathUtil.tryParseDouble(longBegin.getText(), () -> "Unable to parse value");
final double longEndDouble = MathUtil.tryParseDouble(longEnd.getText(), () -> "Unable to parse value");
final double latBeginDouble = MathUtil.tryParseDouble(latBegin.getText(), () -> "Unable to parse value");
final double latEndDouble = MathUtil.tryParseDouble(latEnd.getText(), () -> "Unable to parse value");
final Hyperrectangle resultBox = new Hyperrectangle(latBeginDouble, latEndDouble,
longBeginDouble, longEndDouble);
final Color color1 = COLOR_VALUES[color1Box.getSelectedIndex()];
final Color color2 = COLOR_VALUES[color2Box.getSelectedIndex()];
final boolean receiveWatermarks = BOOL_VALUES[receiveWatermarksField.getSelectedIndex()];
final boolean receiveInvalidations = BOOL_VALUES[receiveInvalidationsField.getSelectedIndex()];
switch (queryType) {
case QUERY_RANGE:
executeRangeQuery(resultBox, table1, color1, filter, value);
break;
case QUERY_JOIN:
executeJoinQuery(resultBox, table1, color1, table2, color2, filter, value);
break;
case QUERY_RANGE_CONTINUOUS:
executeRangeQueryContinuous(resultBox, table1, color1, filter, value,
receiveWatermarks, receiveInvalidations);
break;
case QUERY_JOIN_CONTINUOUS:
executeJoinQueryContinuous(resultBox, table1, table2, color1, color2,
filter, value, receiveWatermarks, receiveInvalidations);
break;
default:
throw new IllegalArgumentException("Unknown action: " + queryType);
}
mainframe.dispose();
} catch (InputParseException exception) {
JOptionPane.showMessageDialog(mainframe, "Got an error: " + exception.getMessage());
}
}
/***
* Execute a join query
* @param customValue
* @param customFilter
* @param table2
* @param table1
* @param bbox
*/
private void executeJoinQuery(final Hyperrectangle bbox, final String table1,
final Color color1, final String table2, final Color color2,
final String customFilter, final String customValue) {
try {
final List<UserDefinedFilterDefinition> udfs = new ArrayList<>();
if(customFilter.length() > 1) {
final UserDefinedFilterDefinition udf = new UserDefinedFilterDefinition(customFilter, customValue);
udfs.add(udf);
}
final Stopwatch stopwatch = Stopwatch.createStarted();
final JoinedTupleListFuture result = guimodel.getConnection().querySpatialJoin(
Arrays.asList(table1, table2), bbox, udfs);
result.waitForCompletion();
stopwatch.stop();
if(result.isFailed()) {
logger.error("Got an error" + result.getAllMessages());
return;
}
final List<OverlayElementGroup> elements = new ArrayList<>();
final List<Color> colors = Arrays.asList(color1, color2);
for(final MultiTuple joinedTuple : result) {
final OverlayElementGroup group
= OverlayElementBuilder.createOverlayElementGroup(joinedTuple, colors);
elements.add(group);
}
logger.info("Got {} tuples back in {} / {} ms",
elements.size(), result.getCompletionTime(TimeUnit.MILLISECONDS), stopwatch.elapsed(TimeUnit.MILLISECONDS));
painter.addElementToDrawBulk(elements);
} catch (BBoxDBException e) {
logger.error("Got error while performing query", e);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
}
}
/**
* Execute a range query
* @param customValue
* @param customFilter
* @param table
* @param bbox
*/
private void executeRangeQuery(final Hyperrectangle bbox, final String table,
final Color color, final String customFilter, final String customValue) {
try {
final List<UserDefinedFilterDefinition> udfs = new ArrayList<>();
if(customFilter.length() > 1) {
final UserDefinedFilterDefinition udf = new UserDefinedFilterDefinition(customFilter, customValue);
udfs.add(udf);
}
final Stopwatch stopwatch = Stopwatch.createStarted();
final TupleListFuture result = guimodel.getConnection().queryRectangle(
table, bbox, udfs);
result.waitForCompletion();
stopwatch.stop();
if(result.isFailed()) {
logger.error("Got an error" + result.getAllMessages());
return;
}
final List<OverlayElementGroup> elements = new ArrayList<>();
for(final Tuple tuple : result) {
final OverlayElementGroup overlayElement = OverlayElementBuilder.createOverlayElementGroup(tuple, table, color);
elements.add(overlayElement);
}
logger.info("Got {} tuples back in {} / {} ms",
elements.size(), result.getCompletionTime(TimeUnit.MILLISECONDS), stopwatch.elapsed(TimeUnit.MILLISECONDS));
painter.addElementToDrawBulk(elements);
} catch (BBoxDBException e) {
logger.error("Got error while performing query", e);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
}
}
/**
* Execute a continuous join query
* @param customValue
* @param customFilter
* @param table
* @param bbox
* @param receiveInvalidations
* @param receiveWatermarks
*/
private void executeJoinQueryContinuous(final Hyperrectangle bbox, final String table1,
final String table2, final Color color1, final Color color2,
final String customFilter, final String customValue,
final boolean receiveWatermarks, final boolean receiveInvalidations) {
QueryPlanBuilder qpb = QueryPlanBuilder
.createQueryOnTable(table1)
.spatialJoinWithTable(table2)
.forAllNewTuplesInSpace(bbox);
if(customFilter.length() > 2) {
final UserDefinedFilterDefinition userDefinedFilter
= new UserDefinedFilterDefinition(customFilter, customValue);
qpb.addJoinFilter(userDefinedFilter);
}
if(receiveWatermarks) {
qpb.receiveWatermarks();
}
if(receiveInvalidations) {
qpb.receiveInvalidations();
}
final BBoxDBCluster connection = guimodel.getConnection();
final List<Color> colors = Arrays.asList(color1, color2);
final ContinuousQueryPlan qp = qpb.build();
startQueryRunable(qp, connection, colors);
}
/**
* Start the given query runable
* @param qp
* @param connection
* @param colors
*/
private void startQueryRunable(final ContinuousQueryPlan qp, final BBoxDBCluster connection,
final List<Color> colors) {
final Runnable runable = new ContinuousQueryRunable(colors, qp, connection, painter);
final Thread fetchThread = new Thread(runable);
backgroundThreads.add(fetchThread);
fetchThread.start();
}
/**
* Execute a continuous range query
* @param customValue
* @param customFilter
* @param table
* @param bbox
* @param receiveInvalidations
* @param receiveWatermarks
*/
private void executeRangeQueryContinuous(final Hyperrectangle bbox, final String table,
final Color color, final String customFilter, final String customValue,
final boolean receiveWatermarks, final boolean receiveInvalidations) {
final QueryPlanBuilder qpb = QueryPlanBuilder
.createQueryOnTable(table)
.forAllNewTuplesInSpace(bbox)
.compareWithStaticSpace(bbox);
if(customFilter.length() > 2) {
final UserDefinedFilterDefinition userDefinedFilter
= new UserDefinedFilterDefinition(customFilter, customValue);
qpb.addStreamFilter(userDefinedFilter);
}
if(receiveWatermarks) {
qpb.receiveWatermarks();
}
if(receiveInvalidations) {
qpb.receiveInvalidations();
}
final BBoxDBCluster connection = guimodel.getConnection();
final ContinuousQueryPlan qp = qpb.build();
final List<Color> colors = Arrays.asList(color);
startQueryRunable(qp, connection, colors);
}
};
return ececuteAction;
}
/**
* Set the latitude begin coordinate
* @param selectedLatBegin
*/
public void setSelectedLatBegin(final String selectedLatBegin) {
this.selectedLatBegin = selectedLatBegin;
}
/**
* Set the latitude end coordinate
* @param selectedLatEnd
*/
public void setSelectedLatEnd(final String selectedLatEnd) {
this.selectedLatEnd = selectedLatEnd;
}
/**
* Set the longitude begin coordinate
* @param selectedLongBegin
*/
public void setSelectedLongBegin(final String selectedLongBegin) {
this.selectedLongBegin = selectedLongBegin;
}
/**
* Set the longitude end coordinate
* @param selectedLongEnd
*/
public void setSelectedLongEnd(final String selectedLongEnd) {
this.selectedLongEnd = selectedLongEnd;
}
}