/* * JaninoGenerator.java * Copyright (c) 2005 by University of Hamburg. All Rights Reserved. * Departament of Informatics. * Distributed Systems and Information Systems. * * Created by walczak on Jun 29, 2006. * Last revision $Revision: 6926 $ by: * $Author: braubach $ on $Date: 2008-09-28 22:16:58 +0200 (So, 28 Sep 2008) $. */ package nuggets; import java.io.StringReader; import java.util.Map; import nuggets.delegate.AGeneratedDelegate; import org.codehaus.janino.ClassBodyEvaluator; import org.codehaus.janino.Scanner; /** JaninoGenerator * @author walczak * @since Jun 29, 2006 */ public class JaninoGenerator implements IDelegateGenerator { static final String ICRUNCHER_INTERFACE = ICruncher.class.getName(); static final String IASSEMBLER_INTERFACE = IAssembler.class.getName(); /** * Constructor for JaninoGenerator. */ public JaninoGenerator() { System.out.println("Using JaninoGenerator for generating delegates."); } /** * @param clazz * @param props * @return a compiled delegate * @see nuggets.IDelegateGenerator#generateDelegate(java.lang.Class, java.util.Map) */ public IDelegate generateDelegate(Class clazz, Map props, ClassLoader classloader) { String classbody = createDelegateClassBody(clazz, props); // System.out.println("BeanAnalyzer: generating delegate for class "+clazz.getName() +"\n"+classbody); // System.out.println("cl: "+Thread.currentThread().getContextClassLoader()); try { return (IDelegate)ClassBodyEvaluator.createFastClassBodyEvaluator(new Scanner( "<generated>", new StringReader(classbody)), "persistence.Delegate" + clazz.getName(), AGeneratedDelegate.class, new Class[]{IDelegate.class}, classloader); } catch(Exception e) { throw new PersistenceException(e); } } /** * @param clazz * @return the class body definition for janino compiler */ private static String createDelegateClassBody(Class clazz, Map props) { try { String clazzname = clazz.getName(); String classbody = ""; // calculate perfect hash int size = props.size(); String[] keys = (String[])props.keySet().toArray(new String[size]); String persist_body = ""; String reference_body = ""; int ref_counter = 0; for(int k = 0; k < size; k++) { BeanProperty bp = (BeanProperty)props.get(keys[k]); Class getter_type = bp.getGetterType(); IDelegate getter_del = PersistenceHelper.getDefaultDelegate(getter_type); if(getter_del.isSimple()) { if(getter_type.isPrimitive()) { persist_body += " c.put(\"" + bp.getName() + "\"," + getter_del.getMarshallString("x." + bp.getGetterName() + "()") + ");\n"; } else { persist_body += " {" + getClassName(getter_type) + " t = x." + bp.getGetterName() + "(); " + "if (t!=null) c.put(\"" + bp.getName() + "\"," + getter_del.getMarshallString("t") + ");}\n"; } } else { // all primitive classes can be represented as a string ref_counter++; reference_body += " int id" + ref_counter + " = c.declare(x." + bp.getGetterName() + "()"+", classloader"+");\n"; persist_body += " if (id" + ref_counter + "!=0) c.put(\"" + bp.getName() + "\", id" + ref_counter + ");\n"; } } // ---------------------- persist ------------------------------------- classbody += "\npublic void persist(Object o, " + ICRUNCHER_INTERFACE + " c"+", ClassLoader classloader"+") throws Exception {\n" + " " + clazzname + " x=(" + clazzname + ")o;\n" + reference_body + " c.startConcept(o);\n" + persist_body + "}\n"; //----------------------- put --------------------------- classbody += "\npublic void set(Object o, String attribute, Object value) throws Exception {\n " + clazzname + " x=(" + clazzname + ")o;\n"; if(size > 1) { // choose the hash method classbody += " switch(hash(attribute)) {\n"; PerfectHash ph = new PerfectHash(keys); keys = ph.getKeys(); // write the switch case construct for(int k = 0; k < keys.length; k++) { String name = keys[k]; if(name != null) { BeanProperty bp = (BeanProperty)props.get(name); classbody += " case " + k + ":"; Class param_clazz = bp.getSetterType(); IDelegate del = PersistenceHelper.getDefaultDelegate(param_clazz); classbody += " x." + bp.getSetterName() + "(" + del.getUnmarshallString(getClassName(param_clazz), "value") + "); return; \n"; } } classbody += "}}\n"; // perfect hash method classbody += ph.getHashMethodString(); } else if(size == 1) { // simple method BeanProperty bp = (BeanProperty)props.get(keys[0]); Class param_clazz = bp.getSetterType(); IDelegate del = PersistenceHelper.getDefaultDelegate(param_clazz); classbody += " x." + bp.getSetterName() + "(" + del.getUnmarshallString(getClassName(param_clazz), "value") + ");\n}\n"; } else { classbody += "}\n"; } // ----------------------- getInstance ------------------------------- classbody += "\npublic Object getInstance(Class clazz, " + IASSEMBLER_INTERFACE + " asm) throws Exception {\n" + " return new " + clazzname + "();\n}\n"; return classbody; } catch(Exception e) { e.printStackTrace(); throw new RuntimeException(e.getMessage()); } } /** Respects arrays * @param ret * @return the name of this class */ private static String getClassName(Class ret) { if(ret.isArray()) return getClassName(ret.getComponentType()) + "[]"; return ret.getName(); } }