KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > speedo > generation > jorm > JormGenerator


1 /**
2  * Speedo: an implementation of JDO compliant personality on top of JORM generic
3  * I/O sub-system.
4  * Copyright (C) 2001-2004 France Telecom R&D
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  *
21  *
22  * Contact: speedo@objectweb.org
23  *
24  * Authors: S.Chassande-Barrioz.
25  *
26  */

27
28 package org.objectweb.speedo.generation.jorm;
29
30 import java.util.ArrayList JavaDoc;
31 import java.util.Collection JavaDoc;
32 import java.util.Iterator JavaDoc;
33 import java.util.List JavaDoc;
34 import java.util.Set JavaDoc;
35
36 import org.objectweb.jorm.api.PException;
37 import org.objectweb.jorm.compiler.api.JormCompilerConfigurator;
38 import org.objectweb.jorm.compiler.api.JormCompilerParameter;
39 import org.objectweb.jorm.compiler.lib.JormCompiler;
40 import org.objectweb.jorm.metainfo.api.Class;
41 import org.objectweb.jorm.metainfo.api.ClassProject;
42 import org.objectweb.jorm.metainfo.api.CompositeName;
43 import org.objectweb.jorm.metainfo.api.GenClassRef;
44 import org.objectweb.jorm.metainfo.api.Manager;
45 import org.objectweb.jorm.metainfo.api.Mapping;
46 import org.objectweb.jorm.metainfo.api.NameDef;
47 import org.objectweb.jorm.metainfo.api.TypedElement;
48 import org.objectweb.jorm.util.io.lib.DirJavaExplorer;
49 import org.objectweb.speedo.api.ExceptionHelper;
50 import org.objectweb.speedo.api.SpeedoException;
51 import org.objectweb.speedo.api.SpeedoProperties;
52 import org.objectweb.speedo.generation.api.SpeedoXMLError;
53 import org.objectweb.speedo.generation.lib.AbstractGeneratorComponent;
54 import org.objectweb.speedo.metadata.SpeedoClass;
55 import org.objectweb.speedo.metadata.SpeedoField;
56 import org.objectweb.speedo.metadata.SpeedoIdentity;
57 import org.objectweb.speedo.metadata.SpeedoModifier;
58 import org.objectweb.speedo.metadata.SpeedoPackage;
59 import org.objectweb.speedo.metadata.SpeedoXMLDescriptor;
60 import org.objectweb.util.monolog.api.BasicLevel;
61
62 /**
63  * Generates the JORM Files corresponding to a set of Java Classes.
64  * <p>See <a HREF="http://www.objectweb.org/jorm">http://www.objectweb.org/jorm</a>for more information.</p>
65  * @author S.Chassande-Barrioz
66  */

67 public class JormGenerator extends AbstractGeneratorComponent {
68
69     public final static String JavaDoc LOGGER_NAME
70             = SpeedoProperties.LOGGER_NAME + ".generation.jorm";
71
72     /**
73      * Jorm classes intended for JORM generation
74      */

75     protected JormCompiler jormcompiler;
76
77
78     // IMPLEMENTATION OF THE GeneratorComponent INTERFACE //
79
//----------------------------------------------------//
80

81     public boolean init() throws SpeedoException {
82         if (scp.getXmldescriptor().isEmpty()) {
83             return false;
84         }
85         logger = scp.loggerFactory.getLogger(LOGGER_NAME);
86         jormcompiler = new JormCompiler();
87         JormCompilerParameter jcp = jormcompiler.getCompilerParameter();
88         JormCompilerConfigurator jcc = jormcompiler.getCompilerConfigurator();
89         try {
90             jcc.configure();
91             jcp.loadConfFile(jcc.getGlobalJormcOptsFile(), jcc.knownMappers());
92             jcc.setLoggerFactory(scp.loggerFactory);
93             jcp.setProjectName(scp.projectName);
94             jcp.setBindingInheritance("%p%c");
95             jcp.setClassMappingInheritance("%p%cHome");
96             jcp.setOutput(scp.output);
97             jcp.setBindingAbstract(true);
98             jcp.setDtdLocations(scp.dtdLocations);
99             jcp.setInputFiles(scp.jorm);
100             DirJavaExplorer pe = new DirJavaExplorer();
101             pe.setLogger(scp.loggerFactory.getLogger("org.objectweb.jorm.io.pathexplorer"));
102             pe.addPath(scp.jormclasspath);
103             jcp.setClasspath(pe);
104             jcp.setGenerateBinding(false);
105             jcp.setGeneratedWithMapperPackage(false);
106             int idx = scp.mapperName.indexOf('.');
107             if (idx == -1) {
108                 jcc.removeMapper(scp.mapperName);
109                 jcc.addSubMapper(scp.mapperName, "generic");
110             } else {
111                 String JavaDoc actualmn = scp.mapperName.substring(0,idx);
112                 jcc.removeMapper(actualmn);
113                 jcc.addSubMapper(actualmn, scp.mapperName.substring(idx + 1));
114             }
115             if (logger.isLoggable(BasicLevel.DEBUG)) {
116                 logger.log(BasicLevel.DEBUG, "jormcOpts file:" + jcc.getJormcOptsFile());
117                 Iterator JavaDoc it = jcc.knownMappers();
118                 while(it.hasNext()) {
119                     String JavaDoc mapperName = (String JavaDoc) it.next();
120                     logger.log(BasicLevel.DEBUG, mapperName + " sub mappers: "
121                             + jcc.getSubMappers(mapperName ));
122                 }
123             }
124         } catch (PException e) {
125             logger.log(BasicLevel.ERROR,
126                     "Impossible to configure Jorm", ExceptionHelper.getNested(e));
127             throw new SpeedoException("Impossible to configure Jorm", e);
128         }
129         return true;
130     }
131
132     /**
133      * Performs the JORM objects' generation.
134      */

135     public void process() throws SpeedoException {
136         if (scp.getXmldescriptor().isEmpty()) {
137             return;
138         }
139         try {
140             //The list of .pd files specified by the user
141
Collection JavaDoc pdfiles = jormcompiler.getCompilerParameter().getInputFiles();
142             if (logger.isLoggable(BasicLevel.DEBUG)) {
143                 for (Iterator JavaDoc it = pdfiles.iterator(); it.hasNext();)
144                     logger.log(BasicLevel.DEBUG, "source file: " + it.next());
145             }
146
147             //The list of SpeedoClass requiring the JMI generation
148
ArrayList JavaDoc notFoundMOs = new ArrayList JavaDoc();
149             for (Iterator JavaDoc itDesc = scp.getXmldescriptor().values().iterator(); itDesc.hasNext();) {
150                 SpeedoXMLDescriptor desc = (SpeedoXMLDescriptor) itDesc.next();
151                 List JavaDoc scs = desc.getSpeedoClasses();
152                 for (int i=0; i<scs.size(); i++) {
153                     SpeedoClass sc = (SpeedoClass) scs.get(i);
154                     String JavaDoc fn = sc.getJormFileName();
155                     logger.log(BasicLevel.DEBUG, "looking for the file: " + fn);
156                     if (!pdfiles.contains(fn)) {
157                         //No .pd file is availlable, add the SpeedoClass into the list
158
notFoundMOs.add(sc);
159                     }
160                 }
161             }
162
163             // if .pd files are not specified by the user then the jorm meta
164
// information is generated
165
jormcompiler.setupLogger();
166             jormcompiler.setupMIManager();
167             Collection JavaDoc createdMOs = null;
168             if (!notFoundMOs.isEmpty()) {
169                 createdMOs = new JormMIBuilder(
170                         jormcompiler.getMIManager(), scp.nmf, logger)
171                         .createMI(notFoundMOs, scp.projectName, scp.mapperName);
172             }
173
174
175             // parse the .pd files ==> Collection(jorm MetaObject)
176
Collection JavaDoc mos = new ArrayList JavaDoc(jormcompiler.parseFiles(pdfiles));
177
178             isCompatible();
179
180             // Generate the .pd files
181
if (scp.generateNeededJormFile
182                     && createdMOs != null && !createdMOs.isEmpty()) {
183                 jormcompiler.generateJormFiles(createdMOs);
184             }
185             mos.addAll(createdMOs);
186
187             if (logger.isLoggable(BasicLevel.DEBUG))
188                 for (Iterator JavaDoc it = mos.iterator(); it.hasNext();) {
189                     Object JavaDoc o = it.next();
190                     if (o instanceof Class JavaDoc) {
191                         logger.log(BasicLevel.DEBUG, "Class : "
192                                 + ((Class JavaDoc) o).getFQName());
193                     } else if (o instanceof CompositeName) {
194                         logger.log(BasicLevel.DEBUG, "compositeName : "
195                                 + ((CompositeName) o).getFQName());
196                     } else
197                         logger.log(BasicLevel.DEBUG, "metaObject : " + o);
198                 }
199
200             //Verify the meta information
201
//jormcompiler.verifyMetaInfo(c);
202

203             //Launch the jorm generation
204
mos = jormcompiler.generateFiles(mos);
205
206             if (logger.isLoggable(BasicLevel.DEBUG))
207                 for (Iterator JavaDoc it = mos.iterator(); it.hasNext();)
208                     logger.log(BasicLevel.DEBUG, "Generated files: " + it.next());
209
210             //Serialize the meta information for each xml descriptor
211
for (Iterator JavaDoc itDesc = scp.getXmldescriptor().values().iterator(); itDesc.hasNext();) {
212                 addSerializeJormMI((SpeedoXMLDescriptor) itDesc.next());
213             }
214         } catch (PException e) {
215             throw new SpeedoException("Error during Jorm generation", e);
216         }
217     }
218
219     /**
220      * Verifies that all persistent capable field for jdo is described in JORM.
221      *
222      * @exception org.objectweb.speedo.generation.api.SpeedoXMLError if JORM an JDO MetaData are not coherent
223      */

224     protected void isCompatible() throws SpeedoException {
225
226         List JavaDoc except = new ArrayList JavaDoc();
227
228         Manager manager = jormcompiler.getMIManager();
229         for (Iterator JavaDoc itDesc = scp.getXmldescriptor().values().iterator(); itDesc.hasNext();) {
230             SpeedoXMLDescriptor desc = (SpeedoXMLDescriptor) itDesc.next();
231             List JavaDoc scs = desc.getSpeedoClasses();
232             for (int i=0; i<scs.size(); i++) {
233                 compareClass((SpeedoClass) scs.get(i), manager, except);
234             }
235         }
236         if (!except.isEmpty() && logger.isLoggable(BasicLevel.ERROR))
237             for (Iterator JavaDoc it = except.iterator(); it.hasNext();)
238                 logger.log(BasicLevel.ERROR, it.next());
239     }
240
241     protected void compareClass(SpeedoClass clas,
242                                 Manager manager,
243                                 List JavaDoc except) throws SpeedoException {
244         debug = logger.isLoggable(BasicLevel.DEBUG);
245         if (debug) {
246             logger.log(BasicLevel.DEBUG,
247                     "Verify the definition of the class " + clas.getFQName());
248         }
249         Class JavaDoc classJorm = manager.getClass(clas.getFQName());
250         if (classJorm == null) {
251             throw new SpeedoException("Jorm description of the class '"
252                     + clas.getFQName() + "' is not availlable");
253         }
254         NameDef pName = null;
255         SpeedoClass sc = clas;
256         while(sc.superClassName != null) {
257             SpeedoClass _sc = sc;
258             sc = sc.jdoPackage.jdoXMLDescriptor.smi.getSpeedoClass(sc.superClassName, sc.jdoPackage);
259             if (sc == null) {
260                 throw new SpeedoException("Class " + _sc.getFQName() + " not defined in the jorm meta information");
261             }
262         }
263         Class JavaDoc pclassJorm = manager.getClass(sc.getFQName());
264         pName = getClassNameDef(pclassJorm);
265
266         if (classJorm == null) {
267             throw new SpeedoXMLError("Class '" + clas.name + "' not defined in JORM metadata");
268         }
269
270         // Comparison from JDO
271
clas.jormclass = classJorm;
272         for (Iterator JavaDoc efield = clas.jdoField.values().iterator(); efield.hasNext();) {
273             SpeedoField field = (SpeedoField) efield.next();
274             String JavaDoc fieldName = field.name;
275
276             // Fields with this persistent modifier shouldn't stay in JDO Metadata
277
if (field.persistenceModifier == SpeedoModifier.none)
278                 continue;
279
280             TypedElement tElem = classJorm.getTypedElement(fieldName);
281             if (tElem == null) {
282                 throw new SpeedoXMLError("Field '" + fieldName
283                     + "' not defined in JORM metadata of the class '"
284                     + clas.getFQName() + "'");
285             }
286
287             // for application identity key fields have to be compared
288
if (field.primaryKey) {
289                 boolean found = false;
290                 for (Iterator JavaDoc it = pName.iterateField(); it.hasNext() && !found;) {
291                     found = fieldName.equals(it.next());
292                 }
293                 if (!found) {
294                     throw new SpeedoXMLError("Field '" + fieldName
295                         + "' not defined in Class NameDef's Fields of the class '"
296                         + clas.getFQName() + "'");
297                 }
298             }
299
300             if (tElem instanceof GenClassRef && field.jdoTuple == null)
301                 throw new SpeedoXMLError("field '" + fieldName + "' should be a tuple in JDO metadata of the class '" + clas.getFQName() + "'");
302         }
303
304         // Comparison from JORM
305
for (Iterator JavaDoc jormfield = classJorm.getFields().iterator(); jormfield.hasNext();) {
306             TypedElement te = (TypedElement) jormfield.next();
307             String JavaDoc fieldName = te.getName();
308             if (!clas.jdoField.containsKey(fieldName)
309                     && !isContainerIdField(classJorm, te, clas))
310                 throw new SpeedoXMLError("Field '" + fieldName + "' of the class '"
311                             + clas.getFQName() + "' is not defined in the '"
312                             + clas.jdoPackage.jdoXMLDescriptor.xmlFile
313                             + "' file (found: " + clas.jdoField.keySet() + ").");
314         }
315
316         // for application identity key fields have to be compared
317
if (clas.identityType == SpeedoIdentity.USER_ID) {
318             SpeedoClass classWithId = clas;
319             while(classWithId.superClassName != null) {
320                 classWithId = classWithId.getSpeedoClassFromContext(classWithId.superClassName);
321             }
322             boolean found = false;
323             for (Iterator JavaDoc it = pName.iterateField(); it.hasNext() && !found;) {
324                 String JavaDoc fn = (String JavaDoc) it.next();
325                 SpeedoField sf = (SpeedoField) classWithId.jdoField.get(fn);
326                 if (sf == null) {
327                     logger.log(BasicLevel.WARN, "Field " + fn + " defined in the identifier of "
328                             + classWithId.name
329                             + ".pd file but not availlable in the class (or .pd file).");
330                 } else if (!sf.primaryKey) {
331                     except.add("Field " + fn + " defined in the "
332                             + classWithId.name
333                             + ".pd file but is not marked as a primary key field in the "
334                             + classWithId.jdoPackage.jdoXMLDescriptor.xmlFile
335                             + " file.");
336                 }
337             }
338         }
339     }
340
341     private boolean isContainerIdField(Class JavaDoc clazz,
342                                        TypedElement te,
343                                        SpeedoClass sc) throws SpeedoException {
344         return sc.identityType == SpeedoIdentity.CONTAINER_ID
345                 && getClassNameDef(clazz).getNameRef()
346                 .getProjection().containsValue(te.getName());
347     }
348
349
350     private Mapping getMapping(Class JavaDoc clazz) throws SpeedoException {
351         ClassProject cp = clazz.getClassProject(scp.projectName);
352         if (cp == null) {
353             throw new SpeedoException("No classproject found for the class "
354                     + clazz.getFQName() + " and the project " + scp.projectName);
355         }
356         int idx = scp.mapperName.indexOf('.');
357         Mapping m = cp.getMapping(idx == -1
358                 ? scp.mapperName
359                 : scp.mapperName.substring(0, idx));
360         if (m == null) {
361             throw new SpeedoException("No mapping found for the class "
362                     + clazz.getFQName() + ", the project " + scp.projectName
363                     + " and the mapper " + scp.mapperName);
364         }
365         return m;
366     }
367
368     private NameDef getClassNameDef(Class JavaDoc clazz) throws SpeedoException {
369         return (NameDef) getMapping(clazz).getClassMapping()
370                 .getIdentifierMapping().getLinkedMO();
371     }
372
373     private void addSerializeJormMI(SpeedoXMLDescriptor desc)
374             throws SpeedoException {
375         // Calculate the list of the Jorm Meta Object which must be serialized
376
//Set mos = new HashSet(desc.jdoPackage.size());
377
for (Iterator JavaDoc itPack = desc.jdoPackage.values().iterator(); itPack.hasNext();) {
378             SpeedoPackage sp = (SpeedoPackage) itPack.next();
379             for (Iterator JavaDoc itclass = sp.jdoClass.values().iterator(); itclass.hasNext();) {
380                 SpeedoClass jdoClass = (SpeedoClass) itclass.next();
381                 if (jdoClass.jormclass == null)
382                     throw new SpeedoException(
383                             "The Jorm meta information of the jdo descriptor "
384                             + desc.xmlFile + " is not complete: class "
385                             + jdoClass.name + " has not been found");
386                 // The class meta object
387
addMOClass(jdoClass.jormclass, desc.mos);
388
389                 // Add the CompositeName which could be used in the class name def
390
for (Iterator JavaDoc it = jdoClass.jormclass.getNameDefs().iterator(); it.hasNext();) {
391                     NameDef nd = (NameDef) it.next();
392                     if (nd.isNameRef()) {
393                         desc.mos.add(nd.getNameRef().getCompositeName());
394                     }
395                 }
396
397                 //The compositeName used for the reference will be added by the
398
// name definition of the referenced class.
399
}
400         }
401     }
402
403     private void addMOClass(Class JavaDoc mo, Set JavaDoc mos) {
404         mos.add(mo);
405         for(Iterator JavaDoc it = mo.getSuperClasses().iterator();it.hasNext();) {
406             addMOClass((Class JavaDoc) it.next(), mos);
407         }
408     }
409 }
410
Popular Tags