/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 1997-2017 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://oss.oracle.com/licenses/CDDL+GPL-1.1
* or 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 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<File>();
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</code> 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</code> 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</code> 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</code> 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</code> 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);
}
}
}