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;
}
}
|