View Javadoc
1   /*
2    * Copyright 2013-2023 Medical Information Systems Research Group (https://medical.zcu.cz),
3    * Department of Computer Science and Engineering, University of West Bohemia.
4    * Address: Univerzitni 8, 306 14 Plzen, Czech Republic.
5    *
6    * This file is part of Sparkle project.
7    *
8    * Sparkle is free software: you can redistribute it and/or modify
9    * it under the terms of the GNU General Public License as published by
10   * the Free Software Foundation, either version 3 of the License.
11   *
12   * Sparkle is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15   * GNU General Public License for more details.
16   *
17   * You should have received a copy of the GNU General Public License
18   * along with Sparkle. If not, see <http://www.gnu.org/licenses/>.
19   */
20  package cz.zcu.mre.sparkle.gui.query.modifiers;
21  
22  import cz.zcu.mre.sparkle.gui.query.QueryFormPane;
23  import cz.zcu.mre.sparkle.gui.query.clause.SingleClausePane;
24  import cz.zcu.mre.sparkle.gui.query.clause.SingleValuesDataClausePane;
25  import cz.zcu.mre.sparkle.gui.query.clause.SingleValuesVariableClausePane;
26  import cz.zcu.mre.sparkle.gui.query.helpers.*;
27  import cz.zcu.mre.sparkle.gui.tools.Components;
28  import cz.zcu.mre.sparkle.gui.tools.ReferenceKeeper;
29  import cz.zcu.mre.sparkle.tools.*;
30  import cz.zcu.mre.sparkle.tools.SparqlParser;
31  import cz.zcu.mre.sparkle.tools.sparqlParser.SparqlParserNode;
32  import javafx.beans.InvalidationListener;
33  import javafx.beans.property.BooleanProperty;
34  import javafx.beans.property.IntegerProperty;
35  import javafx.beans.property.SimpleBooleanProperty;
36  import javafx.beans.property.SimpleIntegerProperty;
37  import javafx.collections.ObservableList;
38  import javafx.event.ActionEvent;
39  import javafx.fxml.FXML;
40  import javafx.geometry.Pos;
41  import javafx.scene.Node;
42  import javafx.scene.control.Button;
43  import javafx.scene.control.Label;
44  import javafx.scene.layout.FlowPane;
45  import javafx.scene.layout.HBox;
46  import javafx.scene.layout.VBox;
47  import javafx.scene.shape.LineTo;
48  import javafx.scene.shape.MoveTo;
49  import javafx.scene.shape.Path;
50  import org.antlr.v4.runtime.tree.ParseTree;
51  import org.w3c.dom.Document;
52  import org.w3c.dom.Element;
53  import org.w3c.dom.NodeList;
54  import java.util.*;
55  import static cz.zcu.mre.sparkle.tools.Definitions.*;
56  import static cz.zcu.mre.sparkle.tools.sparqlParser.SparqlParserUtils.getTreeChild;
57  
58  /**
59   * Controller of Values clause. It creates instances of
60   * {@link SingleValuesVariableClausePane} and
61   * {@link SingleValuesDataClausePane}.
62   *
63   * @author Josef Kazak
64   * @author Klara Hlavacova
65   * @author Petr Vcelak (vcelak@kiv.zcu.cz)
66   */
67  public class ValuesClausePane
68          extends VBox
69          implements PartialQueryGenerator, VariablesGenerator, VariablesCollector, PrefixesUser, Saveable, Changeable {
70  
71      private static final String XML_ELEMENT_NAME = "Values"; //$NON-NLS-1$
72      private static final String XML_VALUES_NODE_NAME = "ValuesNode"; //$NON-NLS-1$
73  
74      @FXML
75      private Button addValuesButton;
76  
77      @FXML
78      private FlowPane variablesFlowPane, dataFlowPane;
79  
80      private final QueryFormPane<?> parentQueryFormPane;
81      private final Set<VariablesCollector> variablesCollectors = new HashSet<>();
82      private final ReferenceKeeper keeper = new ReferenceKeeper();
83      private final Set<InvalidationListener> observers = new HashSet<>();
84      private Label leftBracketOfVarQueryPart, rightBracketOfVarQueryPart, leftCurlyBracketOfVarQueryPart,
85              rightCurlyBracketOfVarQueryPart;
86      private final IntegerProperty countOfVariables = new SimpleIntegerProperty(0);
87      private final BooleanProperty removableProperty = new SimpleBooleanProperty(false);
88      private final Button addVariableButton = new Button("+ Variable"); //$NON-NLS-1$
89      private final Button addDataButton = new Button("+ Data"); //$NON-NLS-1$
90  
91      public ValuesClausePane(final QueryFormPane<?> parentQueryFormPane) {
92          Components.load(this);
93  
94          this.parentQueryFormPane = parentQueryFormPane;
95  
96          setLabels();
97  
98          addVariableButton.setOnAction((ActionEvent event) -> addValuesVariable());
99          addDataButton.setOnAction((ActionEvent event) -> addValuesData(true));
100 
101         countOfVariables.addListener((observable, oldValue, newValue) -> {
102             int newValueInt = newValue.intValue();
103             if (newValueInt == 0) {
104                 dataFlowPane.getChildren().clear();
105                 dataFlowPane.getChildren()
106                         .addAll(addDataButton, leftCurlyBracketOfVarQueryPart, rightCurlyBracketOfVarQueryPart);
107                 this.getChildren().add(0, addValuesButton);
108                 this.removableProperty.set(true);
109             } else if (oldValue.intValue() == 0 && newValueInt > 0) {
110                 this.getChildren().remove(addValuesButton);
111                 this.removableProperty.set(false);
112             }
113         });
114 
115         variablesFlowPane.getChildren()
116                 .addAll(addVariableButton, leftBracketOfVarQueryPart, rightBracketOfVarQueryPart);
117         dataFlowPane.getChildren()
118                 .addAll(addDataButton, leftCurlyBracketOfVarQueryPart, rightCurlyBracketOfVarQueryPart);
119 
120         // Auto watching changes of nested components.
121         autoWatch(variablesFlowPane.getChildren(), SingleValuesVariableClausePane.class);
122         autoWatch(dataFlowPane.getChildren(), SingleValuesDataClausePane.class);
123     }
124 
125     /**
126      * Method sets default state of query brackets.
127      */
128     private void setLabels() {
129         leftBracketOfVarQueryPart = new Label(LEFT_BRACKET);
130         rightBracketOfVarQueryPart = new Label(RIGHT_BRACKET);
131         leftCurlyBracketOfVarQueryPart = new Label(LEFT_CURLY_BRACKET);
132         rightCurlyBracketOfVarQueryPart = new Label(RIGHT_CURLY_BRACKET);
133 
134         // Brackets are invisible if a value variable not exists.
135         leftBracketOfVarQueryPart.visibleProperty().bind(countOfVariables.isNotEqualTo(0));
136         rightBracketOfVarQueryPart.visibleProperty().bind(leftBracketOfVarQueryPart.visibleProperty());
137         leftCurlyBracketOfVarQueryPart.visibleProperty().bind(leftBracketOfVarQueryPart.visibleProperty());
138         rightCurlyBracketOfVarQueryPart.visibleProperty().bind(leftBracketOfVarQueryPart.visibleProperty());
139         addVariableButton.visibleProperty().bind(leftBracketOfVarQueryPart.visibleProperty());
140         addDataButton.visibleProperty().bind(leftBracketOfVarQueryPart.visibleProperty());
141     }
142 
143     public void addInitialValues() {
144         this.addVariableButton.fire();
145         this.addDataButton.fire();
146     }
147 
148     public BooleanProperty getRemovableProperty() {
149         return this.removableProperty;
150     }
151 
152     @FXML
153     private void addValuesButtonOnAction(final ActionEvent event) {
154         addValuesVariable().requestFocus();
155     }
156 
157     /**
158      * It adds new VALUES variable into a relevant clause.
159      *
160      * @return Instance of {@link SingleValuesVariableClausePane}.
161      */
162     private SingleValuesVariableClausePane addValuesVariable() {
163         final SingleValuesVariableClausePane pane = new SingleValuesVariableClausePane(parentQueryFormPane);
164         final ObservableList<Node> children = variablesFlowPane.getChildren();
165         children.add(children.indexOf(rightBracketOfVarQueryPart), pane);
166 
167         this.countOfVariables.set(this.countOfVariables.get() + 1);
168 
169         dataFlowPane.getChildren().stream().filter((dataChild) -> (dataChild instanceof HBox)).forEach((dataChild) -> {
170             HBox element = (HBox) dataChild;
171             addValuesDataTextField(element, element.getChildren().size() - 1);
172         });
173 
174         pane.addVariablesCollector(this);
175         pane.setOnRemovalRequested(keeper.toWeak((final ObjectRelatedActionEvent<SingleClausePane> e) -> {
176             setValuesOrder(pane);
177             variablesFlowPane.getChildren().remove(e.relatedObject);
178             ((SingleValuesVariableClausePane) e.relatedObject).getVariables().stream().forEach(this::onVariableRemoved);
179             this.countOfVariables.set(this.countOfVariables.get() - 1);
180         }));
181         return pane;
182     }
183 
184     /**
185      * It adjusts VALUES data according to changes of variables.
186      *
187      * @param pane The changed variable.
188      */
189     private void setValuesOrder(final SingleValuesVariableClausePane pane) {
190         int indexOfVariable = 0;
191         for (Node node : variablesFlowPane.getChildren()) { // Obtaining of variable index.
192             if (node instanceof SingleValuesVariableClausePane) {
193                 if (node == pane) {
194                     break;
195                 }
196                 indexOfVariable++;
197             }
198         }
199 
200         for (Node node : dataFlowPane.getChildren()) { // Editing of VALUES data.
201             if (node instanceof HBox) {
202                 final List<Node> nodesToRemove = new LinkedList<>();
203                 ObservableList<Node> hBoxChildren = ((HBox) node).getChildren();
204                 int indexOfHBox = 0;
205                 for (Node hBoxChild : hBoxChildren) {
206                     if (hBoxChild instanceof SingleValuesDataClausePane) {
207                         if (indexOfHBox == indexOfVariable) {
208                             nodesToRemove.add(hBoxChild);
209                             break;
210                         }
211                         indexOfHBox++;
212                     }
213                 }
214                 hBoxChildren.removeAll(nodesToRemove);
215             }
216         }
217     }
218 
219     /**
220      * It adds new VALUES data into existing data box.
221      *
222      * @param hBox The existing data box.
223      * @param position The position of new
224      *
225      * @return Pane of the added VALUES data.
226      */
227     private SingleValuesDataClausePane addValuesDataTextField(final HBox hBox, int position) {
228         SingleValuesDataClausePane pane = new SingleValuesDataClausePane(parentQueryFormPane);
229         hBox.getChildren().add(position, pane);
230         return pane;
231     }
232 
233     /**
234      * It creates containers for VALUES data.
235      *
236      * @param addTextFields If it is <code>true</code> then the new container
237      * has immediately some {@link SingleValuesDataClausePane} according to a
238      * count of existing VALUES variables.
239      *
240      * @return Instance of {@link SingleValuesDataClausePane}.
241      */
242     private HBox addValuesData(final boolean addTextFields) {
243         final Label rightBracket = new Label(RIGHT_BRACKET);
244         final HBox hBox = new HBox(new Label("  ("), rightBracket);
245         hBox.setId("guiFontStyle");
246         hBox.setAlignment(Pos.CENTER_LEFT);
247         final Button removeButton = getRemoveButton();
248         final int indexOfNewPane = dataFlowPane.getChildren().indexOf(rightCurlyBracketOfVarQueryPart);
249         removeButton.setOnAction((ActionEvent event) -> {
250             dataFlowPane.getChildren().remove(hBox);
251             dataFlowPane.getChildren().remove(removeButton);
252         });
253         dataFlowPane.getChildren().add(indexOfNewPane, removeButton);
254         dataFlowPane.getChildren().add(indexOfNewPane, hBox);
255 
256         if (addTextFields) {
257             final int indexOfRightBracket = hBox.getChildren().indexOf(rightBracket);
258             for (int i = 0; i < this.countOfVariables.get(); i++) {
259                 hBox.getChildren().add(indexOfRightBracket, new SingleValuesDataClausePane(parentQueryFormPane));
260             }
261         }
262 
263         return hBox;
264     }
265 
266     @Override
267     public final Set<String> getVariables() {
268         final Set<String> result = new HashSet<>();
269         variablesFlowPane.getChildren().stream().filter((node) -> (node instanceof SimpleVariablesGenerator))
270                 .forEach((node) -> result.addAll(((SimpleVariablesGenerator) node).getVariables()));
271 
272         return result;
273     }
274 
275     private Button getRemoveButton() {
276         Button removeButton = new Button();
277 
278         Path path = new Path();
279         path.setStrokeWidth(1.5);
280         path.getElements().add(new MoveTo(-3.0, -3.0));
281         path.getElements().add(new LineTo(3.0, 3.0));
282         path.getElements().add(new MoveTo(-3.0, 3.0));
283         path.getElements().add(new LineTo(3.0, -3.0));
284 
285         removeButton.setGraphic(path);
286         return removeButton;
287     }
288 
289     @Override
290     public final void onVariableAdded(final String variableName) {
291         notifyVariableAdded(variableName);
292     }
293 
294     @Override
295     public final void onVariableChanged(final String oldVariableName, final String newVariableName) {
296         notifyVariableChanged(oldVariableName, newVariableName);
297     }
298 
299     @Override
300     public final void onVariableRemoved(final String variableName) {
301         notifyVariableRemoved(variableName);
302     }
303 
304     @Override
305     public final void notifyVariableAdded(final String variableName) {
306         variablesCollectors.stream().forEach((collector) -> collector.onVariableAdded(variableName));
307     }
308 
309     @Override
310     public final void notifyVariableChanged(final String oldVariableName, final String newVariableName) {
311         if (getVariables().contains(oldVariableName)) {
312             variablesCollectors.stream().forEach((collector) -> collector.onVariableAdded(newVariableName));
313         } else {
314             variablesCollectors.stream().forEach((collector) -> collector.onVariableChanged(oldVariableName, newVariableName));
315         }
316     }
317 
318     @Override
319     public final void notifyVariableRemoved(final String variableName) {
320         if (getVariables().contains(variableName)) {
321             return;
322         }
323         variablesCollectors.stream().forEach((collector) -> collector.onVariableRemoved(variableName));
324     }
325 
326     @Override
327     public final void addVariablesCollector(final VariablesCollector collector) {
328         variablesCollectors.add(collector);
329     }
330 
331     @Override
332     public final void removeVariablesCollector(final VariablesCollector collector) {
333         variablesCollectors.remove(collector);
334     }
335 
336     @Override
337     public final String getQueryPart() {
338         final StringBuilder sb = new StringBuilder();
339 
340         variablesFlowPane.getChildren().stream().filter((node) -> (node instanceof PartialQueryGenerator)).
341                 forEach((node) -> sb.append(((PartialQueryGenerator) node).getQueryPart()));
342 
343         if (sb.length() > 0) {
344             sb.insert(0, "VALUES ("); //$NON-NLS-1$
345             sb.append(RIGHT_BRACKET).append(LEFT_CURLY_BRACKET);
346             dataFlowPane.getChildren().stream().filter((node) -> (node instanceof HBox)).map((node) -> {
347                 StringBuilder hBoxSB = new StringBuilder();
348                 ((HBox) node).getChildren().stream().filter((hBoxChild) -> (hBoxChild instanceof PartialQueryGenerator))
349                         .forEach((hBoxChild) -> hBoxSB.append(((PartialQueryGenerator) hBoxChild).getQueryPart())
350                         .append(Definitions.SPACE));
351                 return hBoxSB;
352             }).filter((hBoxSB) -> (hBoxSB.length() > 0)).forEach((hBoxSB) -> sb.append(LEFT_BRACKET).append(hBoxSB.toString()).append(Definitions.RIGHT_BRACKET));
353             sb.append(RIGHT_CURLY_BRACKET);
354         }
355         return sb.toString();
356     }
357 
358     @Override
359     public final Set<String> getPrefixesUsed(final boolean appendDelimiter) {
360         final Set<String> result = new HashSet<>();
361         dataFlowPane.getChildren().stream().filter((child) -> (child instanceof HBox))
362                 .map((child) -> ((HBox) child).getChildren()).forEach((hBoxChildren) -> hBoxChildren.stream().filter((hBoxChild) -> (hBoxChild instanceof PrefixesUser)).forEach((hBoxChild) -> result.addAll(((PrefixesUser) hBoxChild).getPrefixesUsed(appendDelimiter))));
363         return result;
364     }
365 
366     private List<SingleValuesDataClausePane> getDataOfVariable(final int variablePosition,
367             final ObservableList<Node> dataChildren) {
368         final List<SingleValuesDataClausePane> results = new LinkedList<>();
369         for (Node dataChild : dataChildren) {
370             if (dataChild instanceof HBox) {
371                 int dataPosition = 0;
372                 ObservableList<Node> hBoxChildren = ((HBox) dataChild).getChildren();
373                 for (Node hBoxChild : hBoxChildren) {
374                     if (hBoxChild instanceof SingleValuesDataClausePane) {
375                         if (dataPosition == variablePosition) {
376                             results.add((SingleValuesDataClausePane) hBoxChild);
377                             break;
378                         }
379                         dataPosition++;
380                     }
381                 }
382 
383             }
384         }
385         return results;
386     }
387 
388     @Override
389     public final void save(final Element e) {
390         final Document doc = e.getOwnerDocument();
391         int variableIndex = 0;
392         for (Node variableChild : variablesFlowPane.getChildren()) {
393             if (variableChild instanceof SingleValuesVariableClausePane) {
394                 final Element element = doc.createElement(XML_VALUES_NODE_NAME);
395                 ((SingleValuesVariableClausePane) variableChild).save(element);
396                 e.appendChild(element);
397                 Saveable.defaultSave(element, getDataOfVariable(variableIndex, dataFlowPane.getChildren()));
398                 variableIndex++;
399             }
400         }
401     }
402 
403     /**
404      * It obtains VALUES data of one variable.
405      *
406      * @param childNode Selected VALUES variable.
407      *
408      * @return List of VALUES data of one variable.
409      */
410     private List<Element> getValuesData(org.w3c.dom.Node childNode) {
411         final NodeList valuesDataNodes = childNode.getChildNodes();
412         final int valuesDataNodeCount = valuesDataNodes.getLength();
413         final List<Element> elementList = new LinkedList<>();
414         for (int j = 0; j < valuesDataNodeCount; j++) {
415             final org.w3c.dom.Node valuesDataNode = valuesDataNodes.item(j);
416             if (valuesDataNode instanceof Element) {
417                 final Element valuesDataElement = (Element) valuesDataNode;
418                 if (valuesDataElement.hasAttribute(SingleValuesDataClausePane.XML_VALUES_DATA_TEXT)
419                         && valuesDataElement.hasAttribute(SingleValuesDataClausePane.XML_VALUES_DATA_TYPE)) {
420                     elementList.add(valuesDataElement);
421                 }
422             }
423         }
424         return elementList;
425     }
426 
427     /**
428      * It loads VALUES variables and their data. It puts VALUES data into the
429      * <code>dataOfVariables</code>.
430      *
431      * @param e Root of the tree that contains VALUES.
432      * @param variableCount Count of variables.
433      * @param nodes Variables and their data.
434      * @param dataOfVariables It stores obtained VALUES data.
435      *
436      * @return Count of obtained data of one variable.
437      *
438      * @throws cz.zcu.mre.sparkle.tools.Saveable.LoadException
439      */
440     private int loadVariablesDataAndGetDataCount(final Element e, final int variableCount, final NodeList nodes,
441             final List<List<Element>> dataOfVariables) throws LoadException {
442         int countOfDataGroup = -1;
443         for (int i = 0; i < variableCount; i++) {
444             final org.w3c.dom.Node childNode = nodes.item(i);
445             if (childNode instanceof Element) {
446                 final Element eNode = (Element) childNode;
447                 if (eNode.hasAttribute(SingleValuesVariableClausePane.XML_VALUES_VARIABLE_TEXT)
448                         && eNode.hasAttribute(SingleValuesVariableClausePane.XML_VALUES_VARIABLE_TYPE)) {
449                     addValuesVariable().load(childNode); // Add variable
450 
451                     final List<Element> elementList = getValuesData(childNode);
452                     dataOfVariables.add(elementList);
453 
454                     if (countOfDataGroup < 0) {
455                         countOfDataGroup = elementList.size();
456                     } else {
457                         if (countOfDataGroup != elementList.size()) {
458                             throw new LoadException(e, "Some of loaded data are missing or damaged."); //$NON-NLS-1$
459                         }
460                     }
461                 } else {
462                     throw new LoadException(e, "Some of the attributes is missing."); //$NON-NLS-1$
463                 }
464             }
465         }
466         return countOfDataGroup;
467     }
468 
469     @Override
470     public final void load(final Object e) throws Saveable.LoadException {
471         if (e instanceof Element) {
472             final Element eNode = (Element) e;
473             final NodeList nodes = eNode.getElementsByTagName(XML_VALUES_NODE_NAME);
474             final int nodesCount = nodes.getLength();
475 
476             if (nodesCount > 0) {
477                 final List<List<Element>> dataOfVariables = new ArrayList<>(nodesCount);
478                 final int listSize = loadVariablesDataAndGetDataCount(eNode, nodesCount, nodes, dataOfVariables);
479                 for (int i = 0; i < listSize; i++) {
480                     final HBox currentHBox = addValuesData(false);
481                     for (int j = 0; j < nodesCount; j++) {
482                         addValuesDataTextField(currentHBox, currentHBox.getChildren().size() - 1)
483                                 .load(dataOfVariables.get(j).get(i));
484                     }
485                 }
486             }
487         } else if (e instanceof ParseTree) {
488             final Stack<SparqlParserNode> nodeStack = new Stack<>();
489             nodeStack.push(new SparqlParserNode((ParseTree) e));
490             while (!nodeStack.isEmpty()) {
491                 SparqlParserNode currentNode = nodeStack.pop();
492                 ParseTree nodeData = currentNode.getNodeData();
493                 if (nodeData instanceof SparqlParser.InlineDataOneVarContext
494                         || nodeData instanceof SparqlParser.InlineDataFullContext) {
495                     addNewValuesFromFile(nodeData);
496                     break;
497                 } else {
498                     nodeStack.push(currentNode);
499                     getTreeChild(currentNode, nodeStack);
500                 }
501             }
502         }
503     }
504 
505     /**
506      * This method adds found VALUES data.
507      *
508      * @param valueOfDataBlock The found data.
509      * @param previousValue Value of previous node.
510      * @param currentDataBlock Owner of the found data.
511      *
512      * @throws cz.zcu.mre.sparkle.tools.Saveable.LoadException
513      */
514     private void processDataBlockValue(ParseTree valueOfDataBlock, final String previousValue,
515             final HBox currentDataBlock) throws LoadException {
516         if (valueOfDataBlock.getText().equals(RIGHT_BRACKET)) {
517             if (previousValue != null && previousValue.equals(LEFT_BRACKET)) {
518                 final HBox hBoxOfNIL = currentDataBlock != null ? currentDataBlock : addValuesData(false);
519                 addValuesDataTextField(hBoxOfNIL, hBoxOfNIL.getChildren().size() - 1).load(valueOfDataBlock.getText());
520             }
521         } else {
522             addValuesDataTextField(currentDataBlock, currentDataBlock.getChildren().size() - 1).load(valueOfDataBlock);
523         }
524     }
525 
526     /**
527      * It obtains data from
528      * {@link SparqlParser.DataBlockValueWithBracketContext}.
529      *
530      * @param dataBlockValues Root node of
531      * {@link SparqlParser.DataBlockValueWithBracketContext}.
532      *
533      * @throws cz.zcu.mre.sparkle.tools.Saveable.LoadException
534      */
535     private void processDataBlockValues(final SparqlParser.DataBlockValueWithBracketContext dataBlockValues)
536             throws LoadException {
537         String previousNode = null;
538         final HBox dataBlock = addValuesData(false);
539         for (ParseTree valueOfDataBlock : dataBlockValues.children) {
540             if (valueOfDataBlock instanceof SparqlParser.DataBlockValueContext
541                     || valueOfDataBlock.getText().equals(RIGHT_BRACKET)) { // Simple value or NIL of data part of the clause.
542                 processDataBlockValue(valueOfDataBlock, previousNode, dataBlock);
543             }
544             previousNode = valueOfDataBlock.getText();
545         }
546     }
547 
548     /**
549      * It loads VALUES variables and data from text file.
550      *
551      * @param rootNode Root node of VALUES query part.
552      *
553      * @throws cz.zcu.mre.sparkle.tools.Saveable.LoadException
554      */
555     private void addNewValuesFromFile(final ParseTree rootNode) throws LoadException {
556         String valueOfPreviousNode = null;
557         for (int i = 0; i < rootNode.getChildCount(); i++) {
558             final ParseTree child = rootNode.getChild(i);
559             if (child instanceof SparqlParser.VarContext) { // Variable
560                 addValuesVariable().load(child);
561             } else if (child instanceof SparqlParser.DataBlockValueWithBracketContext) { // Complex values of data part of the clause.
562                 processDataBlockValues((SparqlParser.DataBlockValueWithBracketContext) child);
563             } else if (child instanceof SparqlParser.DataBlockValueContext) { // Simple value of data part of the clause.
564                 processDataBlockValue(child, valueOfPreviousNode, addValuesData(false));
565             } else if (child.getText().equals(RIGHT_BRACKET) && valueOfPreviousNode != null
566                     && valueOfPreviousNode.equals(LEFT_BRACKET)) { // NIL
567                 addValuesVariable().load(child.getText());
568             }
569             valueOfPreviousNode = child.getText();
570         }
571     }
572 
573     @Override
574     public final String getXMLElementName() {
575         return XML_ELEMENT_NAME;
576     }
577 
578     @Override
579     public Set<InvalidationListener> getObservers() {
580         return observers;
581     }
582 }