FileDocCategorySizeDatePackage
ImplHelper.javaAPI DocGlassfish v2 API21971Fri May 04 22:34:38 BST 2007com.sun.jdo.api.persistence.enhancer.generator

ImplHelper.java

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 * 
 * Copyright 1997-2007 Sun Microsystems, Inc. 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.html
 * or glassfish/bootstrap/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 glassfish/bootstrap/legal/LICENSE.txt.
 * Sun designates this particular file as subject to the "Classpath" exception
 * as provided by Sun in the GPL Version 2 section of the License file that
 * accompanied this code.  If applicable, add the following below the License
 * Header, with the fields enclosed by brackets [] replaced by your own
 * identifying information: "Portions Copyrighted [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.
 */

package com.sun.jdo.api.persistence.enhancer.generator;

import java.util.List;
import java.util.ArrayList;
import java.util.HashMap;

import com.sun.jdo.api.persistence.enhancer.meta.ExtendedJDOMetaData;
import com.sun.jdo.api.persistence.enhancer.util.Assertion;
import com.sun.jdo.spi.persistence.utility.JavaTypeHelper;
import com.sun.jdo.spi.persistence.utility.generator.JavaClassWriterHelper;

/**
 *
 */
final class ImplHelper extends Assertion
{
    // string constants
    static final String[] COMMENT_ENHANCER_ADDED
    = null; //{ "added by enhancer" };
    static final String[] COMMENT_NOT_ENHANCER_ADDED
    = null; //{ "not added by enhancer" };

    static final String CLASSNAME_JDO_PERSISTENCE_CAPABLE
    = "com.sun.jdo.spi.persistence.support.sqlstore.PersistenceCapable";
    static final String CLASSNAME_JDO_PERSISTENCE_MANAGER
    = "com.sun.jdo.api.persistence.support.PersistenceManager";
    static final String CLASSNAME_JDO_STATE_MANAGER
    = "com.sun.jdo.spi.persistence.support.sqlstore.StateManager";
    static final String CLASSNAME_JDO_SCO
    = "com.sun.jdo.spi.persistence.support.sqlstore.SCO";
    static final String CLASSNAME_JDO_FATAL_EXCEPTION
    = "com.sun.jdo.api.persistence.support.JDOFatalException";

    static final String FIELDNAME_JDO_FLAGS
    = "jdoFlags";
    static final String FIELDNAME_JDO_STATE_MANAGER
    = "jdoStateManager";
    static final String FIELDNAME_JDO_INHERITED_FIELD_COUNT
    = "jdoInheritedFieldCount";
    static final String FIELDNAME_JDO_FIELD_NAMES
    = "jdoFieldNames";
    static final String FIELDNAME_JDO_FIELD_TYPES
    = "jdoFieldTypes";
    static final String FIELDNAME_JDO_FIELD_FLAGS
    = "jdoFieldFlags";
    static final String METHODNAME_JDO_NEW_INSTANCE
    = "jdoNewInstance";
    static final String METHODNAME_JDO_SET_FIELD
    = "jdoSetField";
    static final String METHODNAME_JDO_GET_FIELD
    = "jdoGetField";
    static final String METHODNAME_JDO_GET_STATE_MANAGER
    = "jdoGetStateManager";
    static final String METHODNAME_JDO_SET_STATE_MANAGER
    = "jdoSetStateManager";
    static final String METHODNAME_JDO_GET_FLAGS
    = "jdoGetFlags";
    static final String METHODNAME_JDO_SET_FLAGS
    = "jdoSetFlags";
    static final String METHODNAME_JDO_GET_PERSISTENCE_MANAGER
    = "jdoGetPersistenceManager";
    static final String METHODNAME_JDO_CLEAR
    = "jdoClear";
    static final String METHODNAME_JDO_MAKE_DIRTY
    = "jdoMakeDirty";
    static final String METHODNAME_JDO_GET_OBJECT_ID
    = "jdoGetObjectId";
    static final String METHODNAME_JDO_IS_PERSISTENT
    = "jdoIsPersistent";
    static final String METHODNAME_JDO_IS_TRANSACTIONAL
    = "jdoIsTransactional";
    static final String METHODNAME_JDO_IS_NEW
    = "jdoIsNew";
    static final String METHODNAME_JDO_IS_DIRTY
    = "jdoIsDirty";
    static final String METHODNAME_JDO_IS_DELETED
    = "jdoIsDeleted";

    static private final HashMap typeNameConversion = new HashMap();
    static
    {
        typeNameConversion.put(int.class.getName(), "Int");
        typeNameConversion.put(long.class.getName(), "Long");
        typeNameConversion.put(byte.class.getName(), "Byte");
        typeNameConversion.put(char.class.getName(), "Char");
        typeNameConversion.put(boolean.class.getName(), "Boolean");
        typeNameConversion.put(short.class.getName(), "Short");
        typeNameConversion.put(float.class.getName(), "Float");
        typeNameConversion.put(double.class.getName(), "Double");
        typeNameConversion.put("String", "String");
    }

    static private boolean isPrimitiveClass(String className)
    {
        affirm(!className.equals("void"));      // NOI18N

        return JavaTypeHelper.getWrapperName(className) != null;
    }

    static private String getConvertedTypeName(String fieldType)
    {
        final String name = (String)typeNameConversion.get(fieldType);
        return (name != null ? name : JavaClassWriterHelper.Object_);
    }

    static private String getMethodNameGetField(String fieldType)
    {
        return JavaClassWriterHelper.get_ +
               getConvertedTypeName(fieldType) + "Field";
    }

    static private String getMethodNameSetField(String fieldType)
    {
        return JavaClassWriterHelper.set_ +
               getConvertedTypeName(fieldType) + "Field";
    }


    // Create bodies of methods.

    static String[] getJDOManagedFieldCountImpl(int fieldcount)
    {
        return new String[] {
            FIELDNAME_JDO_INHERITED_FIELD_COUNT + " + " + fieldcount + JavaClassWriterHelper.delim_
        };
    }

    static String[] getDefaultConstructorImpl()
    {
        return JavaClassWriterHelper.super_;
    }

    static String[] getCloneImpl(String className)
    {
        className = normalizeClassName(className);
        String[] bodies = new String[4];
        int i = 0;
        bodies[i++] = (new StringBuffer(className)).append(" clone = (")
                 .append(className).append(")super.clone();").toString();
        bodies[i++] = "clone.jdoFlags = (byte)0;";
        bodies[i++] = "clone.jdoStateManager = null;";
        bodies[i++] = "return clone;";
        return bodies;
    }

    static String[] getJDOConstructorSMImpl(String statemanager)
    {
        String[] bodies = new String[2];
        int i = 0;
        bodies[i++] = FIELDNAME_JDO_FLAGS + " = (byte)1; // == LOAD_REQUIRED";
        bodies[i++] = "this." + FIELDNAME_JDO_STATE_MANAGER
                 + " = " + statemanager + JavaClassWriterHelper.delim_;
        return bodies;
    }

    static String[] getJDONewInstanceImpl(String className,
                                      String statemanager)
    {
        className = getClassName(className);
        return new String[] { (new StringBuffer("return new "))
                  .append(className).append("(").append(statemanager)
                  .append(");").toString() };
    }

    static String[] getFieldDirectReadImpl(String fieldName,
                                       String fieldType,
                                       int fieldNumber)
    {
        fieldType = normalizeClassName(fieldType);
        return new String[] {
            "// annotation: grant direct read access",
            "return " + fieldName + JavaClassWriterHelper.delim_
        };
    }

    static String[] getFieldMediateReadImpl(String fieldName,
                                        String fieldType,
                                        int fieldNumber)
    {
        fieldType = normalizeClassName(fieldType);
        String[] bodies = new String[6];
        int i = 0;
        bodies[i++] = "// annotation: mediate read access";
        bodies[i++] = (new StringBuffer("final "))
                 .append(CLASSNAME_JDO_STATE_MANAGER)
                 .append(" stateManager = this.")
                 .append(FIELDNAME_JDO_STATE_MANAGER)
                 .append(JavaClassWriterHelper.delim_).toString();
        bodies[i++] = "if (stateManager != null) {";
        bodies[i++] = (new StringBuffer("    "))
                .append("stateManager.prepareGetField(").append(fieldNumber)
                .append(");").toString();
        bodies[i++] = "}";
        bodies[i++] = "return " + fieldName + JavaClassWriterHelper.delim_;
        return bodies;
    }

    static String[] getFieldCheckReadImpl(String fieldName,
                                      String fieldType,
                                      int fieldNumber)
    {
        String[] bodies = new String[5];
        int i = 0;
        fieldType = normalizeClassName(fieldType);
        bodies[i++] = "// annotation: check read access";
        bodies[i++] = (new StringBuffer("if ("))
                 .append(FIELDNAME_JDO_FLAGS).append(" > 0) {").toString();
        bodies[i++] = "   " + FIELDNAME_JDO_STATE_MANAGER + ".loadForRead();";
        bodies[i++] = "}";
        bodies[i++] = "return " + fieldName + JavaClassWriterHelper.delim_;
        return bodies;
    }

    static String[] getFieldDirectWriteImpl(String fieldName,
                                           String fieldType,
                                           int fieldNumber,
                                           String newvalue)
    {
        fieldType = normalizeClassName(fieldType);
        return new String[] {
            "// annotation: grant direct write access",
            (new StringBuffer("this."))
                 .append(fieldName).append(" = ").append(newvalue)
                 .append(JavaClassWriterHelper.delim_).toString()
        };
    }

    static String[] getFieldMediateWriteImpl(String fieldName,
                                         String fieldType,
                                         int fieldNumber,
                                         String newvalue)
    {
        String[] bodies = new String[7];
        int i = 0;
        fieldType = normalizeClassName(fieldType);
        bodies[i++] = "// annotation: mediate write access";
        bodies[i++] = (new StringBuffer("final "))
                 .append(CLASSNAME_JDO_STATE_MANAGER)
                 .append(" stateManager = this.")
                 .append(FIELDNAME_JDO_STATE_MANAGER)
                 .append(JavaClassWriterHelper.delim_).toString();
        bodies[i++] = "if (stateManager == null) {";
        bodies[i++] = (new StringBuffer("    this."))
                 .append(fieldName).append(" = ")
                 .append(newvalue).append(JavaClassWriterHelper.delim_)
                 .toString();
        bodies[i++] = "} else {";
        bodies[i++] = (new StringBuffer("    stateManager."))
                 .append(getMethodNameSetField(fieldType)).append('(')
                 .append(fieldNumber).append(", ").append(newvalue)
                 .append(");").toString();
        bodies[i++] = "}";
        return bodies;
    }

    static String[] getFieldCheckWriteImpl(String fieldName,
                                       String fieldType,
                                       int fieldNumber,
                                       String newvalue)
    {
        String[] bodies = new String[5];
        int i = 0;
        fieldType = normalizeClassName(fieldType);
        bodies[i++] = "// annotation: check write access";
        bodies[i++] = "if (" + FIELDNAME_JDO_FLAGS + " != 0) {";
        bodies[i++] = "    " + FIELDNAME_JDO_STATE_MANAGER + ".loadForUpdate();";
        bodies[i++] = "}";
        bodies[i++] = (new StringBuffer("this.")).append(fieldName)
                 .append(" = ").append(newvalue)
                 .append(JavaClassWriterHelper.delim_).toString();
        return bodies;
    }

    static String[] getJDOClearImpl(String className, ExtendedJDOMetaData meta,
            String[] fieldNames, String[] fieldTypes) {
        final List impl = new ArrayList(20);
        for (int i = 0; i < fieldNames.length; i++) {
            String fieldTypeClassPath = fieldTypes[i];
            String fieldType = normalizeClassName(fieldTypes[i]);
            String fieldName = fieldNames[i];
            if (meta.isKeyField(className, fieldName)) {
                continue;
            }
            String primClass = JavaTypeHelper.getWrapperName(fieldType);
            if (meta.isMutableSecondClassObjectType(fieldTypeClassPath)) {
                impl.add((new StringBuffer("if ("))
                        .append(fieldName).append(" instanceof ")
                        .append(CLASSNAME_JDO_SCO).append(") {")
                        .toString());
                impl.add((new StringBuffer("    (("))
                        .append(CLASSNAME_JDO_SCO).append(")")
                        .append(fieldName).append(").unsetOwner();")
                        .toString());
                impl.add("}");
                impl.add(fieldName + " = null;");
            } else if (primClass == null) {
                impl.add(fieldName + " = null;");
            } else if (JavaClassWriterHelper.boolean_.equals(fieldType)) {
                impl.add(fieldName + " = false;");
            } else {
                impl.add(fieldName + " = 0;");
            }
        }
        String[] strArr = new String[impl.size()];
        return (String[])impl.toArray(strArr);
    }

    static String[] getJDOGetFieldImpl(String fieldNumber,
                                   String[] fieldNames,
                                   String[] fieldTypes)
    {
        final List impl = new ArrayList(20);
        impl.add("switch (" + fieldNumber + ") {");
        for (int i = 0; i < fieldNames.length; i++) {
            String fieldType = normalizeClassName(fieldTypes[i]);
            impl.add("case " + i + ':');
            String primClass = JavaTypeHelper.getWrapperName(fieldType);
            if (primClass == null) {
                impl.add("    return " + fieldNames[i] + ";");
            } else {
                impl.add((new StringBuffer("    return new "))
                          .append(primClass).append("(")
                          .append(fieldNames[i]).append(");").toString());
            }
        }
        impl.add("default:");
        impl.add("    throw new " + CLASSNAME_JDO_FATAL_EXCEPTION + "();");
        impl.add("}");
        String[] strArr = new String[impl.size()];
        return (String[])impl.toArray(strArr);
    }

    static String[] getJDOSetFieldImpl(String fieldNumber, String objName,
                                       String[] fieldNames,
                                       String[] fieldTypes)
    {
        final List impl = new ArrayList(20);
        impl.add("switch (" + fieldNumber + ") {");
        for (int i = 0; i < fieldNames.length; i++) {
            String fieldType = normalizeClassName(fieldTypes[i]);
            impl.add("case " + i + ':');
            String primClass = JavaTypeHelper.getWrapperName(fieldType);
            if (primClass == null) {
                impl.add((new StringBuffer("    this."))
                          .append(fieldNames[i])
                          .append(" = (").append(fieldType)
                          .append(")").append(objName)
                          .append(";").toString());
            } else {
                impl.add((new StringBuffer("    this."))
                          .append(fieldNames[i])
                          .append(" = ((").append(primClass)
                          .append(")").append(objName).append(").")
                          .append(((String)typeNameConversion.get(fieldType)).toLowerCase())
                          .append("Value();").toString());
            }
            impl.add("    return;");
        }
        impl.add("default:");
        impl.add("    throw new " + CLASSNAME_JDO_FATAL_EXCEPTION + "();");
        impl.add("}");
        String[] strArr = new String[impl.size()];
        return (String[])impl.toArray(strArr);
    }

    // returnType = null means void
    private static String[] getJDOStateManagerDelegationImpl(
            String delegation, String returnType) {
        final List impl = new ArrayList(7);
        impl.add((new StringBuffer("final "))
                 .append(CLASSNAME_JDO_STATE_MANAGER)
                 .append(" stateManager = this.")
                 .append(FIELDNAME_JDO_STATE_MANAGER)
                 .append(JavaClassWriterHelper.delim_)
                 .toString());
        impl.add("if (stateManager != null) {");
        StringBuffer buf = new StringBuffer("    ");
        if (returnType != null) {
            buf.append("return ");
        }
        impl.add(((buf.append("stateManager."))
                  .append(delegation).append(";")).toString());
        impl.add("}");
        if (returnType != null) {
            impl.add((new StringBuffer("return ")).append(returnType)
                        .append(";").toString());
        };
        String[] strArr = new String[impl.size()];
        return (String[])impl.toArray(strArr);
    }

    static String[] getJDOStateManagerVoidDelegationImpl(String delegation)
    {
        return getJDOStateManagerDelegationImpl(delegation, null);
    }

    static String[] getJDOStateManagerObjectDelegationImpl(String delegation)
    {
        return getJDOStateManagerDelegationImpl(delegation,
                JavaClassWriterHelper.null_);
    }

    static String[] getJDOStateManagerBooleanDelegationImpl(String delegation)
    {
        return getJDOStateManagerDelegationImpl(delegation,
                JavaClassWriterHelper.false_);
    }

    static String[] getOidHashCodeImpl(String[] pknames,
                                   String[] pktypes,
                                   boolean  isRoot)
    {
        final List impl = new ArrayList(3);
        if (isRoot) {
            impl.add("int hash = 0;");
        } else {
            impl.add("int hash = super.hashCode();");
        }
        for (int i = 0; i < pknames.length; i++) {
            if (isPrimitiveClass(pktypes[i])) {
                if (pktypes[i].equals("boolean")) {
                    impl.add("hash += (" + pknames[i] + " ? 1 : 0);");
                } else {
                    impl.add("hash += (int)" + pknames[i] +
                            JavaClassWriterHelper.delim_);
                }
            } else {
                impl.add("hash += (this." + pknames[i]
                         + " != null ? this." + pknames[i]
                         + ".hashCode() : 0);");
            }
        }
        impl.add("return hash;");
        String[] strArr = new String[impl.size()];
        return (String[])impl.toArray(strArr);
    }

    static String[] getOidEqualsImpl(String   oidClassName,
                                 String[] pknames,
                                 String[] pktypes,
                                 String   pk,
                                 boolean  isRoot)
    {
        final List impl = new ArrayList(31);
        if (isRoot) {
            impl.add("if (" + pk + " == null || !this.getClass().equals("
                     + pk + ".getClass())) {");
        } else {
            impl.add("if (!super.equals(" + pk + ")) {");
        }
        impl.add("    return false;");
        impl.add("}");
        oidClassName = getClassName(oidClassName);
        impl.add(oidClassName + " oid = (" + oidClassName + ")" + pk +
                JavaClassWriterHelper.delim_);
        for (int i = 0; i < pknames.length; i++) {
            if (isPrimitiveClass(pktypes[i])) {
                impl.add("if (this." + pknames[i] + " != oid."
                         + pknames[i] + ") return false;");
            } else {
                impl.add("if (this." + pknames[i] + " != oid."
                         + pknames[i] + " && (this." + pknames[i]
                         + " == null || " + "!this." + pknames[i]
                         + ".equals(oid." + pknames[i]
                         + "))) return false;");
            }
        }
        impl.add("return true;");
        String[] strArr = new String[impl.size()];
        return (String[])impl.toArray(strArr);
    }


    //The following three methods are originated from NameHelper.
    /**
     * The input parameter can be a classPath with "/" or a valid
     * full className with package name.
     */
    static String normalizeClassName(String className)
    {
        if (className == null) {
            return null;
        }
        return className.replace('/', '.').replace('$', '.');
    }

    /**
     * The inner class must be represented by $ in className.
     * The input className can be a classPath with "/".
     */
    static String getPackageName(String className)
    {
        if (className == null) {
            return null;
        }
        return JavaTypeHelper.getPackageName(className.replace('/', '.'));
    }

    /**
     * The input parameter can be a classPath with "/" or a valid
     * full className with package name.
     */
    static String getClassName(String className) {
        return JavaTypeHelper.getShortClassName(normalizeClassName(className));
    }
}