|
What this is
This file 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.
Other links
The source code
/*
* Sun Public License Notice
*
* The contents of this file are subject to the Sun Public License
* Version 1.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://www.sun.com/
*
* The Original Code is NetBeans. The Initial Developer of the Original
* Code is Sun Microsystems, Inc. Portions Copyright 1997-2001 Sun
* Microsystems, Inc. All Rights Reserved.
*/
package org.netbeans.mdr.handlers.gen;
import org.netbeans.mdr.persistence.StorageException;
import org.netbeans.mdr.storagemodel.StorableAssociation;
import org.netbeans.mdr.storagemodel.StorableObject;
import org.netbeans.mdr.util.DebugException;
import org.netbeans.mdr.util.Logger;
import org.netbeans.mdr.util.MOFConstants;
import javax.jmi.model.MultiplicityType;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.*;
/**
*
* @author Martin Matula, Dusan Balek
* @version
*/
class AssociationGenerator extends HandlerGenerator {
private static final String ALL_LINKS_NAME = "refAllLinks"; //NOI18N
private static final String ADD_NAME = "add"; //NOI18N
private static final String EXISTS_NAME = "exists"; //NOI18N
private static final String REMOVE_NAME = "remove"; //NOI18N
private static final String QUERY_PREFIX = "get"; //NOI18N
private static final String M_ADD_NAME = "Add"; //NOI18N
private static final String M_ADD_DESC = "(Ljavax/jmi/reflect/RefObject;Ljavax/jmi/reflect/RefObject;)"; //NOI18N
private static final String M_ADD_TYPE = "Ljava/lang/Boolean;"; //NOI18N
private static final String M_EXISTS_NAME = "Exists"; //NOI18N
private static final String M_EXISTS_DESC = "(Ljavax/jmi/reflect/RefObject;Ljavax/jmi/reflect/RefObject;)"; //NOI18N
private static final String M_EXISTS_TYPE = "Ljava/lang/Boolean;"; //NOI18N
private static final String M_REMOVE_NAME = "Remove"; //NOI18N
private static final String M_REMOVE_DESC = "(Ljavax/jmi/reflect/RefObject;Ljavax/jmi/reflect/RefObject;)"; //NOI18N
private static final String M_REMOVE_TYPE = "Ljava/lang/Boolean;"; //NOI18N
private static final String M_ALL_LINKS_NAME = "AllLinks"; //NOI18N
private static final String M_ALL_LINKS_DESC = "()"; //NOI18N
private static final String M_ALL_LINKS_TYPE = "Ljava/util/Collection;"; //NOI18N
private static final String M_QUERY_NAME = "Query"; //NOI18N
private static final String M_QUERY_DESC = "(Ljava/lang/String;Ljavax/jmi/reflect/RefObject;)"; //NOI18N
private static final String M_QUERY_TYPE = "Ljava/lang/Object;"; //NOI18N
private final HashMap dispatchMethods = new HashMap();
private final HashMap dispatchEndMethods = new HashMap();
AssociationGenerator(String name, Class ifc, Class handler, StorableAssociation storable, Class custom) {
super(name, ifc, handler, storable, custom);
dispatchEndMethods.put("_query", new HashMap()); //NOI18N
}
protected MethodInfo[] generateMethods() throws IOException {
try {
ArrayList methods = new ArrayList();
methods.add(generateConstructor());
StorableObject[] ends = new StorableObject[2];
int i = 0;
for (Iterator it = ((List) obj.getMetaObject().getReference(MOFConstants.SH_MODEL_NAMESPACE_CONTENTS)).iterator(); it.hasNext() && i < 2;) {
StorableObject element = (StorableObject) it.next();
String metaTypeName = (String) element.getMetaObject().getAttribute(MOFConstants.SH_MODEL_MODEL_ELEMENT_NAME);
if (metaTypeName.equals(MOFConstants.SH_MODEL_ASSOCIATION_END))
ends[i++] = element;
}
String end1Name = (String) ends[0].getAttribute(MOFConstants.SH_MODEL_MODEL_ELEMENT_NAME);
String end1SubstName = TagSupport.getSubstName(ends[0]);
String end1Class = TagSupport.getTypeFullName(getAttrType(ends[0]));
String end2Name = (String) ends[1].getAttribute(MOFConstants.SH_MODEL_MODEL_ELEMENT_NAME);
String end2SubstName = TagSupport.getSubstName(ends[1]);
String end2Class = TagSupport.getTypeFullName(getAttrType(ends[1]));
// exists(, )
methods.addAll(getAssocMethod(EXISTS_NAME, new String[] {end1Class, end2Class}, "boolean", M_EXISTS_NAME, M_EXISTS_DESC, M_EXISTS_TYPE, null, "_exists")); //NOI18N
// ()
if (((Boolean) ends[0].getAttribute(MOFConstants.SH_MODEL_ASSOCIATION_END_IS_NAVIGABLE)).booleanValue()) {
MultiplicityType multiplicity = (MultiplicityType) ends[0].getAttribute(MOFConstants.SH_MODEL_ASSOCIATION_END_MULTIPLICITY);
methods.addAll(getAssocMethod(QUERY_PREFIX + firstUpper(end1SubstName), new String[] {end2Class}, multiplicity.getUpper() == 1 ? end1Class : (multiplicity.isOrdered() ? DT_ORDERED : DT_MULTIVALUED), M_QUERY_NAME, M_QUERY_DESC, M_QUERY_TYPE, end2Name, "_query")); //NOI18N
}
// ()
if (((Boolean) ends[1].getAttribute(MOFConstants.SH_MODEL_ASSOCIATION_END_IS_NAVIGABLE)).booleanValue()) {
MultiplicityType multiplicity = (MultiplicityType) ends[1].getAttribute(MOFConstants.SH_MODEL_ASSOCIATION_END_MULTIPLICITY);
methods.addAll(getAssocMethod(QUERY_PREFIX + firstUpper(end2SubstName), new String[] {end1Class}, multiplicity.getUpper() == 1 ? end2Class : (multiplicity.isOrdered() ? DT_ORDERED : DT_MULTIVALUED), M_QUERY_NAME, M_QUERY_DESC, M_QUERY_TYPE, end1Name, "_query")); //NOI18N
}
if (((Boolean) ends[0].getAttribute(MOFConstants.SH_MODEL_ASSOCIATION_END_IS_CHANGEABLE)).booleanValue() && ((Boolean) ends[1].getAttribute(MOFConstants.SH_MODEL_ASSOCIATION_END_IS_CHANGEABLE)).booleanValue()) {
// add(, )
methods.addAll(getAssocMethod(ADD_NAME, new String[] {end1Class, end2Class}, "boolean", M_ADD_NAME, M_ADD_DESC, M_ADD_TYPE, null, "_add")); //NOI18N
// remove(, )
methods.addAll(getAssocMethod(REMOVE_NAME, new String[] {end1Class, end2Class}, "boolean", M_REMOVE_NAME, M_REMOVE_DESC, M_REMOVE_TYPE, null, "_remove")); //NOI18N
}
methods.addAll(getAssocMethod(ALL_LINKS_NAME, new String[0], DT_MULTIVALUED, M_ALL_LINKS_NAME, M_ALL_LINKS_DESC, M_ALL_LINKS_TYPE, null, "_all")); //NOI18N
methods.add(getDispatchEndMethod("_query", new String[] {"java.lang.String", "javax.jmi.reflect.RefObject"}, "java.lang.Object", (HashMap) dispatchEndMethods.get("_query"))); //NOI18N
methods.add(getDispatchMethod("_remove", new String[] {"javax.jmi.reflect.RefObject", "javax.jmi.reflect.RefObject"}, "boolean", dispatchMethods.get("_remove"))); //NOI18N
methods.add(getDispatchMethod("_exists", new String[] {"javax.jmi.reflect.RefObject", "javax.jmi.reflect.RefObject"}, "boolean", dispatchMethods.get("_exists"))); //NOI18N
methods.add(getDispatchMethod("_add", new String[] {"javax.jmi.reflect.RefObject", "javax.jmi.reflect.RefObject"}, "boolean", dispatchMethods.get("_add"))); //NOI18N
methods.add(getDispatchMethod("_all", new String[0], DT_MULTIVALUED, dispatchMethods.get("_all"))); //NOI18N
return (MethodInfo[]) methods.toArray(new MethodInfo[methods.size()]);
} catch (Exception e) {
throw (DebugException) Logger.getDefault().annotate(new DebugException(), e);
}
}
protected String getConstructorDescriptor() {
return "(Lorg/netbeans/mdr/storagemodel/StorableAssociation;)V"; //NOI18N
}
protected Collection getAssocMethod(String methodName, String[] parameterTypes, String returnType, String handlerName, String handlerDescriptor, String handlerType, String featureName, String dispatchMethod) throws IOException, StorageException {
if (featureName != null) {
HashMap item = (HashMap) dispatchEndMethods.get(dispatchMethod);
item.put(featureName, new MethodDescHolder(methodName, parameterTypes, returnType));
} else
dispatchMethods.put(dispatchMethod, new MethodDescHolder(methodName, parameterTypes, returnType));
if (((Boolean) obj.getMetaObject().getAttribute(MOFConstants.SH_MODEL_ASSOCIATION_IS_DERIVED)).booleanValue()) {
ArrayList ret = new ArrayList();
ret.add(getDerivedMethod(methodName, parameterTypes, returnType));
return ret;
}
else
return getHandlerMethod(methodName, parameterTypes, returnType, handlerName, handlerDescriptor, handlerType, featureName);
}
protected MethodInfo getDispatchMethod(String methodName, String[] parameterTypes, String returnType, Object delegateObject) throws IOException {
String desc = getMethodDescriptor(parameterTypes, returnType);
MethodInfo minfo = new MethodInfo(methodName, desc, ACC_PUBLIC | ACC_FINAL);
// all the parameters are of object type, thus each takes only 1 slot
int localSlot0 = 1 + parameterTypes.length;
DataOutputStream out = new DataOutputStream(minfo.getCodeStream());
if (delegateObject instanceof MethodDescHolder) {
MethodDescHolder delegate = (MethodDescHolder) delegateObject;
code_aload(0, out);
for (int i = 1; i < localSlot0; i++) {
code_aload(i, out);
out.writeByte(opc_checkcast);
out.writeShort(cp.getClass(dotToSlash(delegate.getParameterTypes()[i - 1])));
}
// if it is equal, return result of a proper method
out.writeByte(opc_invokevirtual);
out.writeShort(cp.getMethodRef(dotToSlash(className), delegate.getName(), getMethodDescriptor(delegate.getParameterTypes(), delegate.getReturnType())));
if (returnType.equals("void")) //NOI18N
out.writeByte(opc_return);
else if (returnType.equals("boolean")) //NOI18N
out.writeByte(opc_ireturn);
else
out.writeByte(opc_areturn);
}
else {
// if the field was not found, throw an exception
out.writeByte(opc_new); // new
out.writeShort(cp.getClass("org/netbeans/mdr/util/DebugException")); //NOI18N
out.writeByte(opc_dup); // dup
out.writeByte(opc_invokespecial);
out.writeShort(cp.getMethodRef("org/netbeans/mdr/util/DebugException", "", "()V")); //NOI18N
out.writeByte(opc_athrow);
}
minfo.setMaxStack((short)10);
minfo.setMaxLocals((short)(localSlot0 + 2));
return minfo;
}
protected MethodInfo getDispatchEndMethod(String methodName, String[] parameterTypes, String returnType, HashMap ends) throws IOException {
String desc = getMethodDescriptor(parameterTypes, returnType);
MethodInfo minfo = new MethodInfo(methodName, desc, ACC_PUBLIC | ACC_FINAL);
// all the parameters are of object type, thus each takes only 1 slot
int localSlot0 = parameterTypes.length + 1;
DataOutputStream out = new DataOutputStream(minfo.getCodeStream());
code_aload(0, out);
for (Iterator it = ends.keySet().iterator(); it.hasNext();) {
String endName = (String) it.next();
MethodDescHolder item = (MethodDescHolder) ends.get(endName);
// load name of feature
code_ldc(cp.getString(endName), out);
//compare it with passed name
code_aload(1, out);
out.writeByte(opc_invokevirtual);
out.writeShort(cp.getMethodRef("java/lang/String", "equals", "(Ljava/lang/Object;)Z")); //NOI18N
// if it is not equal, continue processing
out.writeByte(opc_ifeq);
out.writeShort((short) (7 + 5 * (localSlot0 - 2)));
// if it is equal, return result of a proper method
// but first recast the parameters to see if they are of the correct type
for (int i = 2; i < localSlot0; i++) {
out.writeByte(opc_aload);
out.writeByte(i);
out.writeByte(opc_checkcast);
out.writeShort(cp.getClass(dotToSlash(item.getParameterTypes()[i - 2])));
}
out.writeByte(opc_invokevirtual);
out.writeShort(cp.getMethodRef(dotToSlash(className), item.getName(), getMethodDescriptor(item.getParameterTypes(), item.getReturnType())));
if (returnType.equals("void")) //NOI18N
out.writeByte(opc_return);
else
out.writeByte(opc_areturn);
}
// if the field was not found, throw an exception
out.writeByte(opc_new); // new
out.writeShort(cp.getClass("javax/jmi/reflect/InvalidNameException")); //NOI18N
out.writeByte(opc_dup); // dup
code_aload(1, out);
out.writeByte(opc_invokespecial);
out.writeShort(cp.getMethodRef("javax/jmi/reflect/InvalidNameException", "", "(Ljava/lang/String;)V")); //NOI18N
out.writeByte(opc_athrow);
minfo.setMaxStack((short)10);
minfo.setMaxLocals((short) (localSlot0 + 2));
return minfo;
}
}
|