1 19 package org.netbeans.modules.xml.xam.dom; 20 21 import java.beans.PropertyChangeEvent ; 22 import java.beans.PropertyChangeListener ; 23 import java.io.BufferedReader ; 24 import java.io.File ; 25 import java.io.IOException ; 26 import java.io.InputStream ; 27 import java.io.InputStreamReader ; 28 import java.io.StringReader ; 29 import java.util.HashMap ; 30 import java.util.List ; 31 import java.util.Map ; 32 import javax.swing.event.UndoableEditListener ; 33 import javax.swing.text.BadLocationException ; 34 import javax.swing.text.PlainDocument ; 35 import javax.xml.XMLConstants ; 36 import javax.xml.namespace.QName ; 37 import javax.xml.parsers.DocumentBuilder ; 38 import javax.xml.parsers.DocumentBuilderFactory ; 39 import javax.xml.parsers.ParserConfigurationException ; 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 ; 44 import org.w3c.dom.CDATASection ; 45 import org.w3c.dom.Comment ; 46 import org.w3c.dom.Document ; 47 import org.w3c.dom.Element ; 48 import org.w3c.dom.NamedNodeMap ; 49 import org.w3c.dom.Node ; 50 import org.w3c.dom.NodeList ; 51 import org.w3c.dom.ProcessingInstruction ; 52 import org.xml.sax.InputSource ; 53 import org.xml.sax.SAXException ; 54 55 60 public class ReadOnlyAccess extends DocumentModelAccess { 61 private AbstractDocumentModel model; 62 private Document rootDoc; 63 64 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 node, String prefix) { 74 throw new UnsupportedOperationException ("setPrefix access not supported."); 75 } 76 77 public List <Element > getPathFromRoot(Document root, Element node) { 78 throw new UnsupportedOperationException ("getPathFromRoot access not supported."); 80 } 81 82 public String getXPath(Document root, Element node) { 83 throw new UnsupportedOperationException ("getXPath access not supported."); 84 } 85 86 public Map <QName , String > getAttributeMap(Element element) { 87 Map <QName ,String > qValues = new HashMap <QName ,String >(); 88 NamedNodeMap attributes = element.getAttributes(); 89 for (int i=0; i<attributes.getLength(); i++) { 90 Attr attr = (Attr ) attributes.item(i); 91 if (isXmlnsAttribute(attr)) { 92 continue; 93 } 94 QName q = AbstractDocumentComponent.getQName(attr); 95 qValues.put(q, attr.getValue()); 96 } 97 return qValues; 98 } 99 100 public static boolean isXmlnsAttribute(Attr attr) { 101 return XMLConstants.XMLNS_ATTRIBUTE.equals(attr.getPrefix()) || 102 XMLConstants.XMLNS_ATTRIBUTE.equals(attr.getName()); 103 } 104 105 public Element duplicate(Element element) { 106 throw new UnsupportedOperationException ("getXPath access not supported."); 107 } 108 109 public String getXmlFragment(Element element) { 110 String 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 element, String text, DocumentModelAccess.NodeUpdater updater) throws IOException { 121 throw new UnsupportedOperationException ("setXmlFragment access not supported."); 122 } 123 124 public void setText(Element element, String val, DocumentModelAccess.NodeUpdater updater) { 125 throw new UnsupportedOperationException ("setText access not supported."); 126 } 127 128 public void removeAttribute(Element element, String name, DocumentModelAccess.NodeUpdater updater) { 129 throw new UnsupportedOperationException ("removeAttribute access not supported."); 130 } 131 132 public void setAttribute(Element element, String name, String value, DocumentModelAccess.NodeUpdater updater) { 133 throw new UnsupportedOperationException ("setAttribute access not supported."); 134 } 135 136 public int findPosition(Node node) { 137 Element root = ((DocumentComponent) model.getRootComponent()).getPeer(); 138 javax.swing.text.Document doc = model.getBaseDocument(); 139 try { 140 String buf = doc.getText(0, doc.getLength()); 141 if (node instanceof Element ) { 142 int pos = getRootElementPosition(buf, root); 143 StringScanner scanner = new StringScanner(buf, pos); 144 return findPosition((Element )node, root, scanner); 145 } 146 } catch(BadLocationException e) { 147 } 149 return -1; 150 } 151 152 private int getRootElementPosition(String buf, Element root) { 153 NodeList children = root.getOwnerDocument().getChildNodes(); 154 int pos = 0; 155 for (int i=0; i<children.getLength(); i++) { 156 Node n = children.item(i); 157 if (n != root) { 158 String 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 buf; 172 int pos = -1; 173 public StringScanner(String buf, int pos) { 174 this.buf = buf; 175 this.pos = pos; 176 } 177 public void scanTo(String token) { 178 pos = buf.indexOf(token, pos); 179 if (pos == -1) { 180 throw new IllegalArgumentException ("Scan failed: position -1"); 181 } 182 } 183 public void skip(String 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 target, Element base, StringScanner scanner) { 193 if (target == base) { 194 return scanner.pos; 195 } 196 scanner.skip(">"); 197 NodeList children = base.getChildNodes(); 198 for (int i=0; i<children.getLength(); i++) { 199 Node node = children.item(i); 200 if (! (node instanceof Element )) { 203 String 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 current = (Element )children.item(i); 213 String 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 parent, Element child) { 231 throw new UnsupportedOperationException ("getElementIndexOf access not supported."); 233 } 234 235 public List <Node > findNodes(Document root, String xpath) { 236 throw new UnsupportedOperationException ("findNodes access not supported."); 237 } 238 239 public Node findNode(Document root, String xpath) { 240 throw new UnsupportedOperationException ("findNode access not supported."); 241 } 242 243 public Element getContainingElement(int position) { 244 try { 245 javax.swing.text.Document swingDoc = model.getBaseDocument(); 246 String buf = swingDoc.getText(0, swingDoc.getLength()); 247 Element root = model.getDocument().getDocumentElement(); 248 if (position < 0) return null; 249 return findElement(position, buf, root, getRootElementPosition(buf, root)); 250 } catch(Exception e) { 251 return null; 252 } 253 } 254 255 private String getNonElementString(String buf, int basePos, Node node) { 256 assert ! (node instanceof Element ) : "Element is not expected"; 257 String 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 findElement(int position, String buf, Element base, int basePos) { 266 if (basePos == position) { 267 return base; 268 } 269 270 NodeList children = base.getChildNodes(); 271 272 for (int i=0; i<children.getLength(); i++) { 273 Node node = children.item(i); 274 if (! (node instanceof Element )) { 277 String 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 current = (Element )children.item(i); 287 String tag = "<" + current.getTagName(); basePos = buf.indexOf(tag, basePos); 289 if (basePos > position) { 290 return base; 291 } else { 292 Element 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 )) { 297 String 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 listener) { 310 throw new UnsupportedOperationException ("addUndoableEditListener access not supported."); 311 } 312 313 public void removeUndoableEditListener(UndoableEditListener listener) { 314 throw new UnsupportedOperationException ("removeUndoableEditListener access not supported."); 315 } 316 317 public void appendChild(Node node, Node newChild, DocumentModelAccess.NodeUpdater updater) { 318 throw new UnsupportedOperationException ("appendChild access not supported."); 319 } 320 321 public void insertBefore(Node node, Node newChild, Node refChild, DocumentModelAccess.NodeUpdater updater) { 322 throw new UnsupportedOperationException ("insertBefore access not supported."); 323 } 324 325 public void removeChild(Node node, Node child, DocumentModelAccess.NodeUpdater updater) { 326 throw new UnsupportedOperationException ("removeChild access not supported."); 327 } 328 329 public void replaceChild(Node node, Node child, Node newChild, DocumentModelAccess.NodeUpdater updater) { 330 throw new UnsupportedOperationException ("replaceChild access not supported."); 331 } 332 333 public Model.State sync() throws IOException { 334 try { 335 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 336 dbf.setNamespaceAware(true); 337 dbf.setIgnoringComments(true); 338 dbf.setIgnoringElementContentWhitespace(true); 339 DocumentBuilder db = dbf.newDocumentBuilder(); 340 javax.swing.text.Document buffer = model.getBaseDocument(); 341 String xmlText = buffer.getText(0, buffer.getLength()); 342 BufferedReader reader = new BufferedReader (new StringReader (xmlText)); 343 rootDoc = db.parse(new InputSource (reader)); 344 Element rootElement = rootDoc.getDocumentElement(); 345 if (model.createRootComponent(rootElement) == null) { 346 throw new IOException ("Cannot create model with "+ 347 new QName (rootElement.getNamespaceURI(), rootElement.getLocalName())); 348 } 349 return Model.State.VALID; 350 } catch (ParserConfigurationException pce) { 351 IOException ioe = new IOException (); 352 ioe.initCause(pce); 353 throw ioe; 354 } catch (BadLocationException ble) { 355 IOException ioe = new IOException (); 356 ioe.initCause(ble); 357 throw ioe; 358 } catch (SAXException saxe) { 359 IOException ioe = new IOException (); 360 ioe.initCause(saxe); 361 throw ioe; 362 } 363 } 364 365 public ElementIdentity getElementIdentity() { 366 throw new UnsupportedOperationException ("getElementIdentity access not supported."); 367 } 368 369 public Document getDocumentRoot() { 370 return rootDoc; 371 } 372 373 public void flush() { 374 } 376 377 public void finishUndoRedo() { 378 throw new UnsupportedOperationException ("finishUndoRedo access not supported."); 379 } 380 381 public boolean areSameNodes(Node n1, Node n2) { 382 return n1.equals(n2); 383 } 384 385 public void prepareForUndoRedo() { 386 throw new UnsupportedOperationException ("prepareForUndoRedo access not supported."); 387 } 388 389 public void addMergeEventHandler(PropertyChangeListener l) { 390 } 392 393 public void removeMergeEventHandler(PropertyChangeListener l) { 394 } 396 397 public Node getOldEventParentNode(PropertyChangeEvent evt) { 398 return null; 400 } 401 402 public Node getOldEventNode(PropertyChangeEvent evt) { 403 return null; 405 } 406 407 public Node getNewEventParentNode(PropertyChangeEvent evt) { 408 return null; 410 } 411 412 public Node getNewEventNode(PropertyChangeEvent evt) { 413 return null; 415 } 416 417 public String normalizeUndefinedAttributeValue(String value) { 418 return "".equals(value) ? null : value; } 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 loadSwingDocument(InputStream in) 438 throws IOException , BadLocationException { 439 440 javax.swing.text.Document sd = new PlainDocument (); 441 BufferedReader br = new BufferedReader (new InputStreamReader (in)); 442 try { 443 String line = null; 444 while ((line = br.readLine()) != null) { 445 sd.insertString(sd.getLength(), line+System.getProperty("line.separator"), null); } 447 } finally { 448 br.close(); 449 } 450 return sd; 451 } 452 453 public Object getModelSourceKey(ModelSource source) { 454 return source.getLookup().lookup(File .class); 455 } 456 } 457 458 } 459 | Popular Tags |