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

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;
    }
}
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

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

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