/*
* Copyright (c) 2005
* XDoclet Team
* All rights reserved.
*/
package org.xdoclet.plugin.ejb;
import java.util.Arrays;
import java.util.Collection;
import javax.ejb.CreateException;
import javax.ejb.FinderException;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Predicate;
import org.apache.commons.collections.Transformer;
import org.xdoclet.plugin.ejb.entity.PrimaryKeyClassPlugin;
import org.xdoclet.plugin.ejb.qtags.EjbFinderTag;
import org.xdoclet.plugin.ejb.qtags.TagLibrary;
import org.xdoclet.plugin.ejb.util.DuplicatedJavaMethod;
import com.thoughtworks.qdox.model.JavaClass;
import com.thoughtworks.qdox.model.JavaMethod;
import com.thoughtworks.qdox.model.JavaParameter;
import com.thoughtworks.qdox.model.Type;
/**
* This class holds common functionality used by all EJB plugin.
* These methods will mostly be called by templates (including
* vendor specific templates). Reusable code should be placed here.
*
* @author Diogo Quintela
* @version $Revision: 533 $
*/
public class EjbHomeUtils {
/** Var name for complete jndi name in home interfaces */
public static final String COMPLETE_NAME_CONST_NAME = "COMP_NAME";
/** Var name for jndi name in home interfaces */
public static final String JNDI_NAME_CONST_NAME = "JNDI_NAME";
protected EjbUtils ejbUtils;
public EjbHomeUtils(EjbUtils ejbUtils) {
this.ejbUtils = ejbUtils;
}
public String getJndiNameConst() {
return JNDI_NAME_CONST_NAME;
}
public String getCompleteNameConst() {
return COMPLETE_NAME_CONST_NAME;
}
protected JavaMethod fixReturnType(JavaMethod method, Type newType) {
method = new DuplicatedJavaMethod(method);
method.setReturns(newType);
return method;
}
protected JavaMethod fixFinderReturnType(JavaMethod method, Type newType) {
String returnType = method.getReturns().toString();
boolean isColection = false;
isColection |= returnType.equals("java.util.Collection");
isColection |= returnType.equals("java.util.Enumeration");
isColection |= returnType.equals("java.util.Set");
if (!isColection) {
method = fixReturnType(method, newType);
}
return method;
}
public Collection getCreateMethods(final JavaClass javaClass, final int viewType, final Type newType) {
Collection createMethods = CollectionUtils.select(Arrays.asList(javaClass.getMethods(true)),
new Predicate() {
public boolean evaluate(Object object) {
JavaMethod method = (JavaMethod) object;
boolean retVal = EjbUtils.hasFlag(ejbUtils.getMethodType(method), EjbUtils.IFACE_METHOD_CREATE);
retVal = retVal && EjbUtils.hasFlag(ejbUtils.getViewType(method, javaClass), viewType);
return retVal;
}
});
// Let's remove the "ejb" from it's name
createMethods = CollectionUtils.collect(createMethods,
new Transformer() {
public Object transform(Object object) {
return ejbUtils.externalizeMethodName((JavaMethod) object);
// return ejbUtils.removeFromMethodName((JavaMethod) object, "ejb");
}
});
// xdoclet-1.2.3 comment: Add mandatory create() method for stateless beans if the bean is not abstract
if ((createMethods.size() == 0) && ejbUtils.isStateLess(javaClass)) {
// Let's generate it then
JavaMethod createMethod = new JavaMethod();
createMethod.setName("create");
// Let's add it finally
createMethods.add(createMethod);
}
// Fix return type
createMethods = CollectionUtils.collect(createMethods,
new Transformer() {
public Object transform(Object object) {
return fixReturnType((JavaMethod) object, newType);
}
});
createMethods = ejbUtils.injectMethodThrowException(createMethods, CreateException.class);
return createMethods;
}
public Collection getHomeMethods(final JavaClass clazz, final int viewType) {
Collection homeMethods = CollectionUtils.select(Arrays.asList(clazz.getMethods(true)),
new Predicate() {
public boolean evaluate(Object object) {
JavaMethod method = (JavaMethod) object;
boolean retVal = EjbUtils.hasFlag(ejbUtils.getMethodType(method), EjbUtils.IFACE_METHOD_HOME);
retVal = retVal && EjbUtils.hasFlag(ejbUtils.getViewType(method, clazz), viewType);
return retVal;
}
});
// Let's remove the "ejbHome" from it's name
homeMethods = CollectionUtils.collect(homeMethods,
new Transformer() {
public Object transform(Object object) {
return ejbUtils.externalizeMethodName((JavaMethod) object);
// return ejbUtils.removeFromMethodName((JavaMethod) object, "ejbHome");
}
});
return homeMethods;
}
public Collection getFinderMethods(final JavaClass javaClass, final int viewType, final Type newType)
throws Error {
if (!ejbUtils.isEntityBean(javaClass)) {
throw new Error("This must only be called for Entity Beans");
}
// NOTE: xdoclet-1.2.3 makes reference to method-level
// ejb.finder (it's not supported, as it's inconsistent across code base)
Collection finderMethods = CollectionUtils.select(Arrays.asList(javaClass.getMethods(true)),
new Predicate() {
public boolean evaluate(Object object) {
JavaMethod method = (JavaMethod) object;
boolean retVal = EjbUtils.hasFlag(ejbUtils.getMethodType(method), EjbUtils.IFACE_METHOD_FINDER);
retVal = retVal && EjbUtils.hasFlag(ejbUtils.getViewType(method, javaClass), viewType);
return retVal;
}
});
// Let's remove the "ejb" from it's name
finderMethods = CollectionUtils.collect(finderMethods,
new Transformer() {
public Object transform(Object object) {
return ejbUtils.externalizeMethodName((JavaMethod) object);
// return ejbUtils.removeFromMethodName((JavaMethod) object, "ejb");
}
});
Collection finderMethodsBySignature = CollectionUtils.select(Arrays.asList(javaClass.getTagsByName(
TagLibrary.EJB_FINDER, true)),
new Predicate() {
public boolean evaluate(Object object) {
EjbFinderTag finderTag = (EjbFinderTag) object;
boolean retVal = finderTag.getResultTypeMapping() == null ||
finderTag.getResultTypeMapping().equals(EjbUtils.REMOTE_INTERFACE);
retVal = retVal && EjbUtils.hasFlag(ejbUtils.getViewType(finderTag.getViewType()), viewType);
return retVal;
}
});
finderMethods.addAll(CollectionUtils.collect(finderMethodsBySignature,
new Transformer() {
public Object transform(Object object) {
EjbFinderTag finderTag = (EjbFinderTag) object;
return ejbUtils.getFinderMethodBySignature(finderTag.getSignature());
}
}));
// Add mandatory findByPrimaryKey if not already there
// Is this only for CMP ?? (xdoclet-1.2.3 says so, but i'll ignore
// it for consistency, but it has a point anyway..
// TODO: Centralize "findByPrimaryKey" /EjbPkTag somewhere..
// if (ejbUtils.isCMP(javaClass)) {
// Let's check if there is at least one "findByPrimaryKey"
int count = CollectionUtils.countMatches(finderMethods,
new Predicate() {
public boolean evaluate(Object object) {
JavaMethod method = (JavaMethod) object;
return "findByPrimaryKey".equals(method.getName());
}
});
if (count == 0) {
// Let's generate it then
PrimaryKeyClassPlugin pkPlugin = EjbRuntime.getPrimaryKeyClassPlugin();
JavaParameter javaParameter = new JavaParameter(new Type(pkPlugin.pkClass(javaClass)), "pk");
JavaMethod finderMethod = new JavaMethod();
finderMethod.setName("findByPrimaryKey");
finderMethod.setParameters(new JavaParameter[] {javaParameter});
// Let's add it finally
finderMethods.add(finderMethod);
}
// }
finderMethods = CollectionUtils.collect(finderMethods,
new Transformer() {
public Object transform(Object object) {
return fixFinderReturnType((JavaMethod) object, newType);
}
});
finderMethods = ejbUtils.injectMethodThrowException(finderMethods, FinderException.class);
return finderMethods;
}
}