Title: [755] trunk/core/src/behaviour/org/jbehave/core/story: JBEHAVE-94: Added velocity-based code generator.
Revision
755
Author
mauro
Date
2007-07-11 17:10:48 -0500 (Wed, 11 Jul 2007)

Log Message

JBEHAVE-94:  Added velocity-based code generator.

Modified Paths

Added Paths

Diff

Modified: trunk/core/src/behaviour/org/jbehave/core/story/AllBehaviours.java (754 => 755)

--- trunk/core/src/behaviour/org/jbehave/core/story/AllBehaviours.java	2007-07-11 20:07:29 UTC (rev 754)
+++ trunk/core/src/behaviour/org/jbehave/core/story/AllBehaviours.java	2007-07-11 22:10:48 UTC (rev 755)
@@ -9,6 +9,7 @@
 
 import org.jbehave.core.behaviour.Behaviours;
 import org.jbehave.core.story.codegen.parser.TextStoryParserBehaviour;
+import org.jbehave.core.story.codegen.velocity.VelocityCodeGeneratorBehaviour;
 import org.jbehave.core.story.domain.AbstractStepBehaviour;
 import org.jbehave.core.story.domain.GivenScenarioBehaviour;
 import org.jbehave.core.story.domain.GivenStepBehaviour;
@@ -41,6 +42,7 @@
                 AbstractStepBehaviour.class,
                 PlainTextScenarioListenerBehaviour.class,
 				PlainTextRendererBehaviour.class,
+				VelocityCodeGeneratorBehaviour.class
         };
     }
 }

Added: trunk/core/src/behaviour/org/jbehave/core/story/codegen/velocity/VelocityCodeGeneratorBehaviour.java (0 => 755)

--- trunk/core/src/behaviour/org/jbehave/core/story/codegen/velocity/VelocityCodeGeneratorBehaviour.java	                        (rev 0)
+++ trunk/core/src/behaviour/org/jbehave/core/story/codegen/velocity/VelocityCodeGeneratorBehaviour.java	2007-07-11 22:10:48 UTC (rev 755)
@@ -0,0 +1,60 @@
+package org.jbehave.core.story.codegen.velocity;
+
+import java.io.File;
+
+import org.jbehave.core.mock.UsingMatchers;
+import org.jbehave.core.story.codegen.domain.ScenarioDetails;
+import org.jbehave.core.story.codegen.domain.StoryDetails;
+
+/**
+ * 
+ * @author Mauro Talevi
+ */
+public class VelocityCodeGeneratorBehaviour extends UsingMatchers {
+
+    public void shouldGenerateCodeForStoryWithFullScenario() throws Exception {
+        // given
+        StoryDetails storyDetails = new StoryDetails("Joe drinks vodka", "", "", "");
+        ScenarioDetails scenario1 = new ScenarioDetails();
+        scenario1.name = "Happy path";
+        scenario1.context.givens.add("a bar downtown");
+        scenario1.context.givens.add("a thirsty Joe");
+        scenario1.event.name = "Joe asks for a Smirnov";
+        scenario1.outcome.outcomes.add("bartender serves Joe");
+        scenario1.outcome.outcomes.add("Joe is happy");
+        storyDetails.addScenario(scenario1);
+        ScenarioDetails scenario2 = new ScenarioDetails();
+        scenario2.name = "Unhappy path";
+        scenario2.context.givens.add("a pub uptown");
+        scenario2.context.givens.add("an equally thirsty Joe");
+        scenario2.event.name = "Joe asks for an Absolut";
+        scenario2.outcome.outcomes.add("bartender tells Joe it is sold out");
+        scenario2.outcome.outcomes.add("Joe is unhappy");
+        storyDetails.addScenario(scenario2);
+
+        // when
+        String generatedSourceDir = "delete_me/generated-src";
+        VelocityCodeGenerator generator = new VelocityCodeGenerator(generatedSourceDir,
+                "generated.stories");
+        generator.generateStory(storyDetails);
+
+        // then
+        String[] generatedPaths = new String[]{
+           "events/JoeAsksForASmirnov.java",      
+           "events/JoeAsksForAnAbsolut.java",      
+           "givens/ABarDowntown.java",      
+           "givens/APubUptown.java",      
+           "givens/AThirstyJoe.java",      
+           "givens/AnEquallyThirstyJoe.java",      
+           "outcomes/BartenderServesJoe.java",      
+           "outcomes/BartenderTellsJoeItIsSoldOut.java",      
+           "outcomes/JoeIsHappy.java",      
+           "outcomes/JoeIsUnhappy.java"
+        };
+        
+        for ( int i = 0; i < generatedPaths.length; i++ ){
+            ensureThat(new File(generatedSourceDir+File.separator+generatedPaths[i]).exists() );           
+        }
+    }
+
+}

Added: trunk/core/src/java/org/jbehave/core/story/codegen/velocity/VelocityCodeGenerator.java (0 => 755)

--- trunk/core/src/java/org/jbehave/core/story/codegen/velocity/VelocityCodeGenerator.java	                        (rev 0)
+++ trunk/core/src/java/org/jbehave/core/story/codegen/velocity/VelocityCodeGenerator.java	2007-07-11 22:10:48 UTC (rev 755)
@@ -0,0 +1,124 @@
+package org.jbehave.core.story.codegen.velocity;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.Writer;
+import java.text.MessageFormat;
+import java.util.Iterator;
+import java.util.Properties;
+
+import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.VelocityEngine;
+import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
+import org.jbehave.core.story.codegen.CodeGenerator;
+import org.jbehave.core.story.codegen.domain.ScenarioDetails;
+import org.jbehave.core.story.codegen.domain.StoryDetails;
+import org.jbehave.core.util.CamelCaseConverter;
+
+/**
+ * Velocity-based code generator
+ * 
+ * @author Mauro Talevi
+ */
+public class VelocityCodeGenerator implements CodeGenerator {
+
+    private static final String SOURCE_PATH = "{0}/{1}s/{2}.java";
+    private static final String TEMPLATE_PATH = "org/jbehave/core/story/codegen/velocity/templates/{0}.template";
+    private static final String PACKAGE_NAME = "{0}.{1}s";
+
+    private String rootSourceDirectory;
+    private String rootPackageName;
+
+    /** The velocity engine */
+    private VelocityEngine engine;
+
+    /**
+     * Creates a VelocityCodeGenerator
+     * 
+     * @param rootSourceDirectory the root source directory of the generated
+     *            story code
+     * @param rootPackageName the root package name of the story
+     */
+    public VelocityCodeGenerator(String rootSourceDirectory, String rootPackageName) {
+        this.rootSourceDirectory = rootSourceDirectory;
+        this.rootPackageName = rootPackageName;
+        this.engine = new VelocityEngine();
+        initialiseEngine(engine);
+    }
+
+    public void generateStory(StoryDetails storyDetails) {
+        for (Iterator i = storyDetails.scenarios.iterator(); i.hasNext();) {
+            ScenarioDetails scenario = (ScenarioDetails) i.next();
+            generateSource(scenario.event.name, "event");
+            for (Iterator j = scenario.context.givens.iterator(); j.hasNext();) {
+                generateSource((String) j.next(), "given");
+            }
+            for (Iterator j = scenario.outcome.outcomes.iterator(); j.hasNext();) {
+                generateSource((String) j.next(), "outcome");
+            }
+        }
+    }
+
+    private String toCamelCase(String name) {
+        return new CamelCaseConverter(name).toCamelCase();
+    }
+
+    private void generateSource(String name, String type) {
+        String className = toCamelCase(name);
+        String sourcePath = MessageFormat.format(SOURCE_PATH, new Object[] { rootSourceDirectory, type, className });
+        String templatePath = MessageFormat.format(TEMPLATE_PATH, new Object[] { type });
+        String packageName = MessageFormat.format(PACKAGE_NAME, new Object[] { rootPackageName, type });
+        generateSource(sourcePath, templatePath, className, packageName);
+    }
+
+    private void generateSource(String sourcePath, String templatePath, String className, String packageName) {
+        try {
+            VelocityContext context = new VelocityContext();
+            context.put("className", className);
+            context.put("packageName", packageName);
+            File file = new File(sourcePath);
+            file.getParentFile().mkdirs();
+            Writer writer = new FileWriter(file);
+            process(templatePath, context, writer);
+            writer.close();
+        } catch (IOException e) {
+            throw new RuntimeException("Failed to generate source", e);
+        }
+    }
+
+    /**
+     * Initialises VelocityEngine to retrieve resources from classpath
+     * 
+     * @param engine the VelocityEngine
+     */
+    private void initialiseEngine(VelocityEngine engine) {
+        try {
+            Properties properties = new Properties();
+            properties.setProperty(VelocityEngine.RESOURCE_LOADER, "classpath");
+            properties.setProperty("classpath." + VelocityEngine.RESOURCE_LOADER + ".class",
+                    ClasspathResourceLoader.class.getName());
+            engine.init(properties);
+        } catch (Exception e) {
+            throw new RuntimeException("Failed to initialise VelocityEngine " + engine, e);
+        }
+    }
+
+    /**
+     * Processes a template with context
+     * 
+     * @param resource the template resource
+     * @param context the VelocityContext
+     * @param writer the Writer to merge into
+     */
+    private void process(String resource, VelocityContext context, Writer writer) {
+        try {
+            Template template = engine.getTemplate(resource);
+            template.merge(context, writer);
+        } catch (Exception e) {
+            throw new RuntimeException("Failed to process template " + resource + " with context " + context, e);
+        }
+    }
+
+}

Added: trunk/core/src/java/org/jbehave/core/story/codegen/velocity/templates/event.template (0 => 755)

--- trunk/core/src/java/org/jbehave/core/story/codegen/velocity/templates/event.template	                        (rev 0)
+++ trunk/core/src/java/org/jbehave/core/story/codegen/velocity/templates/event.template	2007-07-11 22:10:48 UTC (rev 755)
@@ -0,0 +1,12 @@
+package ${packageName};
+
+import org.jbehave.core.minimock.story.domain.EventUsingMiniMock;
+import org.jbehave.core.story.domain.World;
+
+public class ${className} extends EventUsingMiniMock {
+
+    public void occurIn(World world) {
+		// TODO     
+    }
+
+}

Added: trunk/core/src/java/org/jbehave/core/story/codegen/velocity/templates/given.template (0 => 755)

--- trunk/core/src/java/org/jbehave/core/story/codegen/velocity/templates/given.template	                        (rev 0)
+++ trunk/core/src/java/org/jbehave/core/story/codegen/velocity/templates/given.template	2007-07-11 22:10:48 UTC (rev 755)
@@ -0,0 +1,12 @@
+package ${packageName};
+
+import org.jbehave.core.minimock.story.domain.GivenUsingMiniMock;
+import org.jbehave.core.story.domain.World;
+
+public class ${className} extends GivenUsingMiniMock {
+
+    public void setUp(World world) {
+    	// TODO
+    }
+
+}

Added: trunk/core/src/java/org/jbehave/core/story/codegen/velocity/templates/outcome.template (0 => 755)

--- trunk/core/src/java/org/jbehave/core/story/codegen/velocity/templates/outcome.template	                        (rev 0)
+++ trunk/core/src/java/org/jbehave/core/story/codegen/velocity/templates/outcome.template	2007-07-11 22:10:48 UTC (rev 755)
@@ -0,0 +1,12 @@
+package ${packageName};
+
+import org.jbehave.core.minimock.story.domain.OutcomeUsingMiniMock;
+import org.jbehave.core.story.domain.World;
+
+public class ${className} extends OutcomeUsingMiniMock {
+
+    public void verify(World world) {
+    	// TODO
+    }
+
+}


To unsubscribe from this list please visit:

http://xircles.codehaus.org/manage_email

Reply via email to