KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > xquark > xquery > normalize > TransformXQueryExpression


1 /*
2  * This file belongs to the XQuark distribution.
3  * Copyright (C) 2003 Universite de Versailles Saint-Quentin.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307.
18  * You can also get it at http://www.gnu.org/licenses/lgpl.html
19  *
20  * For more information on this software, see http://www.xquark.org.
21  */

22
23 package org.xquark.xquery.normalize;
24
25 import java.util.ArrayList JavaDoc;
26 import java.util.HashMap JavaDoc;
27
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30 import org.xquark.xquery.parser.*;
31 import org.xquark.xquery.parser.util.Constants;
32
33 public class TransformXQueryExpression {
34
35     private static final String JavaDoc RCSRevision = "$Revision: 1.3 $";
36     private static final String JavaDoc RCSName = "$Name: $";
37
38     private static Log log = LogFactory.getLog("internal." + TransformXQueryExpression.class.getName());
39
40     protected ArrayList JavaDoc QDB = null;
41     protected XQueryExpression QMEM = null;
42     protected ArrayList JavaDoc dependMaps = null;
43     protected ArrayList JavaDoc varList = null;
44     protected ArrayList JavaDoc returnVarList = null;
45     protected ArrayList JavaDoc idVarList = null;
46
47     // public TransformXQueryExpression(ArrayList QDB, XQueryExpression QMEM, ArrayList dependMaps, ArrayList varList, ArrayList returnVarList, ArrayList idVarList) {
48
// this.QDB = QDB;
49
// this.QMEM = QMEM;
50
// this.dependMaps = dependMaps;
51
// this.varList = varList;
52
// this.returnVarList = returnVarList;
53
// this.idVarList = idVarList;
54
// }
55

56     public TransformXQueryExpression(ArrayList JavaDoc QDB, XQueryExpression QMEM) throws ParseException {
57         this.QDB = QDB;
58         this.QMEM = QMEM;
59         varList = new ArrayList JavaDoc();
60         ArrayList JavaDoc keyVars = new ArrayList JavaDoc();
61         dependMaps = new ArrayList JavaDoc();
62         XQueryExpression remainingWhereExpr = null;
63         try {
64             if (log.isDebugEnabled())
65                 log.debug("START SPECIAL TREATMENT いいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいい");
66             GetBoundVariablesVisitor gbvv = new GetBoundVariablesVisitor(true, true);
67             QMEM.accept(gbvv);
68             // list of all variables appearing in QMEM (eather idvariables or reconstruction variables)
69
ArrayList JavaDoc boundVariables = gbvv.getVariables();
70             // list of all reconstruction variables appearing in QMEM
71
returnVarList = gbvv.getOnlyVariables();
72             // list of all id variables appearing in QMEM
73
idVarList = gbvv.getIDsVariables();
74
75             /*
76             ALGORITHM
77             Iterating on QDBs from bottom to top
78             1. elimination of for $x in 1 (added by restructuration or canonization) whenever possible
79                 conditions :
80                     must be unique variable
81                     no subpaths exist
82                 if let binding and more than one QDB
83                     do erase
84                     !!! DANGER !!!
85                     if first QDB erased and remaining where expression is empty
86                         put root label on QMEM for reconstruction
87             2. replacing QDBs in FLWRs
88             example
89             let $1 := for $x1 in COLX1, $x2 in COLX2 where C1 order by x3, x4 return $x1, $x2
90             let $2 := for $X in $1, $y1 in COLY1, $y2 in COLY2 where C2 order by y3, y4 return $X, $y1, $y2
91             becomes
92             let $1 := for $x in COL1 return $x
93             let $2 := for $x1 in COLX1, $x2 in COLX2, $y1 in COLY1, $y2 in COLY2 where C1 & C2 orderby x3, x4, y4 return $x1, $x2, $y1, $y2
94             */

95             if (QDB != null) {
96                 for (int l = QDB.size() - 1; l >= 0; l--) {
97                     Variable qdbVari = (Variable) QDB.get(l);
98                     FLWRExpression qdbFlwri = (FLWRExpression) qdbVari.getExpression();
99                     ArrayList JavaDoc qbdFlwriVars = qdbFlwri.getVariables();
100                     ArrayList JavaDoc qbdFlwriOrders = qdbFlwri.getOrderBy();
101
102                     // some special treatment to avoid having for $x in 1 !!!! ATTENTION !!!
103
if (qbdFlwriVars.size() == 1) {
104                         Variable qbdFlwriVar0 = (Variable) qbdFlwriVars.get(0);
105                         ArrayList JavaDoc paths = qbdFlwriVar0.getSubPathList();
106                         if (paths == null || paths.isEmpty()) {
107                             if (qbdFlwriVar0.getBindingType() == Constants.LET_BINDINGTYPE && QDB.size() > 1) {
108                                 //erasing from QDB
109
QDB.remove(l);
110                                 l--;
111                                 // remember where expression if it is the last QBD (it is a silly expression anyway)
112
if (QDB.isEmpty())
113                                     remainingWhereExpr = qdbFlwri.getWhereClause();
114                                 // erasing from idvariables
115
idVarList.remove(qbdFlwriVar0);
116                                 // erasing from skolemIDs
117
EraseSkolemIDVisitor eraseSkolemIDVisitor = new EraseSkolemIDVisitor(qbdFlwriVar0);
118                                 QMEM.accept(eraseSkolemIDVisitor);
119                                 if (l < 0 && remainingWhereExpr == null)
120                                     QMEM.setRoot(true);
121                                 continue;
122                             } else if (!returnVarList.contains(qbdFlwriVar0) && qbdFlwriVar0.getExpression().getQType().isAtom() && qdbFlwri.getWhereClause() == null) {
123                                 // erasing from other variables
124
for (int m = QDB.size() - 1; m > l; m--) {
125                                     ArrayList JavaDoc tmpList = ((FLWRExpression) ((Variable) QDB.get(m)).getExpression()).getVariables();
126                                     tmpList.remove(qbdFlwriVar0);
127                                 }
128                                 //erasing from QDB
129
QDB.remove(l);
130                                 l--;
131                                 // erasing from idvariables
132
idVarList.remove(qbdFlwriVar0);
133                                 // erasing from skolemIDs
134
EraseSkolemIDVisitor eraseSkolemIDVisitor = new EraseSkolemIDVisitor(qbdFlwriVar0);
135                                 QMEM.accept(eraseSkolemIDVisitor);
136                                 if (l < 0)
137                                     QMEM.setRoot(true);
138                                 continue;
139                             }
140                         }
141                     }
142
143                     for (int m = qbdFlwriVars.size() - 1; m >= 0; m--) {
144                         Variable qbdFlwriVari = (Variable) qbdFlwriVars.get(m);
145                         XQueryExpression qbdFlwriVariExpr = qbdFlwriVari.getExpression();
146                         if (QDB.contains(qbdFlwriVariExpr)) {
147                             FLWRExpression tmpFlwr = (FLWRExpression) ((Variable) qbdFlwriVariExpr).getExpression();
148                             ArrayList JavaDoc tmpList = tmpFlwr.getVariables();
149                             qbdFlwriVars.remove(m);
150                             int add = 0;
151                             for (int n = 0; n < tmpList.size(); n++) {
152                                 Variable tmpVar = (Variable) tmpList.get(n);
153                                 if (!qbdFlwriVars.contains(tmpVar)) {
154                                     qdbFlwri.insertVariableAtPosition(tmpVar, m + add);
155                                     qbdFlwriVars = qdbFlwri.getVariables();
156                                     add++;
157                                 }
158                             }
159                             tmpList = tmpFlwr.getOrderBy();
160                             if (tmpList != null)
161                                 for (int n = 0; n < tmpList.size(); n++) {
162                                     XQueryExpression tmpExpr = (XQueryExpression) tmpList.get(n);
163                                     if (qbdFlwriOrders == null || !qbdFlwriOrders.contains(tmpExpr)) {
164                                         qdbFlwri.addOrderBy(n, tmpExpr);
165                                         qbdFlwriOrders = qdbFlwri.getOrderBy();
166                                     }
167                                 }
168                             m += add;
169                             if (add != 0) {
170                                 qdbFlwri.addWhereClause(tmpFlwr.getWhereClause());
171                             }
172                         }
173                     }
174                 }
175             }
176             // creating variable dependencies
177
// ATTENTION : this could have been done much easier (and faster!) in between the previous algorithms
178
// TODO
179
/*
180             temporary HashMap
181             QBD -> dependNode
182                 
183             ALGORITHM
184             Iterating on QDBs from bottom to top
185                 Iterating on QDBs from just above to top
186                 if all variables of above QDB are contained in QDB
187                     there is a parent relationship
188                     if son node does not exist create it with no parent
189                     if parent node does exist add the son node
190                     else create the parent node, add the son node
191                     add all parent variables to keyvars list
192             */

193             if (QDB != null && !QDB.isEmpty()) {
194                 // make dependency map
195
HashMap JavaDoc tmpHash = new HashMap JavaDoc(QDB.size());
196                 for (int l = QDB.size() - 1; l >= 0; l--) {
197                     Variable qdbVarl = (Variable) QDB.get(l);
198                     FLWRExpression qdbFlwrl = (FLWRExpression) qdbVarl.getExpression();
199                     ArrayList JavaDoc qbdFlwrlVars = qdbFlwrl.getVariables();
200
201                     boolean foundParent = false;
202                     for (int m = l - 1; m >= 0; m--) {
203                         Variable qdbVarm = (Variable) QDB.get(m);
204                         FLWRExpression qdbFlwrm = (FLWRExpression) qdbVarm.getExpression();
205                         ArrayList JavaDoc qbdFlwrmVars = qdbFlwrm.getVariables();
206
207                         if (qbdFlwrlVars.containsAll(qbdFlwrmVars)) {
208                             foundParent = true;
209                             DependNode parentNode = (DependNode) tmpHash.get(qdbFlwrm);
210                             DependNode sonNode = (DependNode) tmpHash.get(qdbFlwrl);
211                             if (sonNode == null) {
212                                 sonNode = new DependNode((DependNode) null, null, qdbFlwrl);
213                                 tmpHash.put(qdbFlwrl, sonNode);
214                             }
215                             if (parentNode != null)
216                                 parentNode.addSon(0, sonNode);
217                             else {
218                                 parentNode = new DependNode((DependNode) null, null, qdbFlwrm);
219                                 parentNode.addSon(0, sonNode);
220                                 tmpHash.put(qdbFlwrm, parentNode);
221                             }
222                             // add parent Node variables to keyvars
223
for (int n = qbdFlwrmVars.size() - 1; n >= 0; n--) {
224                                 Variable parVarn = (Variable) qbdFlwrmVars.get(n);
225                                 if (!keyVars.contains(parVarn))
226                                     keyVars.add(0, parVarn);
227                             }
228                             break;
229                         }
230                     }
231                     if (!foundParent) {
232                         if (tmpHash.get(qdbFlwrl) != null)
233                             dependMaps.add(0, tmpHash.get(qdbFlwrl));
234                         else
235                             dependMaps.add(0, new DependNode((DependNode) null, null, qdbFlwrl));
236                     }
237                 }
238
239                 // TODO check if this code is useful?!!!
240
/*
241                 adds variables to allvars
242                 adds variables to varlist (only for binding?)
243                 */

244                 ArrayList JavaDoc allVars = new ArrayList JavaDoc();
245                 for (int l = 0; l < QDB.size(); l++) {
246                     FLWRExpression tmpExpr = (FLWRExpression) ((Variable) QDB.get(l)).getExpression();
247                     ArrayList JavaDoc tmpList = tmpExpr.getVariables();
248                     for (int m = 0; m < tmpList.size(); m++) {
249                         Variable tmpVar = (Variable) tmpList.get(m);
250                         if (!(allVars.contains(tmpVar)))
251                             allVars.add(tmpVar);
252                         //else keyVars.add(tmpVar);
253
if (tmpVar.getBindingType() == Constants.FOR_BINDINGTYPE)
254                             if (!(varList.contains(tmpVar)))
255                                 varList.add(tmpVar);
256                     }
257                 }
258
259                 // TODO check if this code is useful?!!!
260
/*
261                 erases variables in return clause that are not bound or keys
262                 if no variables left keep the first
263                 */

264                 for (int l = 0; l < QDB.size(); l++) {
265                     Variable vari = (Variable) QDB.get(l);
266                     FLWRExpression tmpExpr = (FLWRExpression) vari.getExpression();
267                     XQueryExpressionSequence tmpSeq = (XQueryExpressionSequence) tmpExpr.getReturnClause();
268                     ArrayList JavaDoc subExprs = (ArrayList JavaDoc) tmpSeq.getSubExpressions().clone();
269                     for (int m = 0; m < subExprs.size(); m++) {
270                         Variable tmpVar = (Variable) subExprs.get(m);
271                         if (!(boundVariables.contains(tmpVar)) && !keyVars.contains(tmpVar)) {
272                             subExprs.remove(m);
273                             m--;
274                         }
275                     }
276                     if (subExprs.isEmpty()) {
277                         subExprs.add(tmpSeq.getSubExpressions().get(0));
278                         tmpSeq.setSubExpressions(subExprs);
279                     } else
280                         tmpSeq.setSubExpressions(subExprs);
281                 }
282
283                 SetVariablePathsVisitor varPathVisitor = new SetVariablePathsVisitor();
284                 for (int l = 0; l < QDB.size(); l++) {
285                     ((Variable) QDB.get(l)).getExpression().accept(varPathVisitor);
286                 }
287                 QMEM.accept(varPathVisitor);
288
289             }
290             // special verification for extractor : verify that all variables in varlist have at least one path associated
291
// if not add the variable itself (but only for variable bound on Values)
292
for (int l = 0; l < varList.size(); l++) {
293                 Variable var = (Variable) varList.get(l);
294                 ArrayList JavaDoc pathslist = var.getSubPathList();
295                 if (pathslist == null || pathslist.isEmpty())
296                     var.addSubPath(var);
297             }
298
299             if (log.isDebugEnabled())
300                 log.debug("STOP SPECIAL TREATMENT いいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいい");
301         } catch (XQueryException e) {
302             throw new ParseException("Invalid expression : " + this +" -> " + e.getMessage());
303         }
304         /***********************************/
305
306         if (log.isTraceEnabled()) {
307             log.trace("dependMaps = " + dependMaps);
308             log.trace("varList = " + varList);
309             //log.trace("keyVars = " + keyVars);
310
log.trace("returnVariables = " + returnVarList);
311             log.trace("idVariables = " + idVarList);
312             if (varList != null)
313                 for (int l = 0; l < varList.size(); l++) {
314                     ArrayList JavaDoc trees = ((Variable) varList.get(l)).getXTrees();
315                     log.trace(((Variable) varList.get(l)) + " --> trees --> " + trees);
316                     ArrayList JavaDoc subPathList = ((Variable) varList.get(l)).getSubPathList();
317                     log.trace(((Variable) varList.get(l)) + " --> subPathList --> " + subPathList);
318                     if (subPathList != null)
319                         for (int m = 0; m < subPathList.size(); m++) {
320                             log.trace(((XQueryExpression) subPathList.get(m)) + " --> xtrees--> " + ((XQueryExpression) subPathList.get(m)).getXTrees());
321                             log.trace(((XQueryExpression) subPathList.get(m)) + " --> loopIDs --> " + ((XQueryExpression) subPathList.get(m)).getLoopIDs());
322                         }
323                 }
324             for (int si = 0; si < QDB.size(); si++) {
325                 log.trace("QDB[" + si + "]: " + ((Variable) QDB.get(si)).getExpression());
326             }
327             log.trace("QMEM: " + QMEM);
328         }
329     }
330
331     public ArrayList JavaDoc getQDB() {
332         return QDB;
333     }
334
335     public XQueryExpression getQMEM() {
336         return QMEM;
337     }
338
339     public ArrayList JavaDoc getDependMap() {
340         return dependMaps;
341     }
342
343     public ArrayList JavaDoc getVarList() {
344         return varList;
345     }
346
347     public ArrayList JavaDoc getReturnVarList() {
348         return returnVarList;
349     }
350
351     public ArrayList JavaDoc getIdVarList() {
352         return idVarList;
353     }
354
355     // For debugging
356
public String JavaDoc toString() {
357         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
358         sb.append("\n%%% QDB: " + QDB + "\n");
359         sb.append("%%% QMEM: " + QMEM + "\n");
360         sb.append("%%% dependMap: " + dependMaps + "\n");
361         sb.append("%%% varList: " + varList + "\n");
362         sb.append("%%% returnVarList: " + returnVarList + "\n");
363         sb.append("%%% idVarList: " + idVarList + "\n");
364         return sb.toString();
365     }
366
367 }
368
Popular Tags