KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > xml > text > syntax > dom > Tag


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.xml.text.syntax.dom;
21
22 import java.util.*;
23 import javax.swing.text.BadLocationException JavaDoc;
24
25 import org.w3c.dom.*;
26 import org.netbeans.modules.xml.text.syntax.*;
27 import org.netbeans.modules.xml.spi.dom.*;
28 import org.netbeans.editor.*;
29
30 /**
31  * Represents tag syntax element. It also represent DOM <code>Element</code>.
32  * This duality means that one document element is represented by
33  * two DOM <code>Element</code> instances - one for start tag and one for
34  * end tag. This is hidden during document traversal but never relay on
35  * <code>equals</code>. The <code>equals</code> is used for syntax element
36  * purposes.
37  */

38 public abstract class Tag extends SyntaxNode implements Element, XMLTokenIDs {
39     
40     protected NamedNodeMap domAttributes;
41     
42     protected String JavaDoc name;
43     
44     public Tag(XMLSyntaxSupport support, TokenItem from, int to, String JavaDoc name, Collection attribs) {
45         super( support, from,to );
46         this.name = name;
47     }
48     
49     public final short getNodeType() {
50         return Node.ELEMENT_NODE;
51     }
52     
53     public final String JavaDoc getNodeName() {
54         return getTagName();
55     }
56     
57     public final String JavaDoc getTagName() {
58         return name;
59     }
60     
61     /**
62      * Create properly bound attributes and cache results.
63      * Parse attributes from first token.
64      */

65     public synchronized NamedNodeMap getAttributes() {
66         
67         // cached results not implemented
68
if (domAttributes != null) return domAttributes;
69         
70         Map map = new HashMap(3);
71         
72         SCAN_LOOP:
73             for (TokenItem next = first.getNext(); next != null; next = next.getNext()) {
74                 TokenID id = next.getTokenID();
75                 String JavaDoc name;
76                 String JavaDoc value;
77                 if (id == ARGUMENT) {
78                     TokenItem attributeStart = next;
79                     name = next.getImage();
80                     while (next.getTokenID() != VALUE) {
81                         next = next.getNext();
82                         if (next == null) break SCAN_LOOP;
83                     }
84                     
85                     // fuzziness to relax minor tokenization changes
86
String JavaDoc image = next.getImage();
87                     char test = image.charAt(0);
88                     if (image.length() == 1) {
89                         if (test == '"' || test == '\'') {
90                             next = next.getNext();
91                         }
92                     }
93                     
94                     if (next == null) break SCAN_LOOP;
95                     value = next.getImage();
96                     
97                     Object JavaDoc key = NamedNodeMapImpl.createKey(name);
98                     map.put(key, new AttrImpl(support, attributeStart, this));
99                     
100                     next = Util.skipAttributeValue(next, test);
101                     if (next == null) break SCAN_LOOP;
102                 } else if (id == WS) {
103                     // just skip
104
} else {
105                     break; // end of element markup
106
}
107             }
108             
109             // domAttributes = new NamedNodeMapImpl(map);
110
return new NamedNodeMapImpl(map);
111     }
112     
113     public String JavaDoc getAttribute(String JavaDoc name) {
114         Attr attribute = getAttributeNode(name);
115         if (attribute == null) return null;
116         return attribute.getValue();
117     }
118     
119     public final void setAttribute(String JavaDoc name, String JavaDoc value) {
120         NamedNodeMap attributes = getAttributes();
121         Node attr = attributes.getNamedItem(name);
122         if (attr != null) {
123             attr.setNodeValue(value);
124         } else {
125             String JavaDoc stringToInsert = " " + name + "=" + '"' + value + '"';
126             
127             // Get the document and lock it
128
BaseDocument doc = (BaseDocument)support.getDocument();
129             doc.atomicLock();
130             
131             // An attribute with the name was not found for the element
132
// Let's add it to the end
133
int insertStart = offset + length - 1;
134             
135             SCAN_LOOP:
136                 for (TokenItem next = first.getNext(); next != null; next = next.getNext()) {
137                     TokenID id = next.getTokenID();
138                     if (id == ARGUMENT) {
139                         while (next.getTokenID() != VALUE) {
140                             next = next.getNext();
141                             if (next == null) break SCAN_LOOP;
142                         }
143                         
144                         if (next == null) break SCAN_LOOP;
145                         
146                         String JavaDoc image = next.getImage();
147                         char test = image.charAt(0);
148                         
149                         while (next.getTokenID() == VALUE || next.getTokenID() == CHARACTER) {
150                             String JavaDoc actualValue = Util.actualAttributeValue(image);
151                             if (!actualValue.equals(image)) {
152                                 insertStart = next.getOffset() + actualValue.length();
153                                 break SCAN_LOOP;
154                             }
155                             next = next.getNext();
156                             if (next == null) break SCAN_LOOP;
157                             
158                             // Check if this is the last token in the element and set the
159
// insertStart if it is
160
image = next.getImage();
161                             insertStart = next.getOffset();
162                             if (image.length() > 0 && image.charAt(image.length() - 1) == '>') {
163                                 // The element is closing
164
insertStart += image.length() - 1;
165                                 if (image.length() > 1 && image.charAt(image.length() - 2) == '/') {
166                                     // We have a closed element at the form <blu/>
167
insertStart--;
168                                 }
169                             }
170                         }
171                         
172                         if (next == null) break SCAN_LOOP;
173                     } else if (id == WS) {
174                         // just skip
175
} else {
176                         break; // end of element markup
177
}
178                 }
179                 
180                 // Update the document
181
try {
182                     doc.insertString(insertStart, stringToInsert, null);
183                     doc.invalidateSyntaxMarks();
184                 } catch( BadLocationException JavaDoc e ) {
185                     throw new DOMException(DOMException.INVALID_STATE_ERR , e.getMessage());
186                 } finally {
187                     doc.atomicUnlock();
188                 }
189         }
190         
191         // Update this object's member variables
192
retokenizeObject();
193     }
194     
195     public final void removeAttribute(String JavaDoc name) {
196         throw new ROException();
197     }
198     
199     public Attr getAttributeNode(String JavaDoc name) {
200         NamedNodeMap map = getAttributes();
201         Node node = map.getNamedItem(name);
202         return (Attr) node;
203     }
204     
205     public final Attr setAttributeNode(Attr attribute) {
206         throw new ROException();
207     }
208     
209     public final Attr removeAttributeNode(Attr attribute) {
210         throw new ROException();
211     }
212     
213     public NodeList getElementsByTagName(String JavaDoc name) {
214         throw new ROException();
215     }
216     
217     /**
218      * Returns previous sibling by locating pairing start tag
219      * and asking it for previous non-start tag SyntaxNode.
220      */

221     public Node getPreviousSibling() {
222         SyntaxNode prev = getStartTag();
223         if (prev == null) return null;
224         prev = findPrevious(prev);
225         if (prev instanceof StartTag) {
226             return null;
227         } else {
228             return prev;
229         }
230     }
231     
232     /**
233      * Returns next sibling by locating pairing end tag
234      * and asking it for next non-end tag SyntaxNode.
235      */

236     public Node getNextSibling() {
237         SyntaxNode next = getEndTag();
238         if (next == null) return null;
239         next = findNext(next);
240         if (next instanceof EndTag) {
241             return null;
242         } else {
243             return next;
244         }
245     }
246     
247     public Node getFirstChild() {
248         NodeList list = getChildNodes();
249         if (list.getLength() == 0) return null;
250         return getChildNodes().item(0);
251     }
252     
253     public Node getLastChild() {
254         NodeList list = getChildNodes();
255         if (list.getLength() == 0) return null;
256         return list.item(list.getLength());
257     }
258     
259     protected abstract Tag getStartTag();
260     
261     protected abstract Tag getEndTag();
262     
263     // public boolean equals(Object obj) {
264
// if ((obj instanceof Tag) == false) return false;
265
// return false;
266
// }
267

268     
269     // unsupported DOM level 2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
270

271     public String JavaDoc getAttributeNS(String JavaDoc namespaceURI, String JavaDoc localName) {
272         throw new UOException();
273     }
274     
275     public void setAttributeNS(String JavaDoc namespaceURI, String JavaDoc qualifiedName, String JavaDoc value) {
276         throw new UOException();
277     }
278     
279     public void removeAttributeNS(String JavaDoc namespaceURI, String JavaDoc localName) {
280         throw new UOException();
281     }
282     
283     public Attr getAttributeNodeNS(String JavaDoc namespaceURI, String JavaDoc localName) {
284         throw new UOException();
285     }
286     
287     public Attr setAttributeNodeNS(Attr newAttr) {
288         throw new UOException();
289     }
290     
291     public NodeList getElementsByTagNameNS(String JavaDoc namespaceURI, String JavaDoc localName) {
292         throw new UOException();
293     }
294     
295     public boolean hasAttribute(String JavaDoc name) {
296         throw new UOException();
297     }
298     
299     public boolean hasAttributeNS(String JavaDoc namespaceURI, String JavaDoc localName) {
300         throw new UOException();
301     }
302     
303     public void retokenizeObject() {
304         // Update this object's member variables
305
try {
306             first = support.getTokenChain(offset, support.getDocument().getLength());
307         } catch (BadLocationException JavaDoc e) {
308             throw new DOMException(DOMException.INVALID_STATE_ERR , e.getMessage());
309         }
310     }
311
312     /**
313      * We guarantee DOM Node equality by using Java Object's equals.
314      * It's potentionally dangerous as it mixes StartTags and EndTags.
315      * Never put this object into vector of so until you assumes DOM Node
316      * equality.
317      * <p>
318      * I would appreciate a methos at DOM that would define
319      * Node equals not Objevt's equals.
320      */

321     public final boolean equals(Object JavaDoc obj) {
322         if (obj == this) return true;
323         if (obj instanceof Tag) {
324             Tag tag = (Tag) obj;
325             Tag t1 = tag.getStartTag();
326             Tag t2 = getStartTag();
327             if (t1 == null || t2 == null) return false;
328             return t1.superEquals(t2);
329         }
330         return false;
331     }
332
333     private boolean superEquals(Tag tag) {
334         return super.equals(tag);
335     }
336
337     /**
338      * The same as for equals it's DOM node hashcode.
339      */

340     public final int hashCode() {
341         Tag tag = getStartTag();
342         if (tag == null || tag == this) {
343             return super.hashCode();
344         } else {
345             return tag.hashCode();
346         }
347     }
348 }
349
350
Popular Tags