KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > relaxng > program > InterleaveItem


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  * Free SoftwareFoundation, Inc.
23  * 59 Temple Place, Suite 330
24  * Boston, MA 02111-1307 USA
25  *
26  * @author Scott Ferguson
27  */

28
29 package com.caucho.relaxng.program;
30
31 import com.caucho.relaxng.RelaxException;
32 import com.caucho.util.CharBuffer;
33 import com.caucho.util.L10N;
34 import com.caucho.xml.QName;
35
36 import java.util.ArrayList JavaDoc;
37 import java.util.HashSet JavaDoc;
38 import java.util.Iterator JavaDoc;
39
40 /**
41  * Generates programs from patterns.
42  */

43 public class InterleaveItem extends Item {
44   protected final static L10N L = new L10N(InterleaveItem.class);
45
46   private ArrayList JavaDoc<Item> _items = new ArrayList JavaDoc<Item>();
47
48   public InterleaveItem()
49   {
50   }
51
52   public static Item create(Item left, Item right)
53   {
54     InterleaveItem item = new InterleaveItem();
55
56     item.addItem(left);
57     item.addItem(right);
58     
59     return item.getMin();
60   }
61
62   public void addItem(Item item)
63   {
64     if (item == null)
65       return;
66     else if (item instanceof EmptyItem) {
67       return;
68     }
69     else if (item instanceof InterleaveItem) {
70       InterleaveItem interleave = (InterleaveItem) item;
71
72       for (int i = 0; i < interleave._items.size(); i++)
73         addItem(interleave._items.get(i));
74
75       return;
76     }
77
78     /* XXX: remove for perf?
79     for (int i = 0; i < _items.size(); i++) {
80       Item subItem = _items.get(i);
81
82       if (item instanceof InElementItem &&
83           subItem instanceof InElementItem) {
84         InElementItem elt1 = (InElementItem) item;
85         InElementItem elt2 = (InElementItem) subItem;
86
87         if (elt1.getElementItem().equals(elt2.getElementItem())) {
88           subItem = InElementItem.create(elt1.getElementItem(),
89                                          create(elt1.getContinuationItem(),
90                                                 elt2.getContinuationItem()));
91           _items.remove(i);
92           addItem(subItem);
93           return;
94         }
95       }
96       
97       if (item instanceof GroupItem &&
98           subItem instanceof GroupItem) {
99         GroupItem group1 = (GroupItem) item;
100         GroupItem group2 = (GroupItem) subItem;
101
102         if (group1.getFirst().equals(group2.getFirst())) {
103           subItem = GroupItem.create(group1.getFirst(),
104                                      create(group1.getSecond(),
105                                             group2.getSecond()));
106           _items.remove(i);
107           addItem(subItem);
108           return;
109         }
110       }
111     }
112     */

113
114     _items.add(item);
115   }
116
117   public Item getMin()
118   {
119     if (_items.size() == 0)
120       return null;
121     else if (_items.size() == 1)
122       return _items.get(0);
123     else
124       return this;
125   }
126
127   /**
128    * Returns the first set, the set of element names possible.
129    */

130   public void firstSet(HashSet JavaDoc<QName> set)
131   {
132     for (int i = 0; i < _items.size(); i++)
133       _items.get(i).firstSet(set);
134   }
135
136   /**
137    * Returns the first set, the set of element names possible.
138    */

139   public void requiredFirstSet(HashSet JavaDoc<QName> set)
140   {
141     if (allowEmpty())
142       return;
143     
144     for (int i = 0; i < _items.size(); i++)
145       _items.get(i).requiredFirstSet(set);
146   }
147   
148   /**
149    * Only allow empty if all allow empty.
150    */

151   public boolean allowEmpty()
152   {
153     for (int i = 0; i < _items.size(); i++) {
154       if (! _items.get(i).allowEmpty())
155         return false;
156     }
157       
158     return true;
159   }
160
161   /**
162    * Interleaves a continuation.
163    */

164   public Item interleaveContinuation(Item cont)
165   {
166     InterleaveItem item = new InterleaveItem();
167
168     for (int i = 0; i < _items.size(); i++)
169       item.addItem(_items.get(i).interleaveContinuation(cont));
170
171     return item.getMin();
172   }
173
174   /**
175    * Adds an inElement continuation.
176    */

177   public Item inElementContinuation(Item cont)
178   {
179     InterleaveItem item = new InterleaveItem();
180
181     for (int i = 0; i < _items.size(); i++)
182       item.addItem(_items.get(i).inElementContinuation(cont));
183
184     return item.getMin();
185   }
186
187   /**
188    * Adds a group continuation.
189    */

190   public Item groupContinuation(Item cont)
191   {
192     InterleaveItem item = new InterleaveItem();
193
194     for (int i = 0; i < _items.size(); i++)
195       item.addItem(_items.get(i).groupContinuation(cont));
196
197     return item.getMin();
198   }
199     
200   /**
201    * Return all possible child items or null
202    */

203   public Iterator JavaDoc<Item> getItemsIterator()
204   {
205     if ( _items.size() == 0 )
206       return emptyItemIterator();
207     else
208       return _items.iterator();
209   }
210
211
212   /**
213    * Returns the next item on the match.
214    */

215   public Item startElement(QName name)
216     throws RelaxException
217   {
218     Item result = null;
219     ChoiceItem choice = null;
220
221     for (int i = 0; i < _items.size(); i++) {
222       Item item = _items.get(i);
223
224       Item nextItem = item.startElement(name);
225
226       if (nextItem == null)
227         continue;
228
229       Item resultItem;
230
231       if (nextItem == item)
232         resultItem = this;
233       else {
234         InterleaveItem rest = new InterleaveItem();
235         for (int j = 0; j < _items.size(); j++) {
236           if (i != j)
237             rest.addItem(_items.get(j));
238         }
239
240         resultItem = nextItem.interleaveContinuation(rest);
241       }
242       
243       if (result == null)
244         result = resultItem;
245       else {
246         if (choice == null) {
247           choice = new ChoiceItem();
248           choice.addItem(result);
249         }
250         choice.addItem(resultItem);
251       }
252     }
253
254     if (choice != null)
255       return choice.getMin();
256     else
257       return result;
258   }
259   
260   /**
261    * Returns true if the attribute is allowed.
262    *
263    * @param name the name of the attribute
264    * @param value the value of the attribute
265    *
266    * @return true if the attribute is allowed
267    */

268   public boolean allowAttribute(QName name, String JavaDoc value)
269     throws RelaxException
270   {
271     for (int i = _items.size() - 1; i >= 0; i--)
272       if (_items.get(i).allowAttribute(name, value))
273         return true;
274
275     return false;
276   }
277
278   /**
279    * Returns the first set, the set of attribute names possible.
280    */

281   public void attributeSet(HashSet JavaDoc<QName> set)
282   {
283     for (int i = 0; i < _items.size(); i++)
284       _items.get(i).attributeSet(set);
285   }
286   
287   /**
288    * Sets an attribute.
289    *
290    * @param name the name of the attribute
291    * @param value the value of the attribute
292    *
293    * @return the program for handling the element
294    */

295   public Item setAttribute(QName name, String JavaDoc value)
296     throws RelaxException
297   {
298     if (! allowAttribute(name, value))
299       return this;
300
301     InterleaveItem interleave = new InterleaveItem();
302
303     for (int i = _items.size() - 1; i >= 0; i--) {
304       Item next = _items.get(i).setAttribute(name, value);
305
306       if (next != null)
307         interleave.addItem(next);
308     }
309
310     return interleave.getMin();
311   }
312
313   /**
314    * Returns true if the item can match empty.
315    */

316   public Item attributeEnd()
317   {
318     InterleaveItem interleave = new InterleaveItem();
319
320     for (int i = _items.size() - 1; i >= 0; i--) {
321       Item next = _items.get(i).attributeEnd();
322
323       if (next == null)
324         return null;
325
326       interleave.addItem(next);
327     }
328
329     if (interleave.equals(this))
330       return this;
331     else
332       return interleave.getMin();
333   }
334     
335   /**
336    * Returns the next item on some text
337    */

338   public Item text(String JavaDoc string)
339     throws RelaxException
340   {
341     Item result = null;
342     ChoiceItem choice = null;
343
344     for (int i = 0; i < _items.size(); i++) {
345       Item item = _items.get(i);
346
347       Item nextItem = item.text(string);
348
349       if (nextItem == null)
350         continue;
351
352       Item resultItem;
353
354       if (nextItem == item)
355         resultItem = this;
356       else {
357         InterleaveItem rest = new InterleaveItem();
358         for (int j = 0; j < _items.size(); j++) {
359           if (i != j)
360             rest.addItem(_items.get(j));
361         }
362
363         resultItem = nextItem.interleaveContinuation(rest);
364       }
365       
366       if (result == null)
367         result = resultItem;
368       else {
369         if (choice == null) {
370           choice = new ChoiceItem();
371           choice.addItem(result);
372         }
373         choice.addItem(resultItem);
374       }
375     }
376
377     if (choice != null)
378       return choice.getMin();
379     else
380       return result;
381   }
382   
383   /**
384    * Returns true if the element is allowed somewhere in the item.
385    * allowsElement is used for error messages to give more information
386    * in cases of order dependency.
387    *
388    * @param name the name of the element
389    *
390    * @return true if the element is allowed somewhere
391    */

392   public boolean allowsElement(QName name)
393   {
394     for (int i = 0; i < _items.size(); i++) {
395       Item subItem = _items.get(i);
396
397       if (subItem.allowsElement(name))
398         return true;
399     }
400
401     return false;
402   }
403
404   /**
405    * Returns the pretty printed syntax.
406    */

407   public String JavaDoc toSyntaxDescription(int depth)
408   {
409     if (_items.size() == 1)
410       return _items.get(0).toSyntaxDescription(depth);
411     
412     CharBuffer cb = CharBuffer.allocate();
413
414     cb.append("(");
415     
416     boolean isSimple = true;
417     for (int i = 0; i < _items.size(); i++) {
418       Item item = _items.get(i);
419
420       if (! item.isSimpleSyntax())
421     isSimple = false;
422       
423       if (i == 0) {
424     if (! isSimple)
425       cb.append(" ");
426       }
427       else if (isSimple) {
428     cb.append(" & ");
429       }
430       else {
431     addSyntaxNewline(cb, depth);
432     cb.append("& ");
433       }
434       
435       cb.append(item.toSyntaxDescription(depth + 2));
436     }
437
438     cb.append(')');
439
440     return cb.close();
441   }
442
443   /**
444    * Returns the hash code for the empty item.
445    */

446   public int hashCode()
447   {
448     int hash = 37;
449
450     for (int i = 0; i < _items.size(); i++)
451       hash += _items.get(i).hashCode();
452
453     return hash;
454   }
455
456   /**
457    * Returns true if the object is an empty item.
458    */

459   public boolean equals(Object JavaDoc o)
460   {
461     if (this == o)
462       return true;
463     
464     if (! (o instanceof InterleaveItem))
465       return false;
466
467     InterleaveItem interleave = (InterleaveItem) o;
468
469     return isSubset(interleave) && interleave.isSubset(this);
470   }
471
472   private boolean isSubset(InterleaveItem item)
473   {
474     if (_items.size() != item._items.size())
475       return false;
476
477     for (int i = 0; i < _items.size(); i++) {
478       Item subItem = _items.get(i);
479
480       if (! item._items.contains(subItem))
481         return false;
482     }
483
484     return true;
485   }
486 }
487
488
Popular Tags