1 19 20 package org.netbeans.modules.xml.xdm.xam; 21 22 import java.beans.PropertyChangeEvent ; 23 import java.beans.PropertyChangeListener ; 24 import java.io.IOException ; 25 import java.util.ArrayList ; 26 import java.util.Collection ; 27 import java.util.HashMap ; 28 import java.util.HashSet ; 29 import java.util.Iterator ; 30 import java.util.List ; 31 import java.util.Map ; 32 import javax.swing.event.UndoableEditListener ; 33 import javax.xml.namespace.QName ; 34 import org.netbeans.modules.xml.xam.dom.AbstractDocumentComponent; 35 import org.netbeans.modules.xml.xam.dom.DocumentModel; 36 import org.netbeans.modules.xml.xam.dom.DocumentModelAccess; 37 import org.netbeans.modules.xml.xam.dom.AbstractDocumentModel; 38 import org.netbeans.modules.xml.xam.dom.ElementIdentity; 39 import org.netbeans.modules.xml.xdm.XDMModel; 40 import org.netbeans.modules.xml.xdm.diff.NodeInfo; 41 import org.netbeans.modules.xml.xdm.nodes.Attribute; 42 import org.netbeans.modules.xml.xdm.nodes.Document; 43 import org.netbeans.modules.xml.xdm.nodes.Element; 44 import org.netbeans.modules.xml.xdm.nodes.Node; 45 import org.netbeans.modules.xml.xdm.nodes.NodeImpl; 46 import org.netbeans.modules.xml.xdm.nodes.Token; 47 import org.netbeans.modules.xml.xdm.visitor.NodeByPositionVisitor; 48 import org.netbeans.modules.xml.xdm.visitor.PathFromRootVisitor; 49 import org.netbeans.modules.xml.xdm.visitor.PositionFinderVisitor; 50 import org.netbeans.modules.xml.xdm.visitor.XPathFinder; 51 import org.w3c.dom.NamedNodeMap ; 52 53 57 public class XDMAccess extends DocumentModelAccess { 58 private XDMModel xdmModel; 59 private AbstractDocumentModel model; 60 private XDMListener xdmListener; 61 62 public XDMAccess(AbstractDocumentModel model) { 63 xdmModel = new XDMModel(model.getModelSource()); 64 xdmModel.setPretty(true); 65 this.model = model; 66 xdmListener = new XDMListener(this.model); 67 xdmModel.setQNameValuedAttributes(model.getQNameValuedAttributes()); 68 } 69 70 public org.w3c.dom.Document getDocumentRoot() { 71 return getReferenceModel().getCurrentDocument(); 72 } 73 74 public void removeUndoableEditListener(UndoableEditListener listener) { 75 xdmModel.removeUndoableEditListener(listener); 76 } 77 78 public void addUndoableEditListener(UndoableEditListener listener) { 79 xdmModel.addUndoableEditListener(listener); 80 } 81 82 public AbstractDocumentModel getModel() { return model; } 83 public XDMModel getReferenceModel() { 84 return xdmModel; 85 } 86 87 public void flush() { 88 xdmModel.flush(); 89 } 90 91 public void prepareForUndoRedo() { 92 xdmListener.startSync(); 93 } 94 public void finishUndoRedo() { 95 xdmListener.endSync(); 96 } 97 98 public void prepareSync() { 99 xdmModel.prepareSync(); 100 } 101 102 public DocumentModel.State sync() throws IOException { 103 if (model.getRootComponent() == null) { 104 xdmModel.sync(); 105 if(xdmModel.getStatus() == XDMModel.Status.STABLE){ 106 Element root = Element.class.cast(xdmModel.getDocument().getDocumentElement()); 107 if (root == null) { 108 throw new IOException ("Cannot create model from non-XML document"); 109 } 110 if (model.createRootComponent(root) == null) { 111 throw new IOException ("Cannot create model with "+ 112 new QName (root.getNamespaceURI(), root.getLocalName())); 113 } 114 } 115 } else { 116 boolean error = true; 117 try { 118 xdmListener.startSync(); 119 xdmModel.sync(); 120 error = false; 121 xdmListener.endSync(); 122 } catch(IllegalArgumentException ex) { 123 IOException ioe = new IOException (); 124 ioe.initCause(ex); 125 throw ioe; 126 } finally { 127 if (error) { 128 xdmListener.endSync(false); 129 } 130 } 131 } 132 133 return xdmModel.getStatus() == XDMModel.Status.STABLE ? DocumentModel.State.VALID : DocumentModel.State.NOT_WELL_FORMED; 134 } 135 136 public boolean areSameNodes(org.w3c.dom.Node node1, org.w3c.dom.Node node2) { 137 if (! (node1 instanceof NodeImpl && node2 instanceof NodeImpl)) { 138 return false; 139 } 140 NodeImpl n1 = (NodeImpl) node1; 141 NodeImpl n2 = (NodeImpl) node2; 142 boolean areSameNodes = n1.isEquivalentNode(n2); 143 144 150 return areSameNodes; 151 } 152 153 158 private boolean compareTokens(NodeImpl n1, NodeImpl n2) { 159 List <Token> n1Tokens = n1.getTokens(); 160 List <Token> n2Tokens = n2.getTokens(); 161 if (n1Tokens.size() != n2Tokens.size()) { 162 return false; 163 } 164 165 for( int i=0;i<n1Tokens.size();i++) { 166 if (! n1Tokens.get(i).getValue().equals(n2Tokens.get(i).getValue())) { 167 return false; 168 } 169 } 170 171 NamedNodeMap n1Attrs = n1.getAttributes(); 172 NamedNodeMap n2Attrs = n2.getAttributes(); 173 if (n1Attrs.getLength() != n2Attrs.getLength()) { 174 return false; 175 } 176 177 for(int i=0;i<n1Attrs.getLength();i++) { 178 List <Token> n1AttrTokens = ((NodeImpl)n1Attrs.item(i)).getTokens(); 179 List <Token> n2AttrTokens = ((NodeImpl)n2Attrs.item(i)).getTokens(); 180 if (n1AttrTokens.size() != n2AttrTokens.size()) { 181 return false; 182 } 183 184 for (int j=0;j<n1AttrTokens.size();j++) { 185 if (! n1AttrTokens.get(j).getValue().equals(n2AttrTokens.get(j).getValue())) { 186 return false; 187 } 188 } 189 } 190 191 return true; 192 } 193 194 public int getElementIndexOf(org.w3c.dom.Node parent, org.w3c.dom.Element child) { 195 if (child == null) return -1; 196 int elementIndex = -1; 197 for (int i = 0; i < parent.getChildNodes().getLength(); i++) { 198 org.w3c.dom.Node n = parent.getChildNodes().item(i); 199 if (! (n instanceof Element)) continue; 200 elementIndex++; 201 if (areSameNodes(n, child)) { 202 return elementIndex; 203 } 204 } 205 return -1; 206 } 207 208 private boolean noMutations() { 209 return model.inSync() && ! model.startedFiringEvents() || model.inUndoRedo(); 210 } 211 212 public void setAttribute(org.w3c.dom.Element element, String name, String value, NodeUpdater updater) { 213 if (noMutations()) return; 214 if(element instanceof Node) { 215 Element xdmElem = (Element)element; 216 if(xdmElem.isInTree()) { 217 updater.updateReference(xdmModel.setAttribute(xdmElem,name,value)); 218 } else { 219 xdmElem.setAttribute(name,value); 220 } 221 } else { 222 throw new IllegalArgumentException (); 223 } 224 } 225 226 public void removeAttribute(org.w3c.dom.Element element, String name, NodeUpdater updater) { 227 if (noMutations()) return; 228 if(element instanceof Node) { 229 Element xdmElem = (Element)element; 230 if(xdmElem.isInTree()) { 231 updater.updateReference(xdmModel.removeAttribute(xdmElem,name)); 232 } else { 233 xdmElem.removeAttribute(name); 234 } 235 } else { 236 throw new IllegalArgumentException (); 237 } 238 } 239 240 public void appendChild(org.w3c.dom.Node node, org.w3c.dom.Node newChild, NodeUpdater updater) { 241 if (noMutations()) return; 242 if(node instanceof Node && newChild instanceof Node) { 243 Node xdmNode = (Node)node; 244 if (xdmNode.isInTree()) { 245 updater.updateReference(xdmModel.append(xdmNode,(Node)newChild)); 246 } else { 247 xdmNode.appendChild(newChild); 248 } 249 } else { 250 throw new IllegalArgumentException (); 251 } 252 } 253 254 public void insertBefore(org.w3c.dom.Node node, org.w3c.dom.Node newChild, org.w3c.dom.Node refChild, NodeUpdater updater) { 255 if (noMutations()) return; 256 if (node instanceof Node && newChild instanceof Node && refChild instanceof Node) { 257 Node xdmNode = (Node)node; 258 if(xdmNode.isInTree()) { 259 updater.updateReference(xdmModel.insertBefore(xdmNode,(Node)newChild,(Node)refChild)); 260 } else { 261 xdmNode.insertBefore(newChild,refChild); 262 } 263 } else { 264 throw new IllegalArgumentException (); 265 } 266 } 267 268 public void removeChild(org.w3c.dom.Node node, org.w3c.dom.Node child, NodeUpdater updater) { 269 if (noMutations()) return; 270 if(node instanceof Node && child instanceof Node) { 271 Node xdmNode = (Node)node; 272 if(xdmNode.isInTree()) { 273 updater.updateReference(xdmModel.remove(xdmNode,(Node)child)); 274 } else { 275 xdmNode.removeChild(child); 276 } 277 } else { 278 throw new IllegalArgumentException (); 279 } 280 } 281 282 public void removeChildren(org.w3c.dom.Node node, Collection <org.w3c.dom.Node > children, NodeUpdater updater) { 283 if (noMutations()) return; 284 if(node instanceof Node) { 285 ArrayList <Node> nodes = new ArrayList <Node>(); 286 for (org.w3c.dom.Node n : children) { 287 if (n instanceof Node) { 288 nodes.add((Node)n); 289 } else { 290 throw new IllegalArgumentException (); 291 } 292 } 293 Node xdmNode = (Node)node; 294 if(xdmNode.isInTree()) { 295 updater.updateReference(xdmModel.removeChildNodes(xdmNode, nodes)); 296 } else { 297 for (Node child : nodes) { 298 xdmNode.removeChild(child); 299 } 300 } 301 } else { 302 throw new IllegalArgumentException (); 303 } 304 } 305 306 public void replaceChild(org.w3c.dom.Node node, org.w3c.dom.Node child, org.w3c.dom.Node newChild, NodeUpdater updater) { 307 if (noMutations()) return; 308 Node xdmNode = (Node)node; 309 if(xdmNode.isInTree()) { 310 updater.updateReference(xdmModel.replaceChild(xdmNode, (Node)child, (Node)newChild)); 311 } else { 312 xdmNode.replaceChild(newChild, child); 313 } 314 } 315 316 319 public void setText(org.w3c.dom.Element element, String val, NodeUpdater updater) { 320 if (noMutations()) return; 321 Element xdmElem = (Element)element; 322 if(xdmElem.isInTree()) { 323 updater.updateReference(xdmModel.setTextValue(xdmElem,val)); 324 } else { 325 while(xdmElem.hasChildNodes()) { 326 xdmElem.removeChild(xdmElem.getLastChild()); 327 } 328 xdmElem.appendChild(xdmModel.getCurrentDocument().createTextNode(val)); 329 } 330 } 331 332 public String getXmlFragment(org.w3c.dom.Element element) { 333 if (element instanceof Element) { 334 Element xdmElem = (Element)element; 335 return xdmElem.getXmlFragmentText(); 336 } else { 337 throw new IllegalArgumentException (); 338 } 339 } 340 341 344 public void setXmlFragment(org.w3c.dom.Element element, String val, NodeUpdater updater) throws IOException { 345 if (noMutations()) return; 346 Element xdmElem = (Element)element; 347 if(xdmElem.isInTree()) { 348 updater.updateReference(xdmModel.setXmlFragmentText(xdmElem, val)); 349 } else { 350 xdmElem.setXmlFragmentText(val); 351 } 352 } 353 354 public void setPrefix(org.w3c.dom.Element element, String prefix) { 355 if (noMutations()) return; 356 Element xdmElement = (Element)element; 357 if (! xdmElement.isInTree()) { 358 xdmElement.setPrefix(prefix); 359 } 360 } 361 362 public int findPosition(org.w3c.dom.Node node){ 363 return (new PositionFinderVisitor()).findPosition(xdmModel.getDocument(), (Node)node); 364 } 365 366 public Element getContainingElement(int position){ 367 return (new NodeByPositionVisitor(xdmModel.getDocument())).getContainingElement(position); 368 } 369 370 public org.w3c.dom.Element duplicate(org.w3c.dom.Element element){ 371 return (org.w3c.dom.Element ) ((Element)element).copy(); 372 } 373 374 public Map <QName ,String > getAttributeMap(org.w3c.dom.Element element) { 375 Map <QName ,String > qValues = new AttributeMap<QName ,String >(); 376 NamedNodeMap attributes = element.getAttributes(); 377 for (int i=0; i<attributes.getLength(); i++) { 378 Attribute attr = (Attribute) attributes.item(i); 379 if (attr.isXmlnsAttribute()) { 380 continue; 381 } 382 QName q = AbstractDocumentComponent.getQName(attr); 383 ((AttributeMap)qValues).addKey(q); 384 qValues.put(q, attr.getValue()); 385 } 386 return qValues; 387 } 388 389 public List <org.w3c.dom.Element > getPathFromRoot(org.w3c.dom.Document root, org.w3c.dom.Element node) { 390 List <Node> pathToRoot = new PathFromRootVisitor().findPath(root, node); 391 List <org.w3c.dom.Element > pathFromRoot = new ArrayList <org.w3c.dom.Element >(); 392 for (Node n : pathToRoot) { 393 if (! (n instanceof Element)) { 394 break; 395 } 396 pathFromRoot.add(0, (Element) n); 397 } 398 return pathFromRoot; 399 } 400 401 public String getXPath(org.w3c.dom.Document root, org.w3c.dom.Element node) { 402 return XPathFinder.getXpath((Document)root, (Node)node); 403 } 404 405 public org.w3c.dom.Node findNode(org.w3c.dom.Document root, String xpath) { 406 return new XPathFinder().findNode((Document)root, xpath); 407 } 408 409 public List <org.w3c.dom.Node > findNodes(org.w3c.dom.Document root, String xpath) { 410 return XDMListener.toDomNodes(new XPathFinder().findNodes((Document)root, xpath)); 411 } 412 413 public XDMModel getXDMModel() { 414 return xdmModel; 415 } 416 417 public ElementIdentity getElementIdentity() { 418 return getXDMModel().getElementIdentity(); 419 } 420 421 public void addMergeEventHandler(PropertyChangeListener l) { 422 xdmModel.addPropertyChangeListener(l); 423 } 424 425 public void removeMergeEventHandler(PropertyChangeListener l) { 426 xdmModel.removePropertyChangeListener(l); 427 } 428 429 public org.w3c.dom.Node getOldEventParentNode(PropertyChangeEvent event) { 430 NodeInfo oldInfo = (NodeInfo) event.getOldValue(); 431 return oldInfo!=null?(Node) oldInfo.getParent():null; 432 } 433 434 public org.w3c.dom.Node getOldEventNode(PropertyChangeEvent event) { 435 NodeInfo oldInfo = (NodeInfo) event.getOldValue(); 436 return oldInfo!=null?(Node) oldInfo.getNode():null; 437 } 438 439 public org.w3c.dom.Node getNewEventParentNode(PropertyChangeEvent event) { 440 NodeInfo newInfo = (NodeInfo) event.getNewValue(); 441 return newInfo!=null?(Node) newInfo.getParent():null; 442 } 443 444 public org.w3c.dom.Node getNewEventNode(PropertyChangeEvent event) { 445 NodeInfo newInfo = (NodeInfo) event.getNewValue(); 446 return newInfo!=null?(Node) newInfo.getNode():null; 447 } 448 449 public String getIndentation(){ 450 return xdmModel.getIndentation(); 451 } 452 453 public void setIndentation(String indentation){ 454 xdmModel.setIndentation(indentation); 455 } 456 457 public class AttributeMap<K,V> extends HashMap <K,V> { 459 List <K> keys = new ArrayList <K>(); 460 public AttributeKeySet<K> keySet() { 461 return new AttributeKeySet(keys); 462 } 463 464 private void addKey(K q) { 465 keys.add(q); 466 } 467 } 468 469 public class AttributeKeySet<E> extends HashSet <E> { 470 List <E> keys = new ArrayList <E>(); 471 472 public AttributeKeySet(List <E> keys) { 473 this.keys = keys; 474 } 475 476 public boolean isEmpty() { 477 return keys.isEmpty(); 478 } 479 480 public boolean contains(Object key) { 481 return keys.contains(key); 482 } 483 484 public Iterator iterator() { 485 return keys.iterator(); 486 } 487 488 public int size() { 489 return keys.size(); 490 } 491 } 492 } 493 | Popular Tags |