/**
* Speedo: an implementation of JDO compliant personality on top of JORM generic
* I/O sub-system.
* Copyright (C) 2001-2004 France Telecom R&D
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
*
* Contact: speedo@objectweb.org
*
* Authors: S.Chassande-Barrioz.
*
*/
package org.objectweb.speedo.generation.generator.fields;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.context.Context;
import org.objectweb.asm.Type;
import org.objectweb.jorm.api.PException;
import org.objectweb.speedo.api.SpeedoException;
import org.objectweb.speedo.api.SpeedoProperties;
import org.objectweb.speedo.generation.enhancer.common.Util;
import org.objectweb.speedo.generation.generator.api.SpeedoGenerationException;
import org.objectweb.speedo.generation.generator.lib.AbstractSpeedoGenerator;
import org.objectweb.speedo.generation.lib.NamingRules;
import org.objectweb.speedo.lib.Personality;
import org.objectweb.speedo.metadata.SpeedoClass;
import org.objectweb.speedo.metadata.SpeedoField;
import org.objectweb.util.monolog.wrapper.velocity.VelocityLogger;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* This class is used to generate accessor classes. This new file will
* manage status of persistent classes and values of persistent fields.
*
* @author S.Chassande-Barrioz
*/
public class FieldsGenerator extends AbstractSpeedoGenerator {
public final static String LOGGER_NAME
= SpeedoProperties.LOGGER_NAME + ".generation.generator.fields";
public final static String TEMPLATE_NAME = TEMPLATE_DIR + ".fields.Fields";
public FieldsGenerator(Personality p) {
super(p);
}
// IMPLEMENTATION OF THE GeneratorComponent INTERFACE //
//----------------------------------------------------//
public boolean init() throws SpeedoException {
logger = scp.loggerFactory.getLogger(LOGGER_NAME);
return !scp.getXmldescriptor().isEmpty();
}
// IMPLEMENTATION OF THE VelocityGenerator INTERFACE //
//---------------------------------------------------//
/**
* This method generates the a file since a SpeedoClass meta object.
* @param sClass is the speedo meta object.
* @param fileName name of the new file.
* @exception org.objectweb.speedo.generation.generator.api.SpeedoGenerationException If there is a problem during writing
* the new file.
*/
public void generate(SpeedoClass sClass, String fileName)
throws SpeedoException {
computeTemplate(TEMPLATE_NAME.replace('.', '/') + ".vm");
try {
Context ctx = getContext(sClass);
FileWriter fw = new FileWriter(fileName);
ve.setProperty(Velocity.RUNTIME_LOG_LOGSYSTEM,
new VelocityLogger(logger));
template.merge(ctx, fw);
fw.flush();
fw.close();
} catch (Exception e) {
throw new SpeedoGenerationException(
"Error during the generation of the file " + fileName, e);
}
}
// HELPER METHODS FOR THE GENERATION //
//-----------------------------------//
public boolean isNull(Object o) {
return o == null;
}
// PRIVATE METHODS //
//-----------------//
/**
* This method initialises the Velocity context.
*
* @param jdoClass the jdoClass which represents the class to generate.
* @return a Velocity context.
*/
public Map getContextAsMap(SpeedoClass jdoClass) throws SpeedoException {
Map ctx = super.getContextAsMap(jdoClass);
String sc = jdoClass.getSuperClassName();
if (sc != null && sc.length() > 0) {
ctx.put("superclass", NamingRules.fieldsName(sc));
} else {
ctx.put("superclass", "AbstractStateImpl");
}
ctx.put("persistentsuperclass", sc == null ? "" : sc);
ctx.put("personality", personality);
try {
Object nfs = scp.nmf.getNamingManager(jdoClass)
.getNamingfields(jdoClass);
if (nfs != null) {
ctx.put("namingFields", nfs);
}
} catch (PException e) {
throw new SpeedoException(
"Impossible to manage the naming of the class '"
+ jdoClass.getFQName() + "'", e);
}
//Compute user caches
Map userCaches = computeUserCaches(jdoClass);
ctx.put("hasUserCache", Boolean.valueOf(!userCaches.isEmpty()));
ctx.put("userCacheNames", new ArrayList(userCaches.keySet()));
for (Iterator iter = userCaches.entrySet().iterator(); iter.hasNext();) {
Map.Entry me = (Map.Entry) iter.next();
List fields = (List) me.getValue();
StringBuffer sb = new StringBuffer();
if (fields.size() > 1) {
sb.append("new UserCacheKey(new Object[] {");
}
String sep = "";
for (int j = 0; j < fields.size(); j++) {
sb.append(sep);
sep = ", ";
SpeedoField sf = (SpeedoField) fields.get(j);
Class clazz;
try {
clazz = Util.getClass(Type.getType(sf.type), null);
} catch (Exception e1) {
throw new SpeedoException("Field '" + sf.name
+ "' cannot be used in an index: ", e1);
}
if (clazz.isPrimitive()) {
sb.append("new ").append(getJavaLangType(clazz));
sb.append("(").append(sf.name).append(")");
} else {
sb.append(sf.name);
}
}
if (fields.size() > 1) {
sb.append("})");
}
userCaches.put(me.getKey(), sb.toString());
}
ctx.put("userCachekeys", userCaches);
return ctx;
}
public boolean isParentField(SpeedoClass sc, String fn) {
if (sc.getSuperClassName() == null)
return false;
SpeedoClass psc = sc.moPackage.xmlDescriptor.getSpeedoClass(
sc.getSuperClassName(), true);
return psc != null && psc.fields.get(fn) != null;
}
}