KickJava   Java API By Example, From Geeks To Geeks.

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


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  *
23  * Free Software Foundation, Inc.
24  * 59 Temple Place, Suite 330
25  * Boston, MA 02111-1307 USA
26  *
27  * @author Scott Ferguson
28  */

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

44 public class ChoiceItem extends Item {
45   protected final static L10N L = new L10N(ChoiceItem.class);
46
47   private ArrayList JavaDoc<Item> _items = new ArrayList JavaDoc<Item>();
48
49   private boolean _allowEmpty = false;
50
51   public ChoiceItem()
52   {
53   }
54
55   public static Item create(Item left, Item right)
56   {
57     ChoiceItem choice = new ChoiceItem();
58     choice.addItem(left);
59     choice.addItem(right);
60
61     return choice.getMin();
62   }
63
64   public void addItem(Item item)
65   {
66     if (item == null)
67       return;
68     else if (item instanceof EmptyItem) {
69       _allowEmpty = true;
70       return;
71     }
72     else if (item instanceof ChoiceItem) {
73       ChoiceItem choice = (ChoiceItem) item;
74
75       if (choice._allowEmpty)
76         _allowEmpty = true;
77       
78       for (int i = 0; i < choice._items.size(); i++)
79         addItem(choice._items.get(i));
80
81       return;
82     }
83
84     for (int i = 0; i < _items.size(); i++) {
85       Item subItem = _items.get(i);
86
87       if (item.equals(subItem))
88         return;
89
90       if (item instanceof InElementItem &&
91           subItem instanceof InElementItem) {
92         InElementItem elt1 = (InElementItem) item;
93         InElementItem elt2 = (InElementItem) subItem;
94
95         if (elt1.getElementItem().equals(elt2.getElementItem())) {
96           subItem = InElementItem.create(elt1.getElementItem(),
97                                          create(elt1.getContinuationItem(),
98                                                 elt2.getContinuationItem()));
99           _items.remove(i);
100           addItem(subItem);
101           return;
102         }
103       }
104       
105       if (item instanceof GroupItem &&
106           subItem instanceof GroupItem) {
107         GroupItem group1 = (GroupItem) item;
108         GroupItem group2 = (GroupItem) subItem;
109
110         if (group1.getFirst().equals(group2.getFirst())) {
111           subItem = GroupItem.create(group1.getFirst(),
112                                      create(group1.getSecond(),
113                                             group2.getSecond()));
114           _items.remove(i);
115           addItem(subItem);
116           return;
117         }
118       }
119     }
120
121     _items.add(item);
122   }
123
124   public Item getMin()
125   {
126     if (! _allowEmpty && _items.size() == 0)
127       return null;
128     else if (_allowEmpty && _items.size() == 0)
129       return EmptyItem.create();
130     else if (_items.size() == 1 &&
131              (! _allowEmpty || _items.get(0).allowEmpty()))
132       return _items.get(0);
133     else
134       return this;
135   }
136
137   /**
138    * Returns the first set, the set of element names possible.
139    */

140   public void firstSet(HashSet JavaDoc<QName> set)
141   {
142     for (int i = 0; i < _items.size(); i++)
143       _items.get(i).firstSet(set);
144   }
145
146   /**
147    * Returns the first set, the set of element names possible.
148    */

149   public void requiredFirstSet(HashSet JavaDoc<QName> set)
150   {
151     if (allowEmpty())
152       return;
153     
154     for (int i = 0; i < _items.size(); i++)
155       _items.get(i).requiredFirstSet(set);
156   }
157   
158   /**
159    * Allows empty if any item allows empty.
160    */

161   public boolean allowEmpty()
162   {
163     if (_allowEmpty)
164       return true;
165     
166     for (int i = 0; i < _items.size(); i++)
167       if (_items.get(i).allowEmpty())
168         return true;
169
170     return false;
171   }
172
173   /**
174    * Interleaves a continuation.
175    */

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

189   public Item inElementContinuation(Item cont)
190   {
191     ChoiceItem item = new ChoiceItem();
192
193     for (int i = 0; i < _items.size(); i++)
194       item.addItem(_items.get(i).inElementContinuation(cont));
195
196     return item.getMin();
197   }
198
199   /**
200    * Adds a group continuation.
201    */

202   public Item groupContinuation(Item cont)
203   {
204     ChoiceItem item = new ChoiceItem();
205
206     for (int i = 0; i < _items.size(); i++)
207       item.addItem(_items.get(i).groupContinuation(cont));
208
209     return item.getMin();
210   }
211   
212   /**
213    * Return all possible child items or null
214    */

215   public Iterator JavaDoc<Item> getItemsIterator()
216   {
217     if ( _items.size() == 0 )
218       return emptyItemIterator();
219     else
220       return _items.iterator();
221   }
222
223   /**
224    * Returns the next item on the match.
225    */

226   public Item startElement(QName name)
227     throws RelaxException
228   {
229     Item result = null;
230     ChoiceItem choice = null;
231
232     for (int i = 0; i < _items.size(); i++) {
233       Item next = _items.get(i).startElement(name);
234
235       if (next == null) {
236       }
237       else if (result == null)
238         result = next;
239       else {
240         if (choice == null) {
241           choice = new ChoiceItem();
242           choice.addItem(result);
243         }
244
245         choice.addItem(next);
246       }
247     }
248
249     if (choice != null)
250       return choice.getMin();
251     else
252       return result;
253   }
254
255   /**
256    * Returns the first set, the set of attribute names possible.
257    */

258   public void attributeSet(HashSet JavaDoc<QName> set)
259   {
260     for (int i = 0; i < _items.size(); i++)
261       _items.get(i).attributeSet(set);
262   }
263   
264   /**
265    * Returns true if the attribute is allowed.
266    *
267    * @param name the name of the attribute
268    * @param value the value of the attribute
269    *
270    * @return true if the attribute is allowed
271    */

272   public boolean allowAttribute(QName name, String JavaDoc value)
273     throws RelaxException
274   {
275     for (int i = _items.size() - 1; i >= 0; i--)
276       if (_items.get(i).allowAttribute(name, value))
277         return true;
278
279     return false;
280   }
281   
282   /**
283    * Sets an attribute.
284    *
285    * @param name the name of the attribute
286    * @param value the value of the attribute
287    *
288    * @return the program for handling the element
289    */

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

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

341   public Item text(String JavaDoc data)
342     throws RelaxException
343   {
344     Item result = null;
345     ChoiceItem choice = null;
346
347     for (int i = 0; i < _items.size(); i++) {
348       Item next = _items.get(i).text(data);
349
350       if (next == null) {
351       }
352       else if (result == null)
353         result = next;
354       else {
355         if (choice == null) {
356           choice = new ChoiceItem();
357           choice.addItem(result);
358         }
359
360         choice.addItem(next);
361       }
362     }
363
364     if (choice != null)
365       return choice.getMin();
366     else
367       return result;
368   }
369   
370   /**
371    * Returns the next item when the element closes
372    */

373   public Item endElement()
374     throws RelaxException
375   {
376     ChoiceItem choice = new ChoiceItem();
377
378     if (_allowEmpty)
379       choice._allowEmpty = true;
380
381     for (int i = _items.size() - 1; i >= 0; i--) {
382       Item next = _items.get(i).endElement();
383
384       if (next == null)
385         continue;
386
387       choice.addItem(next);
388     }
389
390     if (choice.equals(this))
391       return this;
392     else
393       return choice.getMin();
394   }
395
396   /**
397    * Returns the hash code for the empty item.
398    */

399   public int hashCode()
400   {
401     int hash = 37;
402
403     for (int i = 0; i < _items.size(); i++)
404       hash += _items.get(i).hashCode();
405
406     return hash;
407   }
408
409   /**
410    * Returns true if the object is an empty item.
411    */

412   public boolean equals(Object JavaDoc o)
413   {
414     if (this == o)
415       return true;
416     
417     if (! (o instanceof ChoiceItem))
418       return false;
419
420     ChoiceItem choice = (ChoiceItem) o;
421
422     return isSubset(choice) && choice.isSubset(this);
423   }
424
425   private boolean isSubset(ChoiceItem item)
426   {
427     if (_items.size() != item._items.size())
428       return false;
429
430     for (int i = 0; i < _items.size(); i++) {
431       Item subItem = _items.get(i);
432
433       if (! item._items.contains(subItem))
434         return false;
435     }
436
437     return true;
438   }
439   
440   /**
441    * Returns true if the element is allowed somewhere in the item.
442    * allowsElement is used for error messages to give more information
443    * in cases of order dependency.
444    *
445    * @param name the name of the element
446    *
447    * @return true if the element is allowed somewhere
448    */

449   public boolean allowsElement(QName name)
450   {
451     for (int i = 0; i < _items.size(); i++) {
452       Item subItem = _items.get(i);
453
454       if (subItem.allowsElement(name))
455         return true;
456     }
457
458     return false;
459   }
460
461   /**
462    * Returns the pretty printed syntax.
463    */

464   public String JavaDoc toSyntaxDescription(int depth)
465   {
466     CharBuffer cb = CharBuffer.allocate();
467
468     if (_items.size() > 1)
469       cb.append("(");
470     
471     boolean isSimple = true;
472     for (int i = 0; i < _items.size(); i++) {
473       Item item = _items.get(i);
474       if (! item.isSimpleSyntax())
475     isSimple = false;
476
477       if (i == 0) {
478     if (! isSimple)
479       cb.append(" ");
480       }
481       else if (isSimple) {
482     cb.append(" | ");
483       }
484       else {
485     addSyntaxNewline(cb, depth);
486     cb.append("| ");
487       }
488     
489       cb.append(item.toSyntaxDescription(depth + 2));
490     }
491
492     if (_items.size() > 1)
493       cb.append(')');
494
495     if (_allowEmpty)
496       cb.append('?');
497     
498     return cb.close();
499   }
500
501   /**
502    * Returns true for an element with simple syntax.
503    */

504   protected boolean isSimpleSyntax()
505   {
506     return (_items.size() == 1) && _items.get(0).isSimpleSyntax();
507   }
508
509   public String JavaDoc toString()
510   {
511     StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
512
513     sb.append("ChoiceItem[");
514     for (int i = 0; i < _items.size(); i++) {
515       if (i != 0)
516         sb.append(", ");
517       sb.append(_items.get(i));
518     }
519
520     sb.append("]");
521
522     return sb.toString();
523   }
524 }
525
526
Popular Tags