KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > medor > optim > jorm > JormFilteredInheritance


1 /**
2  * MEDOR: Middleware Enabling Distributed Object Requests
3  *
4  * Copyright (C) 2001-2004 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.jorm;
24
25 import org.objectweb.jorm.mapper.rdb.metainfo.RdbClassMapping;
26 import org.objectweb.jorm.mapper.rdb.metainfo.RdbFilter;
27 import org.objectweb.jorm.mapper.rdb.metainfo.RdbMapping;
28 import org.objectweb.jorm.metainfo.api.Class;
29 import org.objectweb.jorm.naming.api.NamingFilterKeyProvider;
30 import org.objectweb.medor.api.Field;
31 import org.objectweb.medor.api.MedorException;
32 import org.objectweb.medor.expression.api.Expression;
33 import org.objectweb.medor.expression.api.ExpressionException;
34 import org.objectweb.medor.expression.api.Operator;
35 import org.objectweb.medor.expression.api.ParameterOperand;
36 import org.objectweb.medor.expression.lib.ExpressionPrinter;
37 import org.objectweb.medor.expression.lib.Or;
38 import org.objectweb.medor.filter.lib.BasicFieldOperand;
39 import org.objectweb.medor.query.api.QueryNode;
40 import org.objectweb.medor.query.api.QueryTree;
41 import org.objectweb.medor.query.api.QueryTreeField;
42 import org.objectweb.medor.query.jorm.api.JormExtent;
43 import org.objectweb.medor.query.jorm.lib.ClassExtent;
44 import org.objectweb.medor.query.lib.SelectProject;
45 import org.objectweb.util.monolog.api.BasicLevel;
46
47 import java.util.HashMap JavaDoc;
48 import java.util.Iterator JavaDoc;
49 import java.util.Map JavaDoc;
50
51 /**
52  * In the case of filtered inheritance, this rule replaces a QueryTree built on
53  * top of JormExtents with inheritance by a QueryTree with JormExtents without
54  * inheritance, on top of which are inserted new SelectProjects containing the
55  * filter corresponding to the inheritance filter.
56  * <p>MEDOR constructs its filter using the ones in RdbClassMapping, either
57  * accessible through getRdbFilter(), if it has been provided by the user, or
58  * computed from the NameDef filter otherwise (method to be provided in JORM).
59  * </p>
60  * @author A. Lefebvre
61  */

62 public class JormFilteredInheritance extends JormRule {
63
64     public JormFilteredInheritance() {
65         super("JormFilteredInheritance");
66     }
67
68     public QueryTree rewrite(QueryTree qt, QueryNode parent)
69             throws MedorException {
70         if ((qt instanceof ClassExtent)
71             && ((ClassExtent) qt).getPMapper().getMapperName().startsWith("rdb")
72             ) {
73             //obtain the expression corresponding to the filteredExtent
74
Expression inhfilt = filterForExtent(
75                     (ClassExtent) qt,
76                     (Class JavaDoc) ((ClassExtent) qt).getMetaObject(),
77                     ((ClassExtent) qt).getProjectName(),
78                     null,
79                     ((JormExtent) qt).withSubClasses());
80             if (debug) {
81                 log.log(BasicLevel.DEBUG, "Inheritance filter "
82                     + ExpressionPrinter.e2str(inhfilt));
83             }
84             if (inhfilt != null) {
85                 //modify the Extent: do not consider inheritance any more
86
((JormExtent) qt).setWithSubClasses(false);
87                 //create the new SelectProject with the filter
88
QueryNode newSP = new SelectProject(inhfilt, "");
89                 Map JavaDoc localyReplaced = (parent == null ? null : new HashMap JavaDoc());
90                 //add corresponding propagated fields
91
Field[] fs = qt.getTupleStructure().getFields();
92                 for (int i = 0; i < fs.length; i++) {
93                     Field newF = newSP.addPropagatedField(
94                         fs[i].getName(),
95                         fs[i].getType(),
96                         new QueryTreeField[]{(QueryTreeField) fs[i]});
97                     if (parent != null) {
98                         localyReplaced.put(fs[i], newF);
99                     }
100                 }
101                 //propagate changes to the parent
102
replaceUsage(parent, localyReplaced);
103             } // else (no filter found) then do nothing
104

105         } else if (qt instanceof QueryNode) {
106             QueryTree[] children = ((QueryNode) qt).getChildren();
107             for (int i = 0; i < children.length; i++) {
108                 rewrite(children[i], (QueryNode) qt);
109             }
110         }
111         return qt;
112     }
113
114     /**
115      * Calculates the filter expression corresponding to the filtered
116      * inheritance mapping.
117      * @param extent the extent
118      * @param currClass the current Class
119      * @param projectName the project name
120      * @param filter the filter currently computed
121      * @return the expression corresponding to the inheritance filter for that
122      * class
123      * @throws MedorException if concrete class without RdbFilter or if the
124      * NameDef differs for some of the subclasses.
125      */

126     private Expression filterForExtent(
127             ClassExtent extent,
128             Class JavaDoc currClass,
129             String JavaDoc projectName,
130             Expression filter,
131             boolean withSubClass)
132             throws MedorException {
133         //add the filter of the current class, if concrete class
134
if (!currClass.isAbstract()) {
135             if (debug) {
136                 log.log(BasicLevel.DEBUG, "Concrete class " + currClass.getName());
137             }
138             RdbMapping mapping = (RdbMapping) currClass
139                     .getClassProject(projectName)
140                     .getMapping("rdb");
141             RdbClassMapping rdbCM = (RdbClassMapping) mapping.getClassMapping();
142
143             //Fetch the mapping filter
144
RdbFilter mapFilter = rdbCM.getRdbFilter();
145             Expression localFilter = null;
146             if (mapFilter != null) { //there is a Rdbfilter
147
localFilter = mapFilter.getExpression();
148                 if (debug) {
149                     log.log(BasicLevel.DEBUG, "Mapping filter is "
150                         + ExpressionPrinter.e2str(localFilter));
151                 }
152             }
153             if (localFilter == null) {
154                 //No mapping filter specified ==> check if the mode is
155
// filtered mapping
156
if (mapping.isFilteredMapping()) {
157                     Object JavaDoc pcm = extent.getPMapper().lookup(currClass.getFQName());
158                     try {
159                         if (pcm instanceof NamingFilterKeyProvider) {
160                             localFilter = rdbCM.getMappingFilterFromNamingFilter(
161                                 (NamingFilterKeyProvider) pcm);
162                         } else {
163                             localFilter = rdbCM.getMappingFilterFromNamingFilter();
164                         }
165                     } catch (ExpressionException e) {
166                         throw new MedorException(e);
167                     }
168                     if (debug) {
169                         log.log(BasicLevel.DEBUG, "Naming filter is "
170                             + ExpressionPrinter.e2str(localFilter));
171                     }
172                 }
173                 if (localFilter == null) {
174                     return null;
175                 }
176             }
177             //replace the ParameterOperand of the JORM filter with FieldOperands
178
localFilter = modifiesJormFilterForExtent(localFilter, extent);
179
180             //Merge the current filter with the one specified in parameter
181
if (filter == null) {
182                 filter = localFilter;
183             } else {
184                 filter = new Or(filter, localFilter);
185             }
186         }
187         if (withSubClass) {
188             //iterate over subclasses in order to have their filter too
189
Iterator JavaDoc subclassesIt = currClass.getSubClasses().iterator();
190             if (debug) {
191                 log.log(BasicLevel.DEBUG, "Subclasses for " + currClass.getName());
192             }
193             while (subclassesIt.hasNext()) {
194                 Class JavaDoc subcl = (Class JavaDoc) subclassesIt.next();
195                 if (debug) {
196                     log.log(BasicLevel.DEBUG, "Recursing for subclass "
197                         + subcl.getName() + " of class " + currClass.getName());
198                 }
199                 filter = filterForExtent(
200                         extent,
201                         subcl,
202                         projectName,
203                         filter,
204                         true);
205             }
206         }
207         return filter;
208     }
209
210     /**
211      * Takes the JORM filter as input, expressed with ParameterOperands, and
212      * replaces the ParameterOperands with FieldOperands on the ClassExtent.
213      * <p>If the field is not present on the Extent, add it.</p>
214      * @param filter The JORM filter expressed using ParameterOperands
215      * @param extent The ClassExtent
216      * @throws MedorException when adding the field to the Extent.
217      */

218     private Expression modifiesJormFilterForExtent(Expression filter,
219             ClassExtent extent)
220             throws MedorException {
221         if (filter instanceof Operator) {
222             Operator op = (Operator) filter;
223             int opnum = op.getOperandNumber();
224             for (int i = 0; i < opnum; i++) {
225                 op.setExpression(i,
226                     modifiesJormFilterForExtent(op.getExpression(i), extent));
227             }
228             return op;
229         } else if (filter instanceof ParameterOperand) {
230             String JavaDoc fieldName = ((ParameterOperand) filter).getName();
231             Field f = null;
232             try {
233                 f = extent.getField(extent.getJormName() + "." + fieldName);
234                 if (debug) {
235                     log.log(BasicLevel.DEBUG, "Field already on extent: " + fieldName);
236                 }
237             } catch (MedorException me) {
238                 if (debug) {
239                     log.log(BasicLevel.DEBUG, "Catched exception: " + me + " (field not on extent, will be added)");
240                 }
241                 f = extent.addField(((Class JavaDoc)extent.getMetaObject()).getTypedElement(fieldName));
242                 if (debug) {
243                     log.log(BasicLevel.DEBUG, "Added field to extent: " + fieldName + " " + f);
244                 }
245             }
246             return new BasicFieldOperand(f);
247         } else {
248             return filter;
249         }
250     }
251 }
252
Popular Tags