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.queryTypes.ask;
21  
22  import cz.zcu.mre.sparkle.Messages;
23  import cz.zcu.mre.sparkle.data.DataAgent;
24  import cz.zcu.mre.sparkle.data.Storage;
25  import cz.zcu.mre.sparkle.gui.mainForm.MainForm;
26  import cz.zcu.mre.sparkle.gui.query.CustomTitledPane;
27  import cz.zcu.mre.sparkle.gui.query.QueryFormPane;
28  import cz.zcu.mre.sparkle.gui.query.modifiers.LimitOffsetClausePane;
29  import cz.zcu.mre.sparkle.gui.query.modifiers.OrderByClausePane;
30  import cz.zcu.mre.sparkle.gui.query.modifiers.ValuesClausePane;
31  import cz.zcu.mre.sparkle.gui.query.modifiers.groupBy.GroupByClausePane;
32  import cz.zcu.mre.sparkle.gui.query.modifiers.having.HavingClausePane;
33  import cz.zcu.mre.sparkle.gui.query.queryMainParts.FromClausePane;
34  import cz.zcu.mre.sparkle.gui.query.queryMainParts.WhereClausePane;
35  import cz.zcu.mre.sparkle.gui.query.queryTypes.subselect.SubSelectPane;
36  import cz.zcu.mre.sparkle.tools.Saveable;
37  import cz.zcu.mre.sparkle.tools.SparqlParser;
38  import cz.zcu.mre.sparkle.tools.sparqlParser.SparqlParserNode;
39  import cz.zcu.mre.sparkle.tools.sparqlParser.SparqlParserWhereClauseWalker;
40  import javafx.collections.FXCollections;
41  import javafx.collections.ObservableList;
42  import javafx.collections.ObservableSet;
43  import javafx.scene.Node;
44  import org.antlr.v4.runtime.tree.ParseTree;
45  import org.w3c.dom.Element;
46  import java.util.ArrayList;
47  import java.util.List;
48  import java.util.Set;
49  import java.util.Stack;
50  import static cz.zcu.mre.sparkle.gui.query.QueryFormPane.QUERY_PARTS.*;
51  import static cz.zcu.mre.sparkle.tools.sparqlParser.SparqlParserUtils.getTreeChild;
52  
53  /**
54   * Kontroler panelu s dotazem typu ASK.
55   *
56   * @author Jan Smucr
57   * @author Klara Hlavacova
58   * @author Petr Vcelak (vcelak@kiv.zcu.cz)
59   */
60  public final class AskQueryFormPane
61          extends QueryFormPane<Boolean> {
62  
63      public static final String XML_QUERY_TYPE_VALUE = "ask"; //$NON-NLS-1$
64  
65      private List<Object> queryFormParts;
66  
67      private ObservableSet<String> whereClauseVariables;
68      private ObservableSet<String> orderByClauseVariables;
69      private ObservableSet<String> groupByClauseVariables;
70      private ObservableSet<String> valuesClauseVariables;
71  
72      public AskQueryFormPane(final MainForm mainForm, final DataAgent dataAgent, final Storage localStorage,
73              String paneType) {
74          super(mainForm, dataAgent, localStorage, paneType);
75      }
76  
77      public AskQueryFormPane(final MainForm mainForm, final DataAgent dataAgent, final Storage localStorage,
78              final Object root, String paneType)
79              throws LoadException {
80          super(mainForm, dataAgent, localStorage, root, paneType);
81      }
82  
83      @Override
84      public final void load(final Object root) throws LoadException {
85          whereClauseVariables = FXCollections.observableSet();
86          orderByClauseVariables = FXCollections.observableSet();
87          groupByClauseVariables = FXCollections.observableSet();
88          valuesClauseVariables = FXCollections.observableSet();
89  
90          initializeQueryFormParts();
91          addVariablesCollectors();
92          addPartsTitles();
93  
94          loadForm(root);
95  
96          // Nastavení hlídání změn
97          addWatches();
98      }
99  
100     /**
101      * Nacte formular.
102      *
103      * @param root rodicovsky element
104      * @throws LoadException
105      */
106     private void loadForm(Object root) throws LoadException {
107         if (root == null) {
108             // Výchozí stav nově vytvořeného dotazu
109             ((WhereClausePane) getPane(WHERE_CLAUSE)).addTriple(null, true);
110 
111         } else if (root instanceof Element) {
112             // Načtení uloženého dotazu
113             loadQueryPartsElements((Element) root, queryFormParts);
114 
115         } else if (root instanceof ParseTree) {
116             setVariables((ParseTree) root);
117         }
118     }
119 
120     /**
121      * Nastavení hlídání změn.
122      */
123     private void addWatches() {
124         watch((FromClausePane) getPane(FROM_CLAUSE));
125         watch((WhereClausePane) getPane(WHERE_CLAUSE));
126         watch(((OrderByClausePane) getPane(ORDER_BY_CLAUSE)));
127         watch(((GroupByClausePane) getPane(GROUP_BY_CLAUSE)));
128         watch(((HavingClausePane) getPane(HAVING_CLAUSE)));
129         watch(((LimitOffsetClausePane) getPane(LIMIT_OFFSET_CLAUSE)));
130         watch(((ValuesClausePane) getPane(VALUES_CLAUSE)));
131     }
132 
133     /**
134      * Titulky panelu.
135      */
136     private void addPartsTitles() {
137         final ObservableList<Node> children = getChildren();
138         addChild(children, "ASK_QUERY_FRAGMENT");
139         addTitlesPanes(children);
140     }
141 
142     private void addTitlesPanes(ObservableList<Node> children) {
143         addChild(children, "FROM_QUERY_FRAGMENT", (FromClausePane) getPane(FROM_CLAUSE));
144         addChild(children, "WHERE_QUERY_FRAGMENT", (WhereClausePane) getPane(WHERE_CLAUSE));
145         addChild(children, "GROUP_BY_QUERY_FRAGMENT", (GroupByClausePane) getPane(GROUP_BY_CLAUSE));
146         addChild(children, "HAVING_QUERY_FRAGMENT", (HavingClausePane) getPane(HAVING_CLAUSE));
147         addChild(children, "ORDER_BY_QUERY_FRAGMENT", (OrderByClausePane) getPane(ORDER_BY_CLAUSE));
148         addChild(children, "MODIFIERS_QUERY_FRAGMENT", (LimitOffsetClausePane) getPane(LIMIT_OFFSET_CLAUSE));
149         addChild(children, "VALUES_QUERY_FRAGMENT", (ValuesClausePane) getPane(VALUES_CLAUSE));
150     }
151 
152     /**
153      * Vlozi {@code CustomTitledPane} do seznamu uzlu.
154      *
155      * @param children seznam uzlu
156      * @param title titulek
157      * @param content obsah (panel)
158      */
159     private void addChild(ObservableList<Node> children, final String title, final Node... content) {
160         children.add(new CustomTitledPane(Messages.getString(title), content));
161     }
162 
163     /**
164      * Inicializace pole casti.
165      */
166     private void initializeQueryFormParts() {
167         queryFormParts = new ArrayList<>();
168 
169         queryFormParts.add(null);
170         queryFormParts.add(new FromClausePane(this));
171         queryFormParts.add(new WhereClausePane(this));
172         queryFormParts.add(new OrderByClausePane(this));
173         queryFormParts.add(new GroupByClausePane(this));
174         queryFormParts.add(new HavingClausePane(this));
175         queryFormParts.add(new LimitOffsetClausePane());
176         queryFormParts.add(new ValuesClausePane(this));
177     }
178 
179     /**
180      * Nastavi kolektory promennych.
181      */
182     private void addVariablesCollectors() {
183         ((WhereClausePane) getPane(WHERE_CLAUSE)).addVariablesCollector(
184                 createCollector(whereClauseVariables, groupByClauseVariables, orderByClauseVariables,
185                         valuesClauseVariables));
186 
187         ((OrderByClausePane) getPane(ORDER_BY_CLAUSE)).addVariablesCollector(
188                 createCollector(orderByClauseVariables, whereClauseVariables, groupByClauseVariables,
189                         valuesClauseVariables));
190         ((GroupByClausePane) getPane(GROUP_BY_CLAUSE)).addVariablesCollector(
191                 createCollector(groupByClauseVariables, whereClauseVariables, orderByClauseVariables,
192                         valuesClauseVariables));
193 
194         ((ValuesClausePane) getPane(VALUES_CLAUSE)).addVariablesCollector(
195                 createCollector(valuesClauseVariables, whereClauseVariables, groupByClauseVariables,
196                         orderByClauseVariables));
197     }
198 
199     /**
200      * Vrati panel ze seznamu casti formulare.
201      *
202      * @param paneType typ panelu
203      *
204      * @return panel ze seznamu casti formulare
205      */
206     private Object getPane(QUERY_PARTS paneType) {
207         return getPane(queryFormParts, paneType);
208     }
209 
210     @Override
211     protected void setVariables(ParseTree root) throws LoadException {
212         Stack<SparqlParserNode> nodeStack = new Stack<>(); //current path in parse tree
213         nodeStack.push(new SparqlParserNode(root));
214 
215         while (!nodeStack.isEmpty()) {
216             SparqlParserNode currentNode = nodeStack.pop();
217             ParseTree nodeData = currentNode.getNodeData();
218 
219             if (nodeData instanceof SparqlParser.DatasetClauseContext) { //from clause
220                 ((FromClausePane) getPane(FROM_CLAUSE)).load(nodeData);
221 
222             } else if (nodeData instanceof SparqlParser.WhereClauseContext) { //where clause
223                 new SparqlParserWhereClauseWalker(nodeData, ((WhereClausePane) getPane(WHERE_CLAUSE)))
224                         .processWhereClauseDFS();
225 
226             } else if (nodeData instanceof SparqlParser.LimitClauseContext) { //limit clause
227                 ((LimitOffsetClausePane) getPane(LIMIT_OFFSET_CLAUSE)).load(nodeData);
228 
229             } else if (nodeData instanceof SparqlParser.OffsetClauseContext) { //offset clause
230                 ((LimitOffsetClausePane) getPane(LIMIT_OFFSET_CLAUSE)).load(nodeData);
231 
232             } else if (nodeData instanceof SparqlParser.OrderConditionContext) { //order clause
233                 ((OrderByClausePane) getPane(ORDER_BY_CLAUSE)).load(nodeData);
234 
235             } else if (nodeData instanceof SparqlParser.HavingConditionContext) { //having clause
236                 ((HavingClausePane) getPane(HAVING_CLAUSE)).load(nodeData);
237 
238             } else if (nodeData instanceof SparqlParser.GroupConditionContext) { //group by clause
239                 ((GroupByClausePane) getPane(GROUP_BY_CLAUSE)).load(nodeData);
240 
241             } else if (nodeData instanceof SparqlParser.ValuesClauseContext) { // Values clause
242                 ((ValuesClausePane) getPane(VALUES_CLAUSE)).load(nodeData);
243 
244             } else { //uninsteresting node -> get next node
245                 nodeStack.push(currentNode);
246                 getTreeChild(currentNode, nodeStack);
247             }
248         }
249     }
250 
251     @Override
252     public final String getQueryPart() {
253         return "ASK " + ((FromClausePane) getPane(FROM_CLAUSE)).getQueryPart()
254                 + "WHERE " //$NON-NLS-1$
255                 + ((WhereClausePane) getPane(WHERE_CLAUSE)).getQueryPart()
256                 + ((GroupByClausePane) getPane(GROUP_BY_CLAUSE)).getQueryPart()
257                 + ((HavingClausePane) getPane(HAVING_CLAUSE)).getQueryPart()
258                 + ((OrderByClausePane) getPane(ORDER_BY_CLAUSE)).getQueryPart()
259                 + ((LimitOffsetClausePane) getPane(LIMIT_OFFSET_CLAUSE)).getQueryPart()
260                 + ((ValuesClausePane) getPane(VALUES_CLAUSE)).getQueryPart()
261                 + " "; //$NON-NLS-1$
262     }
263 
264     @Override
265     public final List<SubSelectPane> getSubSelectPanes() {
266         return ((WhereClausePane) getPane(WHERE_CLAUSE)).getSubSelectPanes();
267     }
268 
269     @Override
270     public final ObservableList<String> getSortedVariables() {
271         ObservableSet<String> variables = FXCollections.observableSet();
272         variables.addAll(this.getNetVariables());
273         ((WhereClausePane) getPane(WHERE_CLAUSE)).getSubSelectPanes().forEach((subSelectPane) -> variables.addAll(subSelectPane.getSubSelectQueryPane().getSelectedVariables()));
274         return FXCollections.observableArrayList(variables).sorted(String.CASE_INSENSITIVE_ORDER);
275     }
276 
277     @Override
278     public final Set<String> getPrefixesUsed(final boolean appendDelimiter) {
279         final Set<String> result = ((WhereClausePane) getPane(WHERE_CLAUSE)).getPrefixesUsed(appendDelimiter);
280         result.addAll(((FromClausePane) getPane(FROM_CLAUSE)).getPrefixesUsed(appendDelimiter));
281         result.addAll(((OrderByClausePane) getPane(ORDER_BY_CLAUSE)).getPrefixesUsed(appendDelimiter));
282         result.addAll(((GroupByClausePane) getPane(GROUP_BY_CLAUSE)).getPrefixesUsed(appendDelimiter));
283         result.addAll(((HavingClausePane) getPane(HAVING_CLAUSE)).getPrefixesUsed(appendDelimiter));
284         result.addAll(((ValuesClausePane) getPane(VALUES_CLAUSE)).getPrefixesUsed(appendDelimiter));
285         return result;
286     }
287 
288     @Override
289     public final void save(final Element root) {
290         Saveable.defaultSave(root, (FromClausePane) getPane(FROM_CLAUSE), ((WhereClausePane) getPane(WHERE_CLAUSE)),
291                 ((LimitOffsetClausePane) getPane(LIMIT_OFFSET_CLAUSE)),
292                 ((OrderByClausePane) getPane(ORDER_BY_CLAUSE)),
293                 ((GroupByClausePane) getPane(GROUP_BY_CLAUSE)),
294                 ((HavingClausePane) getPane(HAVING_CLAUSE)),
295                 ((ValuesClausePane) getPane(VALUES_CLAUSE)));
296     }
297 
298     @Override
299     protected final String getXMLQueryType() {
300         return XML_QUERY_TYPE_VALUE;
301     }
302 
303 }