geoportal-data-viewer-app/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/crossfiltering/CrossFilteringLayerPanel.java

530 lines
16 KiB
Java
Raw Normal View History

2023-05-26 14:45:47 +02:00
package org.gcube.portlets.user.geoportaldataviewer.client.ui.crossfiltering;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import org.gcube.application.geoportalcommon.shared.geoportal.config.GroupedLayersDV;
import org.gcube.application.geoportalcommon.shared.geoportal.config.layers.CrossFilteringLayerDV;
import org.gcube.application.geoportalcommon.shared.geoportal.config.layers.LayerIDV;
import org.gcube.portlets.user.geoportaldataviewer.client.GeoportalDataViewerConstants.MAP_PROJECTION;
2023-05-31 17:02:03 +02:00
import org.gcube.portlets.user.geoportaldataviewer.client.events.ApplyCQLToLayerMapEvent;
2023-05-26 14:45:47 +02:00
import org.gcube.portlets.user.geoportaldataviewer.client.ui.util.OLGeoJSONUtil;
2023-05-31 17:02:03 +02:00
import org.gcube.portlets.user.geoportaldataviewer.shared.GCubeCollection;
2023-05-26 14:45:47 +02:00
import org.gcube.portlets.user.geoportaldataviewer.shared.gis.LayerItem;
import org.gcube.portlets.user.geoportaldataviewer.shared.gis.wms.GeoInformationForWMSRequest;
2023-05-31 17:02:03 +02:00
import com.github.gwtbootstrap.client.ui.Button;
2023-05-26 14:45:47 +02:00
import com.github.gwtbootstrap.client.ui.CheckBox;
import com.github.gwtbootstrap.client.ui.ControlGroup;
import com.github.gwtbootstrap.client.ui.ControlLabel;
import com.github.gwtbootstrap.client.ui.Controls;
2023-05-31 17:02:03 +02:00
import com.github.gwtbootstrap.client.ui.DropdownButton;
2023-05-26 14:45:47 +02:00
import com.github.gwtbootstrap.client.ui.Fieldset;
import com.github.gwtbootstrap.client.ui.ListBox;
2023-05-31 17:02:03 +02:00
import com.github.gwtbootstrap.client.ui.constants.ButtonType;
2023-05-26 14:45:47 +02:00
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
2023-05-31 17:02:03 +02:00
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
2023-05-26 14:45:47 +02:00
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.Response;
2023-05-26 17:49:59 +02:00
import com.google.gwt.http.client.URL;
2023-05-26 14:45:47 +02:00
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;
2023-05-26 17:49:59 +02:00
import jsinterop.base.JsPropertyMap;
2023-05-26 14:45:47 +02:00
import ol.Feature;
/**
* The Class CrossFilteringLayerPanel.
*
* @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it
*
* May 15, 2023
*/
public class CrossFilteringLayerPanel extends Composite {
public static String COLORSCALERANGE = "COLORSCALERANGE";
2023-05-26 17:49:59 +02:00
// @UiField
// WellForm panelContainer;
2023-05-26 14:45:47 +02:00
@UiField
Fieldset fieldSet;
2023-05-31 17:02:03 +02:00
@UiField
Button buttonReset;
2023-05-26 14:45:47 +02:00
private CheckBox checkbox;
private GeoInformationForWMSRequest geoInformation;
private static CrossFilteringLayerPanelUiBinder uiBinder = GWT.create(CrossFilteringLayerPanelUiBinder.class);
private HandlerManager applicationBus;
private LayerItem layerItem;
private LinkedHashMap<Integer, List<? extends LayerIDV>> mapInnestedFiltering = new LinkedHashMap<Integer, List<? extends LayerIDV>>();
2023-05-26 17:49:59 +02:00
private LinkedHashMap<Integer, HashMap<String, SelectableItem>> mapInnestedFeatures = new LinkedHashMap<Integer, HashMap<String, SelectableItem>>();
2023-05-26 14:45:47 +02:00
private LinkedHashMap<Integer, List<ListBox>> mapInnestedListBoxes = new LinkedHashMap<Integer, List<ListBox>>();
private GroupedLayersDV<? extends LayerIDV> groupedLayersDV;
2023-05-31 17:02:03 +02:00
private GCubeCollection gCubeCollection;
private DropdownButton filterButton;
2023-05-26 14:45:47 +02:00
/**
* The Interface LayerCollectionPanelUiBinder.
*
* @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it
*
* Jan 16, 2023
*/
interface CrossFilteringLayerPanelUiBinder extends UiBinder<Widget, CrossFilteringLayerPanel> {
}
2023-05-31 17:02:03 +02:00
/**
* Instantiates a new overlay custom layer panel.
*
* @param gCubeCollection the g cube collection
* @param groupedLayersDV the grouped layers DV
* @param applicationBus the application bus
*/
public CrossFilteringLayerPanel(GCubeCollection gCubeCollection,
GroupedLayersDV<? extends LayerIDV> groupedLayersDV, HandlerManager applicationBus) {
initWidget(uiBinder.createAndBindUi(this));
this.applicationBus = applicationBus;
this.groupedLayersDV = groupedLayersDV;
this.gCubeCollection = gCubeCollection;
GWT.log("Building cross-filtering for: " + groupedLayersDV);
2023-05-26 14:45:47 +02:00
2023-05-31 17:02:03 +02:00
buttonReset.setType(ButtonType.LINK);
2023-05-26 14:45:47 +02:00
2023-05-31 17:02:03 +02:00
int level = 0;
// Building mapInnestedFiltering
recursivelyBuildSelectableLevels(level, groupedLayersDV.getListCustomLayers());
2023-05-26 14:45:47 +02:00
2023-05-31 17:02:03 +02:00
GWT.log("cross-filtering mapInnestedFiltering: " + mapInnestedFiltering);
2023-05-26 14:45:47 +02:00
2023-05-31 17:02:03 +02:00
for (Integer theLevel : mapInnestedFiltering.keySet()) {
addListBoxesLevelToPanel(theLevel, mapInnestedFiltering.get(theLevel));
2023-05-26 14:45:47 +02:00
}
2023-05-31 17:02:03 +02:00
fillSelectableLevel(level, null);
2023-05-26 14:45:47 +02:00
2023-05-31 17:02:03 +02:00
bindEvents();
2023-05-26 14:45:47 +02:00
2023-05-31 17:02:03 +02:00
}
2023-05-26 14:45:47 +02:00
2023-05-31 17:02:03 +02:00
/**
* Bind events.
*/
private void bindEvents() {
2023-05-26 14:45:47 +02:00
2023-05-31 17:02:03 +02:00
buttonReset.addClickHandler(new ClickHandler() {
2023-05-26 14:45:47 +02:00
2023-05-31 17:02:03 +02:00
@Override
public void onClick(ClickEvent event) {
for (int i = 1; i < mapInnestedListBoxes.size(); i++) {
resetListBoxLevel(i);
}
// Selecting the placeholder of the fist list box
List<ListBox> listBox = mapInnestedListBoxes.get(0);
listBox.get(0).setSelectedIndex(0);
// Resetting CQL filtering
applicationBus.fireEvent(new ApplyCQLToLayerMapEvent(gCubeCollection.getIndexes().get(0), null));
setFilterHighLighted(false);
}
});
2023-05-26 14:45:47 +02:00
}
2023-05-31 17:02:03 +02:00
/**
* Recursively build selectable levels.
*
* @param level the level
* @param layersIDV the layers IDV
*/
2023-05-26 14:45:47 +02:00
private void recursivelyBuildSelectableLevels(int level, List<? extends LayerIDV> layersIDV) {
if (layersIDV == null)
return;
mapInnestedFiltering.put(level, layersIDV);
for (LayerIDV layerIDV : layersIDV) {
if (layerIDV instanceof CrossFilteringLayerDV) {
CrossFilteringLayerDV crossFilteringLayer = (CrossFilteringLayerDV) layerIDV;
if (crossFilteringLayer.getRelated_to() != null) {
recursivelyBuildSelectableLevels(++level, crossFilteringLayer.getRelated_to());
}
}
}
}
/**
2023-05-31 17:02:03 +02:00
* Fill selectable level.
2023-05-26 14:45:47 +02:00
*
2023-05-31 17:02:03 +02:00
* @param level the level
* @param selectedItem the selected item
2023-05-26 14:45:47 +02:00
*/
2023-05-31 17:02:03 +02:00
private void fillSelectableLevel(int level, SelectableItem selectedItem) {
2023-05-26 14:45:47 +02:00
2023-05-26 17:49:59 +02:00
List<? extends LayerIDV> layersIDV = mapInnestedFiltering.get(level);
List<ListBox> listBoxes = mapInnestedListBoxes.get(level);
2023-05-26 14:45:47 +02:00
if (layersIDV == null)
return;
2023-05-26 17:49:59 +02:00
final HashMap<String, SelectableItem> mapSelectableFeatures = new HashMap<String, CrossFilteringLayerPanel.SelectableItem>();
LayerIDV layerIDV = layersIDV.get(0); // Expected one
if (layerIDV instanceof CrossFilteringLayerDV) {
CrossFilteringLayerDV crossFilteringLayer = (CrossFilteringLayerDV) layerIDV;
String wfsURL = crossFilteringLayer.getWFS_URL();
2023-05-26 14:45:47 +02:00
2023-05-26 17:49:59 +02:00
if (selectedItem != null) {
2023-05-26 14:45:47 +02:00
2023-05-31 17:02:03 +02:00
String cqlFilterValue = crossFilteringLayer.getTable_parent_key_field() + "=" + selectedItem.keyValue;
2023-05-26 17:49:59 +02:00
wfsURL += "&CQL_FILTER=" + URL.encode(cqlFilterValue);
2023-05-26 14:45:47 +02:00
2023-05-26 17:49:59 +02:00
}
GWT.log("wfsURL request: " + wfsURL);
RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, wfsURL);
2023-05-26 14:45:47 +02:00
2023-05-26 17:49:59 +02:00
try {
2023-05-26 14:45:47 +02:00
2023-05-26 17:49:59 +02:00
Request response = builder.sendRequest(null, new RequestCallback() {
public void onError(Request request, Throwable exception) {
// Code omitted for clarity
}
2023-05-26 14:45:47 +02:00
2023-05-26 17:49:59 +02:00
public void onResponseReceived(Request request, Response response) {
GWT.log("wfsURL response: " + response.getText());
Feature[] features = OLGeoJSONUtil.readGeoJsonFeatures(MAP_PROJECTION.EPSG_4326,
response.getText());
2023-05-26 14:45:47 +02:00
2023-05-26 17:49:59 +02:00
for (Feature feature : features) {
JsPropertyMap<Object> properties = feature.getProperties();
2023-05-31 17:02:03 +02:00
Object keyValue = properties.get(crossFilteringLayer.getTable_key_field());
2023-05-26 17:49:59 +02:00
Object itemField = properties.get(crossFilteringLayer.getTable_show_field());
2023-05-26 14:45:47 +02:00
2023-05-26 17:49:59 +02:00
Object parentKey = null;
if (crossFilteringLayer.getTable_parent_key_field() != null
&& !crossFilteringLayer.getTable_parent_key_field().isEmpty())
parentKey = properties.get(crossFilteringLayer.getTable_parent_key_field());
2023-05-26 14:45:47 +02:00
2023-05-26 17:49:59 +02:00
parentKey = parentKey == null ? "" : parentKey;
2023-05-26 14:45:47 +02:00
2023-05-31 17:02:03 +02:00
SelectableItem selectableItem = new SelectableItem(
crossFilteringLayer.getTable_key_field() + "", keyValue + "",
crossFilteringLayer.getTable_parent_key_field(), itemField + "",
crossFilteringLayer.getName(), crossFilteringLayer.getTable_geometry_name());
GWT.log("selectableItem: " + selectableItem);
2023-05-26 17:49:59 +02:00
String pathFeatureKey = pathFeatureKey(selectableItem);
mapSelectableFeatures.put(pathFeatureKey, selectableItem);
}
2023-05-31 17:02:03 +02:00
GWT.log("mapSelectableFeatures: " + mapSelectableFeatures);
2023-05-26 17:49:59 +02:00
mapInnestedFeatures.put(level, mapSelectableFeatures);
String placholder = placeholderLayer(layersIDV.get(0)); // Expected one
fillListBoxLevel(level, mapSelectableFeatures, listBoxes, placholder);
2023-05-26 14:45:47 +02:00
}
2023-05-26 17:49:59 +02:00
});
} catch (RequestException e) {
// Code omitted for clarity
2023-05-26 14:45:47 +02:00
}
}
}
2023-05-31 17:02:03 +02:00
/**
* Path feature key.
*
* @param selectableItem the selectable item
* @return the string
*/
2023-05-26 17:49:59 +02:00
private String pathFeatureKey(SelectableItem selectableItem) {
2023-05-31 17:02:03 +02:00
return "root_" + selectableItem.parentKeyField + "_" + selectableItem.keyField + "_" + selectableItem.keyValue;
2023-05-26 17:49:59 +02:00
}
2023-05-31 17:02:03 +02:00
/**
* Placeholder layer.
*
* @param layersIDV the layers IDV
* @return the string
*/
2023-05-26 17:49:59 +02:00
private String placeholderLayer(LayerIDV layersIDV) {
2023-05-31 17:02:03 +02:00
String placeholder = "Select";
if (layersIDV != null)
placeholder += " " + layersIDV.getTitle() + "...";
placeholder += " ...";
return placeholder;
2023-05-26 17:49:59 +02:00
}
2023-05-31 17:02:03 +02:00
/**
* Adds the list boxes level to panel.
*
* @param level the level
* @param layersIDV the layers IDV
*/
2023-05-26 14:45:47 +02:00
private void addListBoxesLevelToPanel(int level, List<? extends LayerIDV> layersIDV) {
if (layersIDV == null)
return;
List<ListBox> listBoxes = new ArrayList<ListBox>(layersIDV.size());
for (LayerIDV layerIDV : layersIDV) {
ControlGroup cg = new ControlGroup();
ControlLabel cl = new ControlLabel(layerIDV.getTitle());
Controls controls = new Controls();
ListBox listBox = new ListBox();
2023-05-26 17:49:59 +02:00
String placeholder = placeholderLayer(layerIDV);
listBox.addItem(placeholder);
setEnabledBox(listBox, false);
2023-05-26 14:45:47 +02:00
listBoxes.add(listBox);
controls.add(listBox);
cg.add(cl);
cg.add(controls);
2023-05-26 17:49:59 +02:00
2023-05-26 14:45:47 +02:00
fieldSet.add(cg);
}
mapInnestedListBoxes.put(level, listBoxes);
}
2023-05-31 17:02:03 +02:00
/**
* Sets the enabled box.
*
* @param listBox the list box
* @param bool the bool
*/
2023-05-26 17:49:59 +02:00
public void setEnabledBox(ListBox listBox, boolean bool) {
listBox.setEnabled(bool);
}
2023-05-31 17:02:03 +02:00
/**
* Clear list box.
*
* @param listBox the list box
* @param bool the bool
*/
2023-05-26 17:49:59 +02:00
public void clearListBox(ListBox listBox, boolean bool) {
listBox.setEnabled(bool);
}
2023-05-31 17:02:03 +02:00
/**
* Reset list box level.
*
* @param level the level
*/
2023-05-26 17:49:59 +02:00
private void resetListBoxLevel(int level) {
2023-05-31 17:02:03 +02:00
2023-05-26 17:49:59 +02:00
List<ListBox> listBoxes = mapInnestedListBoxes.get(level);
2023-05-31 17:02:03 +02:00
if (listBoxes != null) {
2023-05-26 17:49:59 +02:00
for (ListBox listBox : listBoxes) {
listBox.clear();
setEnabledBox(listBox, false);
}
}
}
2023-05-31 17:02:03 +02:00
/**
* Fill list box level.
*
* @param level the level
* @param mapSelectableFeatures the map selectable features
* @param listBoxes the list boxes
* @param placeholder the placeholder
*/
2023-05-26 14:45:47 +02:00
private void fillListBoxLevel(int level, HashMap<String, SelectableItem> mapSelectableFeatures,
2023-05-26 17:49:59 +02:00
List<ListBox> listBoxes, String placeholder) {
GWT.log("fillBox level: " + level + " map: " + mapSelectableFeatures);
2023-05-26 14:45:47 +02:00
if (mapSelectableFeatures == null)
return;
ListBox listBox = listBoxes.get(0); // Expected one
2023-05-26 17:49:59 +02:00
listBox.clear();
listBox.addItem(placeholder);
listBox.getElement().getFirstChildElement().setAttribute("disabled", "disabled");
2023-05-26 14:45:47 +02:00
for (String key : mapSelectableFeatures.keySet()) {
SelectableItem selItem = mapSelectableFeatures.get(key);
2023-05-31 17:02:03 +02:00
listBox.addItem(selItem.itemValue, key);
2023-05-26 14:45:47 +02:00
}
listBox.addChangeHandler(new ChangeHandler() {
@Override
public void onChange(ChangeEvent event) {
2023-05-26 17:49:59 +02:00
loadInnerLevel(level, listBox.getSelectedValue());
2023-05-31 17:02:03 +02:00
for (int i = level + 1; i < mapInnestedListBoxes.size(); i++) {
resetListBoxLevel(i);
}
String key = listBox.getSelectedValue();
SelectableItem selectableItem = mapSelectableFeatures.get(key);
buildCrossFilteringCQLAndFireEvent(selectableItem);
setFilterHighLighted(true);
2023-05-26 14:45:47 +02:00
}
2023-05-31 17:02:03 +02:00
2023-05-26 14:45:47 +02:00
});
2023-05-26 17:49:59 +02:00
setEnabledBox(listBox, true);
2023-05-26 14:45:47 +02:00
}
2023-05-31 17:02:03 +02:00
/**
* Builds the cross filtering CQL and fire event.
*
* @param selectableItem the selectable item
*/
private void buildCrossFilteringCQLAndFireEvent(SelectableItem selectableItem) {
String setCqlFilter = "INTERSECTS(geom,querySingle('" + selectableItem.layername + "','"
+ selectableItem.theGeometryName + "','" + selectableItem.keyField + "=''" + selectableItem.keyValue
+ "'''));INCLUDE";
GWT.log("CQL FILTER built: " + setCqlFilter);
// olMapMng.getOLMap().setCQLFilterToWMSLayer(layerName, setCqlFilter);
applicationBus.fireEvent(new ApplyCQLToLayerMapEvent(gCubeCollection.getIndexes().get(0), setCqlFilter));
}
/**
* Load inner level.
*
* @param level the level
* @param selectableItemValue the selectable item value
*/
2023-05-26 17:49:59 +02:00
private void loadInnerLevel(int level, String selectableItemValue) {
GWT.log("selected level " + level + " selectableItemValue " + selectableItemValue);
HashMap<String, SelectableItem> mapSelectableItem = mapInnestedFeatures.get(level);
SelectableItem selectedItem = mapSelectableItem.get(selectableItemValue);
GWT.log("selected selectableItem " + selectedItem);
int innerLevel = level + 1;
List<? extends LayerIDV> selectedLayers = mapInnestedFiltering.get(innerLevel);
2023-05-31 17:02:03 +02:00
// if layer filtering exists at this level
2023-05-26 17:49:59 +02:00
if (selectedLayers != null) {
List<ListBox> selectedListBoxes = mapInnestedListBoxes.get(innerLevel);
GWT.log("loading inner layers " + selectedLayers);
GWT.log("loading selectedListBoxes " + selectedListBoxes);
2023-05-31 17:02:03 +02:00
fillSelectableLevel(innerLevel, selectedItem);
2023-05-26 17:49:59 +02:00
}
2023-05-26 14:45:47 +02:00
}
2023-05-31 17:02:03 +02:00
/**
* Sets the filter high lighted.
*
* @param bool the new filter high lighted
*/
private void setFilterHighLighted(boolean bool) {
if (bool) {
filterButton.getElement().addClassName("highlight-button");
} else {
filterButton.getElement().removeClassName("highlight-button");
}
}
/**
* Sets the search button.
*
* @param searchFacilityButton the new search button
*/
public void setFilterButton(DropdownButton searchFacilityButton) {
this.filterButton = searchFacilityButton;
}
2023-05-26 14:45:47 +02:00
2023-05-31 17:02:03 +02:00
/**
* The Class SelectableItem.
*
* @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it
*
* May 31, 2023
*/
public class SelectableItem {
protected String keyField;
protected String keyValue;
protected String parentKeyField;
protected String itemValue;
protected String layername;
protected String theGeometryName;
/**
* Instantiates a new selectable item.
*/
SelectableItem() {
}
/**
* Instantiates a new selectable item.
*
* @param keyField the key field
* @param keyValue the key value
* @param parentKeyField the parent key field
* @param itemValue the item value
* @param layername the layername
* @param theGeometryName the the geometry name
*/
public SelectableItem(String keyField, String keyValue, String parentKeyField, String itemValue,
String layername, String theGeometryName) {
super();
this.keyField = keyField;
this.keyValue = keyValue;
this.parentKeyField = parentKeyField;
this.itemValue = itemValue;
this.layername = layername;
this.theGeometryName = theGeometryName;
}
/**
* To string.
*
* @return the string
*/
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("SelectableItem [keyField=");
builder.append(keyField);
builder.append(", keyValue=");
builder.append(keyValue);
builder.append(", parentKeyField=");
builder.append(parentKeyField);
builder.append(", itemValue=");
builder.append(itemValue);
builder.append(", layername=");
builder.append(layername);
builder.append(", theGeometryName=");
builder.append(theGeometryName);
builder.append("]");
return builder.toString();
}
}
2023-05-26 14:45:47 +02:00
}