import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.UUID;
+import java.util.function.Consumer;
import javax.inject.Inject;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.Dialog;
-import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
+import org.eclipse.jface.layout.RowDataFactory;
import org.eclipse.jface.layout.RowLayoutFactory;
-import org.eclipse.jface.window.Window;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.resource.LocalResourceManager;
+import org.eclipse.jface.resource.ResourceLocator;
import org.eclipse.swt.SWT;
-import org.eclipse.swt.custom.StackLayout;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
+import org.eclipse.swt.widgets.Widget;
import org.simantics.Simantics;
import org.simantics.db.ReadGraph;
import org.simantics.db.Resource;
-import org.simantics.db.Session;
import org.simantics.db.WriteGraph;
+import org.simantics.db.common.request.IndexRoot;
import org.simantics.db.common.request.ReadRequest;
import org.simantics.db.common.request.WriteRequest;
import org.simantics.db.exception.DatabaseException;
import org.simantics.db.exception.RuntimeDatabaseException;
import org.simantics.db.layer0.QueryIndexUtils;
import org.simantics.db.layer0.request.ActiveModels;
+import org.simantics.db.layer0.request.PropertyInfo;
+import org.simantics.db.layer0.request.PropertyInfoRequest;
import org.simantics.db.layer0.util.Layer0Utils;
-import org.simantics.db.request.Read;
-import org.simantics.db.request.WriteResult;
import org.simantics.diagram.stubs.DiagramResource;
+import org.simantics.district.network.ontology.DistrictNetworkResource;
import org.simantics.district.region.ontology.DiagramRegionsResource;
import org.simantics.district.route.ontology.RouteResource;
import org.simantics.district.selection.ElementSelectionResource;
import org.simantics.district.selection.ElementSelector.RouteCondition;
import org.simantics.district.selection.ElementSelector.Selector;
import org.simantics.layer0.Layer0;
+import org.simantics.layer0.utils.direct.GraphUtils;
import org.simantics.modeling.ModelingResources;
+import org.simantics.structural.stubs.StructuralResource2;
import org.simantics.utils.datastructures.Arrays;
+import org.simantics.utils.datastructures.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class EditSelectorDialog extends Dialog {
+ private static final RowLayoutFactory ROW_LAYOUT = RowLayoutFactory.fillDefaults().wrap(false);
+ private static final ImageDescriptor CROSS_IMAGE = ResourceLocator.imageDescriptorFromBundle("com.famfamfam.silk", "icons/cross.png").get();
+ private static final ImageDescriptor PLUS_IMAGE = ResourceLocator.imageDescriptorFromBundle("com.famfamfam.silk", "icons/add.png").get();
+
private static Logger LOGGER = LoggerFactory.getLogger(EditSelectorDialog.class);
private ElementSelector elementSelector;
Collection<Resource> currentSelection;
// Data for comboboxes
- Map<Resource, String> diagrams;
+ private List<Resource> diagrams;
+ private ArrayList<String> diagramNames;
private String[] regionNames;
private Resource[] regionResources;
private String[] routeNames;
private Resource[] routeResources;
+
+ private List<Resource> componentTypes;
+ private List<String> componentTypeNames;
+
+ private List<String> propertyNames;
+ private List<String> propertyLabels;
+
+ private Composite conditionPanel;
// Dialog fields
private int generatorIndex;
private int selectorIndex;
private Combo selectorField;
+ private Resource componentType;
+ private Combo componentTypeField;
+
private String propertyName;
- private Text propertyField;
+ private Combo propertyField;
private int numberOfItems;
private Text nField;
private Condition condition;
- private Button removeConditionButton;
- private Text conditionLabel;
// Dialog area component
private Composite content;
+ private int diagramIndex;
+
+ private LocalResourceManager resourceManager;
+
+ static class ValidationException extends Exception {
+ private static final long serialVersionUID = 1L;
+
+ public ValidationException(String message) {
+ super(message);
+ }
+ }
+
+ // Function type for updating condition objects with optional validation
+ static interface Updater {
+ // If 'validate' is true, a runtime exception may be thrown for invalid values
+ void update(boolean validate) throws ValidationException;
+ }
+
+ final static Updater NULL_UPDATE = validate -> {};
+
+ // Called to read values from controls into conditions
+ Updater updater = NULL_UPDATE;
+
@Inject
public EditSelectorDialog(Shell shell, ElementSelector elementSelector, Collection<Resource> currentSelection) {
super(shell);
this.currentSelection = currentSelection;
- final Map<Resource, String> regions = new HashMap<>();
- final Map<Resource, String> routes = new HashMap<>();
-
- try {
- Simantics.getSession().syncRequest(new Read<Void>() {
- @Override
- public Void perform(ReadGraph graph) throws DatabaseException {
- Resource model = ActiveModels.getPossibleActiveModel(graph, Simantics.getProjectResource());
- List<Resource> regionCollection = QueryIndexUtils.searchByType(graph, model, DiagramRegionsResource.getInstance(graph).Region);
- for (Resource r : regionCollection) {
- String name = graph.getRelatedValue(r, Layer0.getInstance(graph).HasName);
- regions.put(r, name);
- }
-
- List<Resource> routeCollection = QueryIndexUtils.searchByType(graph, model, RouteResource.getInstance(graph).Route);
- for (Resource r : routeCollection) {
- String name = graph.getRelatedValue(r, Layer0.getInstance(graph).HasName);
- routes.put(r, name);
- }
- return null;
- }
+ Map<Resource, String> diagramMap = ElementSelector.findDiagrams();
+ diagrams = new ArrayList<Resource>(diagramMap.size());
+ diagramNames = new ArrayList<String>(diagramMap.size());
+ diagramMap.entrySet()
+ .stream()
+ .sorted(Comparator.comparing(e -> e.getValue()))
+ .forEachOrdered(e -> {
+ diagrams.add(e.getKey());
+ diagramNames.add(e.getValue());
});
- } catch (DatabaseException e) {
- LOGGER.error("Failed to read routes and/or regions in the model", e);
- }
-
- regionNames = regions.values().toArray(new String[regions.size()]);
- regionResources = regions.keySet().toArray(new Resource[regions.size()]);
- routeNames = routes.values().toArray(new String[routes.size()]);
- routeResources = routes.keySet().toArray(new Resource[routes.size()]);
-
name = elementSelector != null ? elementSelector.getName() : "";
propertyName = "";
numberOfItems = 1;
}
else if (generator instanceof ExplicitGenerator) {
generatorIndex = 2;
- // TODO: Management of explicit lists of elements
}
else {
throw new IllegalStateException("Unknown generator type " + generator.getClass().getName());
}
condition = elementSelector.getCondition();
+
+ componentType = elementSelector.getSelector().componentType;
+ }
+
+ readRegions(diagram);
+ readRoutes();
+ readComponentTypes();
+ updatePropertyList();
+ }
+
+ private void readComponentTypes() {
+ try {
+ Simantics.getSession().syncRequest(new ReadRequest() {
+ @Override
+ public void run(ReadGraph graph) throws DatabaseException {
+ Layer0 L0 = Layer0.getInstance(graph);
+ List<Resource> types = findComponentTypes(graph);
+
+ componentTypes = new ArrayList<>(types.size() + 1);
+ componentTypeNames = new ArrayList<>(types.size() + 1);
+
+ componentTypes.add(null);
+ componentTypeNames.add("Any type");
+ componentTypes.addAll(types);
+ for (Resource t : types) {
+ componentTypeNames.add(graph.getValue2(t, L0.HasName));
+ }
+ }
+ });
+ } catch (DatabaseException e) {
+ LOGGER.error("Failed to read district component types", e);
+ }
+ }
+
+ private void readRoutes() {
+ final Map<Resource, String> routes = new HashMap<>();
+
+ try {
+ Simantics.getSession().syncRequest(new ReadRequest() {
+ @Override
+ public void run(ReadGraph graph) throws DatabaseException {
+ Layer0 L0 = Layer0.getInstance(graph);
+ RouteResource ROUTE = RouteResource.getInstance(graph);
+
+ Resource model = ActiveModels.getPossibleActiveModel(graph, Simantics.getProjectResource());
+ List<Resource> routeCollection = QueryIndexUtils.searchByType(graph, model, ROUTE.Route);
+ for (Resource r : routeCollection) {
+ String name = graph.getRelatedValue(r, L0.HasLabel);
+ routes.put(r, name);
+ }
+ }
+ });
+ } catch (DatabaseException e) {
+ LOGGER.error("Failed to read routes in the model", e);
}
+
+ routeNames = routes.values().toArray(new String[routes.size()]);
+ routeResources = routes.keySet().toArray(new Resource[routes.size()]);
+ }
+
+ private void readRegions(Resource diagram) {
+ final Map<Resource, String> regions = new HashMap<>();
+
+ try {
+ Simantics.getSession().syncRequest(new ReadRequest() {
+ @Override
+ public void run(ReadGraph graph) throws DatabaseException {
+ Layer0 L0 = Layer0.getInstance(graph);
+ ModelingResources MOD = ModelingResources.getInstance(graph);
+ DiagramRegionsResource DR = DiagramRegionsResource.getInstance(graph);
+
+ // If a specific diagram is given, use that
+ Collection<Resource> ds = diagram != null ? Collections.singleton(diagram) : diagrams;
+
+ for (Resource composite : ds) {
+ Resource diagram = graph.getSingleObject(composite, MOD.CompositeToDiagram);
+ for (Resource r : graph.getObjects(diagram, DR.hasRegion)) {
+ if (!graph.isInstanceOf(r, DR.Region))
+ continue;
+ String name = graph.getRelatedValue(r, L0.HasLabel);
+ regions.put(r, name);
+ }
+ }
+ }
+ });
+ } catch (DatabaseException e) {
+ LOGGER.error("Failed to read regions in the model", e);
+ }
+
+ regionNames = regions.values().toArray(new String[regions.size()]);
+ regionResources = regions.keySet().toArray(new Resource[regions.size()]);
}
+ private void updateDialog() {
+ try {
+ updater.update(false);
+ } catch (ValidationException e) {
+ // Should not happend with argument false
+ assert(false);
+ }
+
+ updater = updateConditionPanel();
+
+ content.layout(true, true);
+ getShell().pack();
+ }
+
@Override
protected void okPressed() {
- generatorIndex = sourceField.getSelectionIndex();
- if (generatorIndex == 1) {
- int selectionIndex = diagramField.getSelectionIndex();
- if (selectionIndex < 0) {
- ErrorDialog.openError(getShell(), "Error", "Please select a diagram", new Status(IStatus.ERROR, "org.simantics.district.selection.ui", "No diagram selected"));
- return;
+ try {
+ generatorIndex = sourceField.getSelectionIndex();
+ if (generatorIndex == 1) {
+ int selectionIndex = diagramField.getSelectionIndex();
+ if (selectionIndex < 0) {
+ diagramField.setFocus();
+ throw new ValidationException("Please select a diagram");
+ }
+
+ diagram = diagrams.get(selectionIndex);
+ }
+
+ name = nameField.getText();
+ if (name.isEmpty()) {
+ nameField.setFocus();
+ throw new ValidationException("Please enter a name");
+ }
+
+ componentType = componentTypes.get(componentTypeField.getSelectionIndex());
+
+ selectorIndex = selectorField.getSelectionIndex();
+ if (selectorIndex != 0) {
+ int propertyIndex = propertyField.getSelectionIndex();
+ propertyName = propertyIndex >= 0 ? propertyNames.get(propertyIndex) : propertyField.getText();
+ if (propertyName.isEmpty()) {
+ propertyField.setFocus();
+ throw new ValidationException("Please select a property");
+ }
}
- diagram = new ArrayList<Resource>(diagrams.keySet()).get(selectionIndex);
+ // Try to parse number of items
+ if (useNumberOfItems()) {
+ try {
+ numberOfItems = Integer.parseInt(nField.getText());
+ if (numberOfItems <= 0) {
+ nField.selectAll();
+ nField.setFocus();
+ throw new ValidationException("Number of elements must be positive");
+ }
+ } catch (NumberFormatException e) {
+ nField.selectAll();
+ nField.setFocus();
+ throw new ValidationException("Please enter a valid number of elements");
+ }
+ }
+
+ // To to update condition definitions
+ updater.update(true);
+ } catch (ValidationException e) {
+ MessageDialog.openError(this.getShell(), "Missing data", e.getMessage());
+ return;
}
- name = nameField.getText();
-
- selectorIndex = selectorField.getSelectionIndex();
-
- propertyName = propertyField.getText();
- String text = nField.getText();
- numberOfItems = "".equals(text) ? 0 : Integer.parseInt(text);
-
super.okPressed();
}
}
graph.claim(selector, L0.InstanceOf, selectorType);
graph.claim(selection, ES.Selection_HasSelector, selector);
+ graph.deny(selector, ES.Selector_HasMapping);
+ if (componentType != null)
+ graph.claim(selector, ES.Selector_HasMapping, componentType);
if (selectorIndex > 0) {
graph.claimLiteral(selector, ES.PropertySelector_HasSelectionPropertyName, L0.String, propertyName);
// Condition
if (condition != null) {
- graph.claim(selection, ES.Selection_HasCondition, condition.resource);
+ Resource conditionResource = condition.update(graph);
+ graph.claim(selection, ES.Selection_HasCondition, conditionResource);
}
}
});
}
+ private boolean isDiagramFieldVisible() {
+ return generatorIndex == 1;
+ }
+
+ private boolean useNumberOfItems() {
+ return selectorIndex != 0;
+ }
+
@Override
protected Control createDialogArea(Composite parent) {
+ this.resourceManager = new LocalResourceManager(JFaceResources.getResources(), parent);
+
// Set dialog title
getShell().setText("Edit element selector");
content = new Composite(parent, SWT.NONE);
- GridLayoutFactory.swtDefaults().numColumns(3).applyTo(content);
+ GridLayoutFactory.swtDefaults().numColumns(2).applyTo(content);
// Name
Label nameLabel = new Label(content, SWT.NONE);
nameField = new Text(content, SWT.BORDER);
nameField.setEditable(true);
nameField.setText(name);
- GridDataFactory.swtDefaults().span(2, 1).hint(200, SWT.DEFAULT).applyTo(nameField);
+ GridDataFactory.swtDefaults().hint(200, SWT.DEFAULT).applyTo(nameField);
+
+ // Selector
+ Label selectorLabel = new Label(content, SWT.NONE);
+ selectorLabel.setText("Select");
+ GridDataFactory.swtDefaults().applyTo(selectorLabel);
+
+ Composite selectorComposite = new Composite(content, SWT.NONE);
+ GridDataFactory.swtDefaults().applyTo(selectorComposite);
+ RowLayoutFactory.fillDefaults().applyTo(selectorComposite);
+
+ nField = new Text(selectorComposite, SWT.BORDER);
+ RowDataFactory.swtDefaults().hint(40, SWT.DEFAULT).applyTo(nField);
+ if (useNumberOfItems())
+ nField.setText(Integer.toString(numberOfItems));
+ nField.setEnabled(useNumberOfItems());
+
+ componentTypeField = new Combo(selectorComposite, SWT.READ_ONLY);
+ RowDataFactory.swtDefaults().applyTo(componentTypeField);
+ componentTypeField.setItems(componentTypeNames.toArray(new String[] {}));
+ {
+ int index = componentTypes.indexOf(componentType);
+ componentTypeField.select(index >= 0 ? index : 0);
+ }
+
+ // Update property selection controls when component type changes
+ componentTypeField.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ int index = componentTypeField.getSelectionIndex();
+ componentType = index >= 0 ? componentTypes.get(index) : null;
+ updatePropertyList();
+ propertyField.setItems(propertyLabels.toArray(new String[] {}));
+
+ updateDialog();
+ }
+ });
+
+ new Label(selectorComposite, SWT.NONE).setText("with");
+
+ selectorField = new Combo(selectorComposite, SWT.BORDER | SWT.READ_ONLY);
+ selectorField.setItems("All", "Lowest", "Highest");
+ selectorField.select(selectorIndex);
+ RowDataFactory.swtDefaults().hint(40, SWT.DEFAULT).applyTo(selectorField);
+
+ propertyField = new Combo(selectorComposite, SWT.NONE);
+ RowDataFactory.swtDefaults().hint(120, SWT.DEFAULT).applyTo(propertyField);
+ propertyField.setItems(propertyLabels.toArray(new String[] {}));
+ {
+ int index = propertyName != null ? propertyNames.indexOf(propertyName) : -1;
+ if (index >= 0)
+ propertyField.select(index);
+ else
+ propertyField.setText(propertyName != null ? propertyName : "");
+ }
+ propertyField.setEnabled(useNumberOfItems());
+
+ selectorField.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ selectorIndex = selectorField.getSelectionIndex();
+
+ boolean enable = useNumberOfItems();
+ nField.setEnabled(enable);
+ propertyField.setEnabled(enable);
+
+ nField.setText(enable ? Integer.toString(numberOfItems) : "");
+ }
+ });
// Source
Label sourceLabel = new Label(content, SWT.NONE);
- sourceLabel.setText("Source");
- GridDataFactory.swtDefaults().applyTo(sourceLabel);
+ sourceLabel.setText("from");
+ GridDataFactory.swtDefaults().align(SWT.BEGINNING, SWT.CENTER).applyTo(sourceLabel);
+
+ Composite sourceComposite = new Composite(content, SWT.NONE);
+ GridDataFactory.swtDefaults().applyTo(sourceComposite);
+ RowLayoutFactory.fillDefaults().applyTo(sourceComposite);
- sourceField = new Combo(content, SWT.BORDER | SWT.READ_ONLY);
- sourceField.setItems("Model", "Diagram", "Current selection");
+ sourceField = new Combo(sourceComposite, SWT.BORDER | SWT.READ_ONLY);
+ RowDataFactory.swtDefaults().applyTo(sourceField);
+ sourceField.setItems("Whole model", "Diagram", "Current selection");
sourceField.select(generatorIndex);
- GridDataFactory.swtDefaults().span(1, 1).applyTo(sourceField);
- diagramField = new Combo(content, SWT.BORDER | SWT.READ_ONLY);
- GridDataFactory.swtDefaults().span(1, 1).applyTo(diagramField);
- diagrams = ElementSelector.findDiagrams();
- diagramField.setItems(diagrams.values().toArray(new String[diagrams.size()]));
+ diagramField = new Combo(sourceComposite, SWT.BORDER | SWT.READ_ONLY);
+ RowDataFactory.swtDefaults().hint(120, SWT.DEFAULT).applyTo(diagramField);
+ diagramField.setItems(diagramNames.toArray(new String[diagramNames.size()]));
+ diagramField.setEnabled(isDiagramFieldVisible());
- int diagramIndex = diagram != null ? new ArrayList<>(diagrams.keySet()).indexOf(diagram) : -1;
+ diagramIndex = diagram != null ? diagrams.indexOf(diagram) : -1;
diagramField.select(diagramIndex);
sourceField.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
generatorIndex = sourceField.getSelectionIndex();
- diagramField.setVisible(isDiagramFieldVisible());
+ boolean enabled = isDiagramFieldVisible();
+ if (!enabled) {
+ diagramIndex = diagramField.getSelectionIndex();
+ diagramField.clearSelection();
+ } else {
+ if (diagramIndex >= 0)
+ diagramField.select(diagramIndex);
+ else
+ diagramField.clearSelection();
+ }
+ diagramField.setEnabled(enabled);
+
+ // Refresh list of regions for current diagram
+ diagram = enabled ? (diagramIndex >= 0 ? diagrams.get(diagramIndex) : null) : null;
+ readRegions(diagram);
+ updateDialog();
}
});
sourceField.select(generatorIndex);
- diagramField.setVisible(isDiagramFieldVisible());
- // Selector
- Label selectorLabel = new Label(content, SWT.NONE);
- selectorLabel.setText("Select");
- GridDataFactory.swtDefaults().span(1, 1).applyTo(selectorLabel);
+ // Condition
+ Label label = new Label(content, SWT.NONE);
+ GridDataFactory.swtDefaults().align(SWT.BEGINNING, SWT.CENTER).applyTo(label);
+ label.setText("where");
- selectorField = new Combo(content, SWT.BORDER | SWT.READ_ONLY);
- selectorField.setItems("All", "N lowest", "N highest");
- selectorField.select(selectorIndex);
- GridDataFactory.swtDefaults().span(1, 1).applyTo(selectorField);
+ conditionPanel = new Composite(content, SWT.NONE);
+ GridDataFactory.swtDefaults().span(1, 2).minSize(400, SWT.DEFAULT).grab(true, false).applyTo(conditionPanel);
+ GridLayoutFactory.fillDefaults().numColumns(2).applyTo(conditionPanel);
- Composite selectorComposite = new Composite(content, SWT.NONE);
- GridDataFactory.swtDefaults().span(1, 1).applyTo(selectorComposite);
- GridLayoutFactory.swtDefaults().numColumns(2).applyTo(selectorComposite);
+ updater = updateConditionPanel();
- Label propertyLabel = new Label(selectorComposite, SWT.NONE);
- propertyLabel.setText("Property name");
- GridDataFactory.swtDefaults().applyTo(propertyLabel);
+ return content;
+ }
+
+ private Updater updateConditionPanel() {
+ // Erase contents
+ for (Widget c : conditionPanel.getChildren())
+ c.dispose();
- propertyField = new Text(selectorComposite, SWT.BORDER);
- propertyField.setText(propertyName);
- GridDataFactory.swtDefaults().hint(80, SWT.DEFAULT).applyTo(propertyField);
+ return createConditionPanelFor(conditionPanel, condition, cond -> condition = cond);
+ }
+
+ private Updater createConditionPanelFor(final Composite parent, final Condition condition, final Consumer<Condition> consumer) {
+ // Create new contents
+ Button notCheck = new Button(parent, SWT.CHECK);
+ GridDataFactory.swtDefaults().align(SWT.BEGINNING, SWT.BEGINNING).applyTo(notCheck);
+ notCheck.setText("not");
+ notCheck.setSelection(condition != null && condition.isInverse);
- Label nLabel = new Label(selectorComposite, SWT.NONE);
- nLabel.setText("Number of elements");
- GridDataFactory.swtDefaults().applyTo(nLabel);
+ Composite conditionComp = new Composite(parent, SWT.NONE);
+ GridDataFactory.fillDefaults().applyTo(conditionComp);
- nField = new Text(selectorComposite, SWT.BORDER);
- nField.setText(Integer.toString(numberOfItems));
- GridDataFactory.swtDefaults().hint(40, SWT.DEFAULT).applyTo(nField);
+ Combo typeCombo = new Combo(conditionComp, SWT.BORDER | SWT.READ_ONLY);
+ typeCombo.setItems(
+ "No condition",
+ "Property",
+ "In region",
+ "On route",
+ "All of",
+ "Any of"
+ );
- selectorField.addSelectionListener(new SelectionAdapter() {
- @Override
- public void widgetSelected(SelectionEvent e) {
- selectorIndex = selectorField.getSelectionIndex();
- selectorComposite.setVisible(isSelectorCompositeVisible());
+ typeCombo.addSelectionListener(new ConditionTypeSelectionListener(typeCombo, consumer, condition));
+
+ final Updater updater;
+ if (condition instanceof PropertyCondition) {
+ typeCombo.select(1);
+ updater = createPropertyConditionPanel(conditionComp, (PropertyCondition)condition);
+ } else if (condition instanceof RegionCondition) {
+ typeCombo.select(2);
+ updater = createRegionConditionPanel(conditionComp, (RegionCondition)condition);
+ } else if (condition instanceof RouteCondition) {
+ typeCombo.select(3);
+ updater = createRouteConditionPanel(conditionComp, (RouteCondition)condition);
+ } else if (condition instanceof AggregateCondition) {
+ AggregateCondition cond = (AggregateCondition) condition;
+ typeCombo.select(cond.type.equals(Type.CONJUNCTION) ? 4 : 5);
+ updater = createAggregateConditionPanel(conditionComp, cond);
+ } else {
+ ROW_LAYOUT.applyTo(conditionComp);
+ notCheck.setEnabled(false);
+ typeCombo.select(0);
+ return NULL_UPDATE;
+ }
+
+ return validate -> {
+ updater.update(validate);
+ condition.isInverse = notCheck.getSelection();
+ };
+ }
+
+ private final class ConditionTypeSelectionListener extends SelectionAdapter {
+ private final Combo typeCombo;
+ private final Consumer<Condition> consumer;
+ private final Condition finalCondition;
+
+ private ConditionTypeSelectionListener(Combo typeCombo, Consumer<Condition> consumer, Condition finalCondition) {
+ this.typeCombo = typeCombo;
+ this.consumer = consumer;
+ this.finalCondition = finalCondition;
+ }
+
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ int index = typeCombo.getSelectionIndex();
+ Condition newCondition = finalCondition;
+ switch (index) {
+ case 0:
+ newCondition = null;
+ break;
+ case 1:
+ newCondition = createPropertyCondition("", null, null);
+ break;
+ case 2:
+ newCondition = createRegionCondition(null);
+ break;
+ case 3:
+ newCondition = createRouteCondition(null);
+ break;
+ case 4:
+ if (newCondition instanceof AggregateCondition)
+ ((AggregateCondition)newCondition).type = Type.CONJUNCTION;
+ else
+ newCondition = createAggregateCondition(null, new ArrayList<>(), true, false);
+ break;
+ case 5:
+ if (newCondition instanceof AggregateCondition)
+ ((AggregateCondition)newCondition).type = Type.DISJUNCTION;
+ else
+ newCondition = createAggregateCondition(null, new ArrayList<>(), false, false);
+ break;
}
- });
- selectorField.select(selectorIndex);
- selectorComposite.setVisible(isSelectorCompositeVisible());
+ consumer.accept(newCondition);
+
+ updateDialog();
+ }
+ }
+
+ private Updater createAggregateConditionPanel(Composite conditionComp, AggregateCondition cond) {
+ GridLayoutFactory.fillDefaults().numColumns(2).applyTo(conditionComp);
+ new Label(conditionComp, SWT.NONE); // Eat extra column
- // Condition
- new Label(content, SWT.NONE).setText("Condition");
- conditionLabel = new Text(content, SWT.READ_ONLY);
- GridDataFactory.swtDefaults().span(2, 1).applyTo(conditionLabel);
-
- new Label(content, SWT.NONE);
- Composite conditionPanel = new Composite(content, SWT.NONE);
- GridDataFactory.swtDefaults().span(2, 1).applyTo(conditionPanel);
- GridLayoutFactory.swtDefaults().margins(0, 0).numColumns(2).applyTo(conditionPanel);
- Button conditionButton = new Button(conditionPanel, SWT.PUSH);
- conditionButton.setText("Edit...");
- GridDataFactory.swtDefaults().span(1, 1).applyTo(conditionButton);
- removeConditionButton = new Button(conditionPanel, SWT.PUSH);
- removeConditionButton.setText("Remove");
- GridDataFactory.swtDefaults().span(1, 1).applyTo(removeConditionButton);
-
- updateCondition();
-
- conditionButton.addSelectionListener(new SelectionAdapter() {
+ int n = cond.conditions.size();
+ final Updater[] updates = new Updater[n];
+ for (int i = 0; i < n; i++) {
+ updates[i] = createConditionRowPanel(conditionComp, cond, i);
+ }
+
+ Button addButton = new Button(conditionComp, SWT.PUSH);
+ GridDataFactory.swtDefaults().applyTo(addButton);
+ addButton.setImage(resourceManager.createImage(PLUS_IMAGE));
+
+ addButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
- ConditionDialog dialog = new ConditionDialog(getShell(), condition);
- if (dialog.open() == Window.OK) {
- try {
- condition = dialog.createCondition();
- } catch (DatabaseException e1) {
- LOGGER.error("Creating a condition object failed", e1);
- }
-
- updateCondition();
- }
+ cond.conditions.add(createPropertyCondition("", null, null));
+ updateDialog();
}
});
- removeConditionButton.addSelectionListener(new SelectionAdapter() {
+ return validate -> {
+ for (Updater updater : updates)
+ updater.update(validate);
+ };
+ }
+
+ private Updater createConditionRowPanel(Composite parent, AggregateCondition parentCondition, final int i) {
+ GridLayoutFactory conditionLayout = GridLayoutFactory.fillDefaults().numColumns(2);
+ GridDataFactory swtDefaults = GridDataFactory.swtDefaults();
+
+ Condition c = parentCondition.conditions.get(i);
+
+ Composite row = new Composite(parent, SWT.NONE);
+ conditionLayout.applyTo(row);
+ swtDefaults.applyTo(row);
+
+ Consumer<Condition> update = cd -> {
+ if (cd != null)
+ parentCondition.conditions.set(i, cd);
+ else
+ parentCondition.conditions.remove(i);
+ };
+
+ Updater updater = createConditionPanelFor(row, c, update);
+
+ Button removeButton = new Button(parent, SWT.PUSH);
+ swtDefaults.align(SWT.BEGINNING, SWT.BEGINNING).applyTo(removeButton);
+ removeButton.setImage(resourceManager.createImage(CROSS_IMAGE));
+
+ removeButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
- condition = null;
- updateCondition();
+ parentCondition.conditions.remove(i);
+ updateDialog();
}
});
- return content;
- }
-
- private void updateCondition() {
- if (condition != null) {
- removeConditionButton.setEnabled(true);
- try {
- conditionLabel.setText(ElementSelector.getExpression(Simantics.getSession(), condition.resource));
- } catch (DatabaseException e) {
- LOGGER.error("Error getting expression string for " + condition.resource);
- }
- }
- else {
- conditionLabel.setText("No condition");
- removeConditionButton.setEnabled(false);
- }
-
- content.layout();
+ return updater;
}
- private boolean isDiagramFieldVisible() {
- return generatorIndex == 1;
- }
+ private Updater createRouteConditionPanel(Composite conditionComp, RouteCondition condition) {
+ ROW_LAYOUT.applyTo(conditionComp);
- private boolean isSelectorCompositeVisible() {
- return selectorIndex != 0;
+ // Create combo-box
+ Combo routeCombo = new Combo(conditionComp, SWT.READ_ONLY);
+ RowDataFactory.swtDefaults().hint(120, SWT.DEFAULT).applyTo(routeCombo);
+ routeCombo.setItems(routeNames);
+
+ // Set current selection
+ int index = Arrays.indexOf(routeResources, condition.routeResource);
+ if (index >= 0)
+ routeCombo.select(index);
+
+ // Register update
+ return validate -> {
+ int i = routeCombo.getSelectionIndex();
+ if (validate && i < 0) {
+ routeCombo.forceFocus();
+ throw new RuntimeException("Must select a route");
+ }
+
+ condition.routeResource = i >= 0 ? routeResources[i] : null;
+ };
}
- class ConditionDialog extends Dialog {
- // Resource of the edited condition
- private Resource existingResource;
+ private Updater createRegionConditionPanel(Composite conditionComp, RegionCondition condition) {
+ ROW_LAYOUT.applyTo(conditionComp);
- // Inverse condition button
- private boolean isInverse;
- private Button inverseField;
-
- // Condition type
- private int typeIndex;
- private Combo typeField;
+ // Create combo-box
+ Combo regionCombo = new Combo(conditionComp, SWT.READ_ONLY);
+ RowDataFactory.swtDefaults().hint(120, SWT.DEFAULT).applyTo(regionCombo);
+ regionCombo.setItems(regionNames);
- // Type-specific control panels under a stack layout
- private Composite stackPanel;
- private StackLayout stack;
+ // Set current selection
+ int index = Arrays.indexOf(regionResources, condition.regionResource);
+ if (index >= 0)
+ regionCombo.select(index);
- private Composite propertyPanel;
- private Composite regionPanel;
- private Composite routePanel;
- private Composite aggregatePanel;
+ // Register update
+ return validate -> {
+ int i = regionCombo.getSelectionIndex();
+ if (validate && i < 0) {
+ regionCombo.forceFocus();
+ throw new ValidationException("Please select a region");
+ }
+
+ condition.regionResource = i >= 0 ? regionResources[i] : null;
+ };
+ }
+
+ private Updater createPropertyConditionPanel(Composite conditionComp, PropertyCondition condition) {
+ ROW_LAYOUT.applyTo(conditionComp);
- // Property condition
- private Double lowerLimit;
- private Double upperLimit;
- private String propertyName;
-
- private Text propertyNameField;
- private Text lowerLimitField;
- private Text upperLimitField;
+ Text lowerLimitText = new Text(conditionComp, SWT.BORDER);
+ RowDataFactory.swtDefaults().hint(40, SWT.DEFAULT).applyTo(lowerLimitText);
+ lowerLimitText.setText(condition.lowerLimit != null ? Double.toString(condition.lowerLimit) : "");
- // Region condition
- private Resource region;
- private Combo regionField;
+ new Label(conditionComp, SWT.NONE).setText("\u2264");
- // Route condition
- private Resource route;
- private Combo routeField;
+ Combo propertyNameText = new Combo(conditionComp, SWT.NONE);
+ RowDataFactory.swtDefaults().hint(120, SWT.DEFAULT).applyTo(propertyNameText);
+ propertyNameText.setItems(propertyLabels.toArray(new String[] {}));
+ int index = propertyNames.indexOf(condition.propertyName);
+ if (index >= 0)
+ propertyNameText.select(index);
+ else
+ propertyNameText.setText(condition.propertyName);
- // Aggregate condition
- private List<Condition> subConditions;
- private boolean isConjunction;
+ new Label(conditionComp, SWT.NONE).setText("\u2264");
- private org.eclipse.swt.widgets.List subConditionField;
- private Combo operatorField;
+ Text upperLimitText = new Text(conditionComp, SWT.BORDER);
+ RowDataFactory.swtDefaults().hint(40, SWT.DEFAULT).applyTo(upperLimitText);
+ upperLimitText.setText(condition.upperLimit != null ? Double.toString(condition.upperLimit) : "");
- public ConditionDialog(Shell shell, Condition condition) {
- super(shell);
-
- typeIndex = 0;
- isInverse = false;
- propertyName = "";
- upperLimit = null;
- lowerLimit = null;
- subConditions = new ArrayList<>();
-
- existingResource = condition != null ? condition.resource : null;
-
- if (condition != null) {
- if (condition instanceof PropertyCondition) {
- typeIndex = 0;
- PropertyCondition propertyCondition = (PropertyCondition)condition;
- propertyName = propertyCondition.propertyName;
- upperLimit = propertyCondition.upperLimit;
- lowerLimit = propertyCondition.lowerLimit;
- }
- else if (condition instanceof RegionCondition) {
- typeIndex = 1;
- region = ((RegionCondition)condition).regionResource;
- }
- else if (condition instanceof RouteCondition) {
- typeIndex = 2;
- route = ((RouteCondition)condition).routeResource;
- }
- else if (condition instanceof AggregateCondition) {
- typeIndex = 3;
- subConditions = new ArrayList<>(((AggregateCondition)condition).conditions);
- isConjunction = ((AggregateCondition)condition).type == Type.CONJUNCTION;
- isInverse = ((AggregateCondition)condition).type == Type.NEGATION;
+ // Register update
+ return validate -> {
+ try {
+ String text = lowerLimitText.getText();
+ condition.lowerLimit = text.isEmpty() ? null : Double.parseDouble(text);
+ } catch (NumberFormatException e) {
+ if (validate) {
+ lowerLimitText.selectAll();
+ lowerLimitText.forceFocus();
+ throw new ValidationException("Please enter a valid lower limit");
}
}
- }
-
- @Override
- protected Control createDialogArea(Composite parent) {
- getShell().setText("Edit selector condition");
-
- Composite content = (Composite)super.createDialogArea(parent);
- GridLayoutFactory.swtDefaults().numColumns(1).applyTo(content);
-
- GridDataFactory defaultWidth = GridDataFactory.swtDefaults().hint(200, SWT.DEFAULT);
-
- // Is inverse
- inverseField = new Button(content, SWT.CHECK);
- inverseField.setText("Is inverse");
- inverseField.setSelection(isInverse);
-
- // Condition type
- typeField = new Combo(content, SWT.BORDER | SWT.READ_ONLY);
- typeField.setItems("Property value", "In region", "On route", "Combination");
- typeField.select(typeIndex);
-
- // Type-dependent stacked panels
- stackPanel = new Composite(content, SWT.NONE);
- stack = new StackLayout();
- stackPanel.setLayout(stack);
-
- // Property condition panel
- propertyPanel = new Composite(stackPanel, SWT.NONE);
- GridLayoutFactory.swtDefaults().numColumns(2).applyTo(propertyPanel);
-
- new Label(propertyPanel, SWT.NONE).setText("Property name");
- propertyNameField = new Text(propertyPanel, SWT.BORDER);
- propertyNameField.setText(propertyName);
- defaultWidth.applyTo(propertyNameField);
-
- new Label(propertyPanel, SWT.NONE).setText("Lower limit");
- lowerLimitField = new Text(propertyPanel, SWT.BORDER);
- defaultWidth.applyTo(lowerLimitField);
- if (lowerLimit != null) lowerLimitField.setText(lowerLimit.toString());
-
- new Label(propertyPanel, SWT.NONE).setText("Upper limit");
- upperLimitField = new Text(propertyPanel, SWT.BORDER);
- defaultWidth.applyTo(upperLimitField);
- if (upperLimit != null) upperLimitField.setText(upperLimit.toString());
-
- // Region condition panel
- regionPanel = new Composite(stackPanel, SWT.NONE);
- GridLayoutFactory.swtDefaults().numColumns(2).applyTo(regionPanel);
-
- new Label(regionPanel, SWT.NONE).setText("Region");
- regionField = new Combo(regionPanel, SWT.BORDER | SWT.READ_ONLY);
- regionField.setItems(regionNames);
- defaultWidth.applyTo(regionField);
-
- if (region != null) {
- int regionIndex = Arrays.indexOf(regionResources, region);
- regionField.select(regionIndex);
- }
- else {
- regionField.select(0);
- }
-
- // Route condition panel
- routePanel = new Composite(stackPanel, SWT.NONE);
- GridLayoutFactory.swtDefaults().numColumns(2).applyTo(routePanel);
-
- new Label(routePanel, SWT.NONE).setText("Route");
- routeField = new Combo(routePanel, SWT.BORDER | SWT.READ_ONLY);
- routeField.setItems(routeNames);
- defaultWidth.applyTo(routeField);
-
- if (route != null) {
- int routeIndex = Arrays.indexOf(routeResources, route);
- routeField.select(routeIndex);
- }
- else {
- routeField.select(0);
- }
-
- // Aggregate condition panel
- aggregatePanel = new Composite(stackPanel, SWT.NONE);
- GridLayoutFactory.swtDefaults().numColumns(2).applyTo(aggregatePanel);
-
- new Label(aggregatePanel, SWT.NONE).setText("Operator");
- operatorField = new Combo(aggregatePanel, SWT.READ_ONLY);
- operatorField.setItems("And", "Or");
- operatorField.select(isConjunction ? 0 : 1);
-
- new Label(aggregatePanel, SWT.NONE).setText("Sub-conditions");
- Composite buttons = new Composite(aggregatePanel, SWT.NONE);
- RowLayoutFactory.swtDefaults().justify(true).fill(true).extendedMargins(0, 0, 0, 0).type(SWT.HORIZONTAL).applyTo(buttons);
- Button addButton = new Button(buttons, SWT.PUSH);
- addButton.setText("Add");
- Button removeButton = new Button(buttons, SWT.PUSH);
- removeButton.setText("Remove");
- Button editButton = new Button(buttons, SWT.PUSH);
- editButton.setText("Edit");
-
- new Label(aggregatePanel, SWT.NONE);
- subConditionField = new org.eclipse.swt.widgets.List(aggregatePanel, SWT.BORDER);
- GridDataFactory.swtDefaults().hint(200, 150).applyTo(subConditionField);
- if (subConditions != null) {
- Session session = Simantics.getSession();
- List<String> items = new ArrayList<>();
- for (Condition c : subConditions) {
- try {
- items.add(ElementSelector.getExpression(session, c.resource));
- } catch (DatabaseException e1) {
- LOGGER.error("Condition expression read failed", e1);
- items.add("<Unknown expression>");
- }
+ try {
+ String text = upperLimitText.getText();
+ condition.upperLimit = text.isEmpty() ? null : Double.parseDouble(text);
+ } catch (NumberFormatException e) {
+ if (validate) {
+ upperLimitText.selectAll();
+ upperLimitText.forceFocus();
+ throw new ValidationException("Please enter a valid upper limit");
}
-
- subConditionField.setItems(items.toArray(new String[items.size()]));
}
- addButton.addSelectionListener(new SelectionAdapter() {
- @Override
- public void widgetSelected(SelectionEvent e) {
- ConditionDialog conditionDialog = new ConditionDialog(getShell(), null);
- if (conditionDialog.open() == Window.OK) {
- Condition condition;
- try {
- condition = conditionDialog.createCondition();
- subConditions.add(condition);
-
- try {
- subConditionField.add(ElementSelector.getExpression(Simantics.getSession(), condition.resource));
- } catch (DatabaseException e1) {
- LOGGER.error("Condition expression read failed", e1);
- subConditionField.add("<Unknown expression>");
- }
- } catch (DatabaseException e2) {
- LOGGER.error("Create condition failed", e2);
- }
- }
- }
- });
+ int ind = propertyNameText.getSelectionIndex();
+ String name;
+ if (ind >= 0)
+ name = propertyNames.get(ind);
+ else
+ name = propertyNameText.getText();
- removeButton.addSelectionListener(new SelectionAdapter() {
- @Override
- public void widgetSelected(SelectionEvent e) {
- int index = subConditionField.getSelectionIndex();
- if (index >= 0) {
- subConditionField.deselectAll();
- subConditionField.remove(index);
- subConditions.remove(index);
-
- if (index < subConditions.size())
- subConditionField.setSelection(index);
- }
-
- boolean selected = subConditionField.getSelectionIndex() >= 0;
- removeButton.setEnabled(selected);
- editButton.setEnabled(selected);
- }
- });
-
- editButton.addSelectionListener(new SelectionAdapter() {
- @Override
- public void widgetSelected(SelectionEvent e) {
- int index = subConditionField.getSelectionIndex();
- if (index >= 0) {
- Condition condition = subConditions.get(index);
- ConditionDialog conditionDialog = new ConditionDialog(getShell(), condition);
- if (conditionDialog.open() == Window.OK) {
- try {
- condition = conditionDialog.createCondition();
- subConditions.set(index, condition);
-
- try {
- subConditionField.setItem(index, ElementSelector.getExpression(Simantics.getSession(), condition.resource));
- } catch (DatabaseException e1) {
- LOGGER.error("Condition expression read failed", e1);
- subConditionField.setItem(index, "<Unknown expression>");
- }
- } catch (DatabaseException e2) {
- LOGGER.error("Create condition failed", e2);
- }
- }
- }
- }
- });
-
- subConditionField.addSelectionListener(new SelectionAdapter() {
- @Override
- public void widgetSelected(SelectionEvent e) {
- boolean selected = subConditionField.getSelectionIndex() >= 0;
- removeButton.setEnabled(selected);
- editButton.setEnabled(selected);
- }
- });
-
- // Stack layout update
- typeField.addSelectionListener(new SelectionAdapter() {
- @Override
- public void widgetSelected(SelectionEvent e) {
- updateStack();
- }
- });
-
- updateStack();
-
- return content;
- }
-
- @Override
- protected void okPressed() {
- isInverse = inverseField.getSelection();
-
- switch (typeIndex) {
- case 0: // Property condition
- propertyName = propertyNameField.getText();
- try {
- String lowerLimitText = lowerLimitField.getText();
- lowerLimit = lowerLimitText.equals("") ? null : Double.valueOf(lowerLimitText);
- String upperLimitText = upperLimitField.getText();
- upperLimit = upperLimitText.equals("") ? null : Double.valueOf(upperLimitText);
- }
- catch (NumberFormatException e) {
- ErrorDialog.openError(getShell(), "Error", "Invalid numeric value: " + e.getMessage(), new Status(OK, "org.simantics.district.selection.ui", e.getMessage()));
- return;
- }
- break;
- case 1: { // Region condition
- int selectionIndex = regionField.getSelectionIndex();
- if (selectionIndex < 0) {
- ErrorDialog.openError(getShell(), "Error", "Please select a region", new Status(OK, "org.simantics.district.selection.ui", "No region selection"));
- return;
- }
- region = regionResources[selectionIndex];
- break;
- }
- case 2: // Route condition
- route = routeResources[routeField.getSelectionIndex()];
- break;
- case 3: // Aggregate condition
- isConjunction = operatorField.getSelectionIndex() == 0;
- break;
+ if (validate && name.isEmpty()) {
+ propertyNameText.forceFocus();
+ throw new ValidationException("Please select a property");
+ } else {
+ condition.propertyName = name;
}
-
- super.okPressed();
- }
+ };
+ }
+
+ private static Condition createPropertyCondition(String propertyName, Double lowerLimit, Double upperLimit) {
+ return new PropertyCondition(null, propertyName, lowerLimit, upperLimit);
+ }
- protected Condition createCondition() throws DatabaseException {
- if (isInverse && !(typeIndex == 3 && !isConjunction)) {
- Resource resource0 = createCondition0();
-
- // Create a negation
- Resource resource = Simantics.getSession().syncRequest(new WriteResult<Resource>() {
- @Override
- public Resource perform(WriteGraph graph) throws DatabaseException {
- ElementSelectionResource ES = ElementSelectionResource.getInstance(graph);
- Layer0 L0 = Layer0.getInstance(graph);
-
- Resource r = graph.newResource();
- graph.claim(r, L0.InstanceOf, ES.Negation);
- graph.claim(r, ES.HasSubcondition, resource0);
- return r;
- }
- });
-
- return ElementSelector.getCondition(Simantics.getSession(), resource);
- }
- else {
- return ElementSelector.getCondition(Simantics.getSession(), createCondition0());
- }
- }
+ private static Condition createRegionCondition(Resource regionResource) {
+ return new RegionCondition(null, regionResource, null);
+ }
- private Resource createCondition0() throws DatabaseException {
- switch (typeIndex) {
- case 0: return createPropertyCondition();
- case 1: return createRegionCondition();
- case 2: return createRouteCondition();
- case 3: return createAggregateCondition();
- default: throw new IllegalStateException("Invalid condition type code " + typeIndex);
- }
- }
+ private static Condition createRouteCondition(Resource route) {
+ return new RouteCondition(null, route, null);
+ }
- private Resource createPropertyCondition() throws DatabaseException {
- return Simantics.getSession().syncRequest(new WriteResult<Resource>() {
- @Override
- public Resource perform(WriteGraph graph) throws DatabaseException {
- ElementSelectionResource ES = ElementSelectionResource.getInstance(graph);
- Layer0 L0 = Layer0.getInstance(graph);
-
- Resource r = graph.newResource();
- graph.claim(r, L0.InstanceOf, ES.PropertyCondition);
- graph.claimLiteral(r, ES.PropertyCondition_HasPropertyName, propertyName);
- if (lowerLimit != null)
- graph.claimLiteral(r, ES.PropertyCondition_HasLowerLimit, L0.Double, lowerLimit);
- if (upperLimit != null)
- graph.claimLiteral(r, ES.PropertyCondition_HasUpperLimit, L0.Double, upperLimit);
-
- return r;
- }
- });
- }
+ private static Condition createAggregateCondition(Resource existingResource, List<Condition> subConditions, boolean isConjunction, boolean isInverse) {
+ Type type = isConjunction ? Type.CONJUNCTION : Type.DISJUNCTION;
+ AggregateCondition condition = new AggregateCondition(null, type, subConditions);
+ condition.isInverse = isInverse;
+ return condition;
+ }
+
+ static List<Resource> findComponentTypes(ReadGraph graph) throws DatabaseException {
+ DistrictNetworkResource DN = DistrictNetworkResource.getInstance(graph);
+ Resource project = Simantics.getProjectResource();
+ Resource model = ActiveModels.getPossibleActiveModel(graph, project);
- private Resource createAggregateCondition() throws DatabaseException {
- return Simantics.getSession().syncRequest(new WriteResult<Resource>() {
- @Override
- public Resource perform(WriteGraph graph) throws DatabaseException {
- ElementSelectionResource ES = ElementSelectionResource.getInstance(graph);
- Layer0 L0 = Layer0.getInstance(graph);
-
- Resource r;
- if (existingResource != null) {
- // Reuse existing resource
- r = existingResource;
- // Clear any previous statements
- graph.deny(existingResource);
- }
- else {
- r = graph.newResource();
- }
-
- Resource type;
- type = isConjunction ? ES.Conjunction : isInverse ? ES.Negation : ES.Disjunction;
-
- graph.claim(r, L0.InstanceOf, type);
- for (Condition c : subConditions) {
- graph.claim(r, ES.HasSubcondition, c.resource);
- }
-
- return r;
- }
- });
- }
+ return QueryIndexUtils.searchByType(graph, model, DN.Mapping_Base);
+ }
- private Resource createRouteCondition() throws DatabaseException {
- return Simantics.getSession().syncRequest(new WriteResult<Resource>() {
+ void updatePropertyList() {
+ propertyNames = new ArrayList<>();
+ propertyLabels = new ArrayList<>();
+
+ Collection<Resource> types = componentType != null ? Collections.singleton(componentType) : componentTypes;
+ Set<Pair<String, String>> properties = new HashSet<>();
+
+ try {
+ Simantics.getSession().syncRequest(new ReadRequest() {
@Override
- public Resource perform(WriteGraph graph) throws DatabaseException {
- ElementSelectionResource ES = ElementSelectionResource.getInstance(graph);
+ public void run(ReadGraph graph) throws DatabaseException {
Layer0 L0 = Layer0.getInstance(graph);
- Resource r = graph.newResource();
- graph.claim(r, L0.InstanceOf, ES.RouteCondition);
- graph.claim(r, ES.RouteCondition_HasRoute, route);
- return r;
+ for (Resource type : types) {
+ if (type == null)
+ continue;
+
+ Resource ct = graph.getPossibleObject(type, DistrictNetworkResource.getInstance(graph).Mapping_ComponentType);
+ if (ct == null)
+ continue;
+
+ if (graph.isInstanceOf(ct, L0.String)) {
+ Resource indexRoot = graph.syncRequest(new IndexRoot(type));
+ String name = graph.getValue(ct);
+ ct = GraphUtils.getPossibleChild(graph, indexRoot, name);
+ if (ct == null)
+ continue;
+ }
+
+ for (Resource prop : graph.getObjects(ct, L0.DomainOf)) {
+ if (!graph.isInstanceOf(prop, StructuralResource2.getInstance(graph).Property))
+ continue;
+
+ // Filter only numeric properties
+ PropertyInfo info = graph.syncRequest(new PropertyInfoRequest(prop));
+ if (info != null && info.requiredValueType != null && !isNumericValueType(info.requiredValueType))
+ continue;
+
+ String name = graph.getRelatedValue2(prop, L0.HasName);
+ String label = graph.getPossibleRelatedValue2(prop, L0.HasLabel);
+ if (label == null) label = name;
+
+ properties.add(Pair.make(label, name));
+ }
+ }
}
});
+ } catch (DatabaseException e) {
+ LOGGER.error("Failed to read district component properties", e);
}
+
+ propertyNames.clear();
+ propertyLabels.clear();
+ properties.stream().sorted(Comparator.comparing(p -> p.first)).forEachOrdered(p -> {
+ propertyLabels.add(p.first);
+ propertyNames.add(p.second);
+ });
+ }
- private Resource createRegionCondition() throws DatabaseException {
- return Simantics.getSession().syncRequest(new WriteResult<Resource>() {
- @Override
- public Resource perform(WriteGraph graph) throws DatabaseException {
- ElementSelectionResource ES = ElementSelectionResource.getInstance(graph);
- Layer0 L0 = Layer0.getInstance(graph);
-
- Resource r = graph.newResource();
- graph.claim(r, L0.InstanceOf, ES.RegionCondition);
- graph.claim(r, ES.RegionCondition_HasRegion, region);
- return r;
- }
- });
- }
-
- private void updateStack() {
- typeIndex = typeField.getSelectionIndex();
- switch (typeIndex) {
- case 0: stack.topControl = propertyPanel; break;
- case 1: stack.topControl = regionPanel; break;
- case 2: stack.topControl = routePanel; break;
- case 3: stack.topControl = aggregatePanel; break;
- }
-
- stackPanel.layout();
+ static boolean isNumericValueType(String requiredValueType) {
+ switch (requiredValueType) {
+ case "Integer":
+ case "Long":
+ case "Double":
+ case "Float":
+ return true;
+ default:
+ return false;
}
}
}
import java.util.stream.Collectors;
import org.simantics.Simantics;
+import org.simantics.databoard.Bindings;
import org.simantics.db.ReadGraph;
import org.simantics.db.RequestProcessor;
import org.simantics.db.Resource;
+import org.simantics.db.WriteGraph;
import org.simantics.db.common.request.ResourceRead;
import org.simantics.db.common.utils.ListUtils;
+import org.simantics.db.exception.AssumptionException;
import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.exception.DoesNotContainValueException;
+import org.simantics.db.exception.ManyObjectsForFunctionalRelationException;
+import org.simantics.db.exception.NoSingleResultException;
+import org.simantics.db.exception.ServiceException;
+import org.simantics.db.exception.ValidationException;
import org.simantics.db.layer0.QueryIndexUtils;
import org.simantics.db.layer0.request.ActiveModels;
import org.simantics.db.layer0.request.ActiveRuns;
import org.simantics.diagram.stubs.DiagramResource;
import org.simantics.district.network.ontology.DistrictNetworkResource;
import org.simantics.district.region.ontology.DiagramRegionsResource;
-import org.simantics.district.selection.ElementSelector.AggregateCondition.Type;
import org.simantics.layer0.Layer0;
import org.simantics.modeling.ModelingResources;
import org.simantics.structural.stubs.StructuralResource2;
return Simantics.getSession().syncRequest(new Read<Map<Resource, String>>() {
@Override
public Map<Resource, String> perform(ReadGraph graph) throws DatabaseException {
+ Layer0 L0 = Layer0.getInstance(graph);
+ StructuralResource2 STR = StructuralResource2.getInstance(graph);
+ DistrictNetworkResource DN = DistrictNetworkResource.getInstance(graph);
+ ModelingResources MOD = ModelingResources.getInstance(graph);
+
Map<Resource, String> result = new HashMap<>();
Resource model = graph.syncRequest(new PossibleActiveModel(Simantics.getProjectResource()));
- List<Resource> composites = QueryIndexUtils.searchByType(graph, model, StructuralResource2.getInstance(graph).Composite);
+ List<Resource> composites = QueryIndexUtils.searchByType(graph, model, STR.Composite);
for (Resource r : composites) {
// Get diagram
- Resource diagram = graph.getPossibleObject(r, ModelingResources.getInstance(graph).CompositeToDiagram);
- if (diagram == null) continue;
+ Resource diagram = graph.getPossibleObject(r, MOD.CompositeToDiagram);
+ if (diagram == null || !graph.isInstanceOf(diagram, DN.Diagram))
+ continue;
// Filter out user component diagrams
- Resource parent = graph.getPossibleObject(r, Layer0.getInstance(graph).PartOf);
- if (parent == null || graph.isInheritedFrom(parent, StructuralResource2.getInstance(graph).Component))
+ Resource parent = graph.getPossibleObject(r, L0.PartOf);
+ if (parent == null || graph.isInheritedFrom(parent, STR.Component))
continue;
- result.put(r, graph.getRelatedValue(r, Layer0.getInstance(graph).HasName));
+ result.put(r, graph.getRelatedValue(r, L0.HasName));
}
return result;
if (!graph.isInstanceOf(resource, ES.Generator))
throw new IllegalArgumentException("Resource " + resource + " is not a valid generator");
- if (graph.isInstanceOf(resource, ES.Generator_Model)) {
+ if (graph.isInstanceOf(resource, ES.Generator_Model))
return new ModelGenerator();
- }
- else if (graph.isInstanceOf(resource, ES.Generator_Diagram)) {
+ else if (graph.isInstanceOf(resource, ES.Generator_Diagram))
return new DiagramGenerator(graph.getSingleObject(resource, ES.Generator_HasDiagram));
- }
- else if (graph.isInstanceOf(resource, ES.Generator_Explicit)) {
+ else if (graph.isInstanceOf(resource, ES.Generator_Explicit))
return new ExplicitGenerator(graph.getObjects(resource, ES.Generator_HasSelectedElement));
- }
- else {
+ else
throw new IllegalArgumentException("Unknown generator type " + graph.getURI(graph.getSingleType(resource)));
- }
}
private static Selector buildSelector(ReadGraph graph, Resource resource) throws DatabaseException {
throw new IllegalArgumentException("Resource " + resource + " is not a valid selector");
Selector s;
- if (graph.isInstanceOf(resource, ES.Selector_All)) {
+ if (graph.isInstanceOf(resource, ES.Selector_All))
s = new All();
- }
- else if (graph.isInstanceOf(resource, ES.PropertySelector)) {
- String propertyName = graph.getRelatedValue(resource, ES.PropertySelector_HasSelectionPropertyName);
- Integer resultCount = graph.getRelatedValue(resource, ES.PropertySelector_HasResultCount);
- boolean isSmallest = graph.isInstanceOf(resource, ES.Selector_NLowest);
- s = new PropertySelector(isSmallest, propertyName, resultCount);
- }
- else {
+ else if (graph.isInstanceOf(resource, ES.PropertySelector))
+ s = new PropertySelector(graph, resource);
+ else
throw new IllegalArgumentException("Unknown selector type " + graph.getURI(graph.getSingleType(resource)));
- }
+
+ Resource mapping = graph.getPossibleObject(resource, ES.Selector_HasMapping);
+ s.componentType = mapping;
+
return s;
}
throw new IllegalArgumentException("Resource " + resource + " is not a valid condition");
Condition cond;
- if (graph.isInstanceOf(resource, ES.PropertyCondition)) {
- String propertyName = graph.getRelatedValue(resource, ES.PropertyCondition_HasPropertyName);
- Double lowerLimit = graph.getPossibleRelatedValue(resource, ES.PropertyCondition_HasLowerLimit);
- Double upperLimit = graph.getPossibleRelatedValue(resource, ES.PropertyCondition_HasUpperLimit);
- cond = new PropertyCondition(resource, propertyName, lowerLimit, upperLimit);
+ if (graph.isInstanceOf(resource, ES.PropertyCondition))
+ cond = new PropertyCondition(graph, resource);
+ else if (graph.isInstanceOf(resource, ES.RegionCondition))
+ cond = new RegionCondition(graph, resource);
+ else if (graph.isInstanceOf(resource, ES.RouteCondition))
+ cond = new RouteCondition(graph, resource);
+ else if (graph.isInstanceOf(resource, ES.AggregateCondition))
+ cond = new AggregateCondition(graph, resource);
+ else
+ throw new IllegalArgumentException("Unknown condition type " + graph.getURI(graph.getSingleType(resource)));
+
+ return cond;
+ }
+
+ private static String buildExpression(ReadGraph graph, Resource r) throws DatabaseException {
+ if (graph.isInstanceOf(r, ES.Selection))
+ return buildSelectionExpression(graph, r);
+ else if (graph.isInstanceOf(r, ES.Condition))
+ return buildConditionExpression(graph, r);
+ else if (graph.isInstanceOf(r, ES.Selector))
+ return buildSelectorExpression(graph, r);
+ else if (graph.isInstanceOf(r, ES.Generator))
+ return buildGeneratorExpression(graph, r);
+ else
+ throw new DatabaseException("Unsupported resource type <" + graph.getURI(graph.getSingleType(r)) + ">");
+ }
+
+ private static String buildSelectionExpression(ReadGraph graph, Resource r) throws DatabaseException,
+ NoSingleResultException, ManyObjectsForFunctionalRelationException, ServiceException {
+ String exp = "select " + getExpression(graph, graph.getSingleObject(r, ES.Selection_HasSelector)) +
+ " from " + getExpression(graph, graph.getSingleObject(r, ES.Selection_HasGenerator));
+
+ Resource cond = graph.getPossibleObject(r, ES.Selection_HasCondition);
+ return cond != null ? exp + " where {" + getExpression(graph, cond) + "}" : exp;
+ }
+
+ private static String buildGeneratorExpression(ReadGraph graph, Resource r)
+ throws ServiceException, NoSingleResultException, DoesNotContainValueException,
+ ManyObjectsForFunctionalRelationException, DatabaseException, AssumptionException, ValidationException {
+ if (graph.isInstanceOf(r, ES.Generator_Model)) {
+ return "model";
}
- else if (graph.isInstanceOf(resource, ES.RegionCondition)) {
- DiagramRegionsResource DR = DiagramRegionsResource.getInstance(graph);
- Resource regionResource = graph.getSingleObject(resource, ES.RegionCondition_HasRegion);
- double[] region = graph.getRelatedValue(regionResource, DR.Region_area);
- cond = new RegionCondition(resource, regionResource, region);
+ else if (graph.isInstanceOf(r, ES.Generator_Diagram)) {
+ return "diagram \"" + graph.getRelatedValue(graph.getSingleObject(r, ES.Generator_HasDiagram), L0.HasName) + "\"";
}
- else if (graph.isInstanceOf(resource, ES.RouteCondition)) {
- Resource routeResource = graph.getSingleObject(resource, ES.RouteCondition_HasRoute);
- Set<Resource> routePoints = new HashSet<>(ListUtils.toList(graph, routeResource));
- cond = new RouteCondition(resource, routeResource, routePoints);
+ else if (graph.isInstanceOf(r, ES.Generator_Explicit)) {
+ return "<list of " + graph.getObjects(r, ES.Generator_HasSelectedElement).size() + " elements>";
}
- else if (graph.isInstanceOf(resource, ES.AggregateCondition)) {
- Collection<Resource> conditionResources = graph.getObjects(resource, ES.HasSubcondition);
- List<Condition> conditions = new ArrayList<>(conditionResources.size());
- for (Resource c : conditionResources) {
- conditions.add(buildCondition(graph, c));
- }
- Type type;
- if (graph.isInstanceOf(resource, ES.Conjunction))
- type = AggregateCondition.Type.CONJUNCTION;
- else if (graph.isInstanceOf(resource, ES.Negation))
- type = AggregateCondition.Type.NEGATION;
- else if (graph.isInstanceOf(resource, ES.Disjunction))
- type = AggregateCondition.Type.DISJUNCTION;
- else
- throw new IllegalArgumentException("Unknown aggreate condition type " + graph.getURI(graph.getSingleType(resource)));
-
- cond = new AggregateCondition(resource, type, conditions);
+ else {
+ throw new DatabaseException("Unsupported generator resource type <" + graph.getURI(graph.getSingleType(r)) + ">");
+ }
+ }
+
+ private static String buildSelectorExpression(ReadGraph graph, Resource r)
+ throws ServiceException, NoSingleResultException, DoesNotContainValueException, DatabaseException,
+ AssumptionException, ValidationException, ManyObjectsForFunctionalRelationException {
+ String exp;
+ if (graph.isInstanceOf(r, ES.Selector_All)) {
+ exp = "all";
+ }
+ else if (graph.isInstanceOf(r, ES.PropertySelector)) {
+ Integer count = graph.getRelatedValue(r, ES.PropertySelector_HasResultCount);
+ exp = count.toString();
}
else {
- throw new IllegalArgumentException("Unknown condition type " + graph.getURI(graph.getSingleType(resource)));
+ throw new DatabaseException("Unsupported selector resource type <" + graph.getURI(graph.getSingleType(r)) + ">");
}
- return cond;
+ Resource mapping = graph.getPossibleObject(r, ES.Selector_HasMapping);
+ if (mapping != null) {
+ String name = graph.getRelatedValue2(mapping, L0.HasName);
+ exp = exp + " " + name;
+ } else {
+ exp = exp + " elements";
+ }
+
+ if (graph.isInstanceOf(r, ES.PropertySelector)) {
+ String op;
+ if (graph.isInstanceOf(r, ES.Selector_NLowest))
+ op = "lowest";
+ else if (graph.isInstanceOf(r, ES.Selector_NHighest))
+ op = "highest";
+ else
+ throw new DatabaseException("Unsupported property selector resource type <" + graph.getURI(graph.getSingleType(r)) + ">");
+
+ String name = graph.getRelatedValue(r, ES.PropertySelector_HasSelectionPropertyName);
+ exp = exp + " with " + op + " " + name;
+ }
+
+ return exp;
}
- private static String buildExpression(ReadGraph graph, Resource r) throws DatabaseException {
- if (graph.isInstanceOf(r, ES.Selection)) {
- String exp = "select " + getExpression(graph, graph.getSingleObject(r, ES.Selection_HasSelector)) +
- " from " + getExpression(graph, graph.getSingleObject(r, ES.Selection_HasGenerator));
-
- Resource cond = graph.getPossibleObject(r, ES.Selection_HasCondition);
- return cond != null ? exp + " where {" + getExpression(graph, cond) + "}" : exp;
+ private static String buildConditionExpression(ReadGraph graph, Resource r) throws ServiceException,
+ DatabaseException, NoSingleResultException, ManyObjectsForFunctionalRelationException,
+ DoesNotContainValueException, AssumptionException, ValidationException {
+ String result;
+ boolean isInverse = graph.hasStatement(r, ES.Condition_IsInverse, r);
+ if (graph.isInstanceOf(r, ES.PropertyCondition)) {
+ result = buildPropertyConditionExpression(graph, r);
}
- else if (graph.isInstanceOf(r, ES.Condition)) {
- if (graph.isInstanceOf(r, ES.PropertyCondition)) {
- return buildPropertyConditionExpression(graph, r);
- }
- else if (graph.isInstanceOf(r, ES.RegionCondition)) {
- Resource region = graph.getSingleObject(r, ES.RegionCondition_HasRegion);
- String name = graph.getRelatedValue(region, L0.HasLabel);
- return "in region " + name;
- }
- else if (graph.isInstanceOf(r, ES.RouteCondition)) {
- Resource route = graph.getSingleObject(r, ES.RouteCondition_HasRoute);
- String name = graph.getRelatedValue(route, L0.HasLabel);
- return "in route " + name;
- }
- else if (graph.isInstanceOf(r, ES.AggregateCondition)) {
- String op = graph.isInstanceOf(r, ES.Conjunction) ? " and " : " or ";
- List<String> exps = new ArrayList<>();
- Collection<Resource> objects = graph.getObjects(r, ES.HasSubcondition);
- for (Resource c : objects) {
- String exp = getExpression(graph, c);
- exps.add(objects.size() > 1 ? "{" + exp + "}" : exp);
- }
- String result = String.join(op, exps);
- if (graph.isInstanceOf(r, ES.Negation))
- result = "not {" + result + "}";
- return result;
- }
- else {
- throw new DatabaseException("Unsupported condition resource type <" + graph.getURI(graph.getSingleType(r)) + ">");
- }
+ else if (graph.isInstanceOf(r, ES.RegionCondition)) {
+ result = buildRegionConditionExpression(graph, r);
}
- else if (graph.isInstanceOf(r, ES.Selector)) {
- if (graph.isInstanceOf(r, ES.Selector_All)) {
- return "all";
- }
- else if (graph.isInstanceOf(r, ES.PropertySelector)) {
- String op;
- if (graph.isInstanceOf(r, ES.Selector_NLowest))
- op = "bottom";
- else if (graph.isInstanceOf(r, ES.Selector_NHighest))
- op = "top";
- else
- throw new DatabaseException("Unsupported property selector resource type <" + graph.getURI(graph.getSingleType(r)) + ">");
-
- String name = graph.getRelatedValue(r, ES.PropertySelector_HasSelectionPropertyName);
- Integer count = graph.getRelatedValue(r, ES.PropertySelector_HasResultCount);
- return op + " " + count + " of " + name;
- }
- else {
- throw new DatabaseException("Unsupported selector resource type <" + graph.getURI(graph.getSingleType(r)) + ">");
- }
+ else if (graph.isInstanceOf(r, ES.RouteCondition)) {
+ result = buildRouteConditionExpression(graph, r);
}
- else if (graph.isInstanceOf(r, ES.Generator)) {
- if (graph.isInstanceOf(r, ES.Generator_Model)) {
- return "model";
- }
- else if (graph.isInstanceOf(r, ES.Generator_Diagram)) {
- return "diagram \"" + graph.getRelatedValue(graph.getSingleObject(r, ES.Generator_HasDiagram), L0.HasName) + "\"";
- }
- else if (graph.isInstanceOf(r, ES.Generator_Explicit)) {
- return "<list of " + graph.getObjects(r, ES.Generator_HasSelectedElement).size() + " elements>";
- }
- else {
- throw new DatabaseException("Unsupported generator resource type <" + graph.getURI(graph.getSingleType(r)) + ">");
- }
+ else if (graph.isInstanceOf(r, ES.AggregateCondition)) {
+ // This handles isInverse internally
+ return buildAggregateConditionExpression(graph, r, isInverse);
}
else {
- throw new DatabaseException("Unsupported resource type <" + graph.getURI(graph.getSingleType(r)) + ">");
+ throw new DatabaseException("Unsupported condition resource type <" + graph.getURI(graph.getSingleType(r)) + ">");
}
+
+ if (isInverse)
+ result = "not {" + result + "}";
+
+ return result;
+ }
+
+ private static String buildAggregateConditionExpression(ReadGraph graph, Resource r, boolean isInverse)
+ throws ServiceException, DatabaseException {
+ String result;
+ String op = graph.isInstanceOf(r, ES.Conjunction) ? " and " : " or ";
+ List<String> exps = new ArrayList<>();
+ Collection<Resource> objects = graph.getObjects(r, ES.HasSubcondition);
+ for (Resource c : objects) {
+ String exp = getExpression(graph, c);
+ exps.add(objects.size() > 1 ? "{" + exp + "}" : exp);
+ }
+ result = String.join(op, exps);
+ if (graph.isInstanceOf(r, ES.Negation) ^ isInverse)
+ result = "not {" + result + "}";
+ return result;
+ }
+
+ private static String buildRouteConditionExpression(ReadGraph graph, Resource r) throws NoSingleResultException,
+ ManyObjectsForFunctionalRelationException, ServiceException, DoesNotContainValueException {
+ String result;
+ Resource route = graph.getSingleObject(r, ES.RouteCondition_HasRoute);
+ String name = graph.getRelatedValue(route, L0.HasLabel);
+ result = "in route " + name;
+ return result;
+ }
+
+ private static String buildRegionConditionExpression(ReadGraph graph, Resource r) throws NoSingleResultException,
+ ManyObjectsForFunctionalRelationException, ServiceException, DoesNotContainValueException {
+ String result;
+ Resource region = graph.getSingleObject(r, ES.RegionCondition_HasRegion);
+ String name = graph.getRelatedValue(region, L0.HasLabel);
+ result = "in region " + name;
+ return result;
}
private static String buildPropertyConditionExpression(ReadGraph graph, Resource r) throws DatabaseException {
String propertyName = graph.getRelatedValue(r, ES.PropertyCondition_HasPropertyName);
Double lowerLimit = graph.getPossibleRelatedValue(r, ES.PropertyCondition_HasLowerLimit);
Double upperLimit = graph.getPossibleRelatedValue(r, ES.PropertyCondition_HasUpperLimit);
- if (lowerLimit == null && upperLimit == null) {
- return "has property " + propertyName;
- }
- else {
+ if (upperLimit == null) {
+ if (lowerLimit == null) {
+ return "has property " + propertyName;
+ } else {
+ return propertyName + " \u2265 " + lowerLimit;
+ }
+ } else {
StringBuilder result = new StringBuilder();
if (lowerLimit != null) {
result.append(lowerLimit);
- result.append(" < ");
+ result.append(" \u2264 ");
}
result.append(propertyName);
- if (upperLimit != null) {
- result.append(" < ");
- result.append(upperLimit);
- }
+ result.append(" \u2264 ");
+ result.append(upperLimit);
return result.toString();
}
}
}
public static abstract class Selector {
+ public Resource componentType = null;
+
abstract SelectionResult select(ReadGraph graph, Collection<Resource> elements);
+
+ Collection<Resource> filterElements(ReadGraph graph, Collection<Resource> elements) {
+ if (componentType == null)
+ return elements;
+
+ Collection<Resource> selected = new HashSet<>(elements.size());
+ for (Resource r : elements) {
+ try {
+ if (graph.hasStatement(r, DN.HasMapping, componentType))
+ selected.add(r);
+ } catch (DatabaseException e) {
+ // Just leave it out of the result
+ }
+ }
+
+ return selected;
+ }
}
public static class All extends Selector {
@Override
SelectionResult select(ReadGraph graph, Collection<Resource> elements) {
- return new SelectionResult(elements, 0, 0);
+ Collection<Resource> selected = filterElements(graph, elements);
+ return new SelectionResult(selected, 0, 0);
}
}
this.resultCount = resultCount;
}
+ public PropertySelector(ReadGraph graph, Resource resource) throws DatabaseException {
+ this.propertyName = graph.getRelatedValue(resource, ES.PropertySelector_HasSelectionPropertyName);
+ this.resultCount = graph.getRelatedValue(resource, ES.PropertySelector_HasResultCount);
+ this.smallest = graph.isInstanceOf(resource, ES.Selector_NLowest);
+ }
+
public boolean smallest;
public String propertyName;
public int resultCount;
@Override
SelectionResult select(ReadGraph graph, Collection<Resource> elements) {
+ elements = filterElements(graph, elements);
+
// Select sorting direction
Comparator<Pair<Resource, Double>> comparator = smallest ?
(p1, p2) -> Double.compare(p1.second, p2.second) :
public static abstract class Condition {
public Resource resource;
+ public boolean isInverse;
Condition(Resource r) {
resource = r;
+ isInverse = false;
}
- abstract boolean match(ReadGraph graph, Resource r) throws DatabaseException;
+ Condition(ReadGraph graph, Resource r) throws DatabaseException {
+ this(r);
+ ElementSelectionResource ES = ElementSelectionResource.getInstance(graph);
+ isInverse = graph.hasStatement(r, ES.Condition_IsInverse, r);
+ }
+
+ public abstract boolean match(ReadGraph graph, Resource r) throws DatabaseException;
+ public Resource update(WriteGraph graph) throws DatabaseException {
+ ElementSelectionResource ES = ElementSelectionResource.getInstance(graph);
+
+ assert(resource != null);
+ if (isInverse)
+ graph.claim(resource, ES.Condition_IsInverse, resource);
+ else
+ graph.deny(resource, ES.Condition_IsInverse, resource);
+ return resource;
+ }
}
public static class PropertyCondition extends Condition {
+ public PropertyCondition(ReadGraph graph, Resource r) throws DatabaseException {
+ super(graph, r);
+
+ ElementSelectionResource ES = ElementSelectionResource.getInstance(graph);
+ this.propertyName = graph.getRelatedValue(resource, ES.PropertyCondition_HasPropertyName);
+ this.lowerLimit = graph.getPossibleRelatedValue(resource, ES.PropertyCondition_HasLowerLimit);
+ this.upperLimit = graph.getPossibleRelatedValue(resource, ES.PropertyCondition_HasUpperLimit);
+ }
+
public PropertyCondition(Resource r, String propertyName, Double lowerLimit, Double upperLimit) {
super(r);
public Double upperLimit;
@Override
- boolean match(ReadGraph graph, Resource r) {
+ public boolean match(ReadGraph graph, Resource r) {
Double value = getPropertyValue(graph, r, propertyName);
- return value != null && (lowerLimit == null || value >= lowerLimit) && (upperLimit == null || value <= upperLimit);
+ boolean result = value != null && (lowerLimit == null || value >= lowerLimit) && (upperLimit == null || value <= upperLimit);
+ return result ^ isInverse;
+ }
+
+ @Override
+ public Resource update(WriteGraph graph) throws DatabaseException {
+ ElementSelectionResource ES = ElementSelectionResource.getInstance(graph);
+ Layer0 L0 = Layer0.getInstance(graph);
+
+ if (resource == null) {
+ resource = graph.newResource();
+ graph.claim(resource, L0.InstanceOf, ES.PropertyCondition);
+ }
+
+ super.update(graph);
+
+ graph.claimLiteral(resource, ES.PropertyCondition_HasPropertyName, propertyName);
+ if (lowerLimit != null)
+ graph.claimLiteral(resource, ES.PropertyCondition_HasLowerLimit, L0.Double, lowerLimit);
+ else
+ graph.deny(resource, ES.PropertyCondition_HasLowerLimit);
+
+ if (upperLimit != null)
+ graph.claimLiteral(resource, ES.PropertyCondition_HasUpperLimit, L0.Double, upperLimit);
+ else
+ graph.deny(resource, ES.PropertyCondition_HasUpperLimit);
+ return resource;
}
}
public static class RegionCondition extends Condition {
- public RegionCondition(Resource r, Resource regionResoruce, double[] region) {
+ public RegionCondition(Resource r, Resource regionResource, double[] region) {
super(r);
this.region = region;
+ this.path = createPathForRegion(region);
+ this.regionResource = regionResource;
+ }
+
+ public RegionCondition(ReadGraph graph, Resource r) throws DatabaseException {
+ super(graph, r);
+ ElementSelectionResource ES = ElementSelectionResource.getInstance(graph);
+ DiagramRegionsResource DR = DiagramRegionsResource.getInstance(graph);
+ this.regionResource = graph.getPossibleObject(resource, ES.RegionCondition_HasRegion);
+ this.region = regionResource != null ? graph.getRelatedValue(regionResource, DR.Region_area) : null;
+ this.path = createPathForRegion(region);
+ }
+
+ public static Path2D createPathForRegion(double[] region) {
Path2D path = new Path2D.Double();
- double startX = region[0];
- double startY = region[1];
- path.moveTo(startX, startY);
- for (int i = 2; i < region.length; i+=2)
- path.lineTo(region[i], region[i+1]);
- path.closePath();
+ if (region != null) {
+ double startX = region[0];
+ double startY = region[1];
+ path.moveTo(startX, startY);
+ for (int i = 2; i < region.length; i+=2)
+ path.lineTo(region[i], region[i+1]);
+ path.closePath();
+ }
- this.path = path;
- this.regionResource = regionResoruce;
+ return path;
}
public Resource regionResource;
Path2D path;
@Override
- boolean match(ReadGraph graph, Resource r) throws DatabaseException {
+ public boolean match(ReadGraph graph, Resource r) throws DatabaseException {
double[] transform = graph.getRelatedValue(r, DIA.HasTransform);
double x = transform[4];
double y = transform[5];
- return path.contains(x, y);
- }
+ return path.contains(x, y) ^ isInverse;
+ }
+
+ @Override
+ public Resource update(WriteGraph graph) throws DatabaseException {
+ Layer0 L0 = Layer0.getInstance(graph);
+ ElementSelectionResource ES = ElementSelectionResource.getInstance(graph);
+ DiagramRegionsResource DR = DiagramRegionsResource.getInstance(graph);
+
+ if (resource == null) {
+ resource = graph.newResource();
+ graph.claim(resource, L0.InstanceOf, ES.RegionCondition);
+ }
+
+ super.update(graph);
+
+ graph.claim(resource, ES.RegionCondition_HasRegion, regionResource);
+
+ // Re-read region data to match DB
+ this.region = regionResource != null ? graph.getRelatedValue(regionResource, DR.Region_area, Bindings.DOUBLE_ARRAY) : null;
+ this.path = createPathForRegion(region);
+
+ return resource;
+ }
}
public static class RouteCondition extends Condition {
this.routeResource = routeResource;
}
+ public RouteCondition(ReadGraph graph, Resource r) throws DatabaseException {
+ super(graph, r);
+ this.routeResource = graph.getPossibleObject(resource, ES.RouteCondition_HasRoute);
+ this.routePoints = getRoutePoints(graph, routeResource);
+ }
+
+ public static Set<Resource> getRoutePoints(ReadGraph graph, Resource routeResource) throws DatabaseException {
+ return routeResource != null ?
+ new HashSet<>(ListUtils.toList(graph, routeResource)) :
+ Collections.emptySet();
+ }
+
public Resource routeResource;
Set<Resource> routePoints;
@Override
- boolean match(ReadGraph graph, Resource r) throws DatabaseException {
- return routePoints.contains(r);
+ public boolean match(ReadGraph graph, Resource r) throws DatabaseException {
+ return routePoints.contains(r) ^ isInverse;
+ }
+
+ @Override
+ public Resource update(WriteGraph graph) throws DatabaseException {
+ ElementSelectionResource ES = ElementSelectionResource.getInstance(graph);
+ Layer0 L0 = Layer0.getInstance(graph);
+
+ if (resource == null) {
+ resource = graph.newResource();
+ graph.claim(resource, L0.InstanceOf, ES.RouteCondition);
+ }
+
+ super.update(graph);
+
+ if (routeResource != null)
+ graph.claim(resource, ES.RouteCondition_HasRoute, routeResource);
+
+ this.routePoints = getRoutePoints(graph, routeResource);
+
+ return resource;
}
}
this.conditions = conditions;
}
+ public AggregateCondition(ReadGraph graph, Resource r) throws DatabaseException {
+ super(graph, r);
+ Collection<Resource> conditionResources = graph.getObjects(resource, ES.HasSubcondition);
+ conditions = new ArrayList<>(conditionResources.size());
+ for (Resource c : conditionResources) {
+ conditions.add(buildCondition(graph, c));
+ }
+ if (graph.isInstanceOf(resource, ES.Conjunction))
+ this.type = AggregateCondition.Type.CONJUNCTION;
+ else if (graph.isInstanceOf(resource, ES.Negation))
+ this.type = AggregateCondition.Type.NEGATION;
+ else if (graph.isInstanceOf(resource, ES.Disjunction))
+ this.type = AggregateCondition.Type.DISJUNCTION;
+ else
+ throw new IllegalArgumentException("Unknown aggreate condition type " + graph.getURI(graph.getSingleType(resource)));
+ }
+
public Type type;
public List<Condition> conditions;
@Override
- boolean match(ReadGraph graph, Resource r) throws DatabaseException {
+ public boolean match(ReadGraph graph, Resource r) throws DatabaseException {
+ return doMatch(graph, r) ^ isInverse;
+ }
+
+ private boolean doMatch(ReadGraph graph, Resource r) throws DatabaseException {
switch (type) {
case DISJUNCTION:
for (Condition c : conditions)
throw new IllegalArgumentException("Unknown aggregate condition type " + type);
}
}
+
+ @Override
+ public Resource update(WriteGraph graph) throws DatabaseException {
+ Layer0 L0 = Layer0.getInstance(graph);
+ ElementSelectionResource ES = ElementSelectionResource.getInstance(graph);
+
+ if (resource == null) {
+ resource = graph.newResource();
+ } else {
+ graph.deny(resource, L0.InstanceOf);
+ graph.deny(resource, ES.HasSubcondition);
+ }
+
+ Resource type;
+ switch (this.type) {
+ case CONJUNCTION:
+ type = ES.Conjunction; break;
+ case DISJUNCTION:
+ type = ES.Disjunction; break;
+ case NEGATION:
+ type = ES.Negation; break;
+ default:
+ throw new IllegalStateException("Unknown condition type " + this.type);
+ }
+
+ graph.claim(resource, L0.InstanceOf, type);
+
+ super.update(graph);
+
+ for (Condition c : conditions) {
+ graph.claim(resource, ES.HasSubcondition, c.update(graph));
+ }
+
+ return resource;
+ }
}
public static class ElementSelectorQuery extends ResourceRead<ElementSelector> {