001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: * Free SoftwareFoundation, Inc.
023: * 59 Temple Place, Suite 330
024: * Boston, MA 02111-1307 USA
025: *
026: * @author Scott Ferguson
027: */
028:
029: package com.caucho.relaxng.pattern;
030:
031: import com.caucho.relaxng.RelaxException;
032: import com.caucho.relaxng.program.ChoiceItem;
033: import com.caucho.relaxng.program.EmptyItem;
034: import com.caucho.relaxng.program.Item;
035: import com.caucho.util.CharBuffer;
036:
037: import java.util.ArrayList;
038:
039: /**
040: * Relax element pattern
041: */
042: public class ChoicePattern extends Pattern {
043: private ArrayList<Pattern> _patterns = new ArrayList<Pattern>();
044: private boolean _hasEmpty;
045:
046: private Item _item;
047:
048: /**
049: * Creates a new choice pattern.
050: */
051: public ChoicePattern() {
052: }
053:
054: /**
055: * Returns the number of children.
056: */
057: public int getSize() {
058: return _patterns.size();
059: }
060:
061: /**
062: * Returns the n-th child.
063: */
064: public Pattern getChild(int i) {
065: return _patterns.get(i);
066: }
067:
068: public boolean hasEmpty() {
069: return _hasEmpty;
070: }
071:
072: /**
073: * Returns true if it contains a data element.
074: */
075: public boolean hasData() {
076: for (int i = 0; i < _patterns.size(); i++) {
077: if (_patterns.get(i).hasData())
078: return true;
079: }
080:
081: return false;
082: }
083:
084: /**
085: * Returns true if it contains a data element.
086: */
087: public boolean hasElement() {
088: for (int i = 0; i < _patterns.size(); i++) {
089: if (_patterns.get(i).hasElement())
090: return true;
091: }
092:
093: return false;
094: }
095:
096: /**
097: * Adds an element.
098: */
099: public void addChild(Pattern child) throws RelaxException {
100: child.setElementName(getElementName());
101:
102: if (child instanceof ChoicePattern) {
103: ChoicePattern list = (ChoicePattern) child;
104:
105: if (list._hasEmpty)
106: _hasEmpty = true;
107:
108: for (int i = 0; i < list.getSize(); i++)
109: addChild(list.getChild(i));
110:
111: return;
112: }
113:
114: if (child instanceof EmptyPattern) {
115: _hasEmpty = true;
116: return;
117: }
118:
119: if (!_patterns.contains(child))
120: _patterns.add(child);
121: }
122:
123: /**
124: * Returns the Relax schema name.
125: */
126: public String getTagName() {
127: return "choice";
128: }
129:
130: /**
131: * Creates the production item.
132: */
133: public Item createItem(GrammarPattern grammar)
134: throws RelaxException {
135: if (_item == null) {
136: ChoiceItem item = new ChoiceItem();
137:
138: for (int i = 0; i < _patterns.size(); i++) {
139: item.addItem(_patterns.get(i).createItem(grammar));
140: }
141:
142: if (_hasEmpty)
143: item.addItem(EmptyItem.create());
144:
145: _item = item.getMin();
146: }
147:
148: return _item;
149: }
150:
151: /**
152: * Returns a string for the production.
153: */
154: public String toProduction() {
155: if (_hasEmpty && _patterns.size() == 1)
156: return "(" + _patterns.get(0).toProduction() + ")?";
157:
158: CharBuffer cb = new CharBuffer();
159:
160: if (_hasEmpty)
161: cb.append("(");
162:
163: for (int i = 0; i < _patterns.size(); i++) {
164: if (i != 0)
165: cb.append(" | ");
166: cb.append(_patterns.get(i).toProduction());
167: }
168:
169: if (_hasEmpty)
170: cb.append(")?");
171:
172: return cb.toString();
173: }
174:
175: public boolean equals(Object o) {
176: if (this == o)
177: return true;
178:
179: if (!(o instanceof ChoicePattern))
180: return false;
181:
182: ChoicePattern choice = (ChoicePattern) o;
183:
184: if (_hasEmpty != choice._hasEmpty)
185: return false;
186:
187: if (_patterns.size() != choice._patterns.size())
188: return false;
189:
190: return isSubset(choice) && choice.isSubset(this );
191: }
192:
193: private boolean isSubset(ChoicePattern item) {
194: if (_patterns.size() != item._patterns.size())
195: return false;
196:
197: for (int i = 0; i < _patterns.size(); i++) {
198: Pattern subPattern = _patterns.get(i);
199:
200: if (!item._patterns.contains(subPattern))
201: return false;
202: }
203:
204: return true;
205: }
206:
207: /**
208: * Debugging.
209: */
210: public String toString() {
211: return "ChoicePattern" + _patterns;
212: }
213: }
|