KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > kawa > lang > Record


1 package kawa.lang;
2 //import java.lang.reflect.Field; // Confuses Gcj. Should FIX gcj.
3
import java.lang.reflect.Modifier JavaDoc;
4 import java.util.Vector JavaDoc;
5 import gnu.bytecode.*;
6 import gnu.mapping.*;
7 import gnu.lists.*;
8 import gnu.expr.Compilation;
9
10 public class Record
11 {
12   public String JavaDoc getTypeName()
13   {
14     return getClass().getName();
15   }
16
17   public static boolean isRecord (Object JavaDoc obj) { return obj instanceof Record; }
18
19   public int hashCode()
20   {
21     java.lang.reflect.Field JavaDoc[] fields = getClass().getFields();
22     int hash = 12345;
23     for (int i = 0; i < fields.length; i++)
24       {
25     java.lang.reflect.Field JavaDoc field = fields[i];
26     Object JavaDoc value;
27     try
28       {
29         value = field.get(this);
30       }
31     catch (IllegalAccessException JavaDoc ex)
32       {
33         continue;
34       }
35     if (value != null)
36       hash ^= value.hashCode();
37       }
38     return hash;
39   }
40
41   static java.lang.reflect.Field JavaDoc getField (Class JavaDoc clas, String JavaDoc fname)
42     throws NoSuchFieldException JavaDoc
43   {
44     ClassType ctype = (ClassType) Type.make(clas);
45     for (gnu.bytecode.Field fld = ctype.getFields();
46      fld != null; fld = fld.getNext())
47       {
48     if ((fld.getModifiers() & (Modifier.STATIC|Modifier.PUBLIC))
49         != Modifier.PUBLIC)
50       continue;
51     if (! fld.getSourceName().equals(fname))
52       continue;
53     return fld.getReflectField();
54       }
55     throw new NoSuchFieldException JavaDoc();
56   }
57
58   public Object JavaDoc get (String JavaDoc fname, Object JavaDoc defaultValue)
59   {
60     Class JavaDoc clas = getClass();
61     try
62       {
63     return getField(clas, fname).get(this);
64       }
65     catch (NoSuchFieldException JavaDoc ex)
66       {
67     //return defaultValue;
68
throw new GenericError("no such field "+fname+" in "+clas.getName());
69       }
70     catch (IllegalAccessException JavaDoc ex)
71       {
72     throw new GenericError("illegal access for field "+fname);
73       }
74   }
75
76   public Object JavaDoc put (String JavaDoc fname, Object JavaDoc value)
77   {
78     return set1 (this, fname, value);
79   }
80
81   public static Object JavaDoc set1 (Object JavaDoc record, String JavaDoc fname, Object JavaDoc value)
82   {
83     Class JavaDoc clas = record.getClass();
84     try
85       {
86     java.lang.reflect.Field JavaDoc fld = getField(clas, fname);
87     Object JavaDoc old = fld.get(record);
88     fld.set(record, value);
89     return old;
90       }
91     catch (NoSuchFieldException JavaDoc ex)
92       {
93     //throw new UnboundLocation(fname);
94
throw new GenericError("no such field "+fname+" in "+clas.getName());
95       }
96     catch (IllegalAccessException JavaDoc ex)
97       {
98     throw new GenericError("illegal access for field "+fname);
99       }
100   }
101
102   public boolean equals (Object JavaDoc obj)
103   {
104     if (this == obj)
105       return true;
106     Class JavaDoc thisClass = getClass();
107     if (obj == null || obj.getClass() != thisClass)
108       return false;
109     ClassType ctype = (ClassType) Type.make(thisClass);
110     for (gnu.bytecode.Field fld = ctype.getFields();
111      fld != null; fld = fld.getNext())
112       {
113     if ((fld.getModifiers() & (Modifier.STATIC|Modifier.PUBLIC))
114         != Modifier.PUBLIC)
115       continue;
116     Object JavaDoc value1, value2;
117     try
118       {
119         java.lang.reflect.Field JavaDoc field = fld.getReflectField();
120         value1 = field.get(this);
121         value2 = field.get(obj);
122       }
123     catch (Exception JavaDoc ex)
124       {
125         throw new WrappedException(ex);
126       }
127     if (! (value1.equals(value2)))
128       return false;
129       }
130     return true;
131   }
132
133   public String JavaDoc toString()
134   {
135     StringBuffer JavaDoc buf = new StringBuffer JavaDoc(200);
136     buf.append("#<");
137     buf.append(getTypeName());
138     ClassType ctype = (ClassType) Type.make(getClass());
139     for (gnu.bytecode.Field fld = ctype.getFields();
140      fld != null; fld = fld.getNext())
141       {
142     if ((fld.getModifiers() & (Modifier.STATIC|Modifier.PUBLIC))
143         != Modifier.PUBLIC)
144       continue;
145     Object JavaDoc value;
146     try
147       {
148         java.lang.reflect.Field JavaDoc field = fld.getReflectField();
149         value = field.get(this);
150       }
151     catch (Exception JavaDoc ex)
152       {
153         value = "#<illegal-access>";
154       }
155     buf.append(' ');
156     buf.append(fld.getSourceName());
157     buf.append(": ");
158     buf.append(value);
159       }
160     buf.append(">");
161     return buf.toString();
162   }
163
164   public void print(java.io.PrintWriter JavaDoc ps)
165   {
166     ps.print(toString());
167   }
168
169   public static ClassType makeRecordType (String JavaDoc name, LList fnames)
170   {
171     ClassType superClass = ClassType.make("kawa.lang.Record");
172     String JavaDoc mangledName = Compilation.mangleNameIfNeeded(name);
173     ClassType clas = new ClassType(mangledName);
174     clas.setSuper(superClass);
175     clas.access_flags = Access.PUBLIC;
176
177     // Generate the (default) constructor.
178
Method constructor = clas.addMethod ("<init>", Type.typeArray0,
179                       Type.void_type, Access.PUBLIC);
180     Method superConstructor
181       = superClass.addMethod ("<init>", Type.typeArray0,
182                    Type.void_type, Access.PUBLIC);
183     gnu.bytecode.CodeAttr code = constructor.startCode();
184     code.emitPushThis();
185     code.emitInvokeSpecial(superConstructor);
186     code.emitReturn();
187     if (! name.equals(mangledName))
188       {
189     Method meth = clas.addMethod ("getTypeName", Type.typeArray0,
190                       Compilation.typeString, Access.PUBLIC);
191     code = meth.startCode();
192     code.emitPushString(name);
193     code.emitReturn();
194       }
195
196     //StringBuffer fnamesBuf = new StringBuffer(100);
197
gnu.bytecode.Field fld;
198     while (fnames != LList.Empty)
199       {
200     Pair pair = (Pair) fnames;
201     String JavaDoc fname = pair.car.toString();
202     //fnamesBuf.append(fname); fnamesBuf.append('\n');
203
fld = clas.addField(Compilation.mangleNameIfNeeded(fname),
204                 Type.pointer_type, Access.PUBLIC);
205     fld.setSourceName(fname.intern());
206     fnames = (LList) pair.cdr;
207       }
208     /*
209     fld = clas.addField("$FieldNames$", Compilation.typeString,
210               Access.PUBLIC|Access.STATIC|Access.FINAL);
211     ConstantValueAttr attr = new ConstantValueAttr(fnamesBuf.toString());
212     attr.addToFrontOf(fld);
213     */

214
215     byte[][] arrays = new byte[1][];
216     String JavaDoc[] names = new String JavaDoc[1];
217     names[0] = mangledName;
218     arrays[0] = clas.writeToArray();
219     ArrayClassLoader loader = new ArrayClassLoader(names, arrays);
220     try
221       {
222     Class JavaDoc reflectClass = loader.loadClass (mangledName, true);
223     Type.registerTypeForClass(reflectClass, clas);
224     return clas;
225       }
226     catch (ClassNotFoundException JavaDoc ex)
227       {
228     throw new InternalError JavaDoc (ex.toString());
229       }
230   }
231
232   public static LList typeFieldNames (Class JavaDoc clas)
233   {
234     LList list = LList.Empty;
235     /*
236     try
237       {
238     Field fld = clas.getDeclaredField("$FieldNames$");
239     String names = (String) fld.get(null);
240     int nfields = 0;
241     int limit = names.length() - 1;
242     
243     int ifield;
244     while (limit > 0)
245       {
246         int start = names.lastIndexOf('\n', limit - 1);
247         String fname = names.substring(start + 1, limit);
248         list = new Pair(fname.intern(), list);
249         limit = start;
250       }
251     return list;
252       }
253     catch (Exception ex)
254       {
255       }
256     */

257     ClassType ctype = (ClassType) Type.make(clas);
258     gnu.bytecode.Field field = ctype.getFields();
259     Vector JavaDoc vec = new Vector JavaDoc(100);
260     for (; field != null; field = field.getNext())
261       {
262     if ((field.getModifiers() & (Modifier.STATIC|Modifier.PUBLIC))
263         == Modifier.PUBLIC)
264       vec.addElement(field.getSourceName());
265       }
266     for (int i = vec.size(); --i >= 0; )
267       {
268     list = new Pair(vec.elementAt(i), list);
269       }
270     return list;
271   }
272
273   public static LList typeFieldNames (ClassType ctype)
274   {
275     return typeFieldNames(ctype.getReflectClass());
276   }
277 }
278
Popular Tags