incubator-bval-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From carlosv...@apache.org
Subject svn commit: r956225 - in /incubator/bval/sandbox/jsr303-impl-bench/src/main/java/org/apache/bval/bench: Generator.java metatree/MetaJavaBean.java
Date Sat, 19 Jun 2010 13:43:02 GMT
Author: carlosvara
Date: Sat Jun 19 13:43:02 2010
New Revision: 956225

URL: http://svn.apache.org/viewvc?rev=956225&view=rev
Log:
Cleaned and documented Generator code

Modified:
    incubator/bval/sandbox/jsr303-impl-bench/src/main/java/org/apache/bval/bench/Generator.java
    incubator/bval/sandbox/jsr303-impl-bench/src/main/java/org/apache/bval/bench/metatree/MetaJavaBean.java

Modified: incubator/bval/sandbox/jsr303-impl-bench/src/main/java/org/apache/bval/bench/Generator.java
URL: http://svn.apache.org/viewvc/incubator/bval/sandbox/jsr303-impl-bench/src/main/java/org/apache/bval/bench/Generator.java?rev=956225&r1=956224&r2=956225&view=diff
==============================================================================
--- incubator/bval/sandbox/jsr303-impl-bench/src/main/java/org/apache/bval/bench/Generator.java
(original)
+++ incubator/bval/sandbox/jsr303-impl-bench/src/main/java/org/apache/bval/bench/Generator.java
Sat Jun 19 13:43:02 2010
@@ -25,9 +25,10 @@ import java.util.ArrayList;
 import java.util.List;
 import org.apache.bval.bench.jsr303.Jsr303Annotator;
 import org.apache.bval.bench.metatree.AbstractMetaField;
-import org.apache.bval.bench.metatree.JavaBeanBasicField;
+import org.apache.bval.bench.metatree.AnnotatorVisitor;
 import org.apache.bval.bench.metatree.JavaBeanRefField;
 import org.apache.bval.bench.metatree.MetaJavaBean;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Lists;
 import com.sun.codemodel.JBlock;
 import com.sun.codemodel.JClass;
@@ -42,107 +43,194 @@ import com.sun.codemodel.JVar;
 
 
 /**
- * Temporal entry point for bean graph generation.
+ * Entry point for bean graph generation.
+ * <p>
+ * NOTE: Class is not thread-safe.
  * 
  * @author Carlos Vara
  */
 public class Generator {
 
-    public static void generateBeans() throws IOException, JClassAlreadyExistsException {
+    // The code model root
+    private final JCodeModel cm;
 
-        // Code model root
-        JCodeModel cm = new JCodeModel();
+    // The list of generated rich beans
+    private final List<MetaJavaBean> beans;
 
-        // And the lists of beans
-        List<MetaJavaBean> beans = Lists.newArrayListWithExpectedSize(Config.CFG.getNumBeans());
-        List<MetaJavaBean> baseBeans = Lists.newArrayList();
+    // The list of root simple beans used to inherit from
+    private final List<MetaJavaBean> baseBeans;
 
+    // The annotators used to spice the bean graph
+    private final List<? extends AnnotatorVisitor> annotators;
+
+
+    public Generator() {
+        this.cm = new JCodeModel();
+        this.beans = Lists.newArrayListWithExpectedSize(Config.CFG.getNumBeans());
+        this.baseBeans = Lists.newArrayListWithExpectedSize(Config.CFG.getNumBaseBeans());
+        this.annotators = ImmutableList.of(new Jsr303Annotator(cm));
+    }
+
+
+    /**
+     * Generates a bean graph according to the configuration in
+     * {@link Config#CFG}.
+     */
+    public void generateBeanGraph() {
 
         // PHASE 1: Basic beans with basic type fields
+        generateBasicBeans();
+
+        // PHASE 2: Enrich beans with references to other beans
+        enrichBasicBeans();
+
+        // PHASE 3: Inheritance
+        createInheritanceGraph();
+
+        // PHASE 4: Annotate the beans
+        annotateBeanGraph();
+
+        // PHASE 5: Generate population code
+        generatePopulationCode();
+
+        // PHASE 6: Output the bean graph .java files
+        outputJavaFiles();
+    }
+
+
+    /**
+     * Starts from an empty code model and creates the beans in their initial
+     * state (only basic attributes).
+     * <p>
+     * POST: The {@link #beans} list is filled with simple beans.
+     */
+    private void generateBasicBeans() {
         for (int i = 0; i < Config.CFG.getNumBeans(); ++i) {
             MetaJavaBean mjb = new MetaJavaBean(cm, Config.CFG.getBeansPackageName() + ".Bean"
+ i, Config.CFG.rndNumFields());
             beans.add(mjb);
         }
-        for (int i = 0; i < Config.CFG.getNumBaseBeans(); ++i) {
-            MetaJavaBean mjb = new MetaJavaBean(cm, Config.CFG.getBeansPackageName() + ".BaseBean"
+ i, Config.CFG.rndNumFields());
-            baseBeans.add(mjb);
-        }
+    }
 
-        // PHASE 2: Enrich beans with references to other beans
+    /**
+     * Adds fields referencing other beans to the list of beans. The target of
+     * these references are also beans in the list.
+     * <p>
+     * POST: The beans in the {@link #beans} list get reference fields.
+     */
+    private void enrichBasicBeans() {
         for (MetaJavaBean mjb : beans) {
             mjb.interrelate(beans);
         }
+    }
 
-        // PHASE 3: Inheritance
+    /**
+     * Creates a list of base beans used as root of the inheritance tree, and
+     * sets them as superclass of some of the beans in {@link #beans}.
+     * <p>
+     * POST: The {@link #baseBeans} list is filled with simple beans and some
+     * beans in {@link #beans} mark them as their superclass.
+     */
+    private void createInheritanceGraph() {
+        for (int i = 0; i < Config.CFG.getNumBaseBeans(); ++i) {
+            MetaJavaBean mjb = new MetaJavaBean(cm, Config.CFG.getBeansPackageName() + ".BaseBean"
+ i, Config.CFG.rndNumFields());
+            baseBeans.add(mjb);
+        }
         for (MetaJavaBean mjb : beans) {
             if (Config.CFG.shouldInherit()) {
                 mjb.setSuperClass(Config.CFG.getRandom(baseBeans));
             }
         }
+    }
 
-        // PHASE 4: Annotate the beans with the JSR-303 annotator (other annotators can be
added)
-        Jsr303Annotator annotator = new Jsr303Annotator(cm);
-        for (MetaJavaBean mjb : beans) {
-            mjb.accept(annotator);
-        }
-        for (MetaJavaBean bmjb : baseBeans) {
-            bmjb.accept(annotator);
+    /**
+     * POST: The bean graph pending from the {@link #beans} and
+     * {@link #baseBeans} gets annotated with the available annotators in
+     * {@link #annotators}.
+     */
+    private void annotateBeanGraph() {
+        for (AnnotatorVisitor annotator : annotators) {
+            for (MetaJavaBean mjb : beans) {
+                mjb.accept(annotator);
+            }
+            for (MetaJavaBean bmjb : baseBeans) {
+                bmjb.accept(annotator);
+            }
         }
+    }
 
-        // PHASE 5: Generate population code
-        List<MetaJavaBean> allBeans = Lists.newArrayList(beans);
-        allBeans.addAll(baseBeans);
-        generateHolderClass(cm, allBeans);
 
+    /**
+     * Generates a Holder class that will hold an {@link ArrayList} with all the
+     * first level beans in the graph (contents of {@link #beans}) on it.
+     */
+    private void generatePopulationCode() {
+        try {
+            // Generate the holder class
+            JDefinedClass holderClass = cm._class(Config.CFG.getBasePackageName() + ".Holder");
+            JClass alObject = (JClass) cm._ref(ArrayList.class);
+            alObject = alObject.narrow(Object.class);
+            JFieldVar beansField = holderClass.field(JMod.PUBLIC, alObject, "beans", JExpr._new(alObject));
+            JMethod defConstructor = holderClass.constructor(JMod.PUBLIC);
+            JBlock body = defConstructor.body();
+
+            // Init the beans and add them to the array
+            for (MetaJavaBean mjb : beans) {
+                mjb.generateStaticInitCode();
+                JVar beanDecl = generateBeanNonStaticInitCode(mjb, body, 0);
+                body.add(beansField.invoke("add").arg(beanDecl));
+            }
 
-        // Create the .java files
-        File file = new File(Config.CFG.getOutputDir());
-        file.mkdirs();
-        cm.build(file, (PrintStream)null);
+            // Init the base beans but don't add them to the array
+            for (MetaJavaBean bmjb : baseBeans) {
+                bmjb.generateStaticInitCode();
+            }
 
+        } catch (JClassAlreadyExistsException e) {
+            throw new RuntimeException("Error generating the holder class.", e);
+        }
     }
 
 
-    // The tests will have code that loads the class and instantiates it
-    public static void generateHolderClass(JCodeModel cm, List<MetaJavaBean> beans)
throws JClassAlreadyExistsException {
-
-        JDefinedClass holderClass = cm._class(Config.CFG.getBasePackageName() + ".Holder");
-        JClass alObject = (JClass) cm._ref(ArrayList.class);
-        alObject = alObject.narrow(Object.class);
-        JFieldVar beansField = holderClass.field(JMod.PUBLIC, alObject, "beans", JExpr._new(alObject));
-        JMethod defConstructor = holderClass.constructor(JMod.PUBLIC);
-        JBlock body = defConstructor.body();
-
-        for (MetaJavaBean mjb : beans) {
-            JVar beanDecl = generateBeanInitCode(mjb, body, 0);
-            body.add(beansField.invoke("add").arg(beanDecl));
+    /**
+     * Outputs the meta-contents of {@link #cm} to .java files generated on
+     * {@link Config.CFG#getOutputDir()}.
+     */
+    private void outputJavaFiles() {
+        try {
+            File file = new File(Config.CFG.getOutputDir());
+            file.mkdirs();
+            cm.build(file, (PrintStream) null);
+        } catch (IOException e) {
+            throw new RuntimeException("Error generating the java files", e);
         }
     }
 
-    public static JVar generateBeanInitCode(MetaJavaBean mjb, JBlock body, int level) {
+
+    /**
+     * Recursive method that handles the creation of reference beans at
+     * different depth levels.
+     * 
+     * @param mjb
+     *            The target bean to create an instance of.
+     * @param body
+     *            The current block of code.
+     * @param level
+     *            The current depth level.
+     * @return A generated variable referencing the created bean.
+     */
+    private JVar generateBeanNonStaticInitCode(MetaJavaBean mjb, JBlock body, int level)
{
 
         JVar beanDecl = body.decl(mjb.getGeneratedClass(), "lvl" + level + mjb.getName()
+ "_" + Config.CFG.nextUniqueNum());
         body.assign(beanDecl, JExpr._new(mjb.getGeneratedClass()));
 
         for (AbstractMetaField amf : mjb.getFields()) {
-            if ((amf instanceof JavaBeanBasicField) && level == 0) {
-
-                JavaBeanBasicField jbbf = (JavaBeanBasicField) amf;
-                Object value;
-                if (Config.CFG.shouldAssignValidValue()) {
-                    value = Config.CFG.getRandom(jbbf.getValidValues());
-                } else {
-                    value = Config.CFG.getRandom(jbbf.getInvalidValues());
-                }
-                jbbf.generateAssignCode(value);
-
-            } else if (amf instanceof JavaBeanRefField) {
+            if (amf instanceof JavaBeanRefField) {
 
                 JavaBeanRefField jbrf = (JavaBeanRefField) amf;
 
                 // Should a nested bean be created?
                 if (Config.CFG.shouldAddNestedBean(level)) {
-                    JVar nestedBeanDecl = generateBeanInitCode(jbrf.getRefBean(), body, level
+ 1);
+                    JVar nestedBeanDecl = generateBeanNonStaticInitCode(jbrf.getRefBean(),
body, level + 1);
                     jbrf.generateAssignCode(body, beanDecl, nestedBeanDecl);
                 }
             }
@@ -153,10 +241,17 @@ public class Generator {
     }
 
 
-    public static void main(String[] args) throws IOException, JClassAlreadyExistsException
{
+    /**
+     * Creates a new {@link Generator} object and calls
+     * {@link #generateBeanGraph()} on it.
+     * 
+     * @param args
+     *            Unused.
+     */
+    public static void main(String[] args) {
         System.out.println("Starting bean graph generation...");
         Config.CFG.printProperties();
-        generateBeans();
+        new Generator().generateBeanGraph();
         System.out.println("Generated " + Config.CFG.getNumBeans() + " beans.");
     }
 

Modified: incubator/bval/sandbox/jsr303-impl-bench/src/main/java/org/apache/bval/bench/metatree/MetaJavaBean.java
URL: http://svn.apache.org/viewvc/incubator/bval/sandbox/jsr303-impl-bench/src/main/java/org/apache/bval/bench/metatree/MetaJavaBean.java?rev=956225&r1=956224&r2=956225&view=diff
==============================================================================
--- incubator/bval/sandbox/jsr303-impl-bench/src/main/java/org/apache/bval/bench/metatree/MetaJavaBean.java
(original)
+++ incubator/bval/sandbox/jsr303-impl-bench/src/main/java/org/apache/bval/bench/metatree/MetaJavaBean.java
Sat Jun 19 13:43:02 2010
@@ -125,6 +125,28 @@ public class MetaJavaBean extends Abstra
             return gsAnnot;
         }
     }
+
+    /**
+     * Generate code to initialize the basic fields.
+     * <p>
+     * NOTE: The fields could be initialized (or overriden) externally, giving
+     * it more entropy as different instances of the bean could choose different
+     * values for each field.
+     */
+    public void generateStaticInitCode() {
+        for ( AbstractMetaField field : fields.values() ) {
+            if ( field instanceof JavaBeanBasicField ) {
+                JavaBeanBasicField jbbf = (JavaBeanBasicField) field;
+                Object value;
+                if (Config.CFG.shouldAssignValidValue()) {
+                    value = Config.CFG.getRandom(jbbf.getValidValues());
+                } else {
+                    value = Config.CFG.getRandom(jbbf.getInvalidValues());
+                }
+                jbbf.generateAssignCode(value);
+            }
+        }
+    }
     
     @Override
     public void accept(AnnotatorVisitor annotator) {



Mime
View raw message