summaryrefslogtreecommitdiff
path: root/tutorial/examples/capsule/CapsuleClass.oj
blob: 9d54fe3967c699da68f9ef489390a4e63ce68ef0 (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
125
126
127
128
129
130
/*
 * CapsuleClass.oj
 *
 * Apr 23, 1999 by Michiaki Tatsubori
 */
package examples.capsule;


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


/**
 * The class <code>CapsuleClass</code> is a metaclass which
 * hides all the fields in the class and provides reader and writer
 * methods corresponding to each field.  Furthermore, accesses
 * to fields of the class is to be replaced with these methods.
 */
public class CapsuleClass instantiates Metaclass extends OJClass
{
    /** Overrides to translate definition */
    public void translateDefinition() throws MOPException {
        /* Detect public fields in superclass */
        OJField[] inherited_flds = getSuperclass().getFields();
    if (inherited_flds.length > 0) {
        System.err.println( "WARNING: Leak Possibilities" );
        for (int i = 0; i < inherited_flds.length; ++i)
            System.err.println( inherited_flds[i].toString() );
    }

    /* Get all declared fields and hide it */
    OJField[] fields = getDeclaredFields();
    for (int i = 0; i < fields.length; ++i) {
        OJModifier modif = fields[i].getModifiers();
        if (! modif.isPrivate())  hideField( fields[i] );
    }
    }

    private void hideField( OJField field ) throws MOPException {
        System.err.println( "Hiding a field : " + field.toString() );
    generateReaderMethod( field );
    generateWriterMethod( field );
    field.setModifiers( field.getModifiers().setPrivate() );
    }

    private void generateReaderMethod( OJField field ) throws MOPException {
        StatementList body = makeStatementList(
        "return " + field.getName() + ";"
        );
    OJMethod reader = new OJMethod( this,
        field.getModifiers(), field.getType(),
        fieldReaderName( field.getName() ),
        (OJClass[]) null, null, body
        );
    addMethod( reader );
    }

    private void generateWriterMethod( OJField field ) throws MOPException {
    OJMethod writer = new OJMethod( this,
        field.getModifiers(), field.getType(),
        fieldWriterName( field.getName() ),
        new OJClass[]{ field.getType() }, null, null
        );
    String param = writer.getParameters()[0];
        StatementList body = makeStatementList( writer.getEnvironment(),
        "return " + field.getName() + "=" + param + ";"
        );
    writer.setBody( body );
    addMethod( writer );
    }

    private static final String fieldReaderName( String name ) {
        return "read_" + name;
    }

    private static final String fieldWriterName( String name ) {
        return "write_" + name;
    }

    /* overrides */

    /** Allows references to private fields */
    public OJField resolveException( NoSuchMemberException e, String name )
        throws NoSuchMemberException
    {
        try {
        return getDeclaredField( name );
        } catch ( NoSuchMemberException e2 ) {}
        return super.resolveException( e, name );
    }

    /** Overrides to expand fields to be read */
    public Expression expandFieldRead(
        Environment  env,
        FieldAccess  expr )
    {
        Expression ref = expr.getReferenceExpr();
    String name = fieldReaderName( expr.getName() );
        Expression result;
    if (ref != null) {
        result = new MethodCall( ref, name, null );
    } else {
        result = new MethodCall( expr.getReferenceType(), name, null );
    }
        System.err.println( "Patch FR : " + expr + "\tto\t" + result );
    return result;
    }

    /** Overrides to expand fields to be written */
    public Expression expandFieldWrite(
        Environment           env,
        AssignmentExpression  expr )
    {
    FieldAccess fldac = (FieldAccess) expr.getLeft();
    ExpressionList args = new ExpressionList( expr.getRight() );
        Expression ref = fldac.getReferenceExpr();
    String name = fieldWriterName( fldac.getName() );
        Expression result;
    if (ref != null) {
        result = new MethodCall( ref, name, args );
    } else {
        result = new MethodCall( fldac.getReferenceType(), name, args );
    }
        System.err.println( "Patch FW : " + expr + "\tto\t" + result );
    return result;
    }

}