Source code: com/memoire/foo/FooCategory.java
1 /**
2 * @modification $Date: 2002/12/16 18:56:25 $
3 * @statut unstable
4 * @file FooCategory.java
5 * @version 0.08
6 * @author Guillaume Desnoix
7 * @email guillaume@desnoix.com
8 * @license GNU General Public License 2 (GPL2)
9 * @copyright 1999-2001 Guillaume Desnoix
10 */
11
12 package com.memoire.foo;
13 import com.memoire.foo.*;
14
15 import java.io.*;
16 import java.util.*;
17 import java.lang.reflect.*;
18
19 public class FooCategory
20 {
21 private static FooCategory pkg_=null;
22
23 public static final FooCategory init()
24 {
25 if(pkg_==null)
26 {
27 pkg_=FooCategory.create(FooCategory.class);
28 pkg_.alias("&category");
29
30 // pkg_.setMessage("new" ,FooCategory.class,"newMsg");
31 // pkg_.setMessage("method" ,FooCategory.class,"methodMsg");
32 pkg_.setMessage("message" ,FooCategory.class,"messageEval",false);
33 pkg_.setMessage("message:" ,FooCategory.class,"messageRaw" ,false);
34 }
35
36 return pkg_;
37 }
38
39 /*
40 public void display()
41 {
42 system.out.print(name_+":");
43 for(Enumeration e=messages_.keys(); e.hasMoreElements(); )
44 system.out.print(" "+e.nextElement());
45 system.out.println();
46 }
47
48 public static void displayAll()
49 {
50 for(Enumeration e=classes_.keys(); e.hasMoreElements(); )
51 {
52 Class c=(Class)e.nextElement();
53 system.out.println(c.getName());
54 ((FooCategory)classes_.get(c)).display();
55 }
56 }
57 */
58
59 private static final Hashtable CATEGORIES=new Hashtable(21);
60
61 // static
62
63 public static FooCategory create(Class _class)
64 {
65 return create0(_class.getName());
66 }
67
68 static FooCategory create(String _name)
69 {
70 FooCategory r=create0(_name);
71 FooSymbol.setValue(_name,r);
72 return r;
73 }
74
75 private static FooCategory create0(String _name)
76 {
77 FooCategory r=get_raw(_name);
78
79 if(r==null)
80 {
81 r=new FooCategory(_name);
82 put_raw(_name,r);
83 }
84
85 return r;
86 }
87
88 static FooCategory get_raw(String _name)
89 {
90 return (FooCategory)CATEGORIES.get(_name);
91 }
92
93 static void put_raw(String _name, FooCategory _category)
94 {
95 if(_category==null) CATEGORIES.remove(_name);
96 else CATEGORIES.put(_name,_category);
97 }
98
99 //---------
100
101 private String name_;
102 private Hashtable messages_;
103 //private Hashtable attributes_;
104 private FooList parents_;
105
106 private FooCategory(String _name)
107 {
108 name_ =_name;
109 messages_ =new Hashtable();
110 //attributes_=new Hashtable();
111 parents_ =new FooList();
112 }
113
114 private FooMessage get_msg(String _name)
115 {
116 return (FooMessage)messages_.get(_name);
117 }
118
119 private void put_msg(FooMessage _msg)
120 {
121 String name =_msg.getName();
122 Object previous=get_msg(name);
123 if((previous!=null)&&(!previous.equals(_msg)))
124 FooLib.getParser().warning("message redefined:"+name);
125 messages_.put(name,_msg);
126 }
127
128 private void rem_msg(String _name)
129 {
130 Object previous=get_msg(_name);
131 if(previous==null)
132 FooLib.getParser().warning("message was not defined:"+_name);
133 else
134 messages_.remove(_name);
135 }
136
137 public String getName()
138 { return name_; }
139
140 /*
141 public void alias(Class _similar)
142 {
143 alias(_similar.getName());
144 }
145 */
146
147 public FooCategory alias(String _name)
148 {
149 if(!_name.startsWith("&"))
150 throw new RuntimeException("illegal alias:"+_name);
151 put_raw(_name,this);
152 return this;
153 }
154
155 public void extend(FooCategory _category)
156 {
157 if(!parents_.contains(_category))
158 parents_.add(_category);
159 }
160
161 // official method to get a message
162
163 public FooMessage getMessage(String _name)
164 {
165 FooMessage r=get_msg(_name);
166
167 if(r==null)
168 {
169 for(int i=0;i<parents_.length();i++)
170 {
171 r=((FooCategory)parents_.at(i)).getMessage(_name);
172 if(r!=null) break;
173 }
174 }
175
176 return r;
177 }
178
179 // convenient methods to add messages
180
181 public void setMessage(FooMessage _message)
182 {
183 put_msg(_message);
184 }
185
186 public void setMessage(String _name, Field _field)
187 {
188 put_msg(new FooMessage(_name,_field,true));
189 }
190
191 public void setMessage(String _name, Method _method)
192 {
193 put_msg(new FooMessage(_name,_method,true));
194 }
195
196 public void setMessage(String _name, Method _method, boolean _eval)
197 {
198 put_msg(new FooMessage(_name,_method,_eval));
199 }
200
201 public void setMessage(String _name, String _alias)
202 {
203 put_msg(new FooMessage(_name,_alias,false));
204 }
205
206 public void setMessage(String _name, Object[] _expr, boolean _eval)
207 {
208 put_msg(new FooMessage(_name,_expr,_eval));
209 }
210
211 public void setMessage
212 (String _name, Object[] _expr, String[] _argnames, boolean _eval)
213 {
214 put_msg(new FooMessage(_name,_expr,_argnames,_eval));
215 }
216
217 public void setMessage(String _name, Class _clazz, String _signature)
218 {
219 setMessage(_name,_clazz,_signature,true);
220 }
221
222 public void setMessage(String _name, Class _clazz,
223 String _signature,boolean _evalargs)
224 {
225 Method m=FooLib.getMethod(_clazz,_signature);
226 if(m==null)
227 throw new RuntimeException
228 ("method " + _signature + " can not be found in "+
229 FooLib.getClassName(_clazz));
230 setMessage(_name,m,_evalargs);
231 }
232
233 public String[] getMessages()
234 {
235 String[] r=new String[messages_.size()];
236 int i=0;
237 for(Enumeration e=messages_.keys(); e.hasMoreElements(); )
238 { r[i]=(String)e.nextElement(); i++; }
239 return r;
240 }
241
242 public String toString()
243 {
244 return "category "+name_;
245 }
246
247 public static Object newMsg(Object[] _p)
248 {
249 //for(int i=0;i<_p.length;i++)
250 // System.out.println(""+i+": "+_p[i]);
251
252 FooLib.checkClassArgument(Class.class,_p[0],0);
253 Class c=(Class)_p[0];
254 Constructor m=FooLib.getConstructor(c,c.getName(),_p.length-1);
255 Object[] q=new Object[_p.length-1];
256 for(int i=0;i<q.length;i++)
257 q[i]=_p[i+1];
258
259 return FooLib.invokeConstructor(m,q);
260 }
261
262 public static Object methodMsg(Class _clazz,String _signature)
263 {
264 return FooLib.getMethod(_clazz,_signature);
265 }
266
267 public static Object messageEval(Object[] _p)
268 {
269 return message0(_p,true);
270 }
271
272 public static Object messageRaw(Object[] _p)
273 {
274 return message0(_p,false);
275 }
276
277 private static Object message0(Object[] _p,boolean _eval)
278 {
279 Object r=null;
280 //for(int i=0;i<_p.length;i++)
281 // System.out.println(""+i+": "+_p[i]);
282
283 FooLib.checkClassArgument(FooCategory.class,_p[0],0);
284 FooCategory c=(FooCategory)_p[0];
285
286 switch(_p.length)
287 {
288 case 1:
289 FooList l=new FooList();
290 for(Enumeration e=c.messages_.keys(); e.hasMoreElements(); )
291 l.add(e.nextElement());
292 r=l;
293 break;
294 case 2:
295 r=c.getMessage(_p[1].toString());
296 break;
297 case 3:
298 String name=_p[1].toString();
299 Object obj =FooLib.eval(_p[2]);
300
301 if(obj instanceof FooMessage)
302 c.setMessage((FooMessage)obj);
303 else
304 if(obj instanceof Field)
305 c.setMessage(name,(Field)obj);
306 else
307 if(obj instanceof Method)
308 c.setMessage(name,(Method)obj);
309 else
310 if(obj instanceof String)
311 c.setMessage(name,(String)obj);
312 else
313 throw new RuntimeException
314 ("invalid argument:"+FooLib.toString(_p[2]));
315 r=c;
316 break;
317 default:
318 String[] argnames=null;
319
320 if(_p[2] instanceof FooList)
321 {
322 FooList a=(FooList)_p[2];
323 try
324 {
325 int la=a.length();
326 argnames=new String[la];
327 for(int i=0;i<la;i++)
328 argnames[i]=((FooSymbol)a.at(i)).getName();
329 }
330 catch(Exception ex)
331 {
332 throw new RuntimeException
333 ("invalid list of arguments:"+FooLib.toString(a));
334 }
335 }
336 else
337 FooLib.checkClassArgument(Integer.class,_p[2],2);
338
339 Object[] q=new Object[_p.length-3];
340 for(int i=3;i<_p.length;i++) q[i-3]=_p[i];
341
342 c.setMessage(_p[1].toString(),q,argnames,_eval);
343 r=c;
344
345 break;
346 }
347
348 return r;
349 }
350 }