alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Glassfish example source code file (JDOConcreteBeanGenerator.java)

This example Glassfish source code file (JDOConcreteBeanGenerator.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Glassfish tags/keywords

class, exception, file, io, ioexception, ioexception, jdoqlelements, method, noi18n, noi18n, persistencefieldelement, reflection, string, string, stringbuffer, stringbuffer, text, util

The Glassfish JDOConcreteBeanGenerator.java source code

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */

/*
 * JDOConcreteBeanGenerator.java
 *
 * Created on November 20, 2001
 */

package com.sun.jdo.spi.persistence.support.ejb.ejbc;

import java.util.*;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.text.MessageFormat;

import com.sun.jdo.api.persistence.model.Model;
import com.sun.jdo.api.persistence.model.jdo.*;
import com.sun.jdo.api.persistence.model.mapping.MappingClassElement;
import com.sun.jdo.api.persistence.model.mapping.MappingFieldElement;

import com.sun.jdo.spi.persistence.support.ejb.model.DeploymentDescriptorModel;
import com.sun.jdo.spi.persistence.support.ejb.model.util.NameMapper;
import com.sun.jdo.spi.persistence.support.ejb.ejbqlc.JDOQLElements;

import org.glassfish.persistence.common.I18NHelper;
import com.sun.jdo.spi.persistence.utility.StringHelper;
import com.sun.jdo.spi.persistence.utility.generator.*;
import com.sun.jdo.spi.persistence.utility.generator.io.*;
import com.sun.jdo.spi.persistence.utility.logging.Logger;
 
/*
 * This is the base class for JDO specific generator for the concrete CMP 
 * beans.
 *
 * @author Marina Vatkina
 */
abstract class JDOConcreteBeanGenerator {

    static final Logger logger = LogHelperEJBCompiler.getLogger();

    // used to transform b/w various ejb names and pc class names
    NameMapper nameMapper = null;

    Model model = null;        // used to look up various metadata

    String appName = null;
    String beanName = null;
    String helperName = null;
    String concreteImplName = null;
    String abstractBean = null;
    String pkClass = null;
    String pcname = null;
    boolean hasLocalInterface;
    boolean hasRemoteInterface;
    boolean isUpdateable;

    String setPKField = null;

    // Name of the PC or PK Class as a single String parameter.
    String[] pcnameParam = new String[1];
    String[] pkClassParam = new String[1];

    static String[] objectType = new String[]{CMPTemplateFormatter.Object_};
    static String[] param0 = new String[]{CMPTemplateFormatter.param0_};
    static String[] param0PM = new String[] {CMPTemplateFormatter.param0_,
                    CMPTemplateFormatter.jdoPersistenceManager_};

    // Generic parameters
    String[] oneParam = new String[1];
    String[] twoParams = new String[2];
    String[] threeParams = new String[3];
    String[] fourParams = new String[4];
    String[] fiveParams = new String[5];
    String[] sixParams = new String[6];

    String[] queryParams = new String[10];

    // StringBuffer for loading nonDFG fields into read-only beans
    StringBuffer loadNonDFGBody = null;

    ClassLoader loader;

    // Writer for the concrete bean.
    JavaClassWriter concreteImplWriter;

    // Writer for the static _JDOHelper class.
    JavaClassWriter jdoHelperWriter;

    /**
     * I18N message handler
     */
    final static ResourceBundle messages = I18NHelper.loadBundle(
        JDOConcreteBeanGenerator.class);

    /** Name of the SUPPORT_TRAILING_SPACES_IN_VARCHAR_PK_COLUMNS property. */
    public static final String SUPPORT_TRAILING_SPACES_IN_STRING_PK_COLUMNS_PROPERTY =
        "com.sun.jdo.spi.persistence.support.ejb.ejbc.SUPPORT_TRAILING_SPACES_IN_STRING_PK_COLUMNS"; // NOI18N

    /**
     * Property to swich on/off support for trailing spaces for pk of String types. Note, the default is false, meaning
     * we trip trailing spaces in pk columns
     */
    private static final boolean SUPPORT_TRAILING_SPACES_IN_STRING_PK_COLUMNS = Boolean.valueOf(
        System.getProperty(SUPPORT_TRAILING_SPACES_IN_STRING_PK_COLUMNS_PROPERTY, "false")).booleanValue(); // NOI18N


    /**
     * Signature of the input files. 
     */
    String inputFilesSignature;

    /**
     * Signature of the generator classes for the codegen. 
     */
    String generatorClassesSignature;    

    /**
     * Signature with CVS keyword substitution for identifying the generated code
     */
    static final String SIGNATURE = "$RCSfile: JDOConcreteBeanGenerator.java,v $ $Revision: 1.3 $"; //NOI18N
    
    JDOConcreteBeanGenerator(ClassLoader loader,
                             Model model,
                             NameMapper nameMapper)
                             throws IOException {
        this.loader = loader;
        this.model = model;
        this.nameMapper = nameMapper;

        CMPTemplateFormatter.initHelpers();
        CMPROTemplateFormatter.initHelpers();
    }
    
    void setUpdateable(boolean updateable) {
        isUpdateable = updateable;
    }

    /**
     * Validate this CMP bean. To be overridden in subclass if necessary.
     * No generic validation is done at this time.
     * @param methodHelper the AbstractMethodHelper instance that contains
     * all categorized methods and some other convenience methods for this bean.
     * @param beanName the ejb name for this bean.
     * @return a Collection of Exception instances with a separate instance for 
     * each failed validation. This implementation returns an empty collection 
     * because generic validation always succeeds.
     */
    Collection validate(AbstractMethodHelper methodHelper, String beanName) {
        return new ArrayList();
    }

    /**
     * Generate all required classes for this CMP bean. 
     * @param methodHelper the AbstractMethodHelper instance that contains
     * all categorized methods and some other convenience methods for this bean.
     * @param beanName the ejb-name of this bean.
     * @param appName the name of the application that contains this bean.
     * @param srcout that path to the generated source files.
     * @param classout that path to the compiled class files.
     * @return a Collection of generated source files.
     */
    Collection<File> generate(AbstractMethodHelper methodHelper, 
                       String beanName, String appName, 
                       File srcout, File classout)
                       throws IOException {

        Collection<File> files = new ArrayList();

        this.beanName = beanName;
        this.appName = appName;
        this.abstractBean = nameMapper.getAbstractBeanClassForEjbName(beanName);

        String pkgName = CMPTemplateFormatter.getPackageName(abstractBean);
        concreteImplName = nameMapper.getConcreteBeanClassForEjbName(beanName);
        String shortCmpName = CMPTemplateFormatter.getShortClassName(concreteImplName);

        pcname = nameMapper.getPersistenceClassForEjbName(beanName);
        pcnameParam[0] = pcname;

        PersistenceClassElement pcClassElement =
            model.getPersistenceClass(pcname);

        pkClass = nameMapper.getKeyClassForEjbName(beanName).
            replace('$', '.');
        pkClassParam[0] = pkClass;

        PersistenceFieldElement[] allFields = pcClassElement.getFields();

        String prefix = srcout.getPath() + File.separator + 
            concreteImplName.replace('.', File.separatorChar);
    
        String cmp_file_name = prefix + CMPTemplateFormatter.javaExtension_;
    
        String hlp_file_name = prefix + CMPTemplateFormatter.Helper_ + 
            CMPTemplateFormatter.javaExtension_;

        hasLocalInterface =
            (nameMapper.getLocalInterfaceForEjbName(beanName) != null);
        hasRemoteInterface =
            (nameMapper.getRemoteInterfaceForEjbName(beanName) != null);

        if (logger.isLoggable(Logger.FINE)) {
            logger.fine("allFields: " +                              // NOI18N
                ((allFields != null) ? allFields.length : 0));
            logger.fine("cmp_file_name: " + cmp_file_name); // NOI18N
            logger.fine("hlp_file_name: " + hlp_file_name); // NOI18N
            logger.fine("cmp_name: " + concreteImplName); // NOI18N
            logger.fine("pkClass: " + pkClass); // NOI18N
            logger.fine("PCname: " + pcname); // NOI18N
        }

        File cmp_file = new File(cmp_file_name);
        JavaFileWriter concreteImplFileWriter = new IOJavaFileWriter(cmp_file);
        concreteImplWriter = new IOJavaClassWriter();

        File hlp_file = new File(hlp_file_name);
        JavaFileWriter helperFileWriter = new IOJavaFileWriter(hlp_file);
        jdoHelperWriter = new IOJavaClassWriter();

        // Add package statement to both classes.
        if (pkgName != null && pkgName.length() > 0) {
            concreteImplFileWriter.setPackage(pkgName, null);
            helperFileWriter.setPackage(pkgName, null);
        }

        // Add imports statements to both classes.
        addImportStatements(concreteImplFileWriter, helperFileWriter);

        // Generate class name for the concrete impl.
        oneParam[0] = CMPTemplateFormatter.cmpImplCommentsTemplate;
        concreteImplWriter.setClassDeclaration(Modifier.PUBLIC, 
            shortCmpName, oneParam);

        // Add interfaces to the class declarations.
        addInterfaces();

        concreteImplWriter.setSuperclass(abstractBean);

        // Add no-arg constructor.
        concreteImplWriter.addConstructor(shortCmpName, 
            Modifier.PUBLIC, null, null, null,
            CMPTemplateFormatter.super_, null);

        // Add helper class.
        helperName = shortCmpName + CMPTemplateFormatter.Helper_;

        oneParam[0] = shortCmpName;
        jdoHelperWriter.setClassDeclaration(Modifier.PUBLIC,
            helperName, CMPTemplateFormatter.getBodyAsStrings(
                CMPTemplateFormatter.hcomformatter.format(oneParam)));

        setHelperSuperclass();

        // Print internal variables.
        generateFields();

        // Generate type specific methods.
        generateTypeSpecificMethods(allFields, methodHelper);

        // Add finders for all types and selectors for CMP2.0 only.
        generateFinders(methodHelper);

        // Add ejbCreate<XXX> methods.
        generateCreateMethods(methodHelper.getCreateMethods());

        // Add other required methods.
        generateKnownMethods(methodHelper);

        // Add helper methods for the helper class.
        generateHelperClassMethods();

        // Add conversion methods to the helper class.
        generateConversions();

        // Add ObjectId/PrimaryKey conversion methods.
        generatePKObjectIdConversion(getKeyFields(allFields));

        // Print end of classes.
        concreteImplFileWriter.addClass(concreteImplWriter);
        concreteImplFileWriter.save();

        helperFileWriter.addClass(jdoHelperWriter);
        helperFileWriter.save();

        files.add(cmp_file);
        files.add(hlp_file);

        return files;
    }

    /** Add import statements for for the generated classes.
     */
    void addImportStatements(JavaFileWriter concreteImplFileWriter,
            JavaFileWriter helperFileWriter) throws IOException {

        String[] st = CMPTemplateFormatter.importsArray;
        for (int i = 0; i < st.length; i++) {
            concreteImplFileWriter.addImport(st[i], null);
        }

        st = CMPTemplateFormatter.helperImportsArray;
        for (int i = 0; i < st.length; i++) {
            helperFileWriter.addImport(st[i], null);
        }
    }

    /** 
     * Add interfaces to the class declarations.
     */
    void addInterfaces() throws IOException {

        String[] st = CMPTemplateFormatter.interfacesArray;
        for (int i = 0; i < st.length; i++) {
            concreteImplWriter.addInterface(st[i]);
        }
    }

    /**
     * Super class for the helper class is type specific.
     */
    abstract void setHelperSuperclass() throws IOException;

    /**
     * Generate type specific methods for setters, getters,
     * and any other methods that are completely different
     * between bean types.
     */
    void generateTypeSpecificMethods(
            PersistenceFieldElement[] allFields,
            AbstractMethodHelper methodHelper) 
            throws IOException {

        // Initialize loadNonDFGBody for preloading non-DFG fields
        // in read-only beans.
        if (isUpdateable) {
            loadNonDFGBody = null;
        } else {
            loadNonDFGBody = new StringBuffer();
        }
    }

    /**
     * Sets the signature of the input files for the codegen.
     * @param newSignature The signature of the input files.
     */
    void addCodeGenInputFilesSignature(String newSignature)
    {
        if ((inputFilesSignature == null) || 
            (inputFilesSignature.length() == 0)) {
            inputFilesSignature = newSignature;
        }
        else {
            inputFilesSignature = 
                inputFilesSignature + 
                CMPTemplateFormatter.signatureDelimiter_ + 
                newSignature;
        }
    }    
    
    /**
     * Sets the signature of the generator classes for codegen.
     * @param newSignature The signature of the generator classes.
     */
    void addCodeGeneratorClassSignature(String newSignature)
    {
        if ((generatorClassesSignature == null) || 
            (generatorClassesSignature.length() == 0)) {
            generatorClassesSignature = newSignature;
        }
        else {
            generatorClassesSignature = 
                generatorClassesSignature +
                CMPTemplateFormatter.signatureDelimiter_ +
                newSignature;     
        }
    }

    /**
     * Generates required internal variables.
     */
    void generateFields() throws IOException {

        // Add private transient fields:
        CMPTemplateFormatter.addPrivateField(
            CMPTemplateFormatter.privatetransientvformatter.format(pcnameParam),
            Modifier.TRANSIENT, 
            concreteImplWriter);

        // Add private static fields:
        CMPTemplateFormatter.addPrivateField(
            CMPTemplateFormatter.privateStaticVariablesTemplate,
            Modifier.STATIC, 
            concreteImplWriter);

        // Add private static final fields:
        twoParams[0] = pcname;
        twoParams[1] = beanName;
        CMPTemplateFormatter.addPrivateField(
            CMPTemplateFormatter.privatestaticfinalvformatter.format(twoParams),
            Modifier.STATIC + Modifier.FINAL, 
            concreteImplWriter);

        // Add public static final variables for signatures
        twoParams[0] = generatorClassesSignature;
        twoParams[1] = inputFilesSignature;
        CMPTemplateFormatter.addFields(
             CMPTemplateFormatter.publicstaticfinalvformatter.format(twoParams),
             Modifier.PUBLIC + Modifier.STATIC + Modifier.FINAL,
             concreteImplWriter);
        
        // The static fields holding the Query variables and their monitors
        // are generated during finder/selector method handling.

        CMPTemplateFormatter.addPrivateField(
            CMPTemplateFormatter.otherVariablesTemplate,
            0, concreteImplWriter);

        threeParams[0] = concreteImplName;
        threeParams[1] = beanName;
        threeParams[2] = appName;
        CMPTemplateFormatter.addPrivateField(
            CMPTemplateFormatter.hvformatter.format(threeParams),
            Modifier.TRANSIENT+Modifier.STATIC, 
            jdoHelperWriter);

        // Add read-only fields:
        if (!isUpdateable) {
            // private transient fields:
            CMPTemplateFormatter.addPrivateField(
                CMPROTemplateFormatter.privatetransientvformatter.format(pcnameParam),
                Modifier.TRANSIENT, 
                concreteImplWriter);

            // private static fields:
            CMPTemplateFormatter.addPrivateField(
                CMPROTemplateFormatter.privateStaticFinalVariablesTemplate,
                Modifier.STATIC + Modifier.FINAL, 
                concreteImplWriter);
        }

    }

    /** Adds ejbFindBy methods.
     */
    void generateFinders(AbstractMethodHelper methodHelper) 
            throws IOException {

        boolean debug = logger.isLoggable(Logger.FINE);
        List finders = methodHelper.getFinders();
        for (int i = 0; i < finders.size(); i++) {
            Method m = (Method)finders.get(i);
            String mname = CMPTemplateFormatter.ejb_ +
                StringHelper.getCapitalizedString(m.getName());

            if (debug) {
                logger.fine("Finder: " + mname); // NOI18N
            }

            if (mname.equals(CMPTemplateFormatter.ejbFindByPrimaryKey_)) {
                // ejbFindByPrimaryKey
                String[] exceptionTypes =
                    CMPTemplateFormatter.getExceptionNames(m);

                oneParam[0] = CMPTemplateFormatter.key_;

                concreteImplWriter.addMethod(CMPTemplateFormatter.ejbFindByPrimaryKey_, // name
                    Modifier.PUBLIC , // modifiers
                    pkClass, // returnType
                    oneParam, // parameterNames
                    pkClassParam, //parameterTypes
                    exceptionTypes,// exceptions
                    CMPTemplateFormatter.ejbFindByPrimaryKeyBody, //body
                    null);// comments

            } else {
                JDOQLElements rs = getJDOQLElements(m, methodHelper);

                // check for single-object finder vs. multi-object finder
                String returnType = isSingleObjectFinder(m) ?
                    pkClass : m.getReturnType().getName();
                CMPTemplateFormatter.addGenericMethod(
                    m, mname, returnType,
                    generateFinderMethodBody(methodHelper, rs, mname, m, returnType, i), 
                    concreteImplWriter);
            }
        }


    }

    /** Returns JDOQLElements instance for this finder method.
     * @param m the finder method as a java.lang.reflect.Method
     * @param methodHelper the AbstractMethodHelper instance that contains
     * all categorized methods and some other convenience methods for this bean.
     * @return JDOQLElements instance.
     */
    abstract JDOQLElements getJDOQLElements(Method m,
            AbstractMethodHelper methodHelper) throws IOException;

    /** Adds ejbCreate<XXX> methods.
     */
    private void generateCreateMethods(List createMethods) throws IOException {
        Class beanClass = null;
        try {
            beanClass = Class.forName(abstractBean, true, loader);
        } catch (Exception e) {
            throw new RuntimeException(e.toString());
        }

        // Store generated getters to avoid duplicates.
        HashSet generated = new HashSet();

        for (int i = 0; i < createMethods.size(); i++) {
            Method m = (Method)createMethods.get(i);
            Method m1 = m;

            // Method name is ejbCreate<Method>
            String createName =CMPTemplateFormatter.ejbCreate_;
            String postCreateName =CMPTemplateFormatter.ejbPostCreate_;
            if (m.getName().length() > 6) {
                String suffix = m.getName().substring(6);
                createName += suffix;
                postCreateName += suffix;
            }

            boolean debug = logger.isLoggable(Logger.FINE);
            if (debug) {
                logger.fine("CreateMethod: " + abstractBean + "" + m.getName()); // NOI18N
                logger.fine("ejbCreateMethod: " + createName); // NOI18N
                logger.fine("ejbPostCreateMethod: " + postCreateName); // NOI18N
            }

            // Get actual method in the bean and resolve exception type to generate...
            try {
                Class[] params = m.getParameterTypes();

                // This is a work around the case when the parameter class loader
                // differs from the given class loader ("loader").
                for (int j = 0; j < params.length; j++) {
                    if (params[j].isPrimitive() ||
                        params[j].getClassLoader() == null ||
                        params[j].getClassLoader().equals(loader)) {
                        continue;
                    }
                    String pname = params[j].getName();

                    if (debug) {
                        logger.fine("Replacing parameter class for: " + pname); // NOI18N
                        logger.fine("Param ClassLoader: " + params[j].getClassLoader());
                        logger.fine("Need ClassLoader: " + loader);
                    }

                    params[j] = Class.forName(pname, true, loader);
                }
                // End of the work around the class loader problem.

                // Cannot use getDeclaredMethod() as the actual method can be in a
                // superclass.
                m = beanClass.getMethod(createName, params);
                m1 = beanClass.getMethod(postCreateName, params);
                if (generated.contains(m)) {
                    // Called from more than one interface - skip it.
                    if (debug) {
                        logger.fine("...generated..."); // NOI18N
                    }

                    continue;

                }
                generated.add(m);

            } catch (Exception e) {
                // method does not exist as ejbCreateXxx. It was a business method.
                continue;
            }

            String[] exc = CMPTemplateFormatter.getExceptionNames(m);
            String parametersList = CMPTemplateFormatter.getParametersList(m);
            String parametersListWithSeparator = makeLiteral(
                    CMPTemplateFormatter.getParametersListWithSeparator(
                            m, CMPTemplateFormatter.paramConcatenator_ ));

            String body = getEJBCreateMethodBody(createName, exc, 
                    parametersList, parametersListWithSeparator);

            CMPTemplateFormatter.addGenericMethod(
                    m, createName, pkClass, body, concreteImplWriter);

            body = getEJBPostCreateMethodBody(postCreateName,
                    parametersList, parametersListWithSeparator);

            CMPTemplateFormatter.addGenericMethod(
                    m1, postCreateName, CMPTemplateFormatter.void_, 
                    body, concreteImplWriter);
        }
    }

    /** Returns method body for EJBCreate method.
     * @param createName the actual name of the method as String.
     * @param exc a String[] of decleared exceptions for this method.
     * @param parametersList the list of method parameters as String.
     * @param parametersListWithSeparator the list of concatenated method 
     * parameters to be passed to another method as String.
     * @return method body as String.
     */
    abstract String getEJBCreateMethodBody(String createName,
            String[] exc, String parametersList,
            String parametersListWithSeparator);

    /** Returns method body for EJBPostCreate method.
     * @param postCreateName the actual name of the method as String.
     * @param parametersList the list of method parameters as String.
     * @param parametersListWithSeparator the list of concatenated method 
     * parameters to be passed to another method as String.
     * @return method body as String.
     */
    abstract String getEJBPostCreateMethodBody(String postCreateName,
            String parametersList, String parametersListWithSeparator);

    /** Returns method body for EJBRemove method.
     * @return method body as String.
     */
    abstract String getEJBRemoveMethodBody();

    /** Adds other known required methods 
     * - CMPTemplateFormatter.commonPublicMethods_
     * - CMPTemplateFormatter.commonPrivateMethods
     * - Other generic methods
     * - Special methods that differ between special types (e.g. read-only
     * beans) to be overridden if necessary
     * - CMPTemplateFormatter.otherPublicMethods_ that differ 
     * between CMP 1.1 and 2.x types are added in subclasses.
     */
    void generateKnownMethods(AbstractMethodHelper methodHelper)
                       throws IOException {

        String[] exc = null;
        String[] st = CMPTemplateFormatter.commonPublicMethodsArray;
        for (int i = 0; i < st.length; i++) {
            String mname = st[i];
            exc = getExceptionList(methodHelper, mname);

            String body = null;
            if (mname.equals(CMPTemplateFormatter.ejbRemove_)) {
                body = getEJBRemoveMethodBody();

            } else if (mname.equals(CMPTemplateFormatter.ejb__flush_)) {
                oneParam[0] = CMPTemplateFormatter.DuplicateKeyException_;
                exc = oneParam;
                body = CMPTemplateFormatter.helpers.getProperty(mname);

            } else {
                body = CMPTemplateFormatter.helpers.getProperty(mname);
            }

            concreteImplWriter.addMethod(mname, // name
                Modifier.PUBLIC, // modifiers
                CMPTemplateFormatter.void_, // returnType
                null, // parameterNames
                null,// parameterTypes
                exc,// exceptions
                CMPTemplateFormatter.getBodyAsStrings(body), // body
                null);// comments

        }

        // This is a cleanup method that is public, but has int param.
        oneParam[0] = CMPTemplateFormatter.int_;
        concreteImplWriter.addMethod(CMPTemplateFormatter.afterCompletion_, // name
            Modifier.PUBLIC, // modifiers
            CMPTemplateFormatter.void_, // returnType
            param0, // parameterNames
            oneParam,// parameterTypes
            null,// exceptions
            CMPTemplateFormatter.afterCompletionBody, // body
            null);// comments

        concreteImplWriter.addMethod(CMPTemplateFormatter.ejb__remove_, // name
            Modifier.PUBLIC , // modifiers
            CMPTemplateFormatter.void_, // returnType
            param0, // parameterNames
            objectType, //parameterTypes
            null,// exceptions
            // body is not defined for this method.
            null, // body
            null);// comments

        String body;
        st = CMPTemplateFormatter.commonPrivateMethodsArray;

        for (int i = 0; i < st.length; i++) {
            String mname = st[i];
            body = CMPTemplateFormatter.helpers.getProperty(mname);

            CMPTemplateFormatter.addGenericMethod(mname, 
                CMPTemplateFormatter.getBodyAsStrings(body), concreteImplWriter);
        }

        // Add jdoArrayCopy to return byte[].
        oneParam[0] = CMPTemplateFormatter.byte_;
        body = CMPTemplateFormatter.jdoarraycopyformatter.format(oneParam);

        oneParam[0] = CMPTemplateFormatter.byteArray_;
        concreteImplWriter.addMethod(
            CMPTemplateFormatter.jdoArrayCopy_, // name
            Modifier.PRIVATE, // modifiers
            CMPTemplateFormatter.byteArray_, // returnType
            param0, // parameterNames
            oneParam,// parameterTypes
            null,// exceptions
            CMPTemplateFormatter.getBodyAsStrings(body), // body
            null);// comments

        // Add setEntityContext
        oneParam[0] = CMPTemplateFormatter.EntityContext_;
        concreteImplWriter.addMethod(CMPTemplateFormatter.setEntityContext_, // name
            Modifier.PUBLIC, // modifiers
            CMPTemplateFormatter.void_, // returnType
            param0, // parameterNames
            oneParam,// parameterTypes
            getExceptionList(methodHelper,
                CMPTemplateFormatter.setEntityContext_,
                oneParam),// exceptions
            CMPTemplateFormatter.setEntityContextBody, // body
            null);// comments

        // Add jdoGetObjectId
        oneParam[0] = CMPTemplateFormatter.key_;

        String[] param = new String[]{concreteImplName};

        concreteImplWriter.addMethod(CMPTemplateFormatter.getObjectId_, // name
            Modifier.PRIVATE , // modifiers
            CMPTemplateFormatter.Object_, // returnType
            oneParam, // parameterNames
            pkClassParam,// parameterTypes
            null,// exceptions
            CMPTemplateFormatter.getBodyAsStrings(
                CMPTemplateFormatter.goidformatter.format(param)), // body
            null);// comments

        // Add jdoGetJdoInstanceClass
        oneParam[0] = CMPTemplateFormatter.jdoGetJdoInstanceClassTemplate;

        CMPTemplateFormatter.addGenericMethod(
                CMPTemplateFormatter.jdoGetJdoInstanceClass_, 
                Modifier.PUBLIC + Modifier.STATIC,
                CMPTemplateFormatter.Class_, oneParam,
                concreteImplWriter);

        generateSpecialKnownMethods();
    }

    /** Adds required methods that differ between special types (e.g. read-only
     * beans) to be overridden if necessary;
     */
    void generateSpecialKnownMethods() throws IOException {

        String[] body = null;

        // For the following methods the method body exists only for
        // updateable beans

        // assertPersistenceManagerIsNull 
        if (isUpdateable) {
            body = CMPTemplateFormatter.assertPersistenceManagerIsNullBody;
        }
        CMPTemplateFormatter.addGenericMethod(
                CMPTemplateFormatter.assertPersistenceManagerIsNull_, 
                body, concreteImplWriter);

        // assertInTransaction
        if (isUpdateable) {
            oneParam[0] = I18NHelper.getMessage(messages, "EXC_TransactionNotActive"); // NOI18N
            body = CMPTemplateFormatter.getBodyAsStrings(
                CMPTemplateFormatter.intxformatter.format(oneParam));
        }
        CMPTemplateFormatter.addGenericMethod(
                CMPTemplateFormatter.assertInTransaction_, 
                body, concreteImplWriter);

        // For the following methods the method body exists for
        // all bean types

        // jdoClosePersistenceManager 
        if (isUpdateable) {
            body = CMPTemplateFormatter.jdoClosePersistenceManagerBody;
        } else {
            body = CMPROTemplateFormatter.jdoClosePersistenceManagerBody;
        }

        CMPTemplateFormatter.addGenericMethod(
                CMPTemplateFormatter.jdoClosePersistenceManager_, 
                body, concreteImplWriter);

        // Add jdoGetPersistenceManager as method returning PersistenceManager:
        if (isUpdateable) {
            body = CMPTemplateFormatter.jdoGetPersistenceManagerBody;
        } else {
            body = CMPROTemplateFormatter.jdoGetPersistenceManagerBody;
        }
        CMPTemplateFormatter.addGenericMethod(
                CMPTemplateFormatter.jdoGetPersistenceManager_, 
                CMPTemplateFormatter.jdoPersistenceManagerClass_,
                body, concreteImplWriter);

        // Add methods that use PK as the argument 
        oneParam[0] = CMPTemplateFormatter.key_;
        if (isUpdateable) {
            body = CMPTemplateFormatter.jdoGetPersistenceManager0Body;
        } else {
            body = CMPROTemplateFormatter.jdoGetPersistenceManager0Body;

            // Also add jdoGetPersistenceManagerByPK for RO beans only as method returning 
            // PersistenceManager for this PK:
            concreteImplWriter.addMethod(CMPROTemplateFormatter.jdoGetPersistenceManagerByPK_, // name
                    Modifier.PUBLIC , // modifiers
                    CMPTemplateFormatter.jdoPersistenceManagerClass_, // returnType
                    oneParam, // parameterNames
                    pkClassParam, //parameterTypes
                    null,// exceptions
                    CMPROTemplateFormatter.jdoGetPersistenceManagerByPKBody, //body
                    null);// comments
        }

        concreteImplWriter.addMethod(CMPTemplateFormatter.jdoGetPersistenceManager0_, // name
                Modifier.PUBLIC , // modifiers
                CMPTemplateFormatter.jdoPersistenceManagerClass_, // returnType
                oneParam, // parameterNames
                pkClassParam, //parameterTypes
                null,// exceptions
                body, // body
                null);// comments

        // Add jdoLookupPersistenceManagerFactory as static synchronized method:
        oneParam[0] = concreteImplName;
        MessageFormat mformat = null;
        if (isUpdateable) {
            mformat = CMPTemplateFormatter.jdolookuppmfformatter;
        } else {
            mformat = CMPROTemplateFormatter.jdolookuppmfformatter;
        }
        concreteImplWriter.addMethod(
                CMPTemplateFormatter.jdoLookupPersistenceManagerFactory_, 
                Modifier.PRIVATE + Modifier.STATIC + Modifier.SYNCHRONIZED, // modifiers
                CMPTemplateFormatter.void_, // returnType
                param0, // parameterNames
                objectType, // parameterTypes
                null,// exceptions
                CMPTemplateFormatter.getBodyAsStrings(mformat.format(oneParam)), 
                null);// comments

        // Add jdoGetInstance
        threeParams[0] = pkClass;
        threeParams[1] = pcname;
        threeParams[2] = CMPTemplateFormatter.none_; // will be ignored for updateable beans
        if (isUpdateable) {
            mformat = CMPTemplateFormatter.giformatter;
        } else {
            if (loadNonDFGBody != null) {
                threeParams[2] = loadNonDFGBody.toString();
            }
            mformat = CMPROTemplateFormatter.giformatter;
        }
        CMPTemplateFormatter.addGenericMethod(
                CMPTemplateFormatter.getInstance_, 
                CMPTemplateFormatter.getBodyAsStrings(mformat.format(threeParams)), 
                concreteImplWriter);

        // These are methods that do have arguments.

        // ejb__refresh has method body only for read-only beans
        if (isUpdateable) {
            body = null;
        } else {
            // Reuse threeParams from getInstance_
            body = CMPTemplateFormatter.getBodyAsStrings(
                CMPROTemplateFormatter.ejb__refreshformatter.format(threeParams));
        }
        concreteImplWriter.addMethod(CMPTemplateFormatter.ejb__refresh_, // name
            Modifier.PUBLIC , // modifiers
            CMPTemplateFormatter.void_, // returnType
            param0, // parameterNames
            objectType, //parameterTypes
            null,// exceptions
            body, // body
            null);// comments

        // Add jdoReleasePersistenceManager as method 
        // with PersistenceManager as a param:
        oneParam[0] = CMPTemplateFormatter.jdoPersistenceManagerClass_;
        concreteImplWriter.addMethod(CMPTemplateFormatter.jdoReleasePersistenceManager_, // name
            Modifier.PRIVATE, // modifiers
            CMPTemplateFormatter.void_, // returnType
            param0, // parameterNames
            oneParam,// parameterTypes
            null,// exceptions
            CMPTemplateFormatter.jdoReleasePersistenceManagerBody, // body
            null);// comments

        // Add jdoReleasePersistenceManager0 as method 
        // with PersistenceManager as a param that is different 
        // between updateable and read-only beans:
        if (isUpdateable) {
            body = CMPTemplateFormatter.jdoReleasePersistenceManagerBody;
        } else {
            body = CMPROTemplateFormatter.jdoReleasePersistenceManager0Body;
        }
        concreteImplWriter.addMethod(CMPTemplateFormatter.jdoReleasePersistenceManager0_, // name
            Modifier.PRIVATE, // modifiers
            CMPTemplateFormatter.void_, // returnType
            param0, // parameterNames
            oneParam,// parameterTypes
            null,// exceptions
            body, // body
            null);// comments

    }

    /**
     * Generates helper methods for the helper class.
     */
    void generateHelperClassMethods() throws IOException {
        // Add Helper.assertInstanceOfRemoteInterfaceImpl() method for all beans.
        oneParam[0] = CMPTemplateFormatter.assertInstanceOfRemoteInterfaceImplTemplate;

        jdoHelperWriter.addMethod(CMPTemplateFormatter.assertInstanceOfRemoteInterfaceImpl_, // name
            Modifier.PUBLIC, // modifiers
            CMPTemplateFormatter.void_, // returnType
            param0, // parameterNames
            objectType,// parameterTypes
            null,// exceptions
            oneParam, // body
            null);// comments

        // Add Helper.getHelperInstance() method.
        oneParam[0] = CMPTemplateFormatter.getHelperInstanceTemplate;
        CMPTemplateFormatter.addGenericMethod(
                CMPTemplateFormatter.getHelperInstance_, 
                Modifier.PUBLIC + Modifier.STATIC,
                helperName, oneParam,
                jdoHelperWriter);

        // Add Helper.getContainer() method.
        CMPTemplateFormatter.addGenericMethod(
                CMPTemplateFormatter.getContainer_, 
                Modifier.PUBLIC, CMPTemplateFormatter.Object_, 
                CMPTemplateFormatter.getContainerBody,
                jdoHelperWriter);

        // Add getPCCLass to the helper class
        oneParam[0] = concreteImplName;
        CMPTemplateFormatter.addGenericMethod(
                CMPTemplateFormatter.getPCClass_,
                Modifier.PUBLIC, CMPTemplateFormatter.Class_,
                CMPTemplateFormatter.getBodyAsStrings(
                    CMPTemplateFormatter.pcclassgetterformatter.format(
                    oneParam)),
                jdoHelperWriter);
    }

    private String[] getKeyFields(PersistenceFieldElement[] fields) {
        List returnList = new ArrayList();
        int i, count = ((fields != null) ? fields.length : 0);

        for (i = 0; i < count; i++) {
            PersistenceFieldElement pfe = fields[i];

            if (pfe.isKey())
                returnList.add(pfe.getName());
        }

        return (String[])returnList.toArray(new String[returnList.size()]);
    }

    /** Adds ObjectId/PrimaryKey conversion methods to the helper class.
     */
    private void generatePKObjectIdConversion(String[] keyFields)
                       throws IOException{
        int length = keyFields.length;
        StringBuffer getOid = new StringBuffer(); // PK -> Oid
        StringBuffer getPK = new StringBuffer(); // Oid -> PK
        String[] pkfieldParam = new String[1];

        // Add parameter validation to avoid NullPointerException and
        // other startup lines for the conversions that do not depend
        // on the pk type.
        getOid.append(CMPTemplateFormatter.assertPKNotNullTemplate).
            append(CMPTemplateFormatter.noidformatter.format(pcnameParam));
        getPK.append(CMPTemplateFormatter.assertOidNotNullTemplate).
            append(CMPTemplateFormatter.oidcformatter.format(pcnameParam));

        boolean debug = logger.isLoggable(Logger.FINE);
        if (length == 1) {    
            // only one key field - we don't know yet if there is a special PK class.

            // RESOLVE: Find out what must be null for this case....
            String pkfield = keyFields[0];
            String pkfieldType = model.getFieldType(pcname, pkfield);
            pkfieldParam[0] = pkfield;

            if (debug) {
                logger.fine("pkfield: " + pkfield); // NOI18N
            }

            if (model.isPrimitive(pcname, pkfield) ||
                (!pkClass.equals(pkfieldType) && 
                    !pkClass.equals(Object.class.getName()))) {

                // A single primitive PK field requires a user defined PK class for
                // conversion between Object and primitive value. The same type of conversion
                // is generated for a user defined PK class in case of wrapper field type.
                // Generate conversion as key.id = objectId.id and objectId.id = key.id

                getPK.append(CMPTemplateFormatter.npkformatter.format(pkClassParam));
                getOid.append(CMPTemplateFormatter.pkcformatter.format(pkClassParam));

                pkfieldParam[0] = pkfield;

                getOid.append(
                    CMPTemplateFormatter.oidformatter.format(pkfieldParam));
                getPK.append(
                    CMPTemplateFormatter.pkformatter.format(pkfieldParam));

                getPK.append(CMPTemplateFormatter.returnKey_);

            } else {
                // PK Field is of wrapper type or unknown PK Class - generate conversion
                // as key = objectId.id and objectId.id = key.
                oneParam[0] = pkfieldType;
                getOid.append(CMPTemplateFormatter.pkcformatter.format(oneParam));

                twoParams[0] = pkfield;
                twoParams[1] = pkfieldType;
                getOid.append(
                    requireCloneOnGetAndSet(pkfieldType) ?
                        CMPTemplateFormatter.oid1cloneformatter.format(twoParams) :
                        (requireTrimOnSet(pkfieldType) ?
                            CMPTemplateFormatter.oid1stringformatter.format(pkfieldParam) :
                            CMPTemplateFormatter.oid1formatter.format(pkfieldParam)));

                getPK.append(
                    requireCloneOnGetAndSet(pkfieldType) ?
                        CMPTemplateFormatter.pk1cloneformatter.format(pkfieldParam) :
                        CMPTemplateFormatter.pk1formatter.format(pkfieldParam));

            }
        } else {
            // pkClass declaration with more than 1 field.
            getPK.append(CMPTemplateFormatter.npkformatter.format(pkClassParam));
            getOid.append(CMPTemplateFormatter.pkcformatter.format(pkClassParam));

            for (int i = 0; i < length; i++) {
                String pkfield = keyFields[i];
                pkfieldParam[0] = pkfield;

                if (debug) {
                    logger.fine("pkfield: " + pkfield); // NOI18N
                }

                if (!model.isPrimitive(pcname, pkfield)) {
                    getOid.append(
                        CMPTemplateFormatter.assertpkfieldformatter.format(pkfieldParam));
                }

                String pkfieldType = model.getFieldType(pcname, pkfield);
                twoParams[0] = pkfield;
                twoParams[1] = pkfieldType;
                getOid.append(
                    requireCloneOnGetAndSet(pkfieldType) ?
                        CMPTemplateFormatter.oidcloneformatter.format(twoParams) :
                        (requireTrimOnSet(pkfieldType) ?
                            CMPTemplateFormatter.oidstringformatter.format(pkfieldParam) :
                            CMPTemplateFormatter.oidformatter.format(pkfieldParam)));
                getPK.append(
                    requireCloneOnGetAndSet(pkfieldType) ?
                        CMPTemplateFormatter.pkcloneformatter.format(twoParams) :
                        CMPTemplateFormatter.pkformatter.format(pkfieldParam));
            }

            getPK.append(CMPTemplateFormatter.returnKey_);
        }
        getOid.append(CMPTemplateFormatter.returnOid_);


        // Add ones that can be used for Collection conversion.
        jdoHelperWriter.addMethod(CMPTemplateFormatter.convertPrimaryKeyToObjectId_, // name
            Modifier.PUBLIC, // modifiers
            CMPTemplateFormatter.Object_, // returnType
            param0, // parameterNames
            objectType,// parameterTypes
            null,// exceptions
            CMPTemplateFormatter.getBodyAsStrings(getOid.toString()), // body
            null);// comments

        jdoHelperWriter.addMethod(CMPTemplateFormatter.convertObjectIdToPrimaryKey_, // name
            Modifier.PUBLIC, // modifiers
            CMPTemplateFormatter.Object_, // returnType
            param0, // parameterNames
            objectType,// parameterTypes
            null,// exceptions
            CMPTemplateFormatter.getBodyAsStrings(getPK.toString()), // body
            null);// comments

    }

    /**
     * Returns the name of the concrete bean class for the specified name of
     * the persistence capable class.
     * @param pcClass the name of the persistence capable class
     * @return the name of the corresponding concrete bean class
     */
    String getConcreteBeanForPCClass(String pcClass) {
        return nameMapper.getConcreteBeanClassForEjbName(
            nameMapper.getEjbNameForPersistenceClass(pcClass));
    }

    /**
     * Generates conversion methods from PC to EJBObject and back
     * to the helper class.
     */
    void generateConversions() throws IOException {
        String[] pcParams = new String[] {CMPTemplateFormatter.pc_,
                    CMPTemplateFormatter.jdoPersistenceManager_};
        String[] pcParamTypes = new String[] {CMPTemplateFormatter.Object_,
                    CMPTemplateFormatter.jdoPersistenceManagerClass_};

        String[] collParamTypes = new String[] {CMPTemplateFormatter.Collection_,
                    CMPTemplateFormatter.jdoPersistenceManagerClass_};

        // For PC - PK conversion.
        String[] body = null;

        // Generate for Remote object conversion.
        if (hasRemoteInterface == false) {
            body = CMPTemplateFormatter.getBodyAsStrings(
                CMPTemplateFormatter.returnNull_ );

            jdoHelperWriter.addMethod(CMPTemplateFormatter.convertPCToEJBObject_, // name
                Modifier.PUBLIC, // modifiers
                CMPTemplateFormatter.ejbObject_, // returnType
                pcParams, // parameterNames
                pcParamTypes,// parameterTypes
                null,// exceptions
                body, // body
                null);// comments

            twoParams[0] = CMPTemplateFormatter.ejbObject_;
            twoParams[1] = CMPTemplateFormatter.jdoPersistenceManagerClass_;
            jdoHelperWriter.addMethod(CMPTemplateFormatter.convertEJBObjectToPC_, // name
                Modifier.PUBLIC, // modifiers
                CMPTemplateFormatter.Object_, // returnType
                param0PM, // parameterNames
                twoParams,// parameterTypes
                null,// exceptions
                body, // body
                null);// comments
        }

    }

    /**
     * Verifies if expected exception is part of the throws clause of the
     * corresponding method in the abstract class. 
     * @param exc the list of the Exceptions to check.
     * @param checkExc the Exception to check for as String.
     * @return <code>true if the passed Exception is declared.
     */
    boolean containsException(String[] exc, String checkExc) {
        boolean rc = false;
        if (exc != null) {
            for (int i = 0; i < exc.length; i++) {
                if (exc[i].equals(checkExc)) {
                    rc = true;
                    break;
                }
            }
        }
        return rc;
    }

    /**
     * Verifies if expected exception is part of the throws clause of the
     * corresponding method in the abstract class. Returns EJBException
     * if the requested one is not found.
     * @param exc the list of the Exceptions to check.
     * @param checkExc the Exception to check for as String.
     * @return Exception to be thrown in the try-catch block.
     */
    String getException(String[] exc, String checkExc) {
        return (containsException(exc, checkExc)? checkExc : 
            CMPTemplateFormatter.ejbException_);
    }

    /**
     * Verifies if expected exception or its superclass are part of the 
     * throws clause of the corresponding method in the abstract class. 
     * Returns EJBException if none of the requested exceptions is not found.
     * @param exc the list of the Exceptions to check.
     * @param checkExc the Exception to check for as String.
     * @param superExc the known superclass for the Exception to check for as String.
     * @return Exception to be thrown in the try-catch block.
     */
    String getException(String[] exc, String checkExc, String superExc) {
        String rc = CMPTemplateFormatter.ejbException_;
        if (exc != null) {
            for (int i = 0; i < exc.length; i++) {
                if (exc[i].equals(checkExc) || exc[i].equals(superExc)) {
                    rc = checkExc;
                    break;
                }
            }
        }
        return rc;
    }

    // helper methods to generate finder/selector method bodies

    /**
     * Checks if the finder method is a single-object or multi-object finder.
     * @param finder Method object of the finder
     * @return <code>true if it is a single-object finder
     */
    private boolean isSingleObjectFinder(Method finder) {
        return (!(finder.getReturnType().equals(java.util.Collection.class) ||
                  finder.getReturnType().equals(java.util.Enumeration.class)));
    }

    /**
     * Generates the body of the Entity-Bean finder methods.
     * @param methodHelper the AbstractMethodHelper instance that contains
     * all categorized methods and some other convenience methods for this bean
     * @param jdoqlElements Result of the JDOQL-Compiler
     * @param mname name of the findermethod in
     * the concrete entity bean implementation
     * @param m method instance
     * @param returnType the returnType of this findermethod
     * @param index index of finder method in finders list
     * @return the generated body
     * @exception IOException
     */
    private String generateFinderMethodBody(AbstractMethodHelper methodHelper,
                                            JDOQLElements jdoqlElements,
                                            String mname,
                                            Method m,
                                            String returnType,
                                            int index) throws IOException {

        StringBuffer body = new StringBuffer();
        body.append(CMPTemplateFormatter.assertPersistenceManagerIsNullTemplate);
        body.append(CMPTemplateFormatter.endLine_);
        body.append(generateFinderSelectorCommonBody(methodHelper,
                                                     jdoqlElements,
                                                     mname,
                                                     m,
                                                     returnType,
                                                     index));

        // getting the catch-clause body from the properties
        oneParam[0] = mname;

        // testing if this is a single-object finder
        if (isSingleObjectFinder(m)) {
            // generating the specific single finder method result set handling
            fourParams[0] = mname;
            fourParams[1] = pkClass;
            fourParams[2] = concreteImplName;
            fourParams[3] = CMPTemplateFormatter.catchClauseTemplate;
            body.append(CMPTemplateFormatter.singlefinderformatter.format(fourParams));
        } else {
            // generating the specific multi-object finder method result set handling
            // if CMP11 and the returntype is Enumeration, convert resultCollection
            // to Enumeration else leave Collection
            twoParams[0] = concreteImplName;
            twoParams[1] = CMPTemplateFormatter.catchClauseTemplate;
            if (isFinderReturningEnumeration(m)) {
                body.append(CMPTemplateFormatter.multifinderenumerationformatter.format(twoParams));
            } else {
                body.append(CMPTemplateFormatter.multifinderformatter.format(twoParams));
            }
        }

        return body.toString();
    }

    /**
     * JDOQuery Codegeneration for the common part of the
     * selecter and the finder methods. That consists of:
     * 1. create JDO Query object
     * 2. setting JDO Query elements (declare parameters, set variables etc.)
     * 3. convert parameter values (if available and necessary)
     * 4. execute the JDO Query
     * @param methodHelper the AbstractMethodHelper instance that contains
     * all categorized methods and some other convenience methods for this bean
     * @param jdoqlElements Result of the JDOQL-Compiler
     * @param methodName name of the finder/selector method in
     * the concrete entitybean implementation
     * @param m the method instance
     * @param returnType the return type of the finder/selectormethod
     * @param index index of finder/selector in corresponding list
     * @return the body as a string
     * @exception IOException
     */
    String generateFinderSelectorCommonBody(AbstractMethodHelper methodHelper,
                                                    JDOQLElements jdoqlElements,
                                                    String methodName,
                                                    Method m,
                                                    String returnType,
                                                    int index) throws IOException{
        // unique identifier across finders/selectors
        String queryVariableQualifier = m.getName() + '_' + index;

        // add private static query variables and their monitors
        // no need to check ejbFindByPrimaryKey here
        oneParam[0] = queryVariableQualifier;
        CMPTemplateFormatter.addPrivateField(
            CMPTemplateFormatter.finderselectorstaticvformatter.format(oneParam),
            Modifier.STATIC, 
            concreteImplWriter);
        CMPTemplateFormatter.addPrivateField(
            CMPTemplateFormatter.finderselectorstaticfinalvformatter.format(oneParam),
            Modifier.STATIC + Modifier.FINAL, 
            concreteImplWriter);

        StringBuffer body = new StringBuffer();

        String[] parameterEjbNames = jdoqlElements.getParameterEjbNames();

        // common param check for finder/selector
        body.append(generateFinderSelectorParamCheck(m, parameterEjbNames));
        
        // generating the querydeclaration
        String pcClassName = jdoqlElements.getCandidateClassName();
        String concreteBeanClassName = getConcreteBeanForPCClass(pcClassName);
        queryParams[0] = returnType;
        queryParams[1] = queryVariableQualifier;
        queryParams[2] = concreteBeanClassName;
        queryParams[3] = StringHelper.escape(jdoqlElements.getFilter());
        queryParams[4] = StringHelper.escape(jdoqlElements.getParameters());
        queryParams[5] = StringHelper.escape(jdoqlElements.getVariables());
        queryParams[6] = StringHelper.escape(jdoqlElements.getResult());
        queryParams[7] = StringHelper.escape(jdoqlElements.getOrdering());
        queryParams[8] = Boolean.toString(methodHelper.isQueryPrefetchEnabled(m));
        queryParams[9] = StringHelper.escape(generateQueryIgnoreCache());
        body.append(CMPTemplateFormatter.finderselectorformatter.format(queryParams));

        // now generate the query execution
        // two cases: w/ and w/o query parameters
        String queryParam = generateParamConvBody(m, parameterEjbNames);

        if (jdoqlElements.isAggregate()) {
            if (queryParam == null) {
               oneParam[0] = CMPTemplateFormatter.none_;
               body.append(CMPTemplateFormatter.aggqueryexecformatter.format(oneParam));
            } else {
               oneParam[0] = queryParam;
               body.append(
                 CMPTemplateFormatter.aggqueryexecparamconvformatter.format(oneParam));
            }
        } else {
            if (queryParam == null) {
               oneParam[0] = CMPTemplateFormatter.none_;
               body.append(CMPTemplateFormatter.queryexecformatter.format(oneParam));
            } else {
               oneParam[0] = queryParam;
               body.append(
                 CMPTemplateFormatter.queryexecparamconvformatter.format(oneParam));
            }
        }

        return body.toString();
    }

    /**
     * Generates code that check the finder/selector parameters for the
     * Query.execute call (if necessary).
     * @param m Method instance of the specific finder/selector method
     * @param parameterEjbNames array of ejb names
     * @return the codefragment for the checking local/remote parameters
     *         for method if EJB name is known from ejbql.
     */
    String generateFinderSelectorParamCheck(Method m,
            String[] parameterEjbNames) {
        StringBuffer checkBody = new StringBuffer();

        return checkBody.toString();
    }

    /**
     * Generates a setIgnoreCache(true) call for a JDOQL query, 
     * if necessary.
     * @return the codefragment to set the ignoreCache flag of a JDOQL query.
     */
    String generateQueryIgnoreCache()
    {
        return CMPTemplateFormatter.none_;
    }

    /**
     * Checks if the finder returns an Enumeration.
     * @param finder Methodobject of the finder
     * @return <code>true if the finder returns a Enumeration
     */
    abstract boolean isFinderReturningEnumeration(Method finder); 

    /**
     * Generates code that converts the finder/selector parameters for the
     * Query.execute call (if necessary). It maps local and remote interface
     * values to their corresponding pc instance using JDOHelper methods
     * provided by the concrete entity bean. Primitive type values are wrapped.
     * @param m Method instance of the specific finder/selector method
     * @param parameterEjbNames array of ejb names
     * @return the codefragment for the conversions as a string or null if there
     * aren't any parameters
     */
    private String generateParamConvBody(Method m, String[] parameterEjbNames) {

        StringBuffer paramString = new StringBuffer();
        Class[] paramTypes = m.getParameterTypes();
        int paramLength = paramTypes.length;
        MessageFormat mformat = null;
        String paramClassName = null;

        if (paramLength > 0) {
            // iterate over all paramclasses
            for (int i = 0; i < paramLength; i++) {
                paramClassName = paramTypes[i].getName();

                // if local interface
                if (nameMapper.isLocalInterface(paramClassName) ||
                        nameMapper.isRemoteInterface(paramClassName)) {

                    if (parameterEjbNames[i] != null) {
                        mformat = CMPTemplateFormatter.queryexecparamconvargumentformatter;
                        String concreteImplName =
                            nameMapper.getConcreteBeanClassForEjbName(
                            parameterEjbNames[i]);
                        threeParams[0] = concreteImplName;
                        threeParams[1] = String.valueOf(i);
                        threeParams[2] =
                            nameMapper.isLocalInterface(paramClassName) ?
                            CMPTemplateFormatter.convertEJBLocalObjectToPC_ :
                            CMPTemplateFormatter.convertEJBObjectToPC_;
                        paramString.append(mformat.format(threeParams));
                    } else {
                        paramString.append(CMPTemplateFormatter.param_ + i);
                    }

                // if primitive type, do some wrapping
                } else if(paramTypes[i].isPrimitive()) {
                    paramString.append(
                          JavaClassWriterHelper.getWrapperExpr(
                                             paramTypes[i],
                                             JavaClassWriterHelper.param_ + i
                                             ));

                // else take the param as it is
                } else {
                    paramString.append(CMPTemplateFormatter.param_ + i);
                }
                // normal delimiter
                if (i < paramLength - 1) paramString.append(
                                          CMPTemplateFormatter.paramSeparator_);
            }
        } else return null;

        return paramString.toString();
    }

    /**
     * Returns list of the declared exceptions for the method with this name
     * in the abstract bean. Returns null if such method does not exist
     * or does not have checked exceptions.
     * @param methodHelper the AbstractMethodHelper instance that contains
     * all categorized methods and some other convenience methods for this bean.
     * @param mname method name to check.
     * @param paramTypeNames list of parameter types to the method
     * @return list of the declared exceptions as String[].
     */
    String[] getExceptionList(AbstractMethodHelper methodHelper,
                                      String mname,
                                      String[] paramTypeNames) {
        String[] rc = null;
        Class[] paramTypes = null;

        Map methodNames = methodHelper.getMethodNames();
        Method m = (Method) methodNames.get(mname);

        boolean debug = logger.isLoggable(Logger.FINE);
        if (debug) {
            logger.fine("Processing method: " + mname);
            logger.fine("Known method: " + m);
        }

        if (m == null) {
            // Check the bean class:
            if( paramTypeNames != null ) {
                paramTypes = new Class[ paramTypeNames.length ];
                try {
                    for( int i = paramTypeNames.length - 1; i >= 0; i-- ) {
                        paramTypes[i] = Class.forName( paramTypeNames[i], true, loader );
                    }
                } catch( Exception e ) {
                    // Ignore
                }
            }

            try {
                Class beanClass = Class.forName(abstractBean, true, loader);
                m = beanClass.getMethod(mname, paramTypes);
                if (debug) {
                    logger.fine("Found method: " + m);
                }

            } catch (Exception e) {
                // Ignore. Generate what we know.
            }
        } 

        if (m != null) { 
            rc = CMPTemplateFormatter.getExceptionNames(m);
        }

        return rc;
    }

    /**
     * Returns list of the declared exceptions for the method with this name
     * in the abstract bean. Returns null if such method does not exist
     * or does not have checked exceptions.
     * @param methodHelper the AbstractMethodHelper instance that contains
     * all categorized methods and some other convenience methods for this bean.
     * @param mname method name to check.
     * @return list of the declared exceptions as String[].
     */
    String[] getExceptionList( AbstractMethodHelper methodHelper, String mname ) {
        return getExceptionList( methodHelper, mname, null );
    }

    /**
     * This method will return the given string or "" if it is null or
     * empty string.
     * @param st input string
     */
    private String makeLiteral(String st) {
        return (StringHelper.isEmpty(st)) ? 
            CMPTemplateFormatter.escapedEmptyString_ :
            CMPTemplateFormatter.paramInitializer_ + st;
    }

    /**
     * Returns the signatures of the classes and properties which are
     * involved in the codegen.
     * @return The signatures as a string.
     */
    String getSignaturesOfGeneratorClasses() 
    {
        StringBuffer signatures = new StringBuffer().

            // adding signature of JDOConcreteBeanGenerator
            append(JDOConcreteBeanGenerator.SIGNATURE).
            append(CMPTemplateFormatter.signatureDelimiter_).

            // adding signature of CMPTemplates.properties
            append(CMPTemplateFormatter.signatureTemplate).
            append(CMPTemplateFormatter.signatureDelimiter_).
                
            // adding signature of DeploymentDescriptorModel
            append(DeploymentDescriptorModel.SIGNATURE);
        
        return signatures.toString();
    }

    /** Verifies if this field type requires clone for copy-in, copy-out
     * semantics.
     * @param fieldType the field type as String.
     * @return <code>true if field type requires clone.
     */
    boolean requireCloneOnGetAndSet(String fieldType) {
        return (CMPTemplateFormatter.Date_.equals(fieldType) ||
            CMPTemplateFormatter.SqlDate_.equals(fieldType) ||
            CMPTemplateFormatter.SqlTime_.equals(fieldType) ||
            CMPTemplateFormatter.SqlTimestamp_.equals(fieldType));
    }

    /** Verifies if this field type requires trim on set operation.
     * @param fieldType the field type as String.
     * @return <code>true if field type is java.lang.String.
     */
    boolean requireTrimOnSet(String fieldType) {
         // Strings require trim on set
         boolean requireTrimOnSet = CMPTemplateFormatter.String_.equals(fieldType);
         // do not trim if user has overriden it by specifying to support trailing spaces in pk columns
         // See https://glassfish.dev.java.net/issues/show_bug.cgi?id=7491 for more details
         return requireTrimOnSet && !SUPPORT_TRAILING_SPACES_IN_STRING_PK_COLUMNS;
    }

    /** Generates code that preloads non-DFG fields for read-only beans.
     * @param fieldInfo the FieldInfo instance for this CMP field.
     */
    void loadNonDFGField(FieldInfo fieldInfo) {
        if( !isUpdateable && !fieldInfo.isDFG ) {
            oneParam[0] = fieldInfo.getter;
            loadNonDFGBody.append(
                    CMPROTemplateFormatter.loadNonDFGformatter.format(oneParam));
        }
    }

    /*
     * This class contains the field information to generate get/set methods.
     *
     */
    class FieldInfo {
    
        final PersistenceFieldElement pfe;
    
        final String name;
        final String type;
        final String getter;
        final String setter;
    
        final boolean isKey;
        final boolean isPrimitive;
        final boolean isByteArray;
        final boolean isSerializable;
        final boolean requireCloneOnGetAndSet;
        final boolean isGeneratedField;
        final boolean isDFG;
    
        FieldInfo(Model model, NameMapper nameMapper, 
                PersistenceFieldElement pfe, 
                String beanName, String pcname) {
    
            this.pfe = pfe;
    
            String pfn = pfe.getName();
            name = nameMapper.getEjbFieldForPersistenceField(pcname, pfn);
    
            String fname = StringHelper.getCapitalizedString(name);
            getter = CMPTemplateFormatter.get_ + fname;
            setter = CMPTemplateFormatter.set_ + fname;
    
            boolean debug = logger.isLoggable(Logger.FINE);
            if (debug) {
                logger.fine("-Methods: " + getter + " " + setter); // NOI18N
            }
    
            isKey = pfe.isKey();
            isPrimitive = model.isPrimitive(pcname, pfn);
            isByteArray = model.isByteArray(beanName, name);
            isSerializable = model.isByteArray(pcname, pfn);

            if (isSerializable) {
                // Replace '$' with '.' if it's an inner class.
                type = model.getFieldType(beanName, name).replace('$', '.');
            } else {
                type = model.getFieldType(beanName, name);
            }

            if (debug) {
                logger.fine("Field: " + name + " " + type); // NOI18N
            }
    
            requireCloneOnGetAndSet = requireCloneOnGetAndSet(type);
            isGeneratedField = nameMapper.isGeneratedField(beanName, name);

            // Check if the field is in DFG.
            MappingClassElement mce = model.getMappingClass(pcname);
            MappingFieldElement mfe = mce.getField(name);
            isDFG = (mfe.getFetchGroup() == MappingFieldElement.GROUP_DEFAULT);
        }
    }

}

Other Glassfish examples (source code examples)

Here is a short list of links related to this Glassfish JDOConcreteBeanGenerator.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.