summaryrefslogtreecommitdiff
path: root/tutorial/examples/mixin/MixinedClass.java
blob: c281fb90330aa2fa6ecc3618f49d84650d89d5ce (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/*
 * This code was generated by ojc.
 */
/*
 * MixinedClass.oj
 *
 * An OpenJava example for incorporating mixin mechanism.
 *
 * @author   Michiaki Tatsubori
 * @version  %VERSION% %DATE%
 * @see      java.lang.Object
 *
 * COPYRIGHT 1999 by Michiaki Tatsubori, ALL RIGHTS RESERVED.
 */
package examples.mixin;


import java.lang.Object;
import openjava.mop.*;
import openjava.ptree.*;
import openjava.syntax.*;


/**
 * The metaclass <code>MixinedClass</code> supports classes
 * using mixin.
 * <p>
 * For example, the class <code>MixinedClass</code>:
 * <pre>
 * public class TextboxWithUndo instantiates MixinedClass
 *    extends Textbox mixs Undo
 * {
 * }
 * </pre>
 * would be automatically implemented.
 * <p>
 *
 * @author   Michiaki Tatsubori
 * @version  1.0
 * @since    $Id: MixinedClass.java,v 1.2 2003/02/19 02:55:01 tatsubori Exp $
 * @see java.lang.Object
 */
public class MixinedClass extends OJClass
{

    public static final String KEY_MIXES = "mixes";

    /* overrides for translation */
    public void translateDefinition()
        throws MOPException
    {
        OJClass[] mixinClasses = getMixins();
        for (int i = 0; i < mixinClasses.length; ++i) {
            incorporateMixin( mixinClasses[i] );
        }
    }

    public void incorporateMixin( OJClass mixinClazz )
        throws MOPException
    {
        addInterface( mixinClazz );
        OJMethod[] mixeds = mixinClazz.getMethods();
        for (int i = 0; i < mixeds.length; ++i) {
            addMethod( makeEmptyMethod( mixeds[i] ) );
        }
    }

    /**
     * Generates a empty method with specified name.
     *
     * @param  name  generating method's name.
     * @param forwarded  method to which the generated method forwards.
     * @return  a generated empty method.
     */
    private OJMethod makeEmptyMethod( OJMethod implementee )
        throws MOPException
    {
        StatementList body = new StatementList();
        if (implementee.getReturnType() == OJSystem.VOID) {
            body.add( new ReturnStatement() );
        } else {
            body.add( new ReturnStatement( Literal.constantNull() ) );
        }
        return new OJMethod( this, implementee.getModifiers().remove( OJModifier.ABSTRACT ), implementee.getReturnType(), implementee.getName(), implementee.getParameterTypes(), implementee.getExceptionTypes(), body );
    }

    /* extended information */
    private OJClass[] getMixins()
        throws MOPException
    {
        ObjectList suffix = (ObjectList) getSuffix( KEY_MIXES );
        OJClass[] result = new OJClass[suffix.size()];
        for (int i = 0; i < result.length; ++i) {
            result[i] = OJClass.forName( suffix.get( i ).toString() );
        }
        return result;
    }

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

    /* override to extend syntax */
    public static SyntaxRule getDeclSuffixRule( String keyword )
    {
        if (keyword.equals( KEY_MIXES )) {
            return new DefaultListRule( new TypeNameRule(), TokenID.COMMA );
        }
        return null;
    }

    public MixinedClass( openjava.mop.Environment oj_param0, openjava.mop.OJClass oj_param1, openjava.ptree.ClassDeclaration oj_param2 )
    {
        super( oj_param0, oj_param1, oj_param2 );
    }

    public MixinedClass( java.lang.Class oj_param0, openjava.mop.MetaInfo oj_param1 )
    {
        super( oj_param0, oj_param1 );
    }

}