1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package cz.zcu.mre.sparkle.gui.query.queryTypes.describe;
21
22 import cz.zcu.mre.sparkle.gui.query.helpers.*;
23 import cz.zcu.mre.sparkle.gui.tools.Components;
24 import cz.zcu.mre.sparkle.gui.tools.ReferenceKeeper;
25 import cz.zcu.mre.sparkle.tools.Changeable;
26 import cz.zcu.mre.sparkle.tools.Saveable;
27 import cz.zcu.mre.sparkle.tools.SparqlParser;
28 import javafx.beans.InvalidationListener;
29 import javafx.collections.ObservableList;
30 import javafx.event.EventHandler;
31 import javafx.fxml.FXML;
32 import javafx.scene.Node;
33 import javafx.scene.control.Button;
34 import javafx.scene.control.CheckBox;
35 import javafx.scene.layout.FlowPane;
36 import org.antlr.v4.runtime.ParserRuleContext;
37 import org.antlr.v4.runtime.tree.ParseTree;
38 import org.w3c.dom.Element;
39 import org.w3c.dom.NodeList;
40 import java.util.HashSet;
41 import java.util.List;
42 import java.util.Set;
43 import static cz.zcu.mre.sparkle.tools.sparqlParser.SparqlParserUtils.ALL_VALUES;
44
45
46
47
48
49
50
51
52
53 @SuppressWarnings("SimplifyStreamApiCallChains")
54 public final class DescribeClausePane
55 extends FlowPane
56 implements VariablesGenerator, PartialQueryGenerator, VariablesCollector,
57 PrefixesUser, Saveable, Changeable {
58
59 private static final String XML_DESCRIBE_ALL_FALSE = "0";
60 private static final String XML_DESCRIBE_ALL_TRUE = "1";
61 private static final String XML_DESCRIBE_ALL = "all";
62 private static final String XML_ELEMENT_NAME = "DescribeGroup";
63 @FXML
64 private CheckBox allCheckBox;
65 @FXML
66 private Button addItemButton;
67
68 private final Set<InvalidationListener> observers = new HashSet<>();
69 private final Set<VariablesCollector> variablesCollectors = new HashSet<>();
70 private final DescribeQueryFormPane parentQueryPane;
71
72
73
74 private final Set<String> currentVariables = new HashSet<>();
75 private final ReferenceKeeper keeper = new ReferenceKeeper();
76
77
78
79
80 private final EventHandler<ObjectRelatedActionEvent<DescribeClauseItem>> itemRemovalEventHandler = event
81 -> {
82 getChildren().remove(event.relatedObject);
83 event.relatedObject.getVariables().forEach(this::notifyVariableRemoved);
84 };
85
86 public DescribeClausePane(final DescribeQueryFormPane parentQueryPane) {
87 Components.load(this);
88
89 this.parentQueryPane = parentQueryPane;
90
91
92 autoWatch(getChildren(), DescribeClauseItem.class);
93
94 watch(allCheckBox.selectedProperty());
95
96
97 addItem();
98 }
99
100
101
102
103 @FXML
104 private void addItem() {
105 addVariable(null).requestFocus();
106 }
107
108
109
110
111 private Node getFirstNode() {
112 final ObservableList<Node> children = getChildren();
113 return children.size() > 0 ? children.get(0) : null;
114 }
115
116
117
118
119
120
121
122
123
124
125 public final DescribeClauseItem addVariable(final String variableName) {
126 final Node firstNode = getFirstNode();
127
128 if ((variableName != null) && (firstNode instanceof DescribeClauseItem)) {
129 final DescribeClauseItem item = (DescribeClauseItem) firstNode;
130 if (item.isEmpty()) {
131 item.describeVariable(variableName);
132 return item;
133 }
134 }
135
136 final DescribeClauseItem item = createItem();
137 addItem(item);
138
139 if (variableName != null) {
140 item.describeVariable(variableName);
141 }
142
143 return item;
144 }
145
146
147
148
149
150
151 private void addItem(final DescribeClauseItem item) {
152 final ObservableList<Node> children = getChildren();
153 children.add(children.indexOf(addItemButton), item);
154 item.setOnRemovalRequested(keeper.toWeak(itemRemovalEventHandler));
155 item.addVariablesCollector(this);
156 updateOpacity();
157 }
158
159
160
161
162
163
164 private DescribeClauseItem createItem() {
165 return new DescribeClauseItem(parentQueryPane, getFirstNode() instanceof DescribeClauseItem);
166 }
167
168 @FXML
169 @SuppressWarnings("unused")
170 private void allCheckBoxOnAction() {
171 updateOpacity();
172 }
173
174
175
176
177
178 private void updateOpacity() {
179 final double opacity = allCheckBox.isSelected() ? 0.3 : 1.0;
180 addItemButton.setOpacity(opacity);
181
182 getChildren().stream().filter((node) -> (node instanceof DescribeClauseItem)).forEach((node) -> node.setOpacity(opacity));
183 }
184
185 @Override
186 public final String getQueryPart() {
187 final StringBuffer result = new StringBuffer("DESCRIBE ");
188
189 if (allCheckBox.isSelected()) {
190 result.append("* ");
191 } else {
192 getChildren().stream().filter((node) -> (node instanceof PartialQueryGenerator)).forEach((node) -> result.append(((PartialQueryGenerator) node).getQueryPart()));
193 }
194
195 return result.toString();
196 }
197
198 @Override
199 public final Set<String> getVariables() {
200 final Set<String> result = new HashSet<>();
201 getChildren().stream().filter((node) -> (node instanceof SimpleVariablesGenerator)).forEach((node) -> result.addAll(((SimpleVariablesGenerator) node).getVariables()));
202 return result;
203 }
204
205 @Override
206 public final void notifyVariableRemoved(final String variableName) {
207 currentVariables.remove(variableName);
208 variablesCollectors.stream().forEach((collector) -> collector.onVariableRemoved(variableName));
209 }
210
211 @Override
212 public final void notifyVariableAdded(final String variableName) {
213 currentVariables.add(variableName);
214 variablesCollectors.stream().forEach((collector) -> collector.onVariableAdded(variableName));
215 }
216
217 @Override
218 public final void addVariablesCollector(final VariablesCollector collector) {
219 variablesCollectors.add(collector);
220 }
221
222 @Override
223 public final void removeVariablesCollector(final VariablesCollector collector) {
224 variablesCollectors.remove(collector);
225 }
226
227 @Override
228 public final void notifyVariableChanged(final String oldVariableName, final String newVariableName) {
229 currentVariables.remove(oldVariableName);
230 currentVariables.add(newVariableName);
231 variablesCollectors.stream().forEach((collector) -> collector.onVariableChanged(oldVariableName, newVariableName));
232 }
233
234 @Override
235 public final void onVariableAdded(final String variableName) {
236 if (!currentVariables.contains(variableName)) {
237 notifyVariableAdded(variableName);
238 }
239 }
240
241 @Override
242 public final void onVariableRemoved(final String variableName) {
243 if (!getVariables().contains(variableName)) {
244 notifyVariableRemoved(variableName);
245 }
246 }
247
248 @Override
249 public final void onVariableChanged(final String oldVariableName, final String newVariableName) {
250 final Set<String> newState = getVariables();
251 final boolean added = !currentVariables.contains(newVariableName) && newState.contains(newVariableName);
252 final boolean removed = currentVariables.contains(oldVariableName) && !newState.contains(oldVariableName);
253
254 if (added && removed) {
255 notifyVariableChanged(oldVariableName, newVariableName);
256 } else if (added) {
257 notifyVariableAdded(newVariableName);
258 } else if (removed) {
259 notifyVariableRemoved(oldVariableName);
260 }
261 }
262
263 @Override
264 public final Set<String> getPrefixesUsed(final boolean appendDelimiter) {
265 final Set<String> result = new HashSet<>();
266
267 if (allCheckBox.isSelected()) {
268 return result;
269 }
270
271 getChildren().stream().filter((node) -> (node instanceof PrefixesUser)).forEach((node) -> result.addAll(((PrefixesUser) node).getPrefixesUsed(appendDelimiter)));
272
273 return result;
274 }
275
276 @Override
277 public final void save(final Element e) {
278 Saveable.defaultSave(e, getChildren());
279 e.setAttribute(XML_DESCRIBE_ALL, allCheckBox.isSelected() ? XML_DESCRIBE_ALL_TRUE : XML_DESCRIBE_ALL_FALSE);
280 }
281
282 @Override
283 public final void load(final Object e) throws LoadException {
284 removeAllItems();
285
286 if (e instanceof Element) {
287 Element eNode = (Element) e;
288 final String allString = eNode.getAttribute(XML_DESCRIBE_ALL);
289
290 if (allString.equalsIgnoreCase(XML_DESCRIBE_ALL_TRUE)) {
291 allCheckBox.setSelected(true);
292 } else if (allString.equalsIgnoreCase(XML_DESCRIBE_ALL_FALSE)) {
293 allCheckBox.setSelected(false);
294 } else {
295 throw new LoadException(eNode, XML_DESCRIBE_ALL);
296 }
297
298 final NodeList nodes = eNode.getElementsByTagName(DescribeClauseItem.XML_ELEMENT_NAME);
299 final int nodesCount = nodes.getLength();
300
301 for (int nodeIndex = 0; nodeIndex < nodesCount; nodeIndex++) {
302 final org.w3c.dom.Node childNode = nodes.item(nodeIndex);
303 if (childNode instanceof Element) {
304 loadChild((Element) childNode);
305 }
306 }
307 } else if (e instanceof SparqlParser.DescribeQueryContext) {
308 List<ParseTree> listNodes = ((ParserRuleContext) e).children;
309 for (ParseTree node : listNodes) {
310 if (node instanceof SparqlParser.VarOrIRIContext) {
311 final DescribeClauseItem item = createItem();
312 addItem(item);
313 item.load(node);
314 } else if (node.getText().equals(ALL_VALUES)) {
315 allCheckBox.setSelected(true);
316 break;
317 }
318 }
319 }
320 }
321
322 private void removeAllItems() {
323 final Set<Node> toRemove = new HashSet<>();
324 getChildren().stream().filter((node) -> (node instanceof DescribeClauseItem)).forEach(toRemove::add);
325 getChildren().removeAll(toRemove);
326 }
327
328 private void loadChild(final Element e) throws LoadException {
329 final DescribeClauseItem item = createItem();
330 addItem(item);
331 item.load(e);
332 }
333
334 @Override
335 public final String getXMLElementName() {
336 return XML_ELEMENT_NAME;
337 }
338
339 @Override
340 public final Set<InvalidationListener> getObservers() {
341 return observers;
342 }
343 }