OSDN Git Service

2006-08-14 Mark Wielaard <mark@klomp.org>
[pf3gnuchains/gcc-fork.git] / libjava / classpath / gnu / xml / transform / Bindings.java
1 /* Bindings.java -- 
2    Copyright (C) 2004 Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37
38 package gnu.xml.transform;
39
40 import java.util.Collection;
41 import java.util.Collections;
42 import java.util.HashMap;
43 import java.util.HashSet;
44 import java.util.Iterator;
45 import java.util.LinkedList;
46 import java.util.Map;
47 import javax.xml.namespace.QName;
48 import javax.xml.xpath.XPathVariableResolver;
49 import org.w3c.dom.Node;
50
51 /**
52  * The set of variable bindings in effect for a stylesheet.
53  *
54  * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
55  */
56 public class Bindings
57   implements XPathVariableResolver, Cloneable
58 {
59
60   static final int VARIABLE = 0;
61   static final int PARAM = 1;
62   static final int WITH_PARAM = 2;
63
64   final Stylesheet stylesheet;
65
66   /**
67    * Global variables.
68    */
69   final LinkedList variables;
70
71   /**
72    * Parameter value stack.
73    */
74   final LinkedList parameters;
75
76   /**
77    * Argument (with-param) value stack.
78    */
79   final LinkedList withParameters;
80
81   /**
82    * Only search globals.
83    */
84   boolean global;
85
86   Bindings(Stylesheet stylesheet)
87   {
88     this.stylesheet = stylesheet;
89     variables = new LinkedList();
90     parameters = new LinkedList();
91     withParameters = new LinkedList();
92     for (int i = 0; i < 3; i++)
93       {
94         push(i);
95       }
96   }
97
98   public Object clone()
99   {
100     try
101       {
102         return (Bindings) super.clone();
103       }
104     catch (CloneNotSupportedException e)
105       {
106         throw new Error(e.getMessage());
107       }
108   }
109
110   void push(int type)
111   {
112     switch (type)
113       {
114       case VARIABLE:
115         variables.addFirst(new HashMap());
116         break;
117       case PARAM:
118         parameters.addFirst(new HashMap());
119         break;
120       case WITH_PARAM:
121         withParameters.addFirst(new HashMap());
122         break;
123       }
124   }
125
126   void pop(int type)
127   {
128     switch (type)
129       {
130       case VARIABLE:
131         variables.removeFirst();
132         break;
133       case PARAM:
134         parameters.removeFirst();
135         break;
136       case WITH_PARAM:
137         withParameters.removeFirst();
138         break;
139       }
140   }
141
142   public boolean containsKey(QName name, int type)
143   {
144     if (global)
145       {
146         Map ctx1 = (Map) variables.getLast();
147         Map ctx2 = (Map) parameters.getLast();
148         return (ctx1.containsKey(name) || ctx2.containsKey(name));
149       }
150     Iterator i = null;
151     switch (type)
152       {
153       case VARIABLE:
154         i = variables.iterator();
155         break;
156       case PARAM:
157         i = parameters.iterator();
158         break;
159       case WITH_PARAM:
160         Map ctx = (Map) withParameters.getFirst();
161         return ctx.containsKey(name);
162       }
163     if (i != null)
164       {
165         while (i.hasNext())
166           {
167             Map ctx = (Map) i.next();
168             if (ctx.containsKey(name))
169               {
170                 return true;
171               }
172           }
173       }
174     return false;
175   }
176
177   public Object get(QName name, Node context, int pos, int len)
178   {
179     if (global)
180       {
181         Map ctx = (Map) variables.getLast();
182         Object ret = ctx.get(name);
183         if (ret == null)
184           {
185             ctx = (Map) parameters.getLast();
186             ret = ctx.get(name);
187           }
188         return ret;
189       }
190     //System.err.println("bindings.get: "+name);
191     //System.err.println("\t"+toString());
192     Object ret = null;
193     //if (parameters.size() > 1 && containsKey(name, PARAM))
194       // check that template defines parameter
195       {
196         Map cwp = (Map) withParameters.getFirst();
197         ret = cwp.get(name);
198         //System.err.println("\twith-param: ret="+ret);
199       }
200     if (ret == null)
201       {
202         for (Iterator i = variables.iterator(); i.hasNext() && ret == null; )
203           {
204             Map vctx = (Map) i.next();
205             ret = vctx.get(name);
206           }
207         //System.err.println("\tvariable: ret="+ret);
208       }
209     if (ret == null)
210       {
211         for (Iterator i = parameters.iterator(); i.hasNext() && ret == null; )
212           {
213             Map pctx = (Map) i.next();
214             ret = pctx.get(name);
215           }
216         //System.err.println("\tparam: ret="+ret);
217       }
218     /*if (ret instanceof Expr && context != null)
219       {
220         Expr expr = (Expr) ret;
221         ret = expr.evaluate(context, 1, 1);
222       }*/
223     if (ret instanceof Node)
224       {
225         ret = Collections.singleton(ret);
226       }
227     if (ret == null)
228       {
229         ret = "";
230       }
231     //System.err.println("\tret="+ret);
232     return ret;
233   }
234
235   void set(QName name, Object value, int type)
236   {
237     switch (type)
238       {
239       case VARIABLE:
240         Map vctx = (Map) variables.getFirst();
241         vctx.put(name, value);
242         break;
243       case PARAM:
244         Map pctx = (Map) parameters.getFirst();
245         pctx.put(name, value);
246         break;
247       case WITH_PARAM:
248         Map wctx = (Map) withParameters.getFirst();
249         wctx.put(name, value);
250         break;
251       }
252     //System.err.println("Set "+name+"="+value);
253   }
254
255   public Object resolveVariable(QName qName)
256   {
257     return get(qName, null, 1, 1);
258   }
259   
260   public String toString()
261   {
262     StringBuffer buf = new StringBuffer();
263     boolean next = false;
264     Collection seen = new HashSet();
265     Map wctx = (Map) withParameters.getFirst();
266     buf.append('(');
267     for (Iterator i = wctx.entrySet().iterator(); i.hasNext(); )
268       {
269         if (next)
270           {
271             buf.append(',');
272           }
273         else
274           {
275             next = true;
276           }
277         Map.Entry entry = (Map.Entry) i.next();
278         Object key = entry.getKey();
279         if (!seen.contains(key))
280           {
281             buf.append(key);
282             buf.append('=');
283             buf.append(entry.getValue());
284             seen.add(key);
285           }
286       }
287     buf.append(')');
288     next = false;
289     seen.clear();
290     buf.append('{');
291     for (Iterator i = variables.iterator(); i.hasNext(); )
292       {
293         Map ctx = (Map) i.next();
294         for (Iterator j = ctx.entrySet().iterator(); j.hasNext(); )
295           {
296             if (next)
297               {
298                 buf.append(',');
299               }
300             else
301               {
302                 next = true;
303               }
304             Map.Entry entry = (Map.Entry) j.next();
305             Object key = entry.getKey();
306             if (!seen.contains(key))
307               {
308                 buf.append(key);
309                 buf.append('=');
310                 buf.append(entry.getValue());
311                 seen.add(key);
312               }
313           } 
314       }
315     buf.append('}');
316     next = false;
317     seen.clear();
318     buf.append('[');
319     for (Iterator i = parameters.iterator(); i.hasNext(); )
320       {
321         Map ctx = (Map) i.next();
322         for (Iterator j = ctx.entrySet().iterator(); j.hasNext(); )
323           {
324             if (next)
325               {
326                 buf.append(',');
327               }
328             else
329               {
330                 next = true;
331               }
332             Map.Entry entry = (Map.Entry) j.next();
333             Object key = entry.getKey();
334             if (!seen.contains(key))
335               {
336                 buf.append(key);
337                 buf.append('=');
338                 buf.append(entry.getValue());
339                 seen.add(key);
340               }
341           } 
342       }
343     buf.append(']');
344     return buf.toString();
345   }
346
347 }