You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by aa...@apache.org on 2007/12/09 22:29:17 UTC

svn commit: r602732 - in /cayenne/main/trunk/framework: cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/ cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/tools/ cayenne-jdk1.5-unpublished/src/main/resources/dotemplates/v1_2/ ...

Author: aadamchik
Date: Sun Dec  9 13:29:16 2007
New Revision: 602732

URL: http://svn.apache.org/viewvc?rev=602732&view=rev
Log:
CAY-926 Refactoring class generator classes
(finally an execution flow that supports generic "artifacts" as a base for code generation and hence can support embeddables)

Added:
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/Artifact.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/ArtifactGenerationMode.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/ArtifactsGenerationMode.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/ClientEntityArtifact.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/EmbeddableArtifact.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/EntityArtifact.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/TemplateType.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/resources/dotemplates/v1_2/embeddable-singleclass.vm
Removed:
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/ClassGeneratorMode.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/GenerationMetadata.java
Modified:
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/ClassGenerationAction.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/ClassGenerationAction1_1.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/ClientClassGenerationAction.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/EntityUtils.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/tools/CayenneGeneratorTask.java
    cayenne/main/trunk/framework/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/codegen/CustomModeController.java
    cayenne/main/trunk/framework/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/codegen/GeneratorController.java
    cayenne/main/trunk/framework/maven-cayenne-plugin/src/main/java/org/apache/cayenne/tools/CayenneGeneratorMojo.java

Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/Artifact.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/Artifact.java?rev=602732&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/Artifact.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/Artifact.java Sun Dec  9 13:29:16 2007
@@ -0,0 +1,65 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.gen;
+
+import org.apache.velocity.VelocityContext;
+
+/**
+ * Represents a class generation "artifact" which is a facade to a metadata object used
+ * for a given single generation template run.
+ * 
+ * @since 3.0
+ * @author Andrus Adamchik
+ */
+public interface Artifact {
+
+    public static String STRING_UTILS_KEY = "stringUtils";
+    public static String IMPORT_UTILS_KEY = "importUtils";
+
+    /**
+     * Root object, such as ObjEntity or Embeddable, etc.
+     */
+    public static String OBJECT_KEY = "object";
+    public static String SUPER_CLASS_KEY = "superClassName";
+    public static String SUPER_PACKAGE_KEY = "superPackageName";
+    public static String SUB_CLASS_KEY = "subClassName";
+    public static String SUB_PACKAGE_KEY = "subPackageName";
+    public static String BASE_CLASS_KEY = "baseClassName";
+    public static String BASE_PACKAGE_KEY = "basePackageName";
+
+    TemplateType[] getTemplateTypes(ArtifactGenerationMode mode);
+
+    String getQualifiedBaseClassName();
+
+    String getQualifiedClassName();
+
+    /**
+     * Returns a mapping metadata object for this artifact.
+     */
+    Object getObject();
+
+    /**
+     * A callback method that allows each artifact to add its own special keys to the
+     * context. Invoked from
+     * {@link ClassGenerationAction#resetContextForArtifactTemplate(Artifact, TemplateType)},
+     * after the context is initialized by code generator, so this method can use
+     * predefined keys from the context.
+     */
+    void postInitContext(VelocityContext context);
+}

Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/ArtifactGenerationMode.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/ArtifactGenerationMode.java?rev=602732&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/ArtifactGenerationMode.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/ArtifactGenerationMode.java Sun Dec  9 13:29:16 2007
@@ -0,0 +1,29 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.gen;
+
+/**
+ * Code generator execution mode for a single artifact.
+ * 
+ * @since 3.0
+ * @author Andrus Adamchik
+ */
+public enum ArtifactGenerationMode {
+    SINGLE_CLASS, GENERATION_GAP
+}

Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/ArtifactsGenerationMode.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/ArtifactsGenerationMode.java?rev=602732&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/ArtifactsGenerationMode.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/ArtifactsGenerationMode.java Sun Dec  9 13:29:16 2007
@@ -0,0 +1,30 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.gen;
+
+/**
+ * Code generator execution mode for a collection of artifacts.
+ * 
+ * @since 3.0
+ * @author Andrus Adamchik
+ */
+public enum ArtifactsGenerationMode {
+
+    datamap, entity
+}

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/ClassGenerationAction.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/ClassGenerationAction.java?rev=602732&r1=602731&r2=602732&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/ClassGenerationAction.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/ClassGenerationAction.java Sun Dec  9 13:29:16 2007
@@ -24,14 +24,13 @@
 import java.io.Writer;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Properties;
 
-import org.apache.cayenne.CayenneDataObject;
 import org.apache.cayenne.CayenneRuntimeException;
 import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.Embeddable;
 import org.apache.cayenne.map.ObjEntity;
 import org.apache.cayenne.tools.NamePatternMatcher;
 import org.apache.commons.logging.Log;
@@ -51,73 +50,83 @@
     public static final String SUBCLASS_TEMPLATE = "dotemplates/v1_2/subclass.vm";
     public static final String SUPERCLASS_TEMPLATE = "dotemplates/v1_2/superclass.vm";
 
+    public static final String EMBEDDABLE_SINGLE_CLASS_TEMPLATE = "dotemplates/v1_2/embeddable-singleclass.vm";
+    public static final String EMBEDDABLE_SUBCLASS_TEMPLATE = "dotemplates/v1_2/embeddable-subclass.vm";
+    public static final String EMBEDDABLE_SUPERCLASS_TEMPLATE = "dotemplates/v1_2/embeddable-superclass.vm";
+
     public static final String SUPERCLASS_PREFIX = "_";
     private static final String WILDCARD = "*";
 
-    protected Collection<ObjEntity> entities;
+    protected Collection<Artifact> artifacts;
+
     protected String superPkg;
     protected DataMap dataMap;
-    protected ClassGeneratorMode mode;
-    protected VelocityContext context;
-    protected Map<String, Template> templateCache;
+
+    protected ArtifactsGenerationMode artifactsGenerationMode;
+    protected boolean makePairs;
 
     protected Log logger;
     protected File destDir;
     protected boolean overwrite;
     protected boolean usePkgPath;
-    protected boolean makePairs;
+
     protected String template;
     protected String superTemplate;
+    protected String embeddableTemplate;
+    protected String embeddableSuperTemplate;
     protected long timestamp;
     protected String outputPattern;
     protected String encoding;
 
+    // runtime ivars
+    protected VelocityContext context;
+    protected Map<String, Template> templateCache;
+
     public ClassGenerationAction() {
-        this.mode = ClassGeneratorMode.entity;
         this.outputPattern = "*.java";
         this.timestamp = System.currentTimeMillis();
         this.usePkgPath = true;
         this.makePairs = true;
         this.context = new VelocityContext();
         this.templateCache = new HashMap<String, Template>(5);
-    }
-
-    protected String defaultSingleClassTemplateName() {
-        return ClassGenerationAction.SINGLE_CLASS_TEMPLATE;
-    }
-
-    protected String defaultSubclassTemplateName() {
-        return ClassGenerationAction.SUBCLASS_TEMPLATE;
-    }
-
-    protected String defaultSuperclassTemplateName() {
-        return ClassGenerationAction.SUPERCLASS_TEMPLATE;
-    }
 
-    /**
-     * Returns template file path for Java class when generating single classes.
-     */
-    protected Template singleClassTemplate() throws Exception {
-        String name = (template != null) ? template : defaultSingleClassTemplateName();
-        return getTemplate(name);
+        this.artifacts = new ArrayList<Artifact>();
     }
 
-    /**
-     * Returns template file path for Java subclass when generating class pairs.
-     */
-    protected Template subclassTemplate() throws Exception {
-        String name = (template != null) ? template : defaultSubclassTemplateName();
-        return getTemplate(name);
+    protected String defaultTemplateName(TemplateType type) {
+        switch (type) {
+            case ENTITY_SINGLE_CLASS:
+                return ClassGenerationAction.SINGLE_CLASS_TEMPLATE;
+            case ENTITY_SUBCLASS:
+                return ClassGenerationAction.SUBCLASS_TEMPLATE;
+            case ENTITY_SUPERCLASS:
+                return ClassGenerationAction.SUPERCLASS_TEMPLATE;
+            case EMBEDDABLE_SUBCLASS:
+                return ClassGenerationAction.EMBEDDABLE_SUBCLASS_TEMPLATE;
+            case EMBEDDABLE_SUPERCLASS:
+                return ClassGenerationAction.EMBEDDABLE_SUPERCLASS_TEMPLATE;
+            case EMBEDDABLE_SINGLE_CLASS:
+                return ClassGenerationAction.EMBEDDABLE_SINGLE_CLASS_TEMPLATE;
+            default:
+                throw new IllegalArgumentException("Invalid template type: " + type);
+        }
     }
 
-    /**
-     * Returns template file path for Java superclass when generating class pairs.
-     */
-    protected Template superclassTemplate() throws Exception {
-        String name = (superTemplate != null)
-                ? superTemplate
-                : defaultSuperclassTemplateName();
-        return getTemplate(name);
+    protected String customTemplateName(TemplateType type) {
+        switch (type) {
+            case ENTITY_SINGLE_CLASS:
+                return template;
+            case ENTITY_SUBCLASS:
+                return template;
+            case ENTITY_SUPERCLASS:
+                return superTemplate;
+            case EMBEDDABLE_SUBCLASS:
+                return embeddableTemplate;
+            case EMBEDDABLE_SUPERCLASS:
+                return embeddableSuperTemplate;
+            default:
+                throw new IllegalArgumentException("Invalid template type: " + type);
+        }
     }
 
     /**
@@ -128,113 +137,113 @@
         return ClassGenerationAction.SUPERCLASS_PREFIX;
     }
 
-    protected GenerationMetadata initContext(ObjEntity entity) {
+    /**
+     * VelocityContext initialization method called once per artifact.
+     */
+    protected void resetContextForArtifact(Artifact artifact) {
         StringUtils stringUtils = StringUtils.getInstance();
-        String fqnSubClass = entity.getClassName();
-        String fqnBaseClass = (entity.getSuperClassName() != null) ? entity
-                .getSuperClassName() : CayenneDataObject.class.getName();
 
-        String subPackageName = stringUtils.stripClass(fqnSubClass);
+        String qualifiedClassName = artifact.getQualifiedClassName();
+        String packageName = stringUtils.stripClass(qualifiedClassName);
+        String className = stringUtils.stripPackageName(qualifiedClassName);
+
+        String qualifiedBaseClassName = artifact.getQualifiedBaseClassName();
+        String basePackageName = stringUtils.stripClass(qualifiedBaseClassName);
+        String baseClassName = stringUtils.stripPackageName(qualifiedBaseClassName);
+
         String superClassName = getSuperclassPrefix()
-                + stringUtils.stripPackageName(fqnSubClass);
+                + stringUtils.stripPackageName(qualifiedClassName);
 
         String superPackageName = this.superPkg;
         if (superPackageName == null) {
-            superPackageName = subPackageName;
+            superPackageName = packageName;
         }
-        String fqnSuperClass = superPackageName + "." + superClassName;
 
-        EntityUtils metadata = new EntityUtils(
-                dataMap,
-                entity,
-                fqnBaseClass,
-                fqnSuperClass,
-                fqnSubClass);
+        context.put(Artifact.BASE_CLASS_KEY, baseClassName);
+        context.put(Artifact.BASE_PACKAGE_KEY, basePackageName);
+
+        context.put(Artifact.SUB_CLASS_KEY, className);
+        context.put(Artifact.SUB_PACKAGE_KEY, packageName);
 
-        context.put("objEntity", entity);
-        context.put("stringUtils", StringUtils.getInstance());
-        context.put("entityUtils", metadata);
-        context.put("importUtils", new ImportUtils());
-        return metadata;
+        context.put(Artifact.SUPER_CLASS_KEY, superClassName);
+        context.put(Artifact.SUPER_PACKAGE_KEY, superPackageName);
+
+        context.put(Artifact.OBJECT_KEY, artifact.getObject());
+        context.put(Artifact.STRING_UTILS_KEY, stringUtils);
     }
 
     /**
-     * Runs class generation. Produces a pair of Java classes for each ObjEntity in the
-     * map. This allows developers to use generated <b>subclass </b> for their custom
-     * code, while generated <b>superclass </b> will contain Cayenne code. Superclass will
-     * be generated in the same package, its class name will be derived from the class
-     * name by adding a <code>superPrefix</code>.
+     * VelocityContext initialization method called once per each artifact and template
+     * type combination.
      */
-    protected void generateClassPairs() throws Exception {
+    protected void resetContextForArtifactTemplate(
+            Artifact artifact,
+            TemplateType templateType) {
+        context.put(Artifact.IMPORT_UTILS_KEY, new ImportUtils());
+        artifact.postInitContext(context);
+    }
 
-        Template superTemplate = superclassTemplate();
-        Template classTemplate = subclassTemplate();
+    /**
+     * Executes class generation once per each artifact.
+     */
+    public void execute() throws Exception {
 
-        for (ObjEntity entity : entitiesForCurrentMode()) {
+        validateAttributes();
 
-            GenerationMetadata metadata = initContext(entity);
-            Writer superOut = openWriter(metadata.getSuperPackageName(), metadata
-                    .getSuperClassName());
-            if (superOut != null) {
-                superTemplate.merge(context, superOut);
-                superOut.close();
-            }
+        try {
+            for (Artifact artifact : artifacts) {
+                execute(artifact);
 
-            Writer mainOut = openWriter(metadata.getSubPackageName(), metadata
-                    .getSubClassName());
-            if (mainOut != null) {
-                classTemplate.merge(context, mainOut);
-                mainOut.close();
+                if (artifactsGenerationMode == ArtifactsGenerationMode.datamap) {
+                    // TODO: andrus 12/9/2007 - should we run at least once if there are
+                    // no artifacts? Current behavior is copied from the legacy code.
+                    break;
+                }
             }
         }
+        finally {
+            // must reset engine at the end of class generator run to avoid memory
+            // leaks and stale templates
+            this.templateCache.clear();
+        }
     }
 
     /**
-     * Runs class generation. Produces a single Java class for each ObjEntity in the map.
+     * Executes class generation for a single artifact.
      */
-    protected void generateSingleClasses() throws Exception {
+    protected void execute(Artifact artifact) throws Exception {
+
+        resetContextForArtifact(artifact);
 
-        Template classTemplate = singleClassTemplate();
+        ArtifactGenerationMode artifactMode = makePairs
+                ? ArtifactGenerationMode.GENERATION_GAP
+                : ArtifactGenerationMode.SINGLE_CLASS;
 
-        for (ObjEntity entity : entitiesForCurrentMode()) {
+        TemplateType[] templateTypes = artifact.getTemplateTypes(artifactMode);
+        for (TemplateType type : templateTypes) {
 
-            GenerationMetadata metadata = initContext(entity);
-            Writer out = openWriter(metadata.getSubPackageName(), metadata
-                    .getSubClassName());
+            Writer out = openWriter(type);
             if (out != null) {
-                classTemplate.merge(context, out);
+
+                resetContextForArtifactTemplate(artifact, type);
+                getTemplate(type).merge(context, out);
                 out.close();
             }
         }
     }
 
-    /**
-     * Runs class generation.
-     */
-    public void execute() throws Exception {
-        validateAttributes();
+    protected Template getTemplate(TemplateType type) throws Exception {
 
-        try {
-            if (makePairs) {
-                generateClassPairs();
-            }
-            else {
-                generateSingleClasses();
-            }
-        }
-        finally {
-            // must reset engine at the end of class generator run to avoid memory
-            // leaks and stale templates
-            this.templateCache.clear();
+        String templateName = customTemplateName(type);
+        if (templateName == null) {
+            templateName = defaultTemplateName(type);
         }
-    }
 
-    protected Template getTemplate(String name) throws Exception {
         // Velocity < 1.5 has some memory problems, so we will create a VelocityEngine
         // every time, and store templates in an internal cache, to avoid uncontrolled
         // memory leaks... Presumably 1.5 fixes it.
 
-        Template template = templateCache.get(name);
+        Template template = templateCache.get(templateName);
 
         if (template == null) {
 
@@ -251,25 +260,13 @@
             VelocityEngine velocityEngine = new VelocityEngine();
             velocityEngine.init(props);
 
-            template = velocityEngine.getTemplate(name);
-            templateCache.put(name, template);
+            template = velocityEngine.getTemplate(templateName);
+            templateCache.put(templateName, template);
         }
 
         return template;
     }
 
-    protected Collection<ObjEntity> entitiesForCurrentMode() {
-
-        // TODO: andrus, 12/2/2007 - should we setup a dummy entity for an empty map in
-        // DataMap mode?
-        if (mode != ClassGeneratorMode.entity && !entities.isEmpty()) {
-            return Collections.singleton(entities.iterator().next());
-        }
-        else {
-            return this.entities;
-        }
-    }
-
     /**
      * Validates the state of this class generator. Throws CayenneRuntimeException if it
      * is in an inconsistent state. Called internally from "execute".
@@ -340,21 +337,20 @@
 
     /**
      * Opens a Writer to write generated output. Writer encoding is determined from the
-     * value of the "encoding" property.
+     * value of the "encoding" property. Output file is determined from the current state
+     * of VelocityContext and the TemplateType passed as a parameter.
      */
-    protected Writer openWriter(String pkgName, String className) throws Exception {
-
-        boolean superclass = className.startsWith(SUPERCLASS_PREFIX);
-        File outFile = (superclass)
-                ? fileForSuperclass(pkgName, className)
-                : fileForClass(pkgName, className);
+    protected Writer openWriter(TemplateType templateType) throws Exception {
 
+        File outFile = (templateType.isSuperclass())
+                ? fileForSuperclass()
+                : fileForClass();
         if (outFile == null) {
             return null;
         }
 
         if (logger != null) {
-            String label = superclass ? "superclass" : "class";
+            String label = templateType.isSuperclass() ? "superclass" : "class";
             logger.info("Generating " + label + " file: " + outFile.getCanonicalPath());
         }
 
@@ -370,13 +366,16 @@
      * Returns a target file where a generated superclass must be saved. If null is
      * returned, class shouldn't be generated.
      */
-    protected File fileForSuperclass(String pkgName, String className) throws Exception {
+    protected File fileForSuperclass() throws Exception {
+
+        String packageName = (String) context.get(Artifact.SUPER_PACKAGE_KEY);
+        String className = (String) context.get(Artifact.SUPER_CLASS_KEY);
 
         String filename = NamePatternMatcher.replaceWildcardInStringWithString(
                 WILDCARD,
                 outputPattern,
                 className);
-        File dest = new File(mkpath(destDir, pkgName), filename);
+        File dest = new File(mkpath(destDir, packageName), filename);
 
         // Ignore if the destination is newer than the map
         // (internal timestamp), i.e. has been generated after the map was
@@ -400,13 +399,16 @@
      * Returns a target file where a generated class must be saved. If null is returned,
      * class shouldn't be generated.
      */
-    protected File fileForClass(String pkgName, String className) throws Exception {
+    protected File fileForClass() throws Exception {
+
+        String packageName = (String) context.get(Artifact.SUB_PACKAGE_KEY);
+        String className = (String) context.get(Artifact.SUB_CLASS_KEY);
 
         String filename = NamePatternMatcher.replaceWildcardInStringWithString(
                 WILDCARD,
                 outputPattern,
                 className);
-        File dest = new File(mkpath(destDir, pkgName), filename);
+        File dest = new File(mkpath(destDir, packageName), filename);
 
         if (dest.exists()) {
             // no overwrite of subclasses
@@ -492,18 +494,22 @@
     }
 
     /**
-     * Initializes internal ObjEntities list. This method creates a copy of the provided
-     * list to allow its independent modification and also filters out entities that do
-     * not require class generation.
-     */
-    public void setEntities(Collection<ObjEntity> objEntities) {
-        this.entities = objEntities != null
-                ? new ArrayList<ObjEntity>(objEntities)
-                : new ArrayList<ObjEntity>();
+     * Adds entities to the internal entity list.
+     */
+    public void addEntities(Collection<ObjEntity> entities) {
+        if (entities != null) {
+            for (ObjEntity entity : entities) {
+                artifacts.add(new EntityArtifact(entity));
+            }
+        }
     }
 
-    public void setMode(ClassGeneratorMode mode) {
-        this.mode = mode;
+    public void addEmbeddables(Collection<Embeddable> embeddables) {
+        if (embeddables != null) {
+            for (Embeddable embeddable : embeddables) {
+                artifacts.add(new EmbeddableArtifact(embeddable));
+            }
+        }
     }
 
     /**
@@ -520,5 +526,17 @@
      */
     public void setLogger(Log logger) {
         this.logger = logger;
+    }
+
+    public void setEmbeddableTemplate(String embeddableTemplate) {
+        this.embeddableTemplate = embeddableTemplate;
+    }
+
+    public void setEmbeddableSuperTemplate(String embeddableSuperTemplate) {
+        this.embeddableSuperTemplate = embeddableSuperTemplate;
+    }
+
+    public void setArtifactsGenerationMode(ArtifactsGenerationMode artifactsGenerationMode) {
+        this.artifactsGenerationMode = artifactsGenerationMode;
     }
 }

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/ClassGenerationAction1_1.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/ClassGenerationAction1_1.java?rev=602732&r1=602731&r2=602732&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/ClassGenerationAction1_1.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/ClassGenerationAction1_1.java Sun Dec  9 13:29:16 2007
@@ -18,143 +18,233 @@
  ****************************************************************/
 package org.apache.cayenne.gen;
 
+import java.io.File;
 import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
 
-import org.apache.cayenne.CayenneDataObject;
 import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.Embeddable;
 import org.apache.cayenne.map.ObjEntity;
+import org.apache.commons.logging.Log;
 import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
 
 /**
+ * A backwards compatible class generation action that delegates to the deprecated
+ * {@link DefaultClassGenerator}.
+ * 
  * @since 3.0
  * @author Andrus Adamchik
  * @deprecated since 3.0
  */
 public class ClassGenerationAction1_1 extends ClassGenerationAction {
 
-    public static final String SINGLE_CLASS_TEMPLATE = "dotemplates/singleclass.vm";
-    public static final String SUBCLASS_TEMPLATE = "dotemplates/subclass.vm";
-    public static final String SUPERCLASS_TEMPLATE = "dotemplates/superclass.vm";
+    public static final String SINGLE_CLASS_TEMPLATE = MapClassGenerator.SINGLE_CLASS_TEMPLATE_1_1;
+    public static final String SUBCLASS_TEMPLATE = MapClassGenerator.SUBCLASS_TEMPLATE_1_1;
+    public static final String SUPERCLASS_TEMPLATE = MapClassGenerator.SUPERCLASS_TEMPLATE_1_1;
+
+    protected DefaultClassGenerator generator;
+    protected List<ObjEntity> entities;
+    protected Log logger;
+
+    public ClassGenerationAction1_1() {
+        this.generator = new LoggingGenerator();
+        this.generator.setVersionString(ClassGenerator.VERSION_1_1);
+        this.entities = new ArrayList<ObjEntity>();
+    }
 
     @Override
-    protected String defaultSingleClassTemplateName() {
-        return ClassGenerationAction1_1.SINGLE_CLASS_TEMPLATE;
+    public void addEmbeddables(Collection<Embeddable> embeddables) {
+        throw new UnsupportedOperationException(
+                "Embeddables are not supported in 1.1 mode");
     }
 
     @Override
-    protected String defaultSubclassTemplateName() {
-        return ClassGenerationAction1_1.SUBCLASS_TEMPLATE;
+    public void addEntities(Collection<ObjEntity> entities) {
+        if (entities != null) {
+            this.entities.addAll(entities);
+            generator.setObjEntities(this.entities);
+        }
     }
 
     @Override
-    protected String defaultSuperclassTemplateName() {
-        return ClassGenerationAction1_1.SUPERCLASS_TEMPLATE;
+    protected String customTemplateName(TemplateType type) {
+        throw new UnsupportedOperationException("Not supported in 1.1 mode");
     }
 
     @Override
-    protected void generateClassPairs() throws Exception {
+    protected String defaultTemplateName(TemplateType type) {
+        throw new UnsupportedOperationException("Not supported in 1.1 mode");
+    }
 
-        Template superTemplate = superclassTemplate();
-        Template classTemplate = subclassTemplate();
-        String superPrefix = getSuperclassPrefix();
-        
-        ClassGenerationInfo mainGen = new ClassGenerationInfo();
-        ClassGenerationInfo superGen = new ClassGenerationInfo();
+    @Override
+    public void execute() throws Exception {
+        generator.execute();
+    }
 
-        // prefix is needed for both generators
-        mainGen.setSuperPrefix(superPrefix);
-        superGen.setSuperPrefix(superPrefix);
+    @Override
+    protected void execute(Artifact artifact) throws Exception {
+        throw new UnsupportedOperationException("Not supported in 1.1 mode");
+    }
 
-        for (ObjEntity entity : entitiesForCurrentMode()) {
+    @Override
+    protected File fileForClass() throws Exception {
+        throw new UnsupportedOperationException("Not supported in 1.1 mode");
+    }
 
-            // 1. do the superclass
-            initClassGenerator(superGen, entity, true);
+    @Override
+    protected File fileForSuperclass() throws Exception {
+        throw new UnsupportedOperationException("Not supported in 1.1 mode");
+    }
 
-            Writer superOut = openWriter(superGen.getPackageName(), superPrefix
-                    + superGen.getClassName());
+    @Override
+    protected String getSuperclassPrefix() {
+        return super.getSuperclassPrefix();
+    }
 
-            if (superOut != null) {
-                superTemplate.merge(context, superOut);
-                superOut.close();
-            }
+    @Override
+    protected Template getTemplate(TemplateType type) throws Exception {
+        throw new UnsupportedOperationException("Not supported in 1.1 mode");
+    }
 
-            // 2. do the main class
-            initClassGenerator(mainGen, entity, false);
-            Writer mainOut = openWriter(mainGen.getPackageName(), mainGen.getClassName());
-            if (mainOut != null) {
-                classTemplate.merge(context, mainOut);
-                mainOut.close();
-            }
+    @Override
+    protected void resetContextForArtifact(Artifact artifact) {
+        throw new UnsupportedOperationException("Not supported in 1.1 mode");
+    }
+
+    @Override
+    protected boolean isOld(File file) {
+        throw new UnsupportedOperationException("Not supported in 1.1 mode");
+    }
+
+    @Override
+    protected File mkpath(File dest, String pkgName) throws Exception {
+        throw new UnsupportedOperationException("Not supported in 1.1 mode");
+    }
+
+    @Override
+    protected Writer openWriter(TemplateType templateType) throws Exception {
+        throw new UnsupportedOperationException("Not supported in 1.1 mode");
+    }
+
+    @Override
+    public void setArtifactsGenerationMode(ArtifactsGenerationMode artifactsGenerationMode) {
+        if (artifactsGenerationMode == null) {
+            artifactsGenerationMode = ArtifactsGenerationMode.entity;
         }
+        generator.setMode(artifactsGenerationMode.name());
+    }
 
-        context.remove("classGen");
+    @Override
+    public void setContext(VelocityContext context) {
+        // noop...
     }
 
     @Override
-    protected void generateSingleClasses()
-            throws Exception {
+    public void setDataMap(DataMap dataMap) {
+        generator.setDataMap(dataMap);
+    }
 
-        Template classTemplate = singleClassTemplate();
-        ClassGenerationInfo mainGen = new ClassGenerationInfo();
+    @Override
+    public void setDestDir(File destDir) {
+        generator.setDestDir(destDir);
+    }
 
-        for (ObjEntity entity : entitiesForCurrentMode()) {
+    @Override
+    public void setEmbeddableSuperTemplate(String embeddableSuperTemplate) {
+        // noop
+    }
 
-            initClassGenerator(mainGen, entity, false);
-            Writer out = openWriter(mainGen.getPackageName(), mainGen.getClassName());
-            if (out != null) {
-                classTemplate.merge(context, out);
-                out.close();
-            }
-        }
+    @Override
+    public void setEmbeddableTemplate(String embeddableTemplate) {
+        // noop
     }
 
-    /**
-     * Initializes ClassGenerationInfo with class name and package of a generated class.
-     */
-    private void initClassGenerator(
-            ClassGenerationInfo generatorInfo,
-            ObjEntity entity,
-            boolean superclass) {
-
-        // figure out generator properties
-        String fullClassName = entity.getClassName();
-        int i = fullClassName.lastIndexOf(".");
-
-        String pkg = null;
-        String spkg = null;
-        String cname = null;
-
-        // dot in first or last position is invalid
-        if (i == 0 || i + 1 == fullClassName.length()) {
-            throw new CayenneRuntimeException("Invalid class mapping: " + fullClassName);
-        }
-        else if (i < 0) {
-            pkg = (superclass) ? superPkg : null;
-            spkg = (superclass) ? null : superPkg;
-            cname = fullClassName;
-        }
-        else {
-            cname = fullClassName.substring(i + 1);
-            pkg = (superclass && superPkg != null) ? superPkg : fullClassName.substring(
-                    0,
-                    i);
-
-            spkg = (!superclass && superPkg != null && !pkg.equals(superPkg))
-                    ? superPkg
-                    : null;
-        }
-
-        generatorInfo.setPackageName(pkg);
-        generatorInfo.setClassName(cname);
-        if (entity.getSuperClassName() != null) {
-            generatorInfo.setSuperClassName(entity.getSuperClassName());
+    @Override
+    public void setEncoding(String encoding) {
+        generator.setEncoding(encoding);
+    }
+
+    @Override
+    public void setLogger(Log logger) {
+        this.logger = logger;
+    }
+
+    @Override
+    public void setMakePairs(boolean makePairs) {
+        generator.setMakePairs(makePairs);
+    }
+
+    @Override
+    public void setOutputPattern(String outputPattern) {
+        generator.setOutputPattern(outputPattern);
+    }
+
+    @Override
+    public void setOverwrite(boolean overwrite) {
+        generator.setOverwrite(overwrite);
+    }
+
+    @Override
+    public void setSuperPkg(String superPkg) {
+        generator.setSuperPkg(superPkg);
+    }
+
+    @Override
+    public void setSuperTemplate(String superTemplate) {
+        generator.setSuperTemplate(superTemplate);
+    }
+
+    @Override
+    public void setTemplate(String template) {
+        generator.setTemplate(template);
+    }
+
+    @Override
+    public void setTimestamp(long timestamp) {
+        generator.setTimestamp(timestamp);
+    }
+
+    @Override
+    public void setUsePkgPath(boolean usePkgPath) {
+        generator.setUsePkgPath(usePkgPath);
+    }
+
+    @Override
+    protected void validateAttributes() {
+        try {
+            generator.validateAttributes();
         }
-        else {
-            generatorInfo.setSuperClassName(CayenneDataObject.class.getName());
+        catch (Exception e) {
+            throw new CayenneRuntimeException(e);
         }
-        generatorInfo.setSuperPackageName(spkg);
+    }
+
+    final class LoggingGenerator extends DefaultClassGenerator {
+
+        @Override
+        protected File fileForClass(String pkgName, String className) throws Exception {
+
+            File outFile = super.fileForClass(pkgName, className);
+            if (outFile != null && logger != null) {
+                logger.info("Generating class file: " + outFile.getCanonicalPath());
+            }
 
-        generatorInfo.setObjEntity(entity);
-        context.put("classGen", generatorInfo);
+            return outFile;
+        }
+
+        @Override
+        protected File fileForSuperclass(String pkgName, String className)
+                throws Exception {
+            File outFile = super.fileForSuperclass(pkgName, className);
+            if (outFile != null && logger != null) {
+                logger.info("Generating superclass file: " + outFile.getCanonicalPath());
+            }
+
+            return outFile;
+        }
     }
 }

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/ClientClassGenerationAction.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/ClientClassGenerationAction.java?rev=602732&r1=602731&r2=602732&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/ClientClassGenerationAction.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/ClientClassGenerationAction.java Sun Dec  9 13:29:16 2007
@@ -18,7 +18,8 @@
  ****************************************************************/
 package org.apache.cayenne.gen;
 
-import org.apache.cayenne.PersistentObject;
+import java.util.Collection;
+
 import org.apache.cayenne.map.ObjEntity;
 
 /**
@@ -31,56 +32,27 @@
     public static final String SUPERCLASS_TEMPLATE = "dotemplates/v1_2/client-superclass.vm";
 
     @Override
-    protected String defaultSingleClassTemplateName() {
-        throw new IllegalStateException(
-                "Default generation for single classes on the client is not supported.");
-    }
-
-    @Override
-    protected String defaultSubclassTemplateName() {
-        return ClientClassGenerationAction.SUBCLASS_TEMPLATE;
-    }
-
-    @Override
-    protected String defaultSuperclassTemplateName() {
-        return ClientClassGenerationAction.SUPERCLASS_TEMPLATE;
+    protected String defaultTemplateName(TemplateType type) {
+        switch (type) {
+            case ENTITY_SUBCLASS:
+                return ClientClassGenerationAction.SUBCLASS_TEMPLATE;
+            case ENTITY_SUPERCLASS:
+                return ClientClassGenerationAction.SUPERCLASS_TEMPLATE;
+            case EMBEDDABLE_SUBCLASS:
+                return ClassGenerationAction.EMBEDDABLE_SUBCLASS_TEMPLATE;
+            case EMBEDDABLE_SUPERCLASS:
+                return ClassGenerationAction.EMBEDDABLE_SUPERCLASS_TEMPLATE;
+            default:
+                throw new IllegalArgumentException("Unsupported template type: " + type);
+        }
     }
 
     @Override
-    protected GenerationMetadata initContext(ObjEntity entity) {
-        StringUtils stringUtils = StringUtils.getInstance();
-
-        // use client name, and if not specified use regular class name
-        String fqnSubClass = entity.getClientClassName();
-        if (fqnSubClass == null) {
-            fqnSubClass = entity.getClassName();
+    public void addEntities(Collection<ObjEntity> entities) {
+        if (entities != null) {
+            for (ObjEntity entity : entities) {
+                artifacts.add(new ClientEntityArtifact(entity));
+            }
         }
-
-        // use PersistentObject instead of CayenneDataObject as base ...
-        String fqnBaseClass = (entity.getClientSuperClassName() != null) ? entity
-                .getClientSuperClassName() : PersistentObject.class.getName();
-
-        String subPackageName = stringUtils.stripClass(fqnSubClass);
-        String superClassName = getSuperclassPrefix()
-                + stringUtils.stripPackageName(fqnSubClass);
-
-        String superPackageName = this.superPkg;
-        if (superPackageName == null) {
-            superPackageName = subPackageName;
-        }
-        String fqnSuperClass = superPackageName + "." + superClassName;
-
-        EntityUtils metadata = new EntityUtils(
-                dataMap,
-                entity,
-                fqnBaseClass,
-                fqnSuperClass,
-                fqnSubClass);
-
-        context.put("objEntity", entity);
-        context.put("stringUtils", StringUtils.getInstance());
-        context.put("entityUtils", metadata);
-        context.put("importUtils", new ImportUtils());
-        return metadata;
     }
 }

Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/ClientEntityArtifact.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/ClientEntityArtifact.java?rev=602732&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/ClientEntityArtifact.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/ClientEntityArtifact.java Sun Dec  9 13:29:16 2007
@@ -0,0 +1,44 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.gen;
+
+import org.apache.cayenne.PersistentObject;
+import org.apache.cayenne.map.ObjEntity;
+
+/**
+ * Client code generation artifact based on ObjEntity.
+ * 
+ * @since 3.0
+ * @author Andrus Adamchik
+ */
+public class ClientEntityArtifact extends EntityArtifact {
+
+    public ClientEntityArtifact(ObjEntity entity) {
+        super(entity);
+    }
+
+    public String getQualifiedBaseClassName() {
+        return (entity.getClientSuperClassName() != null) ? entity
+                .getClientSuperClassName() : PersistentObject.class.getName();
+    }
+
+    public String getQualifiedClassName() {
+        return entity.getClientClassName();
+    }
+}

Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/EmbeddableArtifact.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/EmbeddableArtifact.java?rev=602732&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/EmbeddableArtifact.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/EmbeddableArtifact.java Sun Dec  9 13:29:16 2007
@@ -0,0 +1,57 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.gen;
+
+import org.apache.cayenne.map.Embeddable;
+import org.apache.velocity.VelocityContext;
+
+/**
+ * {@link Artifact} facade for an {@link Embeddable}.
+ * 
+ * @since 3.0
+ * @author Andrus Adamchik
+ */
+public class EmbeddableArtifact implements Artifact {
+
+    protected Embeddable embeddable;
+
+    public EmbeddableArtifact(Embeddable embeddable) {
+        this.embeddable = embeddable;
+    }
+
+    public Object getObject() {
+        return embeddable;
+    }
+
+    public String getQualifiedBaseClassName() {
+        return Object.class.getName();
+    }
+
+    public String getQualifiedClassName() {
+        return embeddable.getClassName();
+    }
+
+    public TemplateType[] getTemplateTypes(ArtifactGenerationMode mode) {
+        return null;
+    }
+
+    public void postInitContext(VelocityContext context) {
+        // noop - no special keys...
+    }
+}

Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/EntityArtifact.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/EntityArtifact.java?rev=602732&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/EntityArtifact.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/EntityArtifact.java Sun Dec  9 13:29:16 2007
@@ -0,0 +1,105 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.gen;
+
+import org.apache.cayenne.CayenneDataObject;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.velocity.VelocityContext;
+
+/**
+ * {@link Artifact} facade for an ObjEntity.
+ * 
+ * @since 3.0
+ * @author Andrus Adamchik
+ */
+public class EntityArtifact implements Artifact {
+
+    /**
+     * @deprecated since 3.0 "OBJECT" should be used instead, as the root key in the
+     *             template is not necessarily ObjEntity. Still preserved for ObjEntities
+     *             for backwards compatibility.
+     */
+    public static String OBJ_ENTITY_KEY = "objEntity";
+    public static String ENTITY_UTILS_KEY = "entityUtils";
+
+    protected ObjEntity entity;
+
+    public EntityArtifact(ObjEntity entity) {
+        this.entity = entity;
+    }
+
+    /**
+     * Returns ObjEntity.
+     */
+    public Object getObject() {
+        return entity;
+    }
+
+    public String getQualifiedBaseClassName() {
+        return (entity.getSuperClassName() != null)
+                ? entity.getSuperClassName()
+                : CayenneDataObject.class.getName();
+    }
+
+    public String getQualifiedClassName() {
+        return entity.getClassName();
+    }
+
+    public TemplateType getSingleClassType() {
+        return TemplateType.ENTITY_SINGLE_CLASS;
+    }
+
+    public TemplateType getSubclassType() {
+        return TemplateType.ENTITY_SUBCLASS;
+    }
+
+    public TemplateType getSuperClassType() {
+        return TemplateType.ENTITY_SUPERCLASS;
+    }
+
+    public TemplateType[] getTemplateTypes(ArtifactGenerationMode mode) {
+        switch (mode) {
+            case SINGLE_CLASS:
+                return new TemplateType[] {
+                    TemplateType.ENTITY_SINGLE_CLASS
+                };
+            case GENERATION_GAP:
+                return new TemplateType[] {
+                        TemplateType.ENTITY_SUPERCLASS, TemplateType.ENTITY_SUBCLASS
+                };
+            default:
+                return new TemplateType[0];
+        }
+    }
+
+    public void postInitContext(VelocityContext context) {
+        EntityUtils metadata = new EntityUtils(
+                entity.getDataMap(),
+                entity,
+                (String) context.get(BASE_CLASS_KEY),
+                (String) context.get(BASE_PACKAGE_KEY),
+                (String) context.get(SUPER_CLASS_KEY),
+                (String) context.get(SUPER_PACKAGE_KEY),
+                (String) context.get(SUB_CLASS_KEY),
+                (String) context.get(SUB_PACKAGE_KEY));
+
+        context.put(ENTITY_UTILS_KEY, metadata);
+        context.put(OBJ_ENTITY_KEY, entity);
+    }
+}

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/EntityUtils.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/EntityUtils.java?rev=602732&r1=602731&r2=602732&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/EntityUtils.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/EntityUtils.java Sun Dec  9 13:29:16 2007
@@ -17,7 +17,6 @@
  *  under the License.
  ****************************************************************/
 
-
 package org.apache.cayenne.gen;
 
 import org.apache.cayenne.map.DataMap;
@@ -31,7 +30,7 @@
  * @since 1.2
  * @author Mike Kienenberger
  */
-public class EntityUtils implements GenerationMetadata {
+public class EntityUtils {
 
     // template substitution values
     protected String subClassName;
@@ -61,6 +60,22 @@
         this.objEntity = objEntity;
     }
 
+    EntityUtils(DataMap dataMap, ObjEntity objEntity, String baseClassName,
+            String basePackageName, String superClassName, String superPackageName,
+            String subClassName, String subPackageName) {
+
+        this.baseClassName = baseClassName;
+        this.basePackageName = basePackageName;
+        this.superClassName = superClassName;
+        this.superPackageName = superPackageName;
+        this.subClassName = subClassName;
+        this.subPackageName = subPackageName;
+
+        this.primaryDataMap = dataMap;
+
+        this.objEntity = objEntity;
+    }
+
     /**
      * Returns class name (without a package) of the sub class associated with this
      * generator.
@@ -150,8 +165,8 @@
     }
 
     /**
-     * Returns true if current ObjEntity contains at least one toMany relationship, ignoring
-     * those declared in superentities.
+     * Returns true if current ObjEntity contains at least one toMany relationship,
+     * ignoring those declared in superentities.
      * 
      * @since 1.2
      */
@@ -204,8 +219,8 @@
     }
 
     /**
-     * Returns true if current ObjEntity contains at least one toOne relationship, ignoring
-     * those declared in superentities.
+     * Returns true if current ObjEntity contains at least one toOne relationship,
+     * ignoring those declared in superentities.
      */
     public boolean hasToOneDeclaredRelationships() {
         return hasToOneDeclaredRelationships(objEntity);

Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/TemplateType.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/TemplateType.java?rev=602732&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/TemplateType.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/TemplateType.java Sun Dec  9 13:29:16 2007
@@ -0,0 +1,50 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.gen;
+
+/**
+ * Defines class generation template types.
+ * 
+ * @since 3.0
+ * @author Andrus Adamchik
+ */
+public enum TemplateType {
+
+    ENTITY_SINGLE_CLASS(false),
+
+    ENTITY_SUPERCLASS(true),
+
+    ENTITY_SUBCLASS(false),
+
+    EMBEDDABLE_SINGLE_CLASS(false),
+
+    EMBEDDABLE_SUPERCLASS(true),
+
+    EMBEDDABLE_SUBCLASS(false);
+
+    private boolean superclass;
+
+    private TemplateType(boolean superclass) {
+        this.superclass = superclass;
+    }
+
+    public boolean isSuperclass() {
+        return superclass;
+    }
+}

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/tools/CayenneGeneratorTask.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/tools/CayenneGeneratorTask.java?rev=602732&r1=602731&r2=602732&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/tools/CayenneGeneratorTask.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/tools/CayenneGeneratorTask.java Sun Dec  9 13:29:16 2007
@@ -23,7 +23,7 @@
 import org.apache.cayenne.gen.ClassGenerationAction;
 import org.apache.cayenne.gen.ClassGenerationAction1_1;
 import org.apache.cayenne.gen.ClassGenerator;
-import org.apache.cayenne.gen.ClassGeneratorMode;
+import org.apache.cayenne.gen.ArtifactsGenerationMode;
 import org.apache.cayenne.gen.ClientClassGenerationAction;
 import org.apache.cayenne.gen.DefaultClassGenerator;
 import org.apache.tools.ant.BuildException;
@@ -64,7 +64,7 @@
 
     public CayenneGeneratorTask() {
         this.makepairs = true;
-        this.mode = ClassGeneratorMode.entity.name();
+        this.mode = ArtifactsGenerationMode.entity.name();
         this.outputPattern = "*.java";
         this.usepkgpath = true;
     }
@@ -91,7 +91,7 @@
         action.setDestDir(destDir);
         action.setEncoding(encoding);
         action.setMakePairs(makepairs);
-        action.setMode(ClassGeneratorMode.valueOf(mode));
+        action.setArtifactsGenerationMode(ArtifactsGenerationMode.valueOf(mode.toLowerCase()));
         action.setOutputPattern(outputPattern);
         action.setOverwrite(overwrite);
         action.setSuperPkg(superpkg);
@@ -148,7 +148,7 @@
             generatorAction.setLogger(logger);
             generatorAction.setTimestamp(map.lastModified());
             generatorAction.setDataMap(loadAction.getMainDataMap());
-            generatorAction.setEntities(filterAction.getFilteredEntities(loadAction
+            generatorAction.addEntities(filterAction.getFilteredEntities(loadAction
                     .getMainDataMap()));
             generatorAction.execute();
         }

Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/resources/dotemplates/v1_2/embeddable-singleclass.vm
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/resources/dotemplates/v1_2/embeddable-singleclass.vm?rev=602732&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/resources/dotemplates/v1_2/embeddable-singleclass.vm (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/resources/dotemplates/v1_2/embeddable-singleclass.vm Sun Dec  9 13:29:16 2007
@@ -0,0 +1,30 @@
+##  Licensed to the Apache Software Foundation (ASF) under one
+##  or more contributor license agreements.  See the NOTICE file
+##  distributed with this work for additional information
+##  regarding copyright ownership.  The ASF licenses this file
+##  to you under the Apache License, Version 2.0 (the
+##  "License"); you may not use this file except in compliance
+##  with the License.  You may obtain a copy of the License at
+##
+##    http://www.apache.org/licenses/LICENSE-2.0
+##
+##  Unless required by applicable law or agreed to in writing,
+##  software distributed under the License is distributed on an
+##  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+##  KIND, either express or implied.  See the License for the
+##  specific language governing permissions and limitations
+##  under the License.
+##
+##Terminology:
+##	Base class - super superclass of embeddable, usually java.lang.Object
+##  Super class - superclass of embeddable, ie,  org.apache.cayenne.art.auto._Embeddable
+##	Sub class - class of entity, ie, org.apache.cayenne.art.Embeddable
+##
+##  Classes available in template
+##    embeddable - the Embeddable class: See org.apache.cayenne.map.Embeddable
+##    stringUtils - class for string "helper" functions: See org.apache.cayenne.gen.StringUtils
+##    entityUtils - class for entity "helper" functions: See org.apache.cayenne.gen.EntityUtils
+##    importUtils - class for import statement management: See org.apache.cayenne.gen.ImportUtils
+##
+##
+// singleclass
\ No newline at end of file

Modified: cayenne/main/trunk/framework/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/codegen/CustomModeController.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/codegen/CustomModeController.java?rev=602732&r1=602731&r2=602732&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/codegen/CustomModeController.java (original)
+++ cayenne/main/trunk/framework/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/codegen/CustomModeController.java Sun Dec  9 13:29:16 2007
@@ -31,7 +31,7 @@
 import org.apache.cayenne.gen.ClassGenerationAction;
 import org.apache.cayenne.gen.ClassGenerationAction1_1;
 import org.apache.cayenne.gen.ClassGenerator;
-import org.apache.cayenne.gen.ClassGeneratorMode;
+import org.apache.cayenne.gen.ArtifactsGenerationMode;
 import org.apache.cayenne.modeler.CodeTemplateManager;
 import org.apache.cayenne.modeler.dialog.pref.PreferenceDialog;
 import org.apache.cayenne.modeler.pref.DataMapDefaults;
@@ -224,7 +224,7 @@
         String mode = modesByLabel
                 .get(view.getGenerationMode().getSelectedItem())
                 .toString();
-        generator.setMode(ClassGeneratorMode.valueOf(mode));
+        generator.setArtifactsGenerationMode(ArtifactsGenerationMode.valueOf(mode));
         
         String version = getVersion();
 

Modified: cayenne/main/trunk/framework/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/codegen/GeneratorController.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/codegen/GeneratorController.java?rev=602732&r1=602731&r2=602732&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/codegen/GeneratorController.java (original)
+++ cayenne/main/trunk/framework/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/codegen/GeneratorController.java Sun Dec  9 13:29:16 2007
@@ -146,7 +146,7 @@
 
         ClassGenerationAction generator = newGenerator();
         generator.setDataMap(getParentController().getDataMap());
-        generator.setEntities(entities);
+        generator.addEntities(entities);
 
         // configure encoding from preferences
         Domain generatorPrefs = Application

Modified: cayenne/main/trunk/framework/maven-cayenne-plugin/src/main/java/org/apache/cayenne/tools/CayenneGeneratorMojo.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/maven-cayenne-plugin/src/main/java/org/apache/cayenne/tools/CayenneGeneratorMojo.java?rev=602732&r1=602731&r2=602732&view=diff
==============================================================================
--- cayenne/main/trunk/framework/maven-cayenne-plugin/src/main/java/org/apache/cayenne/tools/CayenneGeneratorMojo.java (original)
+++ cayenne/main/trunk/framework/maven-cayenne-plugin/src/main/java/org/apache/cayenne/tools/CayenneGeneratorMojo.java Sun Dec  9 13:29:16 2007
@@ -20,14 +20,12 @@
 package org.apache.cayenne.tools;
 
 import java.io.File;
-import java.util.List;
 
+import org.apache.cayenne.gen.ArtifactsGenerationMode;
 import org.apache.cayenne.gen.ClassGenerationAction;
 import org.apache.cayenne.gen.ClassGenerationAction1_1;
 import org.apache.cayenne.gen.ClassGenerator;
-import org.apache.cayenne.gen.ClassGeneratorMode;
 import org.apache.cayenne.gen.ClientClassGenerationAction;
-import org.apache.cayenne.map.ObjEntity;
 import org.apache.commons.logging.Log;
 import org.apache.maven.plugin.AbstractMojo;
 import org.apache.maven.plugin.MojoExecutionException;
@@ -224,8 +222,8 @@
 			generator.setLogger(logger);
 			generator.setTimestamp(map.lastModified());
 			generator.setDataMap(loaderAction.getMainDataMap());
-			generator.setEntities((List<ObjEntity>) filterAction
-					.getFilteredEntities(loaderAction.getMainDataMap()));
+			generator.addEntities(filterAction.getFilteredEntities(loaderAction
+					.getMainDataMap()));
 			generator.execute();
 		} catch (Exception e) {
 			throw new MojoExecutionException("Error generating classes: ", e);
@@ -272,8 +270,10 @@
 		action.setDestDir(destDir);
 		action.setEncoding(encoding);
 		action.setMakePairs(makePairs);
-		action.setMode(mode != null ? ClassGeneratorMode.valueOf(mode)
-				: ClassGeneratorMode.entity);
+		action
+				.setArtifactsGenerationMode(mode != null ? ArtifactsGenerationMode
+						.valueOf(mode.toLowerCase())
+						: ArtifactsGenerationMode.entity);
 		action.setOutputPattern(outputPattern);
 		action.setOverwrite(overwrite);
 		action.setSuperPkg(superPkg);