001: /******************************************************************************
002: * JBoss, a division of Red Hat *
003: * Copyright 2006, Red Hat Middleware, LLC, and individual *
004: * contributors as indicated by the @authors tag. See the *
005: * copyright.txt in the distribution for a full listing of *
006: * individual contributors. *
007: * *
008: * This is free software; you can redistribute it and/or modify it *
009: * under the terms of the GNU Lesser General Public License as *
010: * published by the Free Software Foundation; either version 2.1 of *
011: * the License, or (at your option) any later version. *
012: * *
013: * This software is distributed in the hope that it will be useful, *
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of *
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
016: * Lesser General Public License for more details. *
017: * *
018: * You should have received a copy of the GNU Lesser General Public *
019: * License along with this software; if not, write to the Free *
020: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
021: * 02110-1301 USA, or see the FSF site: http://www.fsf.org. *
022: ******************************************************************************/package org.jboss.portal.format.parser.html;
023:
024: import org.jboss.portal.format.parser.AbstractParser;
025: import org.jboss.portal.format.parser.ParseEvent;
026: import org.jboss.portal.format.parser.TextEvent;
027: import org.jboss.portal.format.parser.Token;
028: import org.jboss.portal.format.parser.bbcode.BBCodeParser;
029: import org.jboss.portal.format.parser.chars.MutableChars;
030: import org.jboss.portal.format.util.Stack;
031:
032: import java.util.Iterator;
033:
034: /**
035: * @author <a href="mailto:julien@jboss.org">Julien Viet</a>
036: * @version $Revision: 8784 $
037: */
038: public class TagParser extends AbstractParser {
039:
040: public static final int EVENT_NORMAL = 0;
041: public static final int EVENT_TAG = 1;
042:
043: private MutableChars buffer = new MutableChars();
044: private Analyzer analyzer = new Analyzer(BBCodeParser.NULL_READER);
045:
046: private OpenEvent openEvent = new OpenEvent();
047: private TextEvent textEvent = new TextEvent();
048:
049: private Stack stack = new Stack(10) {
050: protected Stack.Key createKey() {
051: return new CloseEvent();
052: }
053:
054: protected boolean equals(Stack.Key o1, Stack.Key o2) {
055: HTMLKey key1 = (HTMLKey) o1;
056: HTMLKey key2 = (HTMLKey) o2;
057: if (key1.getType() != key2.getType()) {
058: return false;
059: }
060: if (key1.getType() == 1) {
061: return key1.getTag().equals(key2.getTag());
062: }
063: return false;
064: }
065: };
066:
067: public TagParser() {
068: }
069:
070: private HTMLKey temporaryKey = new HTMLKey();
071:
072: public void parse(char[] chars, int off, int len) {
073:
074: // Build the stream
075: stack.reset();
076: analyzer.reset(chars, off, len);
077: buffer.reset();
078:
079: //
080: CloseEvent closeEvent = (CloseEvent) stack.push();
081: closeEvent.type = openEvent.type = EVENT_NORMAL;
082: closeEvent.tag = openEvent.tag = null;
083: openEvent.attributes = null;
084: handler.handle(openEvent);
085:
086: while (true) {
087: // Get the next token
088: Token t = analyzer.next();
089:
090: if (t == null) {
091: // No more token to read
092: break;
093: }
094:
095: switch (t.type) {
096: case Analyzer.STAG: {
097: closeEvent = (CloseEvent) stack.push();
098: String tag = t.value;
099: int start = 1;
100: int end = tag.indexOf(' ', 1);
101: if (end == -1) {
102: openEvent.type = closeEvent.type = EVENT_TAG;
103: openEvent.tag = closeEvent.tag = tag.substring(
104: start, tag.length() - 1);
105: openEvent.attributes = "";
106: } else {
107: openEvent.type = closeEvent.type = EVENT_TAG;
108: openEvent.tag = closeEvent.tag = tag.substring(
109: start, end);
110: openEvent.attributes = tag.substring(end, tag
111: .length() - 1);
112: }
113: text();
114: handler.handle(openEvent);
115: break;
116: }
117: case Analyzer.ETAG: {
118: temporaryKey.type = 1;
119: temporaryKey.tag = t.value.substring(2, t.value
120: .length() - 1);
121: Iterator i = stack.pop(temporaryKey);
122: if (i.hasNext()) {
123: text();
124: do {
125: handler.handle((CloseEvent) i.next());
126: } while (i.hasNext());
127: }
128: break;
129: }
130: case Analyzer.EMPTY: {
131: // String tag = t.value;
132: // int start = 1;
133: // int end = tag.indexOf(' ', 1);
134: // if (end == -1)
135: // {
136: // end = tag.length() - 2;
137: // }
138: // String name = tag.substring(start, end);
139: // helper.empty(1, name);
140: break;
141: }
142: case Analyzer.CDATA:
143: buffer.append(t.value.charAt(0));
144: break;
145: default:
146: throw new IllegalStateException("Unexpected token : "
147: + t.type);
148: }
149: }
150:
151: //
152: text();
153: temporaryKey.type = EVENT_NORMAL;
154: Iterator i = stack.pop(temporaryKey);
155: while (i.hasNext()) {
156: handler.handle((CloseEvent) i.next());
157: }
158: }
159:
160: private void text() {
161: if (buffer.length() > 0) {
162: textEvent.setText(buffer.chars(), 0, buffer.length());
163: buffer.reset();
164: handler.handle(textEvent);
165: }
166: }
167:
168: private static class HTMLKey implements Stack.Key {
169: int type;
170: String tag;
171:
172: private HTMLKey() {
173: type = -1;
174: tag = null;
175: }
176:
177: public int getType() {
178: return type;
179: }
180:
181: public String getTag() {
182: return tag;
183: }
184: }
185:
186: public static class OpenEvent extends HTMLKey implements ParseEvent {
187: private String attributes;
188:
189: public String getAttribute() {
190: return attributes;
191: }
192: }
193:
194: public static class CloseEvent extends HTMLKey implements
195: ParseEvent {
196: }
197: }
|