001: /**
002: * Speedo: an implementation of JDO compliant personality on top of JORM generic
003: * I/O sub-system.
004: * Copyright (C) 2001-2004 France Telecom R&D
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2 of the License, or (at your option) any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: *
020: *
021: *
022: * Contact: speedo@objectweb.org
023: *
024: * Authors: S.Chassande-Barrioz.
025: *
026: */package org.objectweb.speedo.generation.generator.fields;
027:
028: import org.apache.velocity.app.Velocity;
029: import org.apache.velocity.context.Context;
030: import org.objectweb.asm.Type;
031: import org.objectweb.jorm.api.PException;
032: import org.objectweb.speedo.api.SpeedoException;
033: import org.objectweb.speedo.api.SpeedoProperties;
034: import org.objectweb.speedo.generation.enhancer.common.Util;
035: import org.objectweb.speedo.generation.generator.api.SpeedoGenerationException;
036: import org.objectweb.speedo.generation.generator.lib.AbstractSpeedoGenerator;
037: import org.objectweb.speedo.generation.lib.NamingRules;
038: import org.objectweb.speedo.lib.Personality;
039: import org.objectweb.speedo.metadata.SpeedoClass;
040: import org.objectweb.speedo.metadata.SpeedoField;
041: import org.objectweb.util.monolog.wrapper.velocity.VelocityLogger;
042:
043: import java.io.FileWriter;
044: import java.util.ArrayList;
045: import java.util.Iterator;
046: import java.util.List;
047: import java.util.Map;
048:
049: /**
050: * This class is used to generate accessor classes. This new file will
051: * manage status of persistent classes and values of persistent fields.
052: *
053: * @author S.Chassande-Barrioz
054: */
055: public class FieldsGenerator extends AbstractSpeedoGenerator {
056: public final static String LOGGER_NAME = SpeedoProperties.LOGGER_NAME
057: + ".generation.generator.fields";
058: public final static String TEMPLATE_NAME = TEMPLATE_DIR
059: + ".fields.Fields";
060:
061: public FieldsGenerator(Personality p) {
062: super (p);
063: }
064:
065: // IMPLEMENTATION OF THE GeneratorComponent INTERFACE //
066: //----------------------------------------------------//
067:
068: public boolean init() throws SpeedoException {
069: logger = scp.loggerFactory.getLogger(LOGGER_NAME);
070: return !scp.getXmldescriptor().isEmpty();
071: }
072:
073: // IMPLEMENTATION OF THE VelocityGenerator INTERFACE //
074: //---------------------------------------------------//
075:
076: /**
077: * This method generates the a file since a SpeedoClass meta object.
078: * @param sClass is the speedo meta object.
079: * @param fileName name of the new file.
080: * @exception org.objectweb.speedo.generation.generator.api.SpeedoGenerationException If there is a problem during writing
081: * the new file.
082: */
083: public void generate(SpeedoClass sClass, String fileName)
084: throws SpeedoException {
085: computeTemplate(TEMPLATE_NAME.replace('.', '/') + ".vm");
086: try {
087: Context ctx = getContext(sClass);
088: FileWriter fw = new FileWriter(fileName);
089: ve.setProperty(Velocity.RUNTIME_LOG_LOGSYSTEM,
090: new VelocityLogger(logger));
091: template.merge(ctx, fw);
092: fw.flush();
093: fw.close();
094: } catch (Exception e) {
095: throw new SpeedoGenerationException(
096: "Error during the generation of the file "
097: + fileName, e);
098: }
099: }
100:
101: // HELPER METHODS FOR THE GENERATION //
102: //-----------------------------------//
103:
104: public boolean isNull(Object o) {
105: return o == null;
106: }
107:
108: // PRIVATE METHODS //
109: //-----------------//
110:
111: /**
112: * This method initialises the Velocity context.
113: *
114: * @param jdoClass the jdoClass which represents the class to generate.
115: * @return a Velocity context.
116: */
117: public Map getContextAsMap(SpeedoClass jdoClass)
118: throws SpeedoException {
119: Map ctx = super .getContextAsMap(jdoClass);
120: String sc = jdoClass.getSuperClassName();
121: if (sc != null && sc.length() > 0) {
122: ctx.put("superclass", NamingRules.fieldsName(sc));
123: } else {
124: ctx.put("superclass", "AbstractStateImpl");
125: }
126: ctx.put("persistentsuperclass", sc == null ? "" : sc);
127:
128: ctx.put("personality", personality);
129:
130: try {
131: Object nfs = scp.nmf.getNamingManager(jdoClass)
132: .getNamingfields(jdoClass);
133: if (nfs != null) {
134: ctx.put("namingFields", nfs);
135: }
136: } catch (PException e) {
137: throw new SpeedoException(
138: "Impossible to manage the naming of the class '"
139: + jdoClass.getFQName() + "'", e);
140: }
141:
142: //Compute user caches
143: Map userCaches = computeUserCaches(jdoClass);
144: ctx.put("hasUserCache", Boolean.valueOf(!userCaches.isEmpty()));
145: ctx.put("userCacheNames", new ArrayList(userCaches.keySet()));
146: for (Iterator iter = userCaches.entrySet().iterator(); iter
147: .hasNext();) {
148: Map.Entry me = (Map.Entry) iter.next();
149: List fields = (List) me.getValue();
150: StringBuffer sb = new StringBuffer();
151: if (fields.size() > 1) {
152: sb.append("new UserCacheKey(new Object[] {");
153: }
154: String sep = "";
155: for (int j = 0; j < fields.size(); j++) {
156: sb.append(sep);
157: sep = ", ";
158: SpeedoField sf = (SpeedoField) fields.get(j);
159: Class clazz;
160: try {
161: clazz = Util.getClass(Type.getType(sf.type), null);
162: } catch (Exception e1) {
163: throw new SpeedoException("Field '" + sf.name
164: + "' cannot be used in an index: ", e1);
165: }
166: if (clazz.isPrimitive()) {
167: sb.append("new ").append(getJavaLangType(clazz));
168: sb.append("(").append(sf.name).append(")");
169: } else {
170: sb.append(sf.name);
171: }
172: }
173: if (fields.size() > 1) {
174: sb.append("})");
175: }
176: userCaches.put(me.getKey(), sb.toString());
177: }
178: ctx.put("userCachekeys", userCaches);
179: return ctx;
180: }
181:
182: public boolean isParentField(SpeedoClass sc, String fn) {
183: if (sc.getSuperClassName() == null)
184: return false;
185: SpeedoClass psc = sc.moPackage.xmlDescriptor.getSpeedoClass(sc
186: .getSuperClassName(), true);
187: return psc != null && psc.fields.get(fn) != null;
188: }
189: }
|