001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.editor.ext.html.parser;
043:
044: import java.util.*;
045: import javax.swing.text.*;
046: import org.openide.ErrorManager;
047:
048: /**
049: * Represents a semantic element of html code.
050: *
051: * @author Petr Nejedly
052: * @author Marek.Fukala@Sun.com
053: */
054: public class SyntaxElement {
055:
056: public static final int TYPE_COMMENT = 0;
057: public static final int TYPE_DECLARATION = 1;
058: public static final int TYPE_ERROR = 2;
059: public static final int TYPE_TEXT = 3;
060: public static final int TYPE_TAG = 4;
061: public static final int TYPE_ENDTAG = 5;
062: public static final int TYPE_ENTITY_REFERENCE = 6;
063:
064: public static final String[] TYPE_NAMES = new String[] { "comment",
065: "declaration", "error", "text", "tag", "endtag",
066: "entity reference" };
067:
068: private ParserSource source;
069:
070: private int offset;
071: private int length;
072: private int type;
073:
074: SyntaxElement(ParserSource doc, int offset, int length, int type) {
075: this .offset = offset;
076: this .length = length;
077: this .type = type;
078: this .source = doc;
079: }
080:
081: public int offset() {
082: return offset;
083: }
084:
085: public int length() {
086: return length;
087: }
088:
089: public int type() {
090: return type;
091: }
092:
093: public String text() {
094: try {
095: return source.getText(offset(), length()).toString();
096: } catch (BadLocationException ble) {
097: ErrorManager.getDefault().notify(ErrorManager.WARNING, ble);
098: }
099: return null;
100: }
101:
102: @Override
103: public String toString() {
104: //String textContent = type() == TYPE_TEXT ? text() : "";
105: String textContent = text();
106: return "Element(" + TYPE_NAMES[type] + ")[" + offset + ","
107: + (offset + length - 1) + "] \"" + textContent + "\""; // NOI18N
108: }
109:
110: /**
111: * Declaration models SGML declaration with emphasis on <!DOCTYPE
112: * declaration, as other declarations are not allowed inside HTML.
113: * It represents unknown/broken declaration or either public or system
114: * DOCTYPE declaration.
115: */
116: public static class Declaration extends SyntaxElement {
117: private String root;
118: private String publicID;
119: private String file;
120:
121: /**
122: * Creates a model of SGML declaration with some properties of
123: * DOCTYPE declaration.
124: * @param doctypeRootElement the name of the root element for a DOCTYPE.
125: * Can be null to express that the declaration is not DOCTYPE
126: * declaration or is broken.
127: * @param doctypePI public identifier for this DOCTYPE, if available.
128: * null for system doctype or other/broken declaration.
129: * @param doctypeFile system identifier for this DOCTYPE, if available.
130: * null otherwise.
131: */
132: public Declaration(ParserSource document, int from, int length,
133: String doctypeRootElement, String doctypePI,
134: String doctypeFile) {
135: super (document, from, length, TYPE_DECLARATION);
136: root = doctypeRootElement;
137: publicID = doctypePI;
138: file = doctypeFile;
139: }
140:
141: /**
142: * @return the name of the root element for a DOCTYPE declaration
143: * or null if the declatarion is not DOCTYPE or is broken.
144: */
145: public String getRootElement() {
146: return root;
147: }
148:
149: /**
150: * @return a public identifier of the PUBLIC DOCTYPE declaration
151: * or null for SYSTEM DOCTYPE and broken or other declaration.
152: */
153: public String getPublicIdentifier() {
154: return publicID;
155: }
156:
157: /**
158: * @return a system identifier of both PUBLIC and SYSTEM DOCTYPE
159: * declaration or null for PUBLIC declaration with system identifier
160: * not specified and broken or other declaration.
161: */
162: public String getDoctypeFile() {
163: return file;
164: }
165:
166: }
167:
168: public static class Named extends SyntaxElement {
169: String name;
170:
171: public Named(ParserSource document, int from, int to, int type,
172: String name) {
173: super (document, from, to, type);
174: this .name = name;
175: }
176:
177: public String getName() {
178: return name;
179: }
180:
181: public String toString() {
182: return super .toString() + " - \"" + name + '"'; // NOI18N
183: }
184: }
185:
186: public static class Tag extends
187: org.netbeans.editor.ext.html.parser.SyntaxElement.Named {
188: private List<TagAttribute> attribs;
189: private boolean empty, openTag;
190:
191: public Tag(ParserSource document, int from, int length,
192: String name, List attribs, boolean openTag,
193: boolean isEmpty) {
194: super (document, from, length, openTag ? TYPE_TAG
195: : TYPE_ENDTAG, name);
196: this .attribs = attribs;
197: this .openTag = openTag;
198: this .empty = isEmpty;
199: }
200:
201: public boolean isEmpty() {
202: return empty;
203: }
204:
205: /** @return true if the tag represents an open tag, false if the tag is a close tag.
206: */
207: public boolean isOpenTag() {
208: return openTag;
209: }
210:
211: public List<TagAttribute> getAttributes() {
212: return attribs;
213: }
214:
215: public TagAttribute getAttribute(String name) {
216: return getAttribute(name, true);
217: }
218:
219: public TagAttribute getAttribute(String name, boolean ignoreCase) {
220: for (TagAttribute ta : attribs) {
221: if (ta.getName().equals(name)) {
222: return ta;
223: }
224: }
225: return null;
226: }
227:
228: public String toString() {
229: StringBuffer ret = new StringBuffer(super .toString());
230: ret.append(" - {"); // NOI18N
231:
232: for (Iterator i = attribs.iterator(); i.hasNext();) {
233: ret.append(i.next());
234: ret.append(", "); // NOI18N
235: }
236:
237: ret.append("}"); //NOI18N
238: if (isEmpty())
239: ret.append(" (EMPTY TAG)");
240:
241: return ret.toString();
242: }
243: }
244:
245: public static class TagAttribute {
246:
247: private String name, value;
248: private int nameOffset, valueOffset, valueLength;
249:
250: TagAttribute(String name, String value, int nameOffset,
251: int valueOffset, int valueLength) {
252: this .name = name;
253: this .value = value;
254: this .nameOffset = nameOffset;
255: this .valueOffset = valueOffset;
256: this .valueLength = valueLength;
257: }
258:
259: public String getName() {
260: return name;
261: }
262:
263: void setName(String name) {
264: this .name = name;
265: }
266:
267: public String getValue() {
268: return value;
269: }
270:
271: public int getValueLength() {
272: return valueLength;
273: }
274:
275: void setValue(String value) {
276: this .value = value;
277: }
278:
279: public int getNameOffset() {
280: return nameOffset;
281: }
282:
283: void setNameOffset(int ofs) {
284: this .nameOffset = ofs;
285: }
286:
287: public int getValueOffset() {
288: return valueOffset;
289: }
290:
291: void setValueOffset(int ofs) {
292: this .valueOffset = ofs;
293: }
294:
295: public String toString() {
296: return "TagAttribute[name=" + getName() + "; value="
297: + getValue() + "; nameOffset=" + getNameOffset()
298: + "; valueOffset=" + getValueOffset() + "]";
299: }
300:
301: //backward compatibility
302: public boolean equals(Object o) {
303: if (!(o instanceof TagAttribute)) {
304: return false;
305: } else {
306: return getName().equals(((TagAttribute) o).getName());
307: }
308: }
309: }
310: }
|