KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > medor > optim > lib > FlattenQueryTreeRule


1 /**
2  * MEDOR: Middleware Enabling Distributed Object Requests
3  *
4  * Copyright (C) 2001-2003 France Telecom R&D
5  * Contact: alexandre.lefebvre@rd.francetelecom.com
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library 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 GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  *
21  * Initial developers: M. Alia, S. Chassande-Barrioz, A. Lefebvre
22  */

23 package org.objectweb.medor.optim.lib;
24
25 import org.objectweb.medor.api.Field;
26 import org.objectweb.medor.api.MedorException;
27 import org.objectweb.medor.expression.api.Expression;
28 import org.objectweb.medor.expression.api.Operator;
29 import org.objectweb.medor.filter.api.FieldOperand;
30 import org.objectweb.medor.filter.lib.ExpressionPrinter;
31 import org.objectweb.medor.query.api.CalculatedField;
32 import org.objectweb.medor.query.api.FilteredQueryTree;
33 import org.objectweb.medor.query.api.OrderField;
34 import org.objectweb.medor.query.api.PropagatedField;
35 import org.objectweb.medor.query.api.QueryLeaf;
36 import org.objectweb.medor.query.api.QueryNode;
37 import org.objectweb.medor.query.api.QueryTree;
38 import org.objectweb.medor.query.api.QueryTreeField;
39 import org.objectweb.medor.query.lib.Nest;
40 import org.objectweb.util.monolog.api.BasicLevel;
41
42 import java.util.HashMap JavaDoc;
43 import java.util.HashSet JavaDoc;
44 import java.util.Map JavaDoc;
45 import java.util.Set JavaDoc;
46
47 /**
48  *
49  * @author S.Chassande-Barrioz
50  */

51 public class FlattenQueryTreeRule extends BasicRule {
52
53     public FlattenQueryTreeRule() {
54         super("FlattenQueryTreeRule");
55     }
56
57     public QueryTree rewrite(QueryTree qt, QueryNode parent)
58             throws MedorException {
59         return flatten(parent, qt);
60     }
61
62     public QueryTree flatten(QueryNode parent, QueryTree qt)
63             throws MedorException {
64         if (qt instanceof QueryLeaf) {
65             return qt;
66         }
67         if (qt instanceof Nest) {
68             flatten((Nest) qt, ((QueryNode) qt).getChildren()[0]);
69             return qt;
70         }
71         QueryNode qn = (QueryNode) qt;
72         QueryTree[] children = qn.getChildren();
73         //Map of replaced fields, for propagation to the parent node
74
Map JavaDoc localyReplaced = (parent == null ? null : new HashMap JavaDoc());
75         Set JavaDoc inner = findInner(qn);
76         while (containsQueryNode(children)) {
77             log.log(BasicLevel.DEBUG, "node");
78             if (useParent(qn.getQueryFilter())) {
79                 qn.setQueryFilter(qn.getQueryFilter());
80             }
81             Field[] fs = qt.getTupleStructure().getFields();
82             for (int i = 0; i < fs.length; i++) {
83                 if (fs[i] instanceof PropagatedField) {
84                     QueryTreeField childF = (QueryTreeField)
85                             ((PropagatedField) fs[i]).getPreviousFields()[0];
86                     if (childF.getQueryTree() instanceof QueryLeaf) {
87                         continue;
88                     }
89                     if (childF instanceof PropagatedField) {
90                         qn.updatePropagatedField(fs[i].getName(),
91                                 new QueryTreeField[]{(QueryTreeField)
92                                 ((PropagatedField) childF).getPreviousFields()[0]});
93                     } else if (childF instanceof CalculatedField) {
94                         //replace the current field fs[i] by childF
95
qn.replace((QueryTreeField) fs[i], childF);
96                         if (parent != null) {
97                             localyReplaced.put(fs[i], childF);
98                         }
99                     } else {
100                         throw new MedorException("Unmanaged child field: "
101                                 + childF);
102                     }
103                 } else if (fs[i] instanceof CalculatedField) {
104                     CalculatedField cf = (CalculatedField) fs[i];
105                     if (useParent(cf.getExpression())) {
106                         qn.updateCalculatedField(
107                                 cf.getName(), cf.getExpression());
108                     }
109                 } else {
110                     throw new MedorException("Unmanaged Field: " + fs[i]);
111                 }
112             }
113             //Replace the usage of replaced fields in the parent
114
replaceUsage(parent, localyReplaced);
115
116             //managing the order by clause
117
//TODO case where the orderField is already on a QueryLeaf
118
OrderField[] orderFields = qt.getOrderBy();
119             if (orderFields != null) {
120                 for (int i = 0; i < orderFields.length; i++) {
121                     QueryTreeField orderField = orderFields[i].getField();
122                     if (debug) {
123                         log.log(BasicLevel.DEBUG, "managing orderField " + orderField);
124                     }
125                     //nothing to do if orderField already on a leaf
126
if (orderField.getQueryTree() instanceof QueryLeaf) {
127                         if (debug) {
128                             log.log(BasicLevel.DEBUG, "nothing to do for this field (already on a leaf) " + orderField);
129                         }
130                         continue;
131                     }
132                     if (orderField instanceof PropagatedField) {
133                         QueryTreeField childF = (QueryTreeField)
134                                 ((PropagatedField) orderField)
135                                 .getPreviousFields()[0];
136                         if (childF.getQueryTree() instanceof QueryLeaf) {
137                             continue;
138                         }
139                         if (childF instanceof PropagatedField) {
140                             //get down one level
141
orderFields[i].setField(
142                                     (QueryTreeField)
143                                     ((PropagatedField) childF)
144                                     .getPreviousFields()[0]);
145                         } else if (childF instanceof CalculatedField) {
146                             //replace current orderField with childF
147
orderFields[i].setField(childF);
148                         } else {
149                             throw new MedorException("Unmanaged child field: "
150                                     + childF);
151                         }
152                     } else if (orderField instanceof CalculatedField) {
153                         CalculatedField cf = (CalculatedField) orderField;
154                         if (useParent(cf.getExpression())) {
155                             //replace current orderField expression
156
((CalculatedField) orderField)
157                                     .setExpression(cf.getExpression());
158                         }
159                     } else {
160                         throw new MedorException("Unmanaged Field: " + orderField);
161                     }
162                 }
163                 qt.setOrderBy(orderFields);
164             }
165
166             //fetch the filter of my children
167
boolean modified = false;
168             Expression e = qn.getQueryFilter();
169             for (int i = 0; i < children.length; i++) {
170                 if (children[i] instanceof FilteredQueryTree) {
171                     Expression filter = ((FilteredQueryTree) children[i])
172                             .getQueryFilter();
173                     if (filter != null) {
174                         if (e == null) {
175                             e = filter;
176                         } else {
177                             e = new org.objectweb.medor.expression.lib.And(e, filter);
178                         }
179                         modified = true;
180                     }
181                 }
182             }
183             if (modified) {
184                 log.log(BasicLevel.DEBUG, "Filter modified: " + ExpressionPrinter.e2str(e));
185                 qn.setQueryFilter(e);
186             }
187             children = qn.getChildren();
188         }
189         for (int i = 0; i < children.length; i++) {
190             qn.setOuter(children[i], !inner.contains(children[i]));
191         }
192         return qt;
193     }
194
195     private Set JavaDoc findInner(QueryTree qt) {
196         Set JavaDoc result = new HashSet JavaDoc();
197         findInner(qt, false, result);
198         return result;
199     }
200
201     private void findInner(QueryTree qt, boolean inner, Set JavaDoc result) {
202         if (inner) { result.add(qt); }
203         if (qt instanceof QueryNode) {
204             QueryNode qn = (QueryNode) qt;
205             QueryTree[] children = qn.getChildren();
206             for (int i = 0; i < children.length; i++) {
207                 findInner(children[i], inner || !qn.isOuter(children[i]), result);
208             }
209         }
210         }
211
212     private boolean containsQueryNode(QueryTree[] qts) {
213         log.log(BasicLevel.DEBUG, "Entering containsQueryNode for " + qts.length + " QueryTrees.");
214         for (int i = 0; i < qts.length; i++) {
215             if (qts[i] instanceof QueryNode) {
216                 log.log(BasicLevel.DEBUG, "Found QueryNode " + qts[i]);
217                 return true;
218             } else {
219                 log.log(BasicLevel.DEBUG, "Found other QueryTree " + qts[i]);
220             }
221         }
222         log.log(BasicLevel.DEBUG, "containsQueryNode: no QueryNode found. Exiting");
223         return false;
224     }
225
226     private boolean useParent(Expression e) {
227         if (e instanceof Operator) {
228             int size = ((Operator) e).getOperandNumber();
229             boolean res = false;
230             for (int i = 0; i < size; i++) {
231                 res |= useParent(((Operator) e).getExpression(i));
232             }
233             return res;
234         } else if (e instanceof FieldOperand) {
235             FieldOperand fo = (FieldOperand) e;
236             QueryTreeField f = (QueryTreeField) fo.getField();
237             if (f.getQueryTree() instanceof QueryLeaf) {
238                 return false;
239             }
240             if (f instanceof PropagatedField) {
241                 fo.setField(((PropagatedField) f).getPreviousFields()[0]);
242                 return true;
243             } else {
244                 log.log(BasicLevel.ERROR, "Unmanaged FieldOperand: " + f);
245             }
246         }
247         return false;
248     }
249
250 }
251
Popular Tags