CVS: xdoclet/modules/jdo/src/xdoclet/modules/jdo JdoObjectIdGeneratorTagsHandler.java,NONE,1.1 JdoObjectIdGeneratorSubTask.java,NONE,1.1 JdoXmlMetadataSubTask.java,1.14,1.15

Marco Schulze <[email protected]>
Newsgroups gmane.comp.java.xdoclet.devel
Message-ID <[email protected]>
Update of /cvsroot/xdoclet/xdoclet/modules/jdo/src/xdoclet/modules/jdo
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv2274/modules/jdo/src/xdoclet/modules/jdo

Modified Files:
	JdoXmlMetadataSubTask.java 
Added Files:
	JdoObjectIdGeneratorTagsHandler.java 
	JdoObjectIdGeneratorSubTask.java 
Log Message:
XDoclet finally supports the automatic creation of JDO objectid-classes!

--- NEW FILE: JdoObjectIdGeneratorTagsHandler.java ---
/*
 * Copyright (c) 2001, 2002 The XDoclet team
 * All rights reserved.
 */
package xdoclet.modules.jdo;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.Set;

import org.apache.commons.logging.Log;
import xjavadoc.XClass;
import xjavadoc.XDoc;
import xjavadoc.XField;

import xdoclet.XDocletException;
import xdoclet.XDocletTagSupport;
import xdoclet.util.LogUtil;

/**
 * @author               Marco Schulze <[email protected]>
 * @created              August 29, 2005
 * @xdoclet.taghandler   namespace="JdoObjectIdGenerator"
 */
public class JdoObjectIdGeneratorTagsHandler extends XDocletTagSupport
{
    /**
     * This Comparator is used to sort the primary-key-fields by their name.
     */
    protected static Comparator pkFieldComparator =
        new Comparator()
        {
            public int compare(Object obj0, Object obj1)
            {
                XField f0 = (XField) obj0;
                XField f1 = (XField) obj1;

                return f0.getName().compareTo(f1.getName());
            }
        };

    private static boolean lastPrimaryKeyField = false;
    private static XField currentPrimaryKeyField = null;

    /**
     * Used by {@link #isPrimitive(XClass)} to find out whether a class is primitive. Contains instances of {@link
     * java.lang.String} representing the primitive class names (e.g. "long").
     */
    private static Set primitiveClassNames = null;

    public static XField getCurrentPrimaryKeyField()
    {
        return currentPrimaryKeyField;
    }

    public static void setCurrentPrimaryKeyField(XField pkField)
    {
        currentPrimaryKeyField = pkField;
    }

    /**
     * For whatever reason, {@link XClass#isPrimitive()} doesn't work and always returns <tt>true</tt> . Hence, we check
     * it ourselves. This method returns true, if <tt>clazz</tt> is one of the following:
     * <ul>
     *   <li> boolean</li>
     *   <li> byte</li>
     *   <li> char</li>
     *   <li> double</li>
     *   <li> float</li>
     *   <li> int</li>
     *   <li> long</li>
     *   <li> short</li>
     * </ul>
     *
     *
     * @param clazz  The XClass to check.
     * @return       true, if the given clazz is primitive, false otherwise.
     */
    protected static boolean isPrimitive(XClass clazz)
    {
        if (primitiveClassNames == null) {
            Set s = new HashSet();

            s.add("boolean");
            s.add("byte");
            s.add("char");
            s.add("double");
            s.add("float");
            s.add("int");
            s.add("long");
            s.add("short");
            primitiveClassNames = s;
        }

        return primitiveClassNames.contains(clazz.getQualifiedName());
    }

    public String getObjectIdPackage(Properties attributes) throws XDocletException
    {
        return getObjectIdClassOrPackage(true);
    }

    public String getObjectIdClass(Properties attributes) throws XDocletException
    {
        return getObjectIdClassOrPackage(false);
    }

    public String getCurrentPrimaryKeyFieldName(Properties attributes) throws XDocletException
    {
        XField pkf = getCurrentPrimaryKeyField();

        if (pkf == null)
            throw new IllegalStateException("Cannot access current primary key field outside of forAllPrimaryKeyFields-loop!");

        return pkf.getName();
    }

    public String getCurrentPrimaryKeyFieldType(Properties attributes) throws XDocletException
    {
        XField pkf = getCurrentPrimaryKeyField();

        if (pkf == null)
            throw new IllegalStateException("Cannot access current primary key field outside of forAllPrimaryKeyFields-loop!");

        return pkf.getType().getQualifiedName();
    }

    public void ifCurrentPrimaryKeyFieldIsPrimitive(String template, Properties attributes) throws XDocletException
    {
        XField pkf = getCurrentPrimaryKeyField();

        if (pkf == null)
            throw new IllegalStateException("Cannot work with primary key fields outside of forAllPrimaryKeyFields-loop!");

        if (isPrimitive(pkf.getType()))
            generate(template);
    }

    public void ifCurrentPrimaryKeyFieldIsNotPrimitive(String template, Properties attributes) throws XDocletException
    {
        XField pkf = getCurrentPrimaryKeyField();

        if (pkf == null)
            throw new IllegalStateException("Cannot work with primary key fields outside of forAllPrimaryKeyFields-loop!");

        if (!isPrimitive(pkf.getType()))
            generate(template);
    }

    public void ifNotLastPrimaryKeyField(String template, Properties attributes) throws XDocletException
    {
        XField pkf = getCurrentPrimaryKeyField();

        if (pkf == null)
            throw new IllegalStateException("Cannot work with primary key fields outside of forAllPrimaryKeyFields-loop!");

        if (lastPrimaryKeyField)
            generate(template);
    }

    /**
     * The <code>forAllPrimaryKeyFields</code> method iterates through all primary key fields in the current class.
     *
     * @param template              a <code>String</code> value
     * @param attributes            a <code>Properties</code> value
     * @exception XDocletException  if an error occurs
     * @doc:tag                     type="block"
     */
    public void forAllPrimaryKeyFields(String template, Properties attributes) throws XDocletException
    {
        Log log = LogUtil.getLog(this.getClass(), "forAllPrimaryKeyFields");

        log.debug("enter method forAllPrimaryKeyFields...");

        XClass clazz = getCurrentClass();

        List pkFields = new ArrayList();

        for (Iterator it = clazz.getFields().iterator(); it.hasNext(); ) {
            XField field = (XField) it.next();
            XDoc fieldDoc = field.getDoc();

            if (fieldDoc.hasTag("jdo.field")) {
                if ("true".equals(fieldDoc.getTag("jdo.field").getAttributeValue("primary-key")))
                    pkFields.add(field);
            }
        }

        // sort the pk-fields alphabetically by their name
        Collections.sort(pkFields, pkFieldComparator);

        // if there is a desired order specified, we respect it
        String fieldOrderStr = clazz.getDoc().getTagAttributeValue("jdo.create-objectid-class", "field-order");

        if (fieldOrderStr != null && !"".equals(fieldOrderStr)) {
            String[] fieldOrder = fieldOrderStr.replaceAll(" ", "").split(",");
            int newIdx = 0;

            for (int i = 0; i < fieldOrder.length; ++i) {
                String field = fieldOrder[i];
                int oldIdx = -1;

                for (int m = 0; m < pkFields.size(); ++m) {
                    if (((XField) pkFields.get(m)).getName().equals(field)) {
                        oldIdx = m;
                        break;
                    }
                }

                if (oldIdx >= 0) {
                    XField f = (XField) pkFields.remove(oldIdx);

                    pkFields.add(newIdx, f);
                    ++newIdx;
                }
                else
                    throw new XDocletException("Class \"" + clazz.getQualifiedName() + "\" has field \"" + field + "\" specified in '@jdo.create-objectid-class order-fields', but this field does not exist or is not tagged as primary-key-field!");
            }
        }
        // if (fieldsOrderStr != null && !"".equals(fieldsOrderStr)) {

        if (log.isDebugEnabled())
            log.debug("Iterating " + pkFields.size() + " primary-key fields...");

        for (Iterator it = pkFields.iterator(); it.hasNext(); ) {
            XField pkField = (XField) it.next();

            lastPrimaryKeyField = it.hasNext();
            setCurrentPrimaryKeyField(pkField);

            generate(template);
        }
        setCurrentPrimaryKeyField(null);

        log.debug("exit method forAllPrimaryKeyFields.");
    }

    protected String getObjectIdClassOrPackage(boolean pakkage)
    {
        Log log = LogUtil.getLog(this.getClass(), "getObjectIdClassOrPackage");

        XClass clazz = getCurrentClass();
        XDoc classDoc = clazz.getDoc();

        if (!classDoc.hasTag("jdo.create-objectid-class"))
            throw new IllegalStateException("No @jdo.create-objectid-class tag! This class should not be processed!");

        String objectIDClassWithPackage = classDoc.getTag("jdo.persistence-capable").getAttributeValue("objectid-class");

        if (objectIDClassWithPackage == null || "".equals(objectIDClassWithPackage))
            throw new IllegalStateException("No objectid-class specified! This class should not be processed!");

        // extend the package, if it is missing
        if (objectIDClassWithPackage.indexOf('.') < 0) {
            objectIDClassWithPackage = clazz.getContainingPackage().getName() + '.' + objectIDClassWithPackage;
            if (log.isDebugEnabled())
                log.debug("Class " + clazz.getQualifiedName() + " specifies its objectid-class without package. Have extended it to \"" + objectIDClassWithPackage + "\"!");
        }

        String objectIDPackage = objectIDClassWithPackage.substring(0, objectIDClassWithPackage.lastIndexOf('.'));

        if (pakkage)
            return objectIDPackage;

        String objectIDClass = objectIDClassWithPackage.substring(objectIDPackage.length() + 1);

        return objectIDClass;
    }
}

--- NEW FILE: JdoObjectIdGeneratorSubTask.java ---
/*
 * Copyright (c) 2001, 2002 The XDoclet team
 * All rights reserved.
 */
package xdoclet.modules.jdo;

import java.io.File;

import org.apache.commons.logging.Log;
import xjavadoc.XClass;
import xjavadoc.XDoc;

import xdoclet.TemplateSubTask;
import xdoclet.XDocletException;
import xdoclet.util.LogUtil;

/**
 * @author        Marco Schulze ([email protected])
 * @created       August 29, 2005
 * @version       $Revision: 1.1 $
 * @ant.element   display-name="JDO ObjectId Generator" name="jdoobjectidgenerator"
 *      parent="xdoclet.modules.jdo.JdoDocletTask"
 */
public class JdoObjectIdGeneratorSubTask
     extends TemplateSubTask
{
    protected final static String DEFAULT_TEMPLATE_FILE = "resources/java_objectid.xdt";

    public JdoObjectIdGeneratorSubTask()
    {
        Log log = LogUtil.getLog(this.getClass(), "constructor");

        log.debug("New instance of JdoObjectIdGeneratorSubTask created.");

        setTemplateURL(getClass().getResource(DEFAULT_TEMPLATE_FILE));
        setDestinationFile("{0}.java");
        // will be ignored in getGeneratedFileName
        addOfType("java.lang.Object");
        setPackageSubstitutionInheritanceSupported(false);
    }

    protected String getGeneratedFileName(XClass clazz)
         throws XDocletException
    {
        Log log = LogUtil.getLog(this.getClass(), "getGeneratedFileName");
        XDoc classDoc = clazz.getDoc();

        // ignore all classes that do not have the tag @jdo.create-objectid-class
        if (!classDoc.hasTag("jdo.create-objectid-class"))
            throw new IllegalStateException("No @jdo.create-objectid-class tag! This should be checked by matchesGenerationRules(...)!");

        // find out what's the objectid-class
        String objectIDClassWithPackage = classDoc.getTag("jdo.persistence-capable").getAttributeValue("objectid-class");

        if (objectIDClassWithPackage == null || "".equals(objectIDClassWithPackage))
            throw new IllegalStateException("No objectid-class specified! This should be checked by matchesGenerationRules(...)!");

        String res = objectIDClassWithPackage.replace('.', File.separatorChar) + ".java";

        if (log.isDebugEnabled())
            log.debug("result=" + res);

        return res;
    }

    protected boolean matchesGenerationRules(XClass clazz) throws XDocletException
    {
        Log log = LogUtil.getLog(this.getClass(), "matchesGenerationRules");
        XDoc classDoc = clazz.getDoc();

        // ignore all classes that do not have the tag @jdo.create-objectid-class
        if (!classDoc.hasTag("jdo.create-objectid-class")) {
            if (log.isDebugEnabled())
                log.debug("Class " + clazz.getQualifiedName() + " does not have tag @jdo.create-objectid-class - won't create an object-id-class.");
            return false;
        }

        // find out what's the objectid-class
        String objectIDClassWithPackage = classDoc.getTag("jdo.persistence-capable").getAttributeValue("objectid-class");

        if (objectIDClassWithPackage == null || "".equals(objectIDClassWithPackage)) {
            log.warn("Though the class " + clazz.getQualifiedName() + " has the tag @jdo.create-objectid-class present, it does not have an objectid-class specified. Cannot create the class!");
            return false;
        }

        return true;
    }
}

Index: JdoXmlMetadataSubTask.java
===================================================================
RCS file: /cvsroot/xdoclet/xdoclet/modules/jdo/src/xdoclet/modules/jdo/JdoXmlMetadataSubTask.java,v
retrieving revision 1.14
retrieving revision 1.15
diff -C2 -r1.14 -r1.15
*** JdoXmlMetadataSubTask.java	20 Jul 2005 14:43:48 -0000	1.14
--- JdoXmlMetadataSubTask.java	29 Aug 2005 20:28:50 -0000	1.15
***************
*** 12,16 ****
  
  import org.apache.commons.logging.Log;
! import xjavadoc.*;
  import xdoclet.XDocletException;
  import xdoclet.XDocletMessages;
--- 12,18 ----
  
  import org.apache.commons.logging.Log;
! import xjavadoc.XPackage;
! 
! import xdoclet.DocletContext;
  import xdoclet.XDocletException;
  import xdoclet.XDocletMessages;
***************
*** 28,31 ****
--- 30,34 ----
   * @author               Ludovic Claude ([email protected])
   * @author               David Jencks ([email protected])
+  * @author               Marco Schulze ([email protected])
   * @created              June 11, 20012
   * @version              $Revision$
***************
*** 54,58 ****
      private static String JDOXML_DTD_FILE_NAME_2_0 = "resources/jdo_2_0.dtd";
  
-     private String  jdoSpec = null;
      private String  generation = "class";
      private boolean forceGenerationPerPackage;
--- 57,60 ----
***************
*** 68,86 ****
      }
  
-     /**
-      * Gets the Jdospec attribute of the JdoXmlSubTask object
-      *
-      * @return   The Jdospec value
-      */
-     public String getJdoSpec()
-     {
-         if (jdoSpec != null)
-             return jdoSpec;
- 
-         // TODO Why the hell doesn't it copy the parameters from JdoDocletTask to JdoXmlMetadataSubTask???
-         // Fortunately, the correct value can be found in getContext().getConfigParam(...):
-         return (String) getContext().getConfigParam("jdospec");
-     }
- 
      public String getGeneration()
      {
--- 70,73 ----
***************
*** 104,121 ****
  
      /**
-      * Sets the Jdospec attribute of the JdoXmlSubTask object
-      *
-      * @param jdoSpec  The new Jdospec value
-      */
-     public void setJdoSpec(JdoSpecVersion jdoSpec)
-     {
-         // TODO Why is this method never called? see getJdoSpec()!
-         Log log = LogUtil.getLog(JdoXmlMetadataSubTask.class, "setJdoSpec");
- 
-         log.info("new jdoSpec: " + jdoSpec.getValue());
-         this.jdoSpec = jdoSpec.getValue();
-     }
- 
-     /**
       * Called to validate configuration parameters.
       *
--- 91,94 ----
***************
*** 136,142 ****
      public void execute() throws XDocletException
      {
-         String jdoSpec = getJdoSpec();
          Log log = LogUtil.getLog(JdoXmlMetadataSubTask.class, "execute");
  
          log.info("Using jdoSpec \"" + jdoSpec + "\".");
  
--- 109,122 ----
      public void execute() throws XDocletException
      {
          Log log = LogUtil.getLog(JdoXmlMetadataSubTask.class, "execute");
  
+         DocletContext context = getContext();
+ 
+         if (context == null)
+             throw new NullPointerException("Have no DocletContext!");
+ 
+ //        String jdoSpec = getJdoSpec();
+         String jdoSpec = (String) context.getConfigParam("jdospec");
+ 
          log.info("Using jdoSpec \"" + jdoSpec + "\".");
  



-------------------------------------------------------
SF.Net email is Sponsored by the Better Software Conference & EXPO
September 19-22, 2005 * San Francisco, CA * Development Lifecycle Practices
Agile & Plan-Driven Development * Managing Projects & Teams * Testing & QA
Security * Process Improvement & Measurement * http://www.sqe.com/bsce5sf
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.