OpenJava Tutorial


6. Callee-side Translation

In this section, an example of simple translation at callee-side is described.

6.1. What the base-level program should look like



import java.util.*;
public class VectorStack instantiates AdapterClass
          adapts Vector in v to Stack
{
    Vector v;
    public VectorStack( Vector v ) {
    this.v = v;
    }
    public void push( Object o ) {
    v.addElement( o );
    }
    public Object pop() {
    Object result = peek();
    v.removeElementAt( v.size() - 1 );
    return result;
    }
    public Object peek() {
        return v.elementAt( v.size() - 1 );
    }
}


public interface Stack
{
    public int size();
    public boolean isEmpty();
    public Enumeration elements();
    public Object[] toArray();
    public int hashCode();
    public void push( Object o );
    public Object pop();
    public Object peek();
}

6.2. What the base-level program should be translated

Like following:


import java.util.*;
public class VectorStack implements Stack
{
    Vector v;
    public VectorStack( Vector v ) {
    this.v = v;
    }
    public void push( Object o ) {
    v.addElement( o );
    }
    public Object pop() {
    Object result = peek();
    v.removeElementAt( v.size() - 1 );
    return result;
    }
    public Object peek() {
        return v.elementAt( v.size() - 1 );
    }
    public Object[] toArray() {
        return v.toArray();
    }
    public int size() {
        return v.size();
    }
    public Enumeration elements() {
        return v.elements();
    }
    public boolean isEmpty() {
        return v.isEmpty();
    }
    public int hashCode() {
        return v.hashCode();
    }
}

6.3. Write a meta-level program



import io.devnulllabs.openjava.mop.*;
import io.devnulllabs.openjava.ptree.*;
import io.devnulllabs.openjava.syntax.*;

/**
 * The metaclass AdapterClass supports classes
 * implementing an adapter role of the Adapter pattern.
 * The target's methods with same signatures as the adaptee's are
 * automatically implemented into the adapter class.
 */
public class AdapterClass instantiates Metaclass extends OJClass
{

    public static final String KEY_ADAPTS = "adapts";

    /* overrides for translation */
    public void translateDefinition() throws MOPException {
    OJClass target = getTarget(), adaptee = getAdaptee();
        if (target == null || adaptee == null)  return;

        /* implicit forwarding to the same signature's */
        OJMethod[] adapteds = adaptee.getMethods( this );
        for (int i = 0; i < adapteds.length; ++i) {
            /* picks up the method with same signature */
        OJMethod m;
        try {
        m = getTarget().getMethod( adapteds[i].getName(),
                       adapteds[i].getParameterTypes(),
                       this );
        } catch ( NoSuchMemberException e ) { /* not match */ continue; }
            
            /* generate a forwarding method with forwarded's name */
            addMethod( makeForwardingMethod( m.getName(), m ) );
        }

    addInterface( getTarget() );
    }

    /**
     * Generates a forwarding method with specified name.
     *
     * @param  name  generating method's name.
     * @param forwarded  method to which the generated method forwards.
     * @return  a generated forwarding method.
     */
    private OJMethod makeForwardingMethod( String name, OJMethod forwarded )
        throws MOPException
    {
        /* generates a new method without body */
    OJMethod result = new OJMethod(
        this,
        forwarded.getModifiers().remove( OJModifier.ABSTRACT ),
        forwarded.getReturnType(),
        name,
        forwarded.getParameterTypes(),
        forwarded.getExceptionTypes(),
        null
        );

    /* generates a method call and return statement */
    ExpressionList params = result.getParameterVariables();
        Expression expr = new MethodCall( getContainer(), name, params );
        StatementList body = new StatementList();
        if (forwarded.getReturnType() == OJSystem.VOID) {
            body.add( new ExpressionStatement( expr ) );
            body.add( new ReturnStatement() );
        } else {
            body.add( new ReturnStatement( expr ) );
        }

    result.setBody( body );
        return result;
    }

    /* extended information */

    private OJClass getAdaptee() throws MOPException {
        ObjectList suffix = (ObjectList) getSuffix( KEY_ADAPTS );
    return OJClass.forName( suffix.get( 0 ).toString() );
    }

    private Variable getContainer() throws MOPException {
        ObjectList suffix = (ObjectList) getSuffix( KEY_ADAPTS );
    return new Variable( suffix.get( 1 ).toString() );
    }

    private OJClass getTarget() throws MOPException {
        ObjectList suffix = (ObjectList) getSuffix( KEY_ADAPTS );
    return OJClass.forName( suffix.get( 2 ).toString() );
    }

    /* override to extend syntax */
    public static boolean isRegisteredKeyword( String keyword ) {
        return keyword.equals( KEY_ADAPTS );
    }

    /* override to extend syntax */
    public static SyntaxRule getDeclSuffixRule( String keyword ) {
    if (keyword.equals( KEY_ADAPTS )) {
        return new CompositeRule(
                new TypeNameRule(),
        new PrepPhraseRule( "in", new NameRule() ),
        new PrepPhraseRule( "to", new TypeNameRule() ) );
    }
    return null;
    }

}


Please send any message to :
mich@acm.org

Copyright (C) 1999 by Michaki Tatsubori.
Java(TM) is a trademark of Sun Microsystems, Inc.