1 /*
2  * JHandler.java
3  *
4  * Copyright (C) 2003-2005 Andras Simon, Peter Graves
5  * $Id$
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20  *
21  * As a special exception, the copyright holders of this library give you
22  * permission to link this library with independent modules to produce an
23  * executable, regardless of the license terms of these independent
24  * modules, and to copy and distribute the resulting executable under
25  * terms of your choice, provided that you also meet, for each linked
26  * independent module, the terms and conditions of the license of that
27  * module.  An independent module is a module which is not derived from
28  * or based on this library.  If you modify this library, you may extend
29  * this exception to your version of the library, but you are not
30  * obligated to do so.  If you do not wish to do so, delete this
31  * exception statement from your version.
32  */
33 
34 package org.armedbear.lisp;
35 
36 import static org.armedbear.lisp.Lisp.*;
37 
38 import java.util.HashMap;
39 import java.util.Map;
40 import java.util.WeakHashMap;
41 
42 public final class JHandler
43 {
44     static final Map<Object,Map<String,Entry>> table =
45        new WeakHashMap<Object,Map<String,Entry>>();
46 
callLisp(String s, Object o)47     public static void callLisp (String s, Object o)
48     {
49         callLisp(s, o, "");
50     }
51 
callLisp(String s, Object o, String s1)52     public static void callLisp (String s, Object o, String s1)
53     {
54         callLisp(s, o, s1, new int[] {});
55     }
56 
callLisp(String s, Object o, String s1, int ai[])57     public static void callLisp (String s, Object o, String s1, int ai[]) {
58         callLisp(s, o, new String[] { s1 }, ai);
59     }
60 
callLisp(String s, Object o, String as[])61     public static void callLisp (String s, Object o, String as[])
62     {
63         callLisp(s, o, as, new int[] {});
64     }
65 
callLisp(String s, Object o, String as[], int ai[])66     public static void callLisp (String s, Object o, String as[], int ai[])
67     {
68         if (table.containsKey(o)) {
69             Map<String,Entry> entryTable = table.get(o);
70             if (entryTable.containsKey(s)) {
71                 final Entry entry = entryTable.get(s);
72                 final Function f = entry.getHandler();
73                 final LispObject data = entry.getData();
74                 final Fixnum count = entry.getCount();
75                 final Fixnum[] lispAi = new Fixnum[ai.length];
76                 for (int i = 0; i < ai.length; i++) {
77                     lispAi[i] = Fixnum.getInstance(ai[i]);
78                 }
79                 final LispObject lispAiVector = new SimpleVector(lispAi);
80                 final SimpleString[] lispAs = new SimpleString[as.length];
81                 for (int i = 0; i < as.length; i++) {
82                     lispAs[i] = new SimpleString(as[i]);
83                 }
84                 final LispObject lispAsVector = new SimpleVector(lispAs);
85                 LispObject[] args =
86                     new LispObject[] //FIXME: count -> seq_num
87                     { data,
88                       new JavaObject(o),
89                       lispAiVector,
90                       lispAsVector,
91                       internKeyword(s),
92                       count };
93                 f.execute(args);
94             }
95         }
96     }
97 
98     // jregister-handler1 object event handler data count
99     private static final Primitive _JREGISTER_HANDLER =
100         new Primitive("%jregister-handler", PACKAGE_JAVA)
101     {
102         @Override
103         public LispObject execute(LispObject[] args)
104         {
105             if (args.length != 5)
106                 return error(new WrongNumberOfArgumentsException(this, 5));
107             Map<String,Entry> entryTable = null;
108             Object object = args[0].javaInstance();
109             String event = ((Symbol)args[1]).getName();
110             if (!table.containsKey(object)) {
111                 entryTable = new HashMap<String,Entry>();
112                 table.put(object,entryTable);
113             } else {
114                 entryTable = (Map<String,Entry>)table.get(object);
115             }
116             Entry entry = new Entry((Function) args[2], args[3], event, entryTable);
117             if (args[4] != NIL)
118                 entry.addCount(((Fixnum)args[4]).value);
119             entryTable.put(event,entry);
120             return T;
121         }
122     };
123 
124     private static class Entry
125     {
126         Function handler;
127         LispObject data;
128         int count = -1;
129         Map<String,Entry> entryTable;
130         String event;
131 
Entry(Function handler, LispObject data, String event, Map<String,Entry> entryTable)132         public Entry (Function handler, LispObject data, String event,
133                       Map<String,Entry> entryTable)
134         {
135             this.entryTable = entryTable;
136             this.event = event;
137             this.handler = handler;
138             this.data = data;
139         }
140 
getHandler()141         public Function getHandler ()
142         {
143             return handler;
144         }
145 
addData(LispObject data)146         public void addData (LispObject data)
147         {
148             this.data = data;
149         }
150 
getData()151         public LispObject getData ()
152         {
153             return data;
154         }
155 
addCount(int count)156         public void addCount (int count)
157         {
158             this.count = count;
159         }
160 
getCount()161         public Fixnum getCount ()
162         {
163             if (count == 0)
164                 entryTable.remove(event);
165             return (Fixnum.getInstance (count--));
166         }
167     }
168 }
169