1:
37:
38: package ;
39:
40: import ;
41:
42: import ;
43: import ;
44: import ;
45: import ;
46: import ;
47: import ;
48: import ;
49: import ;
50: import ;
51: import ;
52:
53:
58: public class Bindings
59: implements XPathVariableResolver, Cloneable
60: {
61:
62: static final int VARIABLE = 0;
63: static final int PARAM = 1;
64: static final int WITH_PARAM = 2;
65:
66: final Stylesheet stylesheet;
67:
68:
71: final LinkedList<Map<QName,Object>> variables;
72:
73:
76: final LinkedList<Map<QName,Object>> parameters;
77:
78:
81: final LinkedList<Map<QName,Object>> withParameters;
82:
83:
86: boolean global;
87:
88: Bindings(Stylesheet stylesheet)
89: {
90: this.stylesheet = stylesheet;
91: variables = new LinkedList<Map<QName,Object>>();
92: parameters = new LinkedList<Map<QName,Object>>();
93: withParameters = new LinkedList<Map<QName,Object>>();
94: for (int i = 0; i < 3; i++)
95: {
96: push(i);
97: }
98: }
99:
100: public Object clone()
101: {
102: try
103: {
104: return (Bindings) super.clone();
105: }
106: catch (CloneNotSupportedException e)
107: {
108: throw new Error(e.getMessage());
109: }
110: }
111:
112: void push(int type)
113: {
114: switch (type)
115: {
116: case VARIABLE:
117: variables.addFirst(new HashMap<QName,Object>());
118: break;
119: case PARAM:
120: parameters.addFirst(new HashMap<QName,Object>());
121: break;
122: case WITH_PARAM:
123: withParameters.addFirst(new HashMap<QName,Object>());
124: break;
125: }
126: }
127:
128: void pop(int type)
129: {
130: switch (type)
131: {
132: case VARIABLE:
133: variables.removeFirst();
134: break;
135: case PARAM:
136: parameters.removeFirst();
137: break;
138: case WITH_PARAM:
139: withParameters.removeFirst();
140: break;
141: }
142: }
143:
144: public boolean containsKey(QName name, int type)
145: {
146: if (global)
147: {
148: Map<QName,Object> ctx1 = variables.getLast();
149: Map<QName,Object> ctx2 = parameters.getLast();
150: return (ctx1.containsKey(name) || ctx2.containsKey(name));
151: }
152: Iterator<Map<QName,Object>> i = null;
153: switch (type)
154: {
155: case VARIABLE:
156: i = variables.iterator();
157: break;
158: case PARAM:
159: i = parameters.iterator();
160: break;
161: case WITH_PARAM:
162: Map<QName,Object> ctx = withParameters.getFirst();
163: return ctx.containsKey(name);
164: }
165: if (i != null)
166: {
167: while (i.hasNext())
168: {
169: Map<QName,Object> ctx = i.next();
170: if (ctx.containsKey(name))
171: {
172: return true;
173: }
174: }
175: }
176: return false;
177: }
178:
179: public Object get(QName name, Node context, int pos, int len)
180: {
181: if (global)
182: {
183: Map<QName,Object> ctx = variables.getLast();
184: Object ret = ctx.get(name);
185: if (ret == null)
186: {
187: ctx = parameters.getLast();
188: ret = ctx.get(name);
189: }
190: return ret;
191: }
192:
193:
194: Object ret = null;
195:
196:
197: {
198: Map<QName,Object> cwp = withParameters.getFirst();
199: ret = cwp.get(name);
200:
201: }
202: if (ret == null)
203: {
204: for (Iterator<Map<QName,Object>> i = variables.iterator();
205: i.hasNext() && ret == null; )
206: {
207: Map<QName,Object> vctx = i.next();
208: ret = vctx.get(name);
209: }
210:
211: }
212: if (ret == null)
213: {
214: for (Iterator<Map<QName,Object>> i = parameters.iterator();
215: i.hasNext() && ret == null; )
216: {
217: Map<QName,Object> pctx = i.next();
218: ret = pctx.get(name);
219: }
220:
221: }
222:
227: if (ret instanceof Node)
228: {
229: ret = Collections.singleton(ret);
230: }
231: if (ret == null)
232: {
233: ret = "";
234: }
235:
236: return ret;
237: }
238:
239: void set(QName name, Object value, int type)
240: {
241: switch (type)
242: {
243: case VARIABLE:
244: Map<QName,Object> vctx = variables.getFirst();
245: vctx.put(name, value);
246: break;
247: case PARAM:
248: Map<QName,Object> pctx = parameters.getFirst();
249: pctx.put(name, value);
250: break;
251: case WITH_PARAM:
252: Map<QName,Object> wctx = withParameters.getFirst();
253: wctx.put(name, value);
254: break;
255: }
256:
257: }
258:
259: public Object resolveVariable(QName qName)
260: {
261: return get(qName, null, 1, 1);
262: }
263:
264: public String toString()
265: {
266: CPStringBuilder buf = new CPStringBuilder();
267: boolean next = false;
268: Collection<QName> seen = new HashSet<QName>();
269: Map<QName,Object> wctx = withParameters.getFirst();
270: buf.append('(');
271: for (Map.Entry<QName,Object> entry : wctx.entrySet())
272: {
273: if (next)
274: {
275: buf.append(',');
276: }
277: else
278: {
279: next = true;
280: }
281: QName key = entry.getKey();
282: if (!seen.contains(key))
283: {
284: buf.append(key);
285: buf.append('=');
286: buf.append(entry.getValue());
287: seen.add(key);
288: }
289: }
290: buf.append(')');
291: next = false;
292: seen.clear();
293: buf.append('{');
294: for (Map<QName,Object> ctx : variables)
295: {
296: for (Map.Entry<QName,Object> entry : ctx.entrySet())
297: {
298: if (next)
299: {
300: buf.append(',');
301: }
302: else
303: {
304: next = true;
305: }
306: QName key = entry.getKey();
307: if (!seen.contains(key))
308: {
309: buf.append(key);
310: buf.append('=');
311: buf.append(entry.getValue());
312: seen.add(key);
313: }
314: }
315: }
316: buf.append('}');
317: next = false;
318: seen.clear();
319: buf.append('[');
320: for (Map<QName,Object> ctx : parameters)
321: {
322: for (Map.Entry<QName,Object> entry : ctx.entrySet())
323: {
324: if (next)
325: {
326: buf.append(',');
327: }
328: else
329: {
330: next = true;
331: }
332: QName key = entry.getKey();
333: if (!seen.contains(key))
334: {
335: buf.append(key);
336: buf.append('=');
337: buf.append(entry.getValue());
338: seen.add(key);
339: }
340: }
341: }
342: buf.append(']');
343: return buf.toString();
344: }
345:
346: }