KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > xml > xam > dom > ReadOnlyAccess


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-2007 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19 package org.netbeans.modules.xml.xam.dom;
20
21 import java.beans.PropertyChangeEvent JavaDoc;
22 import java.beans.PropertyChangeListener JavaDoc;
23 import java.io.BufferedReader JavaDoc;
24 import java.io.File JavaDoc;
25 import java.io.IOException JavaDoc;
26 import java.io.InputStream JavaDoc;
27 import java.io.InputStreamReader JavaDoc;
28 import java.io.StringReader JavaDoc;
29 import java.util.HashMap JavaDoc;
30 import java.util.List JavaDoc;
31 import java.util.Map JavaDoc;
32 import javax.swing.event.UndoableEditListener JavaDoc;
33 import javax.swing.text.BadLocationException JavaDoc;
34 import javax.swing.text.PlainDocument JavaDoc;
35 import javax.xml.XMLConstants JavaDoc;
36 import javax.xml.namespace.QName JavaDoc;
37 import javax.xml.parsers.DocumentBuilder JavaDoc;
38 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
39 import javax.xml.parsers.ParserConfigurationException JavaDoc;
40 import org.netbeans.modules.xml.xam.Model;
41 import org.netbeans.modules.xml.xam.ModelSource;
42 import org.netbeans.modules.xml.xam.spi.DocumentModelAccessProvider;
43 import org.w3c.dom.Attr JavaDoc;
44 import org.w3c.dom.CDATASection JavaDoc;
45 import org.w3c.dom.Comment JavaDoc;
46 import org.w3c.dom.Document JavaDoc;
47 import org.w3c.dom.Element JavaDoc;
48 import org.w3c.dom.NamedNodeMap JavaDoc;
49 import org.w3c.dom.Node JavaDoc;
50 import org.w3c.dom.NodeList JavaDoc;
51 import org.w3c.dom.ProcessingInstruction JavaDoc;
52 import org.xml.sax.InputSource JavaDoc;
53 import org.xml.sax.SAXException JavaDoc;
54
55 /**
56  * Default document model access with limited support for read-only operations.
57  *
58  * @author Nam Nguyen
59  */

60 public class ReadOnlyAccess extends DocumentModelAccess {
61     private AbstractDocumentModel model;
62     private Document JavaDoc rootDoc;
63     
64     /** Creates a new instance of PlainDOMAccess */
65     public ReadOnlyAccess(AbstractDocumentModel model) {
66         this.model = model;
67     }
68     
69     public AbstractDocumentModel getModel() {
70         return model;
71     }
72     
73     public void setPrefix(Element JavaDoc node, String JavaDoc prefix) {
74         throw new UnsupportedOperationException JavaDoc("setPrefix access not supported.");
75     }
76     
77     public List JavaDoc<Element JavaDoc> getPathFromRoot(Document JavaDoc root, Element JavaDoc node) {
78         // mainly for merge sync, not needed
79
throw new UnsupportedOperationException JavaDoc("getPathFromRoot access not supported.");
80     }
81     
82     public String JavaDoc getXPath(Document JavaDoc root, Element JavaDoc node) {
83         throw new UnsupportedOperationException JavaDoc("getXPath access not supported.");
84     }
85     
86     public Map JavaDoc<QName JavaDoc, String JavaDoc> getAttributeMap(Element JavaDoc element) {
87         Map JavaDoc<QName JavaDoc,String JavaDoc> qValues = new HashMap JavaDoc<QName JavaDoc,String JavaDoc>();
88         NamedNodeMap JavaDoc attributes = element.getAttributes();
89         for (int i=0; i<attributes.getLength(); i++) {
90             Attr JavaDoc attr = (Attr JavaDoc) attributes.item(i);
91             if (isXmlnsAttribute(attr)) {
92                 continue;
93             }
94             QName JavaDoc q = AbstractDocumentComponent.getQName(attr);
95             qValues.put(q, attr.getValue());
96         }
97         return qValues;
98     }
99     
100     public static boolean isXmlnsAttribute(Attr JavaDoc attr) {
101         return XMLConstants.XMLNS_ATTRIBUTE.equals(attr.getPrefix()) ||
102                 XMLConstants.XMLNS_ATTRIBUTE.equals(attr.getName());
103     }
104     
105     public Element JavaDoc duplicate(Element JavaDoc element) {
106         throw new UnsupportedOperationException JavaDoc("getXPath access not supported.");
107     }
108     
109     public String JavaDoc getXmlFragment(Element JavaDoc element) {
110         String JavaDoc fragment = getXmlFragmentInclusive(element);
111         if (fragment.endsWith("/>")) {
112             return null;
113         }
114         int start = fragment.indexOf(">");
115         start++;
116         int end = fragment.lastIndexOf("<");
117         return fragment.substring(start, end);
118     }
119     
120     public void setXmlFragment(Element JavaDoc element, String JavaDoc text, DocumentModelAccess.NodeUpdater updater) throws IOException JavaDoc {
121         throw new UnsupportedOperationException JavaDoc("setXmlFragment access not supported.");
122     }
123     
124     public void setText(Element JavaDoc element, String JavaDoc val, DocumentModelAccess.NodeUpdater updater) {
125         throw new UnsupportedOperationException JavaDoc("setText access not supported.");
126     }
127     
128     public void removeAttribute(Element JavaDoc element, String JavaDoc name, DocumentModelAccess.NodeUpdater updater) {
129         throw new UnsupportedOperationException JavaDoc("removeAttribute access not supported.");
130     }
131     
132     public void setAttribute(Element JavaDoc element, String JavaDoc name, String JavaDoc value, DocumentModelAccess.NodeUpdater updater) {
133         throw new UnsupportedOperationException JavaDoc("setAttribute access not supported.");
134     }
135     
136     public int findPosition(Node JavaDoc node) {
137         Element JavaDoc root = ((DocumentComponent) model.getRootComponent()).getPeer();
138         javax.swing.text.Document JavaDoc doc = model.getBaseDocument();
139         try {
140             String JavaDoc buf = doc.getText(0, doc.getLength());
141             if (node instanceof Element JavaDoc) {
142                 int pos = getRootElementPosition(buf, root);
143                 StringScanner scanner = new StringScanner(buf, pos);
144                 return findPosition((Element JavaDoc)node, root, scanner);
145             }
146         } catch(BadLocationException JavaDoc e) {
147             // just return -1
148
}
149         return -1;
150     }
151     
152     private int getRootElementPosition(String JavaDoc buf, Element JavaDoc root) {
153         NodeList JavaDoc children = root.getOwnerDocument().getChildNodes();
154         int pos = 0;
155         for (int i=0; i<children.getLength(); i++) {
156             Node JavaDoc n = children.item(i);
157             if (n != root) {
158                 String JavaDoc s = n.getNodeValue();
159                 assert (s != null) : "Invalid document";
160                 pos += s.length();
161             } else {
162                 break;
163             }
164         }
165         pos = buf.indexOf(root.getTagName(), pos)-1;
166         assert pos > 0 : "Root element position should be greater than 0";
167         return pos;
168     }
169     
170     private static class StringScanner {
171         String JavaDoc buf;
172         int pos = -1;
173         public StringScanner(String JavaDoc buf, int pos) {
174             this.buf = buf;
175             this.pos = pos;
176         }
177         public void scanTo(String JavaDoc token) {
178             pos = buf.indexOf(token, pos);
179             if (pos == -1) {
180                 throw new IllegalArgumentException JavaDoc("Scan failed: position -1");
181             }
182         }
183         public void skip(String JavaDoc token) {
184             scanTo(token);
185             skip(token.length());
186         }
187         public void skip(int count) {
188             pos += count;
189         }
190     }
191     
192     private int findPosition(Element JavaDoc target, Element JavaDoc base, StringScanner scanner) {
193         if (target == base) {
194             return scanner.pos;
195         }
196         scanner.skip(">");
197         NodeList JavaDoc children = base.getChildNodes();
198         for (int i=0; i<children.getLength(); i++) {
199             Node JavaDoc node = children.item(i);
200             // condition is we always have argument fromPos be the index of the
201
// previous element plus sum length of any text/comment/attribute
202
if (! (node instanceof Element JavaDoc)) {
203                 String JavaDoc s = node.getNodeValue();
204                 if (s == null) {
205                     s = node.getTextContent();
206                 }
207                 if (s != null) {
208                     scanner.skip(s.length());
209                 }
210                 continue;
211             }
212             Element JavaDoc current = (Element JavaDoc)children.item(i);
213             String JavaDoc tag = "<" + current.getTagName();
214             scanner.scanTo(tag);
215             if (current == target) {
216                 return scanner.pos;
217             }
218             
219             int found = findPosition(target, current, scanner);
220             if (found > -1) {
221                 return found;
222             }
223         }
224         if (children.getLength() > 0) {
225             scanner.skip(">");
226         }
227         return -1;
228     }
229     
230     public int getElementIndexOf(Node JavaDoc parent, Element JavaDoc child) {
231         // only needed for sync merge
232
throw new UnsupportedOperationException JavaDoc("getElementIndexOf access not supported.");
233     }
234     
235     public List JavaDoc<Node JavaDoc> findNodes(Document JavaDoc root, String JavaDoc xpath) {
236         throw new UnsupportedOperationException JavaDoc("findNodes access not supported.");
237     }
238     
239     public Node JavaDoc findNode(Document JavaDoc root, String JavaDoc xpath) {
240         throw new UnsupportedOperationException JavaDoc("findNode access not supported.");
241     }
242     
243     public Element JavaDoc getContainingElement(int position) {
244         try {
245             javax.swing.text.Document JavaDoc swingDoc = model.getBaseDocument();
246             String JavaDoc buf = swingDoc.getText(0, swingDoc.getLength());
247             Element JavaDoc root = model.getDocument().getDocumentElement();
248             if (position < 0) return null;
249             return findElement(position, buf, root, getRootElementPosition(buf, root));
250         } catch(Exception JavaDoc e) {
251             return null;
252         }
253     }
254     
255     private String JavaDoc getNonElementString(String JavaDoc buf, int basePos, Node JavaDoc node) {
256         assert ! (node instanceof Element JavaDoc) : "Element is not expected";
257         String JavaDoc s = node.getNodeValue();
258         if (s == null) {
259             s = node.getTextContent();
260         }
261         assert (s != null) : "Expected node has string value";
262         return s;
263     }
264     
265     protected Element JavaDoc findElement(int position, String JavaDoc buf, Element JavaDoc base, int basePos) {
266         if (basePos == position) {
267             return base;
268         }
269         
270         NodeList JavaDoc children = base.getChildNodes();
271         
272         for (int i=0; i<children.getLength(); i++) {
273             Node JavaDoc node = children.item(i);
274             // check if the position is more than boundary of next element
275
// i.e. basePos plus sum length of any text/comment
276
if (! (node instanceof Element JavaDoc)) {
277                 String JavaDoc s = getNonElementString(buf, basePos, node);
278                 basePos = buf.indexOf(s, basePos);
279                 if (position < basePos) {
280                     return base;
281                 } else {
282                     basePos += s.length();
283                 }
284                 continue;
285             }
286             Element JavaDoc current = (Element JavaDoc)children.item(i);
287             String JavaDoc tag = "<" + current.getTagName(); //NOI18N
288
basePos = buf.indexOf(tag, basePos);
289             if (basePos > position) {
290                 return base;
291             } else {
292                 Element JavaDoc found = findElement(position, buf, current, basePos);
293                 if (found != null) {
294                     return found;
295                 }
296                 if (i+1 < children.getLength() && ! (children.item(i+1) instanceof Element JavaDoc)) {
297                     String JavaDoc s = getNonElementString(buf, basePos, children.item(i+1));
298                     int endCurrent = buf.indexOf(s, basePos);
299                     if (endCurrent > position) {
300                         return current;
301                     }
302                 }
303             }
304             
305         }
306         return null;
307     }
308     
309     public void addUndoableEditListener(UndoableEditListener JavaDoc listener) {
310         throw new UnsupportedOperationException JavaDoc("addUndoableEditListener access not supported.");
311     }
312     
313     public void removeUndoableEditListener(UndoableEditListener JavaDoc listener) {
314         throw new UnsupportedOperationException JavaDoc("removeUndoableEditListener access not supported.");
315     }
316     
317     public void appendChild(Node JavaDoc node, Node JavaDoc newChild, DocumentModelAccess.NodeUpdater updater) {
318         throw new UnsupportedOperationException JavaDoc("appendChild access not supported.");
319     }
320     
321     public void insertBefore(Node JavaDoc node, Node JavaDoc newChild, Node JavaDoc refChild, DocumentModelAccess.NodeUpdater updater) {
322         throw new UnsupportedOperationException JavaDoc("insertBefore access not supported.");
323     }
324     
325     public void removeChild(Node JavaDoc node, Node JavaDoc child, DocumentModelAccess.NodeUpdater updater) {
326         throw new UnsupportedOperationException JavaDoc("removeChild access not supported.");
327     }
328     
329     public void replaceChild(Node JavaDoc node, Node JavaDoc child, Node JavaDoc newChild, DocumentModelAccess.NodeUpdater updater) {
330         throw new UnsupportedOperationException JavaDoc("replaceChild access not supported.");
331     }
332     
333     public Model.State sync() throws IOException JavaDoc {
334         try {
335             DocumentBuilderFactory JavaDoc dbf = DocumentBuilderFactory.newInstance();
336             dbf.setNamespaceAware(true);
337             dbf.setIgnoringComments(true);
338             dbf.setIgnoringElementContentWhitespace(true);
339             DocumentBuilder JavaDoc db = dbf.newDocumentBuilder();
340             javax.swing.text.Document JavaDoc buffer = model.getBaseDocument();
341             String JavaDoc xmlText = buffer.getText(0, buffer.getLength());
342             BufferedReader JavaDoc reader = new BufferedReader JavaDoc(new StringReader JavaDoc(xmlText));
343             rootDoc = db.parse(new InputSource JavaDoc(reader));
344             Element JavaDoc rootElement = rootDoc.getDocumentElement();
345             if (model.createRootComponent(rootElement) == null) {
346                 throw new IOException JavaDoc("Cannot create model with "+
347                         new QName JavaDoc(rootElement.getNamespaceURI(), rootElement.getLocalName()));
348             }
349             return Model.State.VALID;
350         } catch (ParserConfigurationException JavaDoc pce) {
351             IOException JavaDoc ioe = new IOException JavaDoc();
352             ioe.initCause(pce);
353             throw ioe;
354         } catch (BadLocationException JavaDoc ble) {
355             IOException JavaDoc ioe = new IOException JavaDoc();
356             ioe.initCause(ble);
357             throw ioe;
358         } catch (SAXException JavaDoc saxe) {
359             IOException JavaDoc ioe = new IOException JavaDoc();
360             ioe.initCause(saxe);
361             throw ioe;
362         }
363     }
364     
365     public ElementIdentity getElementIdentity() {
366         throw new UnsupportedOperationException JavaDoc("getElementIdentity access not supported.");
367     }
368     
369     public Document JavaDoc getDocumentRoot() {
370         return rootDoc;
371     }
372     
373     public void flush() {
374         //NOOP
375
}
376     
377     public void finishUndoRedo() {
378         throw new UnsupportedOperationException JavaDoc("finishUndoRedo access not supported.");
379     }
380     
381     public boolean areSameNodes(Node JavaDoc n1, Node JavaDoc n2) {
382         return n1.equals(n2);
383     }
384     
385     public void prepareForUndoRedo() {
386         throw new UnsupportedOperationException JavaDoc("prepareForUndoRedo access not supported.");
387     }
388     
389     public void addMergeEventHandler(PropertyChangeListener JavaDoc l) {
390         //NOT SUPPORTED
391
}
392     
393     public void removeMergeEventHandler(PropertyChangeListener JavaDoc l) {
394         //NOT SUPPORTED
395
}
396     
397     public Node JavaDoc getOldEventParentNode(PropertyChangeEvent JavaDoc evt) {
398         //NOT SUPPORTED
399
return null;
400     }
401     
402     public Node JavaDoc getOldEventNode(PropertyChangeEvent JavaDoc evt) {
403         //NOT SUPPORTED
404
return null;
405     }
406     
407     public Node JavaDoc getNewEventParentNode(PropertyChangeEvent JavaDoc evt) {
408         //NOT SUPPORTED
409
return null;
410     }
411     
412     public Node JavaDoc getNewEventNode(PropertyChangeEvent JavaDoc evt) {
413         //NOT SUPPORTED
414
return null;
415     }
416     
417     public String JavaDoc normalizeUndefinedAttributeValue(String JavaDoc value) {
418         return "".equals(value) ? null : value; //NOI18N
419
}
420     
421     public static class Provider implements DocumentModelAccessProvider {
422         private static Provider instance;
423         protected Provider() {
424         }
425         
426         public static Provider getInstance() {
427             if (instance == null) {
428                 instance = new Provider();
429             }
430             return instance;
431         }
432         
433         public DocumentModelAccess createModelAccess(AbstractDocumentModel model) {
434             return new ReadOnlyAccess(model);
435         }
436         
437         public javax.swing.text.Document JavaDoc loadSwingDocument(InputStream JavaDoc in)
438         throws IOException JavaDoc, BadLocationException JavaDoc {
439             
440             javax.swing.text.Document JavaDoc sd = new PlainDocument JavaDoc();
441             BufferedReader JavaDoc br = new BufferedReader JavaDoc(new InputStreamReader JavaDoc(in));
442             try {
443                 String JavaDoc line = null;
444                 while ((line = br.readLine()) != null) {
445                     sd.insertString(sd.getLength(), line+System.getProperty("line.separator"), null); // NOI18N
446
}
447             } finally {
448                 br.close();
449             }
450             return sd;
451         }
452         
453         public Object JavaDoc getModelSourceKey(ModelSource source) {
454             return source.getLookup().lookup(File JavaDoc.class);
455         }
456     }
457     
458 }
459
Popular Tags