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/02 23:44:55 UTC

svn commit: r600397 - 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/test/java/org/apache/cayenne/tool...

Author: aadamchik
Date: Sun Dec  2 14:44:53 2007
New Revision: 600397

URL: http://svn.apache.org/viewvc?rev=600397&view=rev
Log:
CAY-926 Refactoring class generator classes
(switching ant and maven to the new generator classes , split by generator version and client vs. server mode)

Added:
    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/ClassGeneratorMode.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/tools/AntLogger.java
      - copied, changed from r600273, cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/tools/AntTaskLogger.java
Removed:
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/tools/AntClassGenerator.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/tools/AntTaskLogger.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/tools/ILog.java
Modified:
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/AntClassGenerator.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/DefaultClassGenerator.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/MapClassGenerator.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/TemplateProcessor.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/TemplateProcessor1_1.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/tools/AntDataPortDelegate.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/tools/CayenneGeneratorTask.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/tools/NamePatternMatcher.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/tools/NamePatternMatcherTest.java
    cayenne/main/trunk/framework/maven-cayenne-plugin/src/main/java/org/apache/cayenne/tools/CayenneGeneratorMojo.java
    cayenne/main/trunk/framework/maven-cayenne-plugin/src/main/java/org/apache/cayenne/tools/MavenLogger.java

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/AntClassGenerator.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/AntClassGenerator.java?rev=600397&r1=600396&r2=600397&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/AntClassGenerator.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/AntClassGenerator.java Sun Dec  2 14:44:53 2007
@@ -27,8 +27,7 @@
  * Ant-specific extension of DefaultClassGenerator that provides logging functions.
  * 
  * @author Andrus Adamchik
- * @deprecated since 3.0 this class is replaced with a non-public class in the tools
- *             package.
+ * @deprecated since 3.0 this class is no longer relevant.
  */
 public class AntClassGenerator extends DefaultClassGenerator {
 

Added: 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=600397&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/ClassGenerationAction.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/ClassGenerationAction.java Sun Dec  2 14:44:53 2007
@@ -0,0 +1,520 @@
+/*****************************************************************
+ *   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 java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+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.ObjEntity;
+import org.apache.cayenne.tools.NamePatternMatcher;
+import org.apache.commons.logging.Log;
+import org.apache.velocity.VelocityContext;
+
+/**
+ * @since 3.0
+ * @author Andrus Adamchik
+ */
+public class ClassGenerationAction {
+
+    public static final String SINGLE_CLASS_TEMPLATE = "dotemplates/v1_2/singleclass.vm";
+    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 SUPERCLASS_PREFIX = "_";
+    private static final String WILDCARD = "*";
+
+    protected List<ObjEntity> objEntities;
+    protected String superPkg;
+    protected DataMap dataMap;
+    protected ClassGeneratorMode mode;
+    protected VelocityContext context;
+
+    protected Log logger;
+    protected File destDir;
+    protected boolean overwrite;
+    protected boolean usePkgPath;
+    protected boolean makePairs;
+    protected String template;
+    protected String superTemplate;
+    protected long timestamp;
+    protected String outputPattern;
+    protected String encoding;
+
+    public ClassGenerationAction() {
+        this.mode = ClassGeneratorMode.entity;
+        this.outputPattern = "*.java";
+        this.timestamp = System.currentTimeMillis();
+        this.usePkgPath = true;
+        this.makePairs = true;
+    }
+
+    protected String defaultSingleClassTemplate() {
+        return ClassGenerationAction.SINGLE_CLASS_TEMPLATE;
+    }
+
+    protected String defaultSubclassTemplate() {
+        return ClassGenerationAction.SUBCLASS_TEMPLATE;
+    }
+
+    protected String defaultSuperclassTemplate() {
+        return ClassGenerationAction.SUPERCLASS_TEMPLATE;
+    }
+
+    /**
+     * 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>.
+     */
+    public void generateClassPairs(
+            String classTemplate,
+            String superTemplate,
+            String superPrefix) throws Exception {
+
+        TemplateProcessor mainGenSetup = new TemplateProcessor(classTemplate, context);
+        TemplateProcessor superGenSetup = new TemplateProcessor(superTemplate, context);
+
+        for (ObjEntity ent : entitiesForCurrentMode()) {
+
+            String fqnSubClass = ent.getClassName();
+            String fqnBaseClass = (null != ent.getSuperClassName()) ? ent
+                    .getSuperClassName() : CayenneDataObject.class.getName();
+
+            StringUtils stringUtils = StringUtils.getInstance();
+
+            String subClassName = stringUtils.stripPackageName(fqnSubClass);
+            String subPackageName = stringUtils.stripClass(fqnSubClass);
+
+            String superClassName = superPrefix
+                    + stringUtils.stripPackageName(fqnSubClass);
+
+            String superPackageName = this.superPkg;
+            String fqnSuperClass = superPackageName + "." + superClassName;
+
+            Writer superOut = openWriter(ent, superPackageName, superClassName);
+
+            if (superOut != null) {
+                superGenSetup.generateClass(
+                        superOut,
+                        dataMap,
+                        ent,
+                        fqnBaseClass,
+                        fqnSuperClass,
+                        fqnSubClass);
+                superOut.close();
+            }
+
+            Writer mainOut = openWriter(ent, subPackageName, subClassName);
+            if (mainOut != null) {
+                mainGenSetup.generateClass(
+                        mainOut,
+                        dataMap,
+                        ent,
+                        fqnBaseClass,
+                        fqnSuperClass,
+                        fqnSubClass);
+                mainOut.close();
+            }
+        }
+    }
+
+    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 && !objEntities.isEmpty()) {
+            return Collections.singleton(objEntities.get(0));
+        }
+        else {
+            return this.objEntities;
+        }
+    }
+
+    /**
+     * Runs class generation. Produces a single Java class for each ObjEntity in the map.
+     */
+    public void generateSingleClasses(String classTemplate, String superPrefix)
+            throws Exception {
+
+        TemplateProcessor generator = new TemplateProcessor(classTemplate, context);
+
+        for (ObjEntity ent : entitiesForCurrentMode()) {
+
+            String fqnSubClass = ent.getClassName();
+            String fqnBaseClass = (null != ent.getSuperClassName()) ? ent
+                    .getSuperClassName() : CayenneDataObject.class.getName();
+
+            StringUtils stringUtils = StringUtils.getInstance();
+
+            String subClassName = stringUtils.stripPackageName(fqnSubClass);
+            String subPackageName = stringUtils.stripClass(fqnSubClass);
+
+            String superClassName = superPrefix
+                    + stringUtils.stripPackageName(fqnSubClass);
+
+            String superPackageName = this.superPkg;
+            String fqnSuperClass = superPackageName + "." + superClassName;
+
+            Writer out = openWriter(ent, subPackageName, subClassName);
+            if (out == null) {
+                continue;
+            }
+
+            generator.generateClass(
+                    out,
+                    dataMap,
+                    ent,
+                    fqnBaseClass,
+                    fqnSuperClass,
+                    fqnSubClass);
+            out.close();
+        }
+    }
+
+    /**
+     * Runs class generation.
+     */
+    public void execute() throws Exception {
+        validateAttributes();
+
+        if (makePairs) {
+            String t = getTemplateForPairs();
+            String st = getSupertemplateForPairs();
+            generateClassPairs(t, st, SUPERCLASS_PREFIX);
+        }
+        else {
+            generateSingleClasses(getTemplateForSingles(), SUPERCLASS_PREFIX);
+        }
+    }
+
+    /**
+     * Validates the state of this class generator. Throws CayenneRuntimeException if it
+     * is in an inconsistent state. Called internally from "execute".
+     */
+    protected void validateAttributes() {
+        if (destDir == null) {
+            throw new CayenneRuntimeException("'destDir' attribute is missing.");
+        }
+
+        if (!destDir.isDirectory()) {
+            throw new CayenneRuntimeException("'destDir' is not a directory.");
+        }
+
+        if (!destDir.canWrite()) {
+            throw new CayenneRuntimeException("Do not have write permissions for "
+                    + destDir);
+        }
+    }
+
+    /**
+     * Sets the destDir.
+     */
+    public void setDestDir(File destDir) {
+        this.destDir = destDir;
+    }
+
+    /**
+     * Sets <code>overwrite</code> property.
+     */
+    public void setOverwrite(boolean overwrite) {
+        this.overwrite = overwrite;
+    }
+
+    /**
+     * Sets <code>makepairs</code> property.
+     */
+    public void setMakePairs(boolean makePairs) {
+        this.makePairs = makePairs;
+    }
+
+    /**
+     * Sets <code>template</code> property.
+     */
+    public void setTemplate(String template) {
+        this.template = template;
+    }
+
+    /**
+     * Sets <code>superTemplate</code> property.
+     */
+    public void setSuperTemplate(String superTemplate) {
+        this.superTemplate = superTemplate;
+    }
+
+    /**
+     * Sets <code>usepkgpath</code> property.
+     */
+    public void setUsePkgPath(boolean usePkgPath) {
+        this.usePkgPath = usePkgPath;
+    }
+
+    /**
+     * Sets <code>outputPattern</code> property.
+     */
+    public void setOutputPattern(String outputPattern) {
+        this.outputPattern = outputPattern;
+    }
+
+    /**
+     * Opens a Writer to write generated output. Writer encoding is determined from the
+     * value of the "encoding" property.
+     */
+    protected Writer openWriter(ObjEntity entity, String pkgName, String className)
+            throws Exception {
+
+        boolean superclass = className.startsWith(SUPERCLASS_PREFIX);
+        File outFile = (superclass)
+                ? fileForSuperclass(pkgName, className)
+                : fileForClass(pkgName, className);
+
+        if (outFile == null) {
+            return null;
+        }
+
+        if (logger != null) {
+            String label = superclass ? "superclass" : "class";
+            logger.info("Generating " + label + " file: " + outFile.getCanonicalPath());
+        }
+
+        // return writer with specified encoding
+        FileOutputStream out = new FileOutputStream(outFile);
+
+        return (getEncoding() != null)
+                ? new OutputStreamWriter(out, getEncoding())
+                : new OutputStreamWriter(out);
+    }
+
+    /**
+     * 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 {
+
+        String filename = NamePatternMatcher.replaceWildcardInStringWithString(
+                WILDCARD,
+                outputPattern,
+                className);
+        File dest = new File(mkpath(destDir, pkgName), filename);
+
+        // Ignore if the destination is newer than the map
+        // (internal timestamp), i.e. has been generated after the map was
+        // last saved AND the template is older than the destination file
+        if (dest.exists() && !isOld(dest)) {
+
+            if (superTemplate == null) {
+                return null;
+            }
+
+            File superTemplateFile = new File(superTemplate);
+            if (superTemplateFile.lastModified() < dest.lastModified()) {
+                return null;
+            }
+        }
+
+        return dest;
+    }
+
+    /**
+     * 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 {
+
+        String filename = NamePatternMatcher.replaceWildcardInStringWithString(
+                WILDCARD,
+                outputPattern,
+                className);
+        File dest = new File(mkpath(destDir, pkgName), filename);
+
+        if (dest.exists()) {
+            // no overwrite of subclasses
+            if (makePairs) {
+                return null;
+            }
+
+            // skip if said so
+            if (!overwrite) {
+                return null;
+            }
+
+            // Ignore if the destination is newer than the map
+            // (internal timestamp), i.e. has been generated after the map was
+            // last saved AND the template is older than the destination file
+            if (!isOld(dest)) {
+
+                if (template == null) {
+                    return null;
+                }
+
+                File templateFile = new File(template);
+                if (templateFile.lastModified() < dest.lastModified()) {
+                    return null;
+                }
+            }
+        }
+
+        return dest;
+    }
+
+    /**
+     * Returns true if <code>file</code> parameter is older than internal timestamp of
+     * this class generator.
+     */
+    protected boolean isOld(File file) {
+        return file.lastModified() <= getTimestamp();
+    }
+
+    /**
+     * Returns a File object corresponding to a directory where files that belong to
+     * <code>pkgName</code> package should reside. Creates any missing diectories below
+     * <code>dest</code>.
+     */
+    protected File mkpath(File dest, String pkgName) throws Exception {
+
+        if (!usePkgPath || pkgName == null) {
+            return dest;
+        }
+
+        String path = pkgName.replace('.', File.separatorChar);
+        File fullPath = new File(dest, path);
+        if (!fullPath.isDirectory() && !fullPath.mkdirs()) {
+            throw new Exception("Error making path: " + fullPath);
+        }
+
+        return fullPath;
+    }
+
+    /**
+     * Returns template file path for Java class when generating single classes.
+     */
+    protected String getTemplateForSingles() throws IOException {
+        return (template != null) ? template : defaultSingleClassTemplate();
+    }
+
+    /**
+     * Returns template file path for Java subclass when generating class pairs.
+     */
+    protected String getTemplateForPairs() throws IOException {
+        return (template != null) ? template : defaultSubclassTemplate();
+    }
+
+    /**
+     * Returns template file path for Java superclass when generating class pairs.
+     */
+    protected String getSupertemplateForPairs() throws IOException {
+        return (superTemplate != null) ? superTemplate : defaultSuperclassTemplate();
+    }
+
+    /**
+     * Returns internal timestamp of this generator used to make decisions about
+     * overwriting individual files.
+     */
+    public long getTimestamp() {
+        return timestamp;
+    }
+
+    public void setTimestamp(long timestamp) {
+        this.timestamp = timestamp;
+    }
+
+    /**
+     * Returns file encoding for the generated files.
+     */
+    public String getEncoding() {
+        return encoding;
+    }
+
+    /**
+     * Sets file encoding. If set to null, default system encoding will be used.
+     */
+    public void setEncoding(String encoding) {
+        this.encoding = encoding;
+    }
+
+    /**
+     * Returns "superPkg" property value - a name of a superclass package that should be
+     * used for all generated superclasses.
+     */
+    public String getSuperPkg() {
+        return superPkg;
+    }
+
+    /**
+     * Sets "superPkg" property value.
+     */
+    public void setSuperPkg(String superPkg) {
+        this.superPkg = superPkg;
+    }
+
+    /**
+     * @return Returns the dataMap.
+     */
+    public DataMap getDataMap() {
+        return dataMap;
+    }
+
+    /**
+     * @param dataMap The dataMap to set.
+     */
+    public void setDataMap(DataMap dataMap) {
+        this.dataMap = dataMap;
+    }
+
+    public List<ObjEntity> getObjEntities() {
+        return objEntities;
+    }
+
+    /**
+     * 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 setObjEntities(List<ObjEntity> objEntities) {
+        this.objEntities = objEntities != null
+                ? new ArrayList<ObjEntity>(objEntities)
+                : new ArrayList<ObjEntity>();
+    }
+
+    public void setMode(ClassGeneratorMode mode) {
+        this.mode = mode;
+    }
+
+    public void setContext(VelocityContext context) {
+        this.context = context;
+    }
+
+    /**
+     * Injects an optional logger that will be used to trace generated files at the info
+     * level.
+     */
+    public void setLogger(Log logger) {
+        this.logger = logger;
+    }
+}

Added: 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=600397&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/ClassGenerationAction1_1.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/ClassGenerationAction1_1.java Sun Dec  2 14:44:53 2007
@@ -0,0 +1,172 @@
+/*****************************************************************
+ *   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 java.io.Writer;
+
+import org.apache.cayenne.CayenneDataObject;
+import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.map.ObjEntity;
+
+/**
+ * @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";
+
+    @Override
+    protected String defaultSingleClassTemplate() {
+        return ClassGenerationAction1_1.SINGLE_CLASS_TEMPLATE;
+    }
+
+    @Override
+    protected String defaultSubclassTemplate() {
+        return ClassGenerationAction1_1.SUBCLASS_TEMPLATE;
+    }
+
+    @Override
+    protected String defaultSuperclassTemplate() {
+        return ClassGenerationAction1_1.SUPERCLASS_TEMPLATE;
+    }
+
+    @Override
+    public void generateClassPairs(
+            String classTemplate,
+            String superTemplate,
+            String superPrefix) throws Exception {
+
+        TemplateProcessor1_1 mainGenerator = new TemplateProcessor1_1(classTemplate);
+        TemplateProcessor1_1 superGenerator = new TemplateProcessor1_1(superTemplate);
+
+        ClassGenerationInfo mainGen = mainGenerator.getClassGenerationInfo();
+        ClassGenerationInfo superGen = superGenerator.getClassGenerationInfo();
+
+        // prefix is needed for both generators
+        mainGen.setSuperPrefix(superPrefix);
+        superGen.setSuperPrefix(superPrefix);
+
+        for (ObjEntity entity : entitiesForCurrentMode()) {
+
+            // 1. do the superclass
+            initClassGenerator(superGen, entity, true);
+
+            Writer superOut = openWriter(entity, superGen.getPackageName(), superPrefix
+                    + superGen.getClassName());
+
+            if (superOut != null) {
+                superGenerator.generateClass(
+                        superOut,
+                        getDataMap(),
+                        entity,
+                        null,
+                        null,
+                        null);
+                superOut.close();
+            }
+
+            // 2. do the main class
+            initClassGenerator(mainGen, entity, false);
+            Writer mainOut = openWriter(entity, mainGen.getPackageName(), mainGen
+                    .getClassName());
+            if (mainOut != null) {
+                mainGenerator.generateClass(
+                        mainOut,
+                        getDataMap(),
+                        entity,
+                        null,
+                        null,
+                        null);
+                mainOut.close();
+            }
+        }
+    }
+
+    @Override
+    public void generateSingleClasses(String classTemplate, String superPrefix)
+            throws Exception {
+
+        TemplateProcessor1_1 generator = new TemplateProcessor1_1(classTemplate);
+
+        for (ObjEntity entity : entitiesForCurrentMode()) {
+
+            initClassGenerator(generator.getClassGenerationInfo(), entity, false);
+            Writer out = openWriter(entity, generator
+                    .getClassGenerationInfo()
+                    .getPackageName(), generator.getClassGenerationInfo().getClassName());
+            if (out == null) {
+                continue;
+            }
+
+            generator.generateClass(out, getDataMap(), entity, null, null, null);
+            out.close();
+        }
+    }
+
+    /**
+     * 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());
+        }
+        else {
+            generatorInfo.setSuperClassName(CayenneDataObject.class.getName());
+        }
+        generatorInfo.setSuperPackageName(spkg);
+    }
+}

Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/ClassGeneratorMode.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/ClassGeneratorMode.java?rev=600397&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/ClassGeneratorMode.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/ClassGeneratorMode.java Sun Dec  2 14:44:53 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;
+
+/**
+ * Defines whether generator is executed once per DataMap or once per ObjEntity.
+ * 
+ * @since 3.0
+ * @author Andrus Adamchik
+ */
+public enum ClassGeneratorMode {
+
+    datamap, entity
+}

Added: 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=600397&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/ClientClassGenerationAction.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/ClientClassGenerationAction.java Sun Dec  2 14:44:53 2007
@@ -0,0 +1,116 @@
+/*****************************************************************
+ *   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 java.io.Writer;
+
+import org.apache.cayenne.PersistentObject;
+import org.apache.cayenne.map.ObjEntity;
+
+/**
+ * @since 3.0
+ * @author Andrus Adamchik
+ */
+public class ClientClassGenerationAction extends ClassGenerationAction {
+
+    public static final String SUBCLASS_TEMPLATE = "dotemplates/v1_2/client-subclass.vm";
+    public static final String SUPERCLASS_TEMPLATE = "dotemplates/v1_2/client-superclass.vm";
+
+    @Override
+    protected String defaultSingleClassTemplate() {
+        throw new IllegalStateException(
+                "Default generation for single classes on the client is not supported.");
+    }
+
+    @Override
+    protected String defaultSubclassTemplate() {
+        return ClientClassGenerationAction.SUBCLASS_TEMPLATE;
+    }
+
+    @Override
+    protected String defaultSuperclassTemplate() {
+        return ClientClassGenerationAction.SUPERCLASS_TEMPLATE;
+    }
+
+    @Override
+    public void generateSingleClasses(String classTemplate, String superPrefix)
+            throws Exception {
+        throw new IllegalStateException(
+                "Single classes generation is not supported for the client.");
+    }
+
+    @Override
+    public void generateClassPairs(
+            String classTemplate,
+            String superTemplate,
+            String superPrefix) throws Exception {
+
+        TemplateProcessor mainGenSetup = new TemplateProcessor(classTemplate, context);
+        TemplateProcessor superGenSetup = new TemplateProcessor(superTemplate, context);
+
+        for (ObjEntity entity : entitiesForCurrentMode()) {
+
+            // use client name, and if not specified use regular class name
+            String fqnSubClass = entity.getClientClassName();
+            if (fqnSubClass == null) {
+                fqnSubClass = entity.getClassName();
+            }
+
+            // use PersistentObject instead of CayenneDataObject as base ...
+            String fqnBaseClass = (entity.getClientSuperClassName() != null) ? entity
+                    .getClientSuperClassName() : PersistentObject.class.getName();
+
+            StringUtils stringUtils = StringUtils.getInstance();
+
+            String subClassName = stringUtils.stripPackageName(fqnSubClass);
+            String subPackageName = stringUtils.stripClass(fqnSubClass);
+
+            String superClassName = superPrefix
+                    + stringUtils.stripPackageName(fqnSubClass);
+
+            String superPackageName = this.superPkg;
+            String fqnSuperClass = superPackageName + "." + superClassName;
+
+            Writer superOut = openWriter(entity, superPackageName, superClassName);
+
+            if (superOut != null) {
+                superGenSetup.generateClass(
+                        superOut,
+                        dataMap,
+                        entity,
+                        fqnBaseClass,
+                        fqnSuperClass,
+                        fqnSubClass);
+                superOut.close();
+            }
+
+            Writer mainOut = openWriter(entity, subPackageName, subClassName);
+            if (mainOut != null) {
+                mainGenSetup.generateClass(
+                        mainOut,
+                        dataMap,
+                        entity,
+                        fqnBaseClass,
+                        fqnSuperClass,
+                        fqnSubClass);
+                mainOut.close();
+            }
+        }
+    }
+}

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/DefaultClassGenerator.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/DefaultClassGenerator.java?rev=600397&r1=600396&r2=600397&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/DefaultClassGenerator.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/DefaultClassGenerator.java Sun Dec  2 14:44:53 2007
@@ -37,6 +37,7 @@
  * state of this object.
  * 
  * @author Andrus Adamchik
+ * @deprecated since 3.0 use {@link ClassGenerationAction} and subclasses.
  */
 public class DefaultClassGenerator extends MapClassGenerator {
 

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/MapClassGenerator.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/MapClassGenerator.java?rev=600397&r1=600396&r2=600397&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/MapClassGenerator.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/MapClassGenerator.java Sun Dec  2 14:44:53 2007
@@ -41,6 +41,7 @@
  * and {@link #closeWriter(Writer)} methods.
  * 
  * @author Andrus Adamchik
+ * @deprecated since 3.0 use {@link ClassGenerationAction} and subclasses.
  */
 public abstract class MapClassGenerator {
 

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/TemplateProcessor.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/TemplateProcessor.java?rev=600397&r1=600396&r2=600397&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/TemplateProcessor.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/TemplateProcessor.java Sun Dec  2 14:44:53 2007
@@ -31,8 +31,6 @@
 import org.apache.velocity.runtime.RuntimeConstants;
 import org.apache.velocity.runtime.log.NullLogSystem;
 
-import foundrylogic.vpp.VPPConfig;
-
 /**
  * Encapsulates a class generation template that can be used repeatedly to generate a set
  * of classes.
@@ -46,22 +44,15 @@
 
     protected Template classTemplate;
     protected Context velocityContext;
+    protected boolean superclass;
 
-    /**
-     * Only used by deprecated subclasses.
-     * 
-     * @deprecated since 3.0.
-     */
-    protected TemplateProcessor() throws Exception {
-    }
-
-    public TemplateProcessor(String template, VPPConfig vppConfig) throws Exception {
+    public TemplateProcessor(String template, Context velocityContext) throws Exception {
 
-        if (vppConfig != null) {
-            velocityContext = vppConfig.getVelocityContext();
+        if (velocityContext != null) {
+            this.velocityContext = velocityContext;
         }
         else {
-            velocityContext = new VelocityContext();
+            this.velocityContext = new VelocityContext();
         }
 
         initializeClassTemplate(template);
@@ -70,8 +61,6 @@
     /**
      * Sets up VelocityEngine properties, creates a VelocityEngine instance, and fetches a
      * template using the VelocityEngine instance.
-     * 
-     * @since 1.2
      */
     protected void initializeClassTemplate(String template)
             throws CayenneRuntimeException {
@@ -102,7 +91,8 @@
     }
 
     /**
-     * Generates Java code for the ObjEntity, writing output to the provided Writer.
+     * Generates code for provided context arguments, writing output to the provided
+     * Writer.
      */
     public void generateClass(
             Writer out,
@@ -125,6 +115,19 @@
                 fqnSuperClass,
                 fqnSubClass));
         velocityContext.put("importUtils", new ImportUtils());
+
         classTemplate.merge(velocityContext, out);
+    }
+
+    public void setClassTemplate(Template classTemplate) {
+        this.classTemplate = classTemplate;
+    }
+
+    public void setVelocityContext(Context velocityContext) {
+        this.velocityContext = velocityContext;
+    }
+
+    public void setSuperclass(boolean superclass) {
+        this.superclass = superclass;
     }
 }

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/TemplateProcessor1_1.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/TemplateProcessor1_1.java?rev=600397&r1=600396&r2=600397&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/TemplateProcessor1_1.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/gen/TemplateProcessor1_1.java Sun Dec  2 14:44:53 2007
@@ -20,8 +20,8 @@
 
 import java.io.Writer;
 
+import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.ObjEntity;
-import org.apache.velocity.VelocityContext;
 
 /**
  * Encapsulates a legacy class generation template.
@@ -33,19 +33,22 @@
 
     private ClassGenerationInfo classGenerationInfo;
 
-    TemplateProcessor1_1(String template) throws Exception {
+    public TemplateProcessor1_1(String template) throws Exception {
 
+        super(template, null);
         this.classGenerationInfo = new ClassGenerationInfo();
-        this.velocityContext = new VelocityContext();
         velocityContext.put("classGen", classGenerationInfo);
-
-        initializeClassTemplate(template);
     }
 
-    /**
-     * Generates Java code for the ObjEntity. Output is written to the provided Writer.
-     */
-    void generateClass(Writer out, ObjEntity entity) throws Exception {
+    @Override
+    public void generateClass(
+            Writer out,
+            DataMap dataMap,
+            ObjEntity entity,
+            String fqnBaseClass,
+            String fqnSuperClass,
+            String fqnSubClass) throws Exception {
+
         classGenerationInfo.setObjEntity(entity);
         classTemplate.merge(velocityContext, out);
     }

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/tools/AntDataPortDelegate.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/tools/AntDataPortDelegate.java?rev=600397&r1=600396&r2=600397&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/tools/AntDataPortDelegate.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/tools/AntDataPortDelegate.java Sun Dec  2 14:44:53 2007
@@ -59,7 +59,7 @@
         this.parentTask = parentTask;
 
         this.namePatternMatcher = new NamePatternMatcher(
-                new AntTaskLogger(parentTask),
+                new AntLogger(parentTask),
                 includeEntitiesPattern,
                 excludeEntitiesPattern);
 

Copied: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/tools/AntLogger.java (from r600273, cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/tools/AntTaskLogger.java)
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/tools/AntLogger.java?p2=cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/tools/AntLogger.java&p1=cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/tools/AntTaskLogger.java&r1=600273&r2=600397&rev=600397&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/tools/AntTaskLogger.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/tools/AntLogger.java Sun Dec  2 14:44:53 2007
@@ -19,21 +19,91 @@
 
 package org.apache.cayenne.tools;
 
+import org.apache.commons.logging.Log;
+import org.apache.tools.ant.Project;
 import org.apache.tools.ant.Task;
 
-public class AntTaskLogger implements ILog {
+/**
+ * @since 3.0
+ * @author Andrus Adamchik
+ */
+class AntLogger implements Log {
 
     private Task parentTask;
-    
-    public AntTaskLogger(Task parentTask) {
+
+    public AntLogger(Task parentTask) {
         this.parentTask = parentTask;
     }
-    
-    public void log(String msg) {
-        parentTask.log(msg);
+
+    public void debug(Object message, Throwable th) {
+        parentTask.log(String.valueOf(message), Project.MSG_DEBUG);
+    }
+
+    public void debug(Object message) {
+        parentTask.log(String.valueOf(message), Project.MSG_DEBUG);
+    }
+
+    public void error(Object message, Throwable th) {
+        parentTask.log(String.valueOf(message), Project.MSG_ERR);
+    }
+
+    public void error(Object message) {
+        parentTask.log(String.valueOf(message), Project.MSG_ERR);
+    }
+
+    public void fatal(Object message, Throwable th) {
+        parentTask.log(String.valueOf(message), Project.MSG_ERR);
+    }
+
+    public void fatal(Object message) {
+        parentTask.log(String.valueOf(message), Project.MSG_ERR);
+    }
+
+    public void info(Object message, Throwable th) {
+        parentTask.log(String.valueOf(message), Project.MSG_INFO);
+    }
+
+    public void info(Object message) {
+        parentTask.log(String.valueOf(message), Project.MSG_INFO);
+    }
+
+    public void trace(Object message, Throwable th) {
+        parentTask.log(String.valueOf(message), Project.MSG_VERBOSE);
+    }
+
+    public void trace(Object message) {
+        parentTask.log(String.valueOf(message), Project.MSG_VERBOSE);
+    }
+
+    public void warn(Object message, Throwable th) {
+        parentTask.log(String.valueOf(message), Project.MSG_WARN);
+    }
+
+    public void warn(Object message) {
+        parentTask.log(String.valueOf(message), Project.MSG_WARN);
+    }
+
+    public boolean isWarnEnabled() {
+        return true;
+    }
+
+    public boolean isDebugEnabled() {
+        return true;
+    }
+
+    public boolean isErrorEnabled() {
+        return true;
+    }
+
+    public boolean isFatalEnabled() {
+        return true;
+    }
+
+    public boolean isInfoEnabled() {
+        return true;
     }
 
-    public void log(String msg, int msgLevel) {
-        parentTask.log(msg, msgLevel);
+    public boolean isTraceEnabled() {
+        return true;
     }
 }

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=600397&r1=600396&r2=600397&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  2 14:44:53 2007
@@ -21,12 +21,17 @@
 import java.io.File;
 import java.util.List;
 
+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.gen.DefaultClassGenerator;
 import org.apache.cayenne.gen.MapClassGenerator;
 import org.apache.cayenne.map.ObjEntity;
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.types.Path;
+import org.apache.velocity.VelocityContext;
 
 import foundrylogic.vpp.VPPConfig;
 
@@ -54,22 +59,60 @@
     protected String supertemplate;
     protected String template;
     protected boolean usepkgpath;
+
+    /**
+     * @deprecated since 3.0
+     */
     protected String version;
 
     public CayenneGeneratorTask() {
         this.makepairs = true;
-        this.mode = MapClassGenerator.MODE_ENTITY;
+        this.mode = ClassGeneratorMode.entity.name();
         this.outputPattern = "*.java";
         this.usepkgpath = true;
         this.version = MapClassGenerator.DEFAULT_VERSION;
     }
 
+    protected VelocityContext getVppContext() {
+        initializeVppConfig();
+        return vppConfig.getVelocityContext();
+    }
+
+    protected ClassGenerationAction createGeneratorAction() {
+        ClassGenerationAction action;
+        if (client) {
+            action = new ClientClassGenerationAction();
+            action.setContext(getVppContext());
+        }
+        else if (ClassGenerator.VERSION_1_1.equals(version)) {
+            action = new ClassGenerationAction1_1();
+        }
+        else {
+            action = new ClassGenerationAction();
+            action.setContext(getVppContext());
+        }
+
+        action.setDestDir(destDir);
+        action.setEncoding(encoding);
+        action.setMakePairs(makepairs);
+        action.setMode(ClassGeneratorMode.valueOf(mode));
+        action.setOutputPattern(outputPattern);
+        action.setOverwrite(overwrite);
+        action.setSuperPkg(superpkg);
+        action.setSuperTemplate(supertemplate);
+        action.setTemplate(template);
+        action.setUsePkgPath(usepkgpath);
+
+        return action;
+    }
+
     /**
      * Factory method to create internal class generator. Called from constructor.
+     * 
+     * @deprecated since 3.0. Use {@link #createGeneratorAction()}.
      */
     protected DefaultClassGenerator createGenerator() {
-        AntClassGenerator gen = new AntClassGenerator();
-        gen.setParentTask(this);
+        DefaultClassGenerator gen = new DefaultClassGenerator();
 
         gen.setClient(client);
         gen.setDestDir(destDir);
@@ -92,16 +135,8 @@
      */
     public void execute() throws BuildException {
         validateAttributes();
-        
-        DefaultClassGenerator generator = createGenerator();
-
-        // Take care of setting up VPP for the generator.
-        if (!ClassGenerator.VERSION_1_1.equals(generator.getVersionString())) {
-            initializeVppConfig();
-            generator.setVppConfig(vppConfig);
-        }
 
-        ILog logger = new AntTaskLogger(this);
+        AntLogger logger = new AntLogger(this);
         CayenneGeneratorMapLoaderAction loadAction = new CayenneGeneratorMapLoaderAction();
 
         loadAction.setMainDataMapFile(map);
@@ -115,12 +150,13 @@
                 excludeEntitiesPattern));
 
         try {
-            generator.setTimestamp(map.lastModified());
-            generator.setDataMap(loadAction.getMainDataMap());
-            generator.setObjEntities((List<ObjEntity>) filterAction
+            ClassGenerationAction generatorAction = createGeneratorAction();
+            generatorAction.setLogger(logger);
+            generatorAction.setTimestamp(map.lastModified());
+            generatorAction.setDataMap(loadAction.getMainDataMap());
+            generatorAction.setObjEntities((List<ObjEntity>) filterAction
                     .getFilteredEntities(loadAction.getMainDataMap()));
-            generator.validateAttributes();
-            generator.execute();
+            generatorAction.execute();
         }
         catch (Exception e) {
             throw new BuildException(e);
@@ -218,6 +254,8 @@
 
     /**
      * Sets <code>version</code> property.
+     * 
+     * @deprecated since 3.0
      */
     public void setVersion(String version) {
         if (!ClassGenerator.VERSION_1_1.equals(version)

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/tools/NamePatternMatcher.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/tools/NamePatternMatcher.java?rev=600397&r1=600396&r2=600397&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/tools/NamePatternMatcher.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/tools/NamePatternMatcher.java Sun Dec  2 14:44:53 2007
@@ -27,6 +27,7 @@
 import java.util.regex.PatternSyntaxException;
 
 import org.apache.cayenne.util.CayenneMapEntry;
+import org.apache.commons.logging.Log;
 
 /**
  * Provides name pattern matching functionality.
@@ -36,12 +37,12 @@
  */
 public class NamePatternMatcher {
 
-    protected ILog logger;
+    protected Log logger;
 
     protected Pattern[] itemIncludeFilters;
     protected Pattern[] itemExcludeFilters;
 
-    public NamePatternMatcher(ILog logger, String includePattern, String excludePattern) {
+    public NamePatternMatcher(Log logger, String includePattern, String excludePattern) {
         this.logger = logger;
         this.itemIncludeFilters = createPatterns(includePattern);
         this.itemExcludeFilters = createPatterns(excludePattern);
@@ -69,10 +70,10 @@
             catch (PatternSyntaxException e) {
 
                 if (logger != null) {
-                    logger.log("Ignoring invalid pattern ["
+                    logger.warn("Ignoring invalid pattern ["
                             + patternStrings[i]
                             + "], reason: "
-                            + e.getMessage(), ILog.MSG_WARN);
+                            + e.getMessage());
                 }
                 continue;
             }

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/tools/NamePatternMatcherTest.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/tools/NamePatternMatcherTest.java?rev=600397&r1=600396&r2=600397&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/tools/NamePatternMatcherTest.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/tools/NamePatternMatcherTest.java Sun Dec  2 14:44:53 2007
@@ -71,7 +71,7 @@
         String includePattern = "billing_*,user?";
         String excludePattern = null;
         NamePatternMatcher namePatternMatcher = new NamePatternMatcher(
-                new AntTaskLogger(parentTask),
+                new AntLogger(parentTask),
                 includePattern,
                 excludePattern);
 
@@ -98,7 +98,7 @@
         String includePattern = "Organization,SecGroup,SecIndividual";
         String excludePattern = null;
         NamePatternMatcher namePatternMatcher = new NamePatternMatcher(
-                new AntTaskLogger(parentTask),
+                new AntLogger(parentTask),
                 includePattern,
                 excludePattern);
 

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=600397&r1=600396&r2=600397&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  2 14:44:53 2007
@@ -22,8 +22,13 @@
 import java.io.File;
 import java.util.List;
 
-import org.apache.cayenne.gen.DefaultClassGenerator;
+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;
 import org.apache.maven.plugin.MojoFailureException;
@@ -195,8 +200,6 @@
 	 */
 	private String version;
 
-	private DefaultClassGenerator generator;
-
 	public void execute() throws MojoExecutionException, MojoFailureException {
 		// Create the destination directory if necessary.
 		// TODO: (KJM 11/2/06) The destDir really should be added as a
@@ -205,9 +208,7 @@
 			destDir.mkdirs();
 		}
 
-		generator = createGenerator();
-
-		ILog logger = new MavenLogger(this);
+		Log logger = new MavenLogger(this);
 		CayenneGeneratorMapLoaderAction loaderAction = new CayenneGeneratorMapLoaderAction();
 		loaderAction.setMainDataMapFile(map);
 
@@ -219,11 +220,12 @@
 		try {
 			loaderAction.setAdditionalDataMapFiles(convertAdditionalDataMaps());
 
+			ClassGenerationAction generator = createGenerator();
+			generator.setLogger(logger);
 			generator.setTimestamp(map.lastModified());
 			generator.setDataMap(loaderAction.getMainDataMap());
 			generator.setObjEntities((List<ObjEntity>) filterAction
 					.getFilteredEntities(loaderAction.getMainDataMap()));
-			generator.validateAttributes();
 			generator.execute();
 		} catch (Exception e) {
 			throw new MojoExecutionException("Error generating classes: ", e);
@@ -256,22 +258,29 @@
 	 * Factory method to create internal class generator. Called from
 	 * constructor.
 	 */
-	protected DefaultClassGenerator createGenerator() {
-		DefaultClassGenerator gen = new DefaultClassGenerator();
+	protected ClassGenerationAction createGenerator() {
+
+		ClassGenerationAction action;
+		if (client) {
+			action = new ClientClassGenerationAction();
+		} else if (ClassGenerator.VERSION_1_1.equals(version)) {
+			action = new ClassGenerationAction1_1();
+		} else {
+			action = new ClassGenerationAction();
+		}
 
-		gen.setClient(client);
-		gen.setDestDir(destDir);
-		gen.setEncoding(encoding);
-		gen.setMakePairs(makePairs);
-		gen.setMode(mode);
-		gen.setOutputPattern(outputPattern);
-		gen.setOverwrite(overwrite);
-		gen.setSuperPkg(superPkg);
-		gen.setSuperTemplate(superTemplate);
-		gen.setTemplate(template);
-		gen.setUsePkgPath(usePkgPath);
-		gen.setVersionString(version);
+		action.setDestDir(destDir);
+		action.setEncoding(encoding);
+		action.setMakePairs(makePairs);
+		action.setMode(mode != null ? ClassGeneratorMode.valueOf(mode)
+				: ClassGeneratorMode.entity);
+		action.setOutputPattern(outputPattern);
+		action.setOverwrite(overwrite);
+		action.setSuperPkg(superPkg);
+		action.setSuperTemplate(superTemplate);
+		action.setTemplate(template);
+		action.setUsePkgPath(usePkgPath);
 
-		return gen;
+		return action;
 	}
 }

Modified: cayenne/main/trunk/framework/maven-cayenne-plugin/src/main/java/org/apache/cayenne/tools/MavenLogger.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/maven-cayenne-plugin/src/main/java/org/apache/cayenne/tools/MavenLogger.java?rev=600397&r1=600396&r2=600397&view=diff
==============================================================================
--- cayenne/main/trunk/framework/maven-cayenne-plugin/src/main/java/org/apache/cayenne/tools/MavenLogger.java (original)
+++ cayenne/main/trunk/framework/maven-cayenne-plugin/src/main/java/org/apache/cayenne/tools/MavenLogger.java Sun Dec  2 14:44:53 2007
@@ -19,48 +19,87 @@
 package org.apache.cayenne.tools;
 
 import org.apache.maven.plugin.AbstractMojo;
-import org.apache.maven.plugin.logging.Log;
 
 /**
  * @since 3.0
  */
-class MavenLogger implements ILog {
+class MavenLogger implements org.apache.commons.logging.Log {
 
-	private Log logger;
+	private org.apache.maven.plugin.logging.Log logger;
 
 	public MavenLogger(AbstractMojo parent) {
 		this.logger = parent.getLog();
 	}
 
-	public void log(String msg) {
-		logger.debug(msg);
+	public void debug(Object message, Throwable th) {
+		logger.debug(String.valueOf(message), th);
 	}
 
-	public void log(String msg, int msgLevel) {
+	public void debug(Object message) {
+		logger.debug(String.valueOf(message));
+	}
+
+	public void error(Object message, Throwable th) {
+		logger.error(String.valueOf(message), th);
+	}
+
+	public void error(Object message) {
+		logger.error(String.valueOf(message));
+	}
+
+	public void fatal(Object message, Throwable th) {
+		logger.error(String.valueOf(message), th);
+	}
+
+	public void fatal(Object message) {
+		logger.error(String.valueOf(message));
+	}
+
+	public void info(Object message, Throwable th) {
+		logger.info(String.valueOf(message), th);
+	}
+
+	public void info(Object message) {
+		logger.info(String.valueOf(message));
+	}
 
-		switch (msgLevel) {
-		case ILog.MSG_DEBUG:
-			logger.debug(msg);
-			break;
+	public boolean isDebugEnabled() {
+		return logger.isDebugEnabled();
+	}
 
-		case ILog.MSG_ERR:
-			logger.error(msg);
-			break;
+	public boolean isErrorEnabled() {
+		return logger.isErrorEnabled();
+	}
 
-		case ILog.MSG_INFO:
-			logger.info(msg);
-			break;
+	public boolean isFatalEnabled() {
+		return logger.isErrorEnabled();
+	}
 
-		case ILog.MSG_VERBOSE:
-			logger.info(msg);
-			break;
+	public boolean isInfoEnabled() {
+		return logger.isInfoEnabled();
+	}
 
-		case ILog.MSG_WARN:
-			logger.warn(msg);
-			break;
+	public boolean isTraceEnabled() {
+		return logger.isDebugEnabled();
+	}
+
+	public boolean isWarnEnabled() {
+		return logger.isWarnEnabled();
+	}
+
+	public void trace(Object message, Throwable th) {
+		logger.debug(String.valueOf(message), th);
+	}
+
+	public void trace(Object message) {
+		logger.debug(String.valueOf(message));
+	}
+
+	public void warn(Object message, Throwable th) {
+		logger.warn(String.valueOf(message), th);
+	}
 
-		default:
-			logger.debug(msg);
-		}
+	public void warn(Object message) {
+		logger.warn(String.valueOf(message));
 	}
 }