summaryrefslogtreecommitdiff
path: root/src/test/java/dardia/MIJava.oj
blob: 574b11c49850555b30a21ebeab37bdf128a2ce73 (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
import io.devnulllabs.openjava.mop.*;
import io.devnulllabs.openjava.ptree.*;
import io.devnulllabs.openjava.syntax.*;

import java.util.*;

public class MIJava instantiates Metaclass extends OJClass {

    // The below logic performs conflict resolution by not overwriting any methods already existing.
    //   This means that if in the TA multiextends Staff, Student example both Staff and Student have a field or
    //   a method with the same name, the field/method that is copied into TA's body is the one from the base
    //   class that occurs earlier in the argument list to multiextends.
    public void translateDefinition() throws MOPException {
        transformMultiextendingClass();
    }

    public void transformMultiextendingClass() throws MOPException {
        ObjectList extendedClasses = (ObjectList)getSuffix("multiextends");

        Collection existingSignatures = new Vector();
        OJMethod[] currentMethods = getDeclaredMethods();
        for (int i = 0; i < currentMethods.length; i++) {
            existingSignatures.add((currentMethods[i].signature()).toString());
        }

        Collection existingFields = new Vector();
        OJField[] currentFields = getDeclaredFields();
        for (int i = 0; i < currentFields.length; i++) {
            existingFields.add((currentFields[i].signature()).toString());
        }

        if (extendedClasses != null) {
            for (int i = 0; i < extendedClasses.size(); i++) {
                try {
                    OJClass currentExtendedClass = OJClass.forName((extendedClasses.get(i)).toString());

                    // open each class that we multiextended and copy its methods into a local variable
                    OJMethod[] currentExtendedClassMethods = currentExtendedClass.getDeclaredMethods();

                    // copy all of the methods for the current extended class into the output if they don't already exist
                    for (int j = 0; j < currentExtendedClassMethods.length; j++) {
                        if (!existingSignatures.contains((currentExtendedClassMethods[j].signature()).toString())) {
                            // if we don't currently have this method, add it
                            //addMethod(currentExtendedClassMethods[j]);

                            // Because the above addMethod() causes odd CannotAlterExceptions to be thrown, I do
                            // the below to describe what is happening in the multiextending class and where its
                            // methods come from.

                            StatementList statementsToInsert = new StatementList();
                            Statement cameFromStatement = makeStatement("System.out.println(\"this body would come from " + (extendedClasses.get(i)).toString() + "\\n\");");
                            statementsToInsert.add(cameFromStatement);


                            OJMethod methodToInsert = new OJMethod((OJClass)this,
                                                                   currentExtendedClassMethods[j].getModifiers(),
                                                                   currentExtendedClassMethods[j].getReturnType(),
                                                                   currentExtendedClassMethods[j].getName(),
                                                                   currentExtendedClassMethods[j].getParameterTypes(),
                                                                   currentExtendedClassMethods[j].getExceptionTypes(),
                                                                   statementsToInsert);

                            addMethod(methodToInsert);

                            // make note that we added a mehtod with some signature so we don't put multiple methods
                            // with the same signature into the class.  this would be invalid Java code and unlogical.
                            existingSignatures.add((methodToInsert.signature()).toString());
                        } // else, a method with the same signature already exists, skip it
                    }


                    // open each class and copy its fields into local variable
                    OJField[] currentExtendedClassFields = currentExtendedClass.getDeclaredFields();

                    // copy all of the fields for the current extended class into the output if they don't already exist
                    for (int j = 0; j < currentExtendedClassFields.length; j++) {
                        if (!existingFields.contains((currentExtendedClassFields[j].signature()).toString())) {
                            // if we don't currently have this field, add it
                            addField(currentExtendedClassFields[j]);
                            existingFields.add((currentExtendedClassFields[j].signature()).toString());
                        }
                    }

                } catch (OJClassNotFoundException e) {
                    System.err.println(e);
                    System.exit(-1);
                }
            }
        }
    }

    // new class modifier: "multiextends".
    public static boolean isRegisteredKeyword(String str) {
        if (str.equals("multiextends")) {
            return(true);
        }

        return OJClass.isRegisteredKeyword(str);
    }

    // overridden to let OpenJava know how multiextends arguments are separated.
    public static SyntaxRule getDeclSuffixRule(String str) {
        if (str.equals("multiextends")) {
            return new DefaultListRule(new TypeNameRule(), TokenID.COMMA );
        }

        return null;
    }
}