1 19 20 package org.netbeans.modules.schema2beans; 21 22 import org.w3c.dom.Node ; 23 import org.w3c.dom.Document ; 24 import org.w3c.dom.NodeList ; 25 import org.w3c.dom.NamedNodeMap ; 26 27 import java.util.Map ; 28 import java.util.HashMap ; 29 import java.util.List ; 30 import java.util.LinkedList ; 31 import java.util.Iterator ; 32 import java.beans.PropertyChangeListener ; 33 import java.beans.PropertyChangeEvent ; 34 import java.io.Writer ; 35 import java.io.IOException ; 36 import java.io.OutputStream ; 37 38 41 public class Schema2BeansUtil { 42 43 50 public static void write(BaseBean bean, Writer writer) throws IOException { 51 GraphManager graphManager = bean.graphManager(); 52 if (graphManager != null) { 53 graphManager.write(writer); 54 } else { 55 throw new IllegalStateException (Common.getMessage("CantWriteBeanNotInDOMTree_msg")); 56 } 57 } 58 59 66 public static void write(BaseBean bean, OutputStream outputStream) throws IOException { 67 try { 68 GraphManager graphManager = bean.graphManager(); 69 if (graphManager != null) { 70 graphManager.write(outputStream); 71 } else { 72 throw new IllegalStateException (Common.getMessage("CantWriteBeanNotInDOMTree_msg")); 73 } 74 } catch (Schema2BeansException e) { 75 throw new Schema2BeansRuntimeException(e); 76 } 77 } 78 79 86 public static void mergeUnsupportedElements(BaseBean bean, BaseBean patternBean) { 87 Map nodeMap = new HashMap (); 88 List l = new LinkedList (); 89 l.add(bean); 90 bean.childBeans(true, l); 91 l.add(patternBean); 92 patternBean.childBeans(true, l); 93 for (Iterator it = l.iterator(); it.hasNext();) { 94 BaseBean baseBean = (BaseBean) it.next(); 95 DOMBinding binding = baseBean.binding; 96 if (binding != null) { 97 nodeMap.put(binding.getNode(), baseBean); 98 } 99 } 100 mergeNode(nodeMap, getOwnerDocument(bean.binding.getNode()), getOwnerDocument(patternBean.binding.getNode())); 101 } 102 103 private static void mergeBeans(Map nodeMap, BaseBean bean, BaseBean patternBean) { 104 if (bean.binding != null && patternBean.binding != null) { 105 Node node = bean. binding.getNode(); 106 Node otherNode = patternBean.binding.getNode(); 107 if (node != null && otherNode != null) { 108 mergeNode(nodeMap, node, otherNode); 109 } 110 } 111 } 112 113 119 private static Document getOwnerDocument(Node node) { 120 return node instanceof Document ? (Document ) node : node.getOwnerDocument(); 121 } 122 123 130 private static void mergeNode(Map nodeMap, Node node, Node patternNode) { 131 mergeAttributes(node, patternNode); 132 NodeList childNodes = node.getChildNodes(); 133 List children = relevantNodes(childNodes); 134 Document document = getOwnerDocument(node); 135 for (int i = childNodes.getLength() - 1; i >= 0; i--) { 136 Node childNode = childNodes.item(i); 137 if (!isRelevantNode(childNode)) { 138 node.removeChild(childNode); 139 } 140 } 141 NodeList patternChildNodes = patternNode.getChildNodes(); 142 for (int i = 0; i < patternChildNodes.getLength(); i++) { 143 Node patternChild = patternChildNodes.item(i); 144 Node currentChild = childNodes.item(i); 145 if (isRelevantNode(patternChild)) { 146 BaseBean patternBean = (BaseBean) nodeMap.get(patternChild); 147 BaseBean foundBean; 148 Node foundChild; 149 if (patternBean != null) { 150 foundBean = takeEqualBean(nodeMap, children, patternBean); 151 foundChild = foundBean == null ? null : foundBean.binding.getNode(); 152 } else { 153 foundBean = null; 154 foundChild = null; 155 } 156 if (foundChild == null) { 157 foundChild = takeEqualNode(children, patternChild); 158 } 159 if (foundChild != null) { 160 if (foundChild != currentChild) { 161 node.removeChild(foundChild); 162 node.insertBefore(foundChild, currentChild); 163 } 164 if (foundBean != null) { 165 mergeBeans(nodeMap, foundBean, patternBean); 166 } else if (isRelevantNode(foundChild)) { 167 mergeNode(nodeMap, foundChild, patternChild); 168 } else { 169 foundChild.setNodeValue(patternChild.getNodeValue()); 170 } 171 } else { 172 Node child = document.importNode(patternChild, true); 173 node.insertBefore(child, currentChild); 174 } 175 } else { 176 Node child = document.importNode(patternChild, true); 177 node.insertBefore(child, currentChild); 178 } 179 } 180 } 181 182 188 private static void mergeAttributes(Node node, Node otherNode) { 189 NamedNodeMap attributes = node.getAttributes(); 190 NamedNodeMap otherAttributes = otherNode.getAttributes(); 191 if (attributes == null) { 192 if (otherAttributes == null) { 193 return; 194 } else { 195 TraceLogger.error( 196 "Attributes merge error: " + node.getClass().getName() + " " + node.getClass().getName()); 197 return; 198 } 199 } 200 List names = new LinkedList (); 201 for (int i = 0; i < attributes.getLength(); i++) { 202 names.add(attributes.item(i).getNodeName()); 203 } 204 for (Iterator it = names.iterator(); it.hasNext();) { 205 String name = (String ) it.next(); 206 if (otherAttributes.getNamedItem(name) == null) { 207 attributes.removeNamedItem(name); 208 } 209 } 210 Document document = getOwnerDocument(node); 211 for (int i = 0; i < otherAttributes.getLength(); i++) { 212 Node newAttribute = otherAttributes.item(i); 213 String name = newAttribute.getNodeName(); 214 String value = newAttribute.getNodeValue(); 215 Node currentAttribute = attributes.getNamedItem(name); 216 if (currentAttribute == null) { 217 currentAttribute = document.createAttribute(name); 218 attributes.setNamedItem(currentAttribute); 219 } 220 currentAttribute.setNodeValue(value); 221 } 222 } 223 224 232 private static BaseBean takeEqualBean(Map nodeMap, List nodes, BaseBean patternBean) { 233 for (Iterator it = nodes.iterator(); it.hasNext();) { 234 Node node = (Node ) it.next(); 235 BaseBean bean = (BaseBean) nodeMap.get(node); 236 if (bean != null && bean.isEqualTo(patternBean)) { 237 it.remove(); 238 return bean; 239 } 240 } 241 return null; 242 } 243 244 251 private static Node takeEqualNode(List nodes, Node patternNode) { 252 List result = filterNodes(nodes, patternNode); 253 if (result.size() == 0) { 254 return null; 255 } else { 256 Node node = (Node ) result.get(0); 257 nodes.remove(node); 258 return node; 259 } 260 } 261 262 private static List filterNodes(List nodes, Node patternNode) { 263 List trueList = new LinkedList (); 264 String name = patternNode.getNodeName(); 265 for (Iterator it = nodes.iterator(); it.hasNext();) { 266 Node node = (Node ) it.next(); 267 if (name.equals(node.getNodeName())) { 268 trueList.add(node); 269 } 270 } 271 if (trueList.size() <= 1) { 272 return trueList; 273 } 274 275 List falseList = new LinkedList (); 276 for (Iterator it = trueList.iterator(); it.hasNext();) { 277 Node node = (Node ) it.next(); 278 if (patternNode.equals(node)) { 279 it.remove(); 280 falseList.add(node); 281 } 282 } 283 if (trueList.size() == 1) { 284 return trueList; 285 } else if (trueList.size() == 0) { 286 trueList = falseList; 287 } 288 289 falseList = new LinkedList (); 290 String value = patternNode.getNodeValue(); 291 for (Iterator it = trueList.iterator(); it.hasNext();) { 292 Node node = (Node ) it.next(); 293 if (!equals(value, node.getNodeValue())) { 294 it.remove(); 295 falseList.add(node); 296 } 297 } 298 if (trueList.size() == 1) { 299 return trueList; 300 } else if (trueList.size() == 0) { 301 trueList = falseList; 302 } 303 304 falseList = new LinkedList (); 305 NamedNodeMap attributes = patternNode.getAttributes(); 306 for (Iterator it = trueList.iterator(); it.hasNext();) { 307 Node node = (Node ) it.next(); 308 if (!equals(attributes, node.getAttributes())) { 309 it.remove(); 310 falseList.add(node); 311 } 312 } 313 if (trueList.size() == 0) { 314 return falseList; 315 } else { 316 return trueList; 317 } 318 } 319 320 327 private static boolean equals(String s1, String s2) { 328 return s1 == null ? s2 == null : !(s2 == null) && s1.trim().equals(s2.trim()); 329 330 } 331 332 339 private static boolean equals(NamedNodeMap attributes1, NamedNodeMap attributes2) { 340 if (attributes1 == null || attributes2 == null) { 341 return attributes1 == attributes2; 342 } else { 343 int n = attributes1.getLength(); 344 if (n != attributes2.getLength()) { 345 return false; 346 } 347 for (int i = 0; i < n; i++) { 348 Node attr1 = attributes1.item(i); 349 Node attr2 = attributes2.getNamedItem(attr1.getNodeName()); 350 if (attr2 == null || !attr2.getNodeValue().equals(attr2.getNodeValue())) { 351 return false; 352 } 353 } 354 return true; 355 } 356 } 357 358 364 private static List relevantNodes(NodeList nodeList) { 365 List list = new LinkedList (); 366 if (nodeList != null) { 367 for (int i = 0; i < nodeList.getLength(); i++) { 368 Node node = nodeList.item(i); 369 if (isRelevantNode(node)) { 370 list.add(node); 371 } 372 } 373 } 374 return list; 375 } 376 377 383 private static boolean isRelevantNode(Node node) { 384 short type = node.getNodeType(); 385 return type != Node.COMMENT_NODE && !isWhiteSpaceNode(node); 386 } 387 388 394 private static boolean isWhiteSpaceNode(Node node) { 395 short type = node.getNodeType(); 396 return (type == Node.TEXT_NODE && node.getNodeValue().trim().length() == 0); 397 } 398 399 405 private static Node findNode(BaseBean bean, String path) { 406 if (path.startsWith(bean.fullName())) { 407 BaseBean matchingChild; 408 while ((matchingChild = getMatchingChild(bean, path)) != null) { 409 bean = matchingChild; 410 } 411 if (path.equals(bean.fullName())) { 412 return bean.binding.node; 413 } 414 BeanProp[] beanProps = bean.beanProps(); 415 for (int i = 0; i < beanProps.length; i++) { 416 BeanProp prop = beanProps[i]; 417 int n = prop.bindingsSize(); 418 for (int j = 0; j < n; j++) { 419 if (path.equals(prop.getFullName(j))) { 420 return prop.getBinding(j).node; 421 } 422 } 423 } 424 } 425 return null; 426 } 427 428 private static BaseBean getMatchingChild(BaseBean bean, String path) { 429 BaseBean[] beans = bean.childBeans(false); 430 for (int i = 0; i < beans.length; i++) { 431 BaseBean baseBean = beans[i]; 432 if (path.startsWith(baseBean.fullName())) { 433 return baseBean; 434 } 435 } 436 return null; 437 } 438 439 443 public static class ReindentationListener implements PropertyChangeListener { 444 String indent = " "; 445 446 public void propertyChange(PropertyChangeEvent evt) { 447 Object oldValue = evt.getOldValue(); 448 Object newValue = evt.getNewValue(); 449 if (oldValue == null && newValue != null) { 450 String path = evt.getPropertyName(); 451 BaseBean bean = (BaseBean) evt.getSource(); 452 Node node = findNode(bean, path); 453 if (node != null) { 454 reindentNode(node); 455 } 456 } 457 } 458 459 private void reindentNode(Node node) { 460 Document document = node.getOwnerDocument(); 461 int level = 0; 462 StringBuffer sb = new StringBuffer ("\n"); 463 for (Node parent = node.getParentNode(); parent != document; parent = parent.getParentNode()) { 464 level++; 465 sb.append(indent); 466 } 467 String indentString = sb.toString(); 468 469 Node parentNode = node.getParentNode(); 470 Node previousNode = node.getPreviousSibling(); 471 if (previousNode != null && isWhiteSpaceNode(previousNode)) { 472 String s = previousNode.getNodeValue(); 473 int i = s.lastIndexOf('\n'); 474 s = i > 0 ? s.substring(0, i) + indentString : indentString; 475 previousNode.setNodeValue(s); } else { 477 parentNode.insertBefore(document.createTextNode(indentString), node); } 479 Node nextNode = node.getNextSibling(); 480 if (nextNode != null && isWhiteSpaceNode(nextNode)) { 481 String s = nextNode.getNodeValue(); 482 int i = s.indexOf('\n'); 483 if (i == -1) { 484 nextNode.setNodeValue(indentString); } 486 } else { 487 parentNode.insertBefore(document.createTextNode(indentString), nextNode); } 489 XMLUtil.reindent(document, node, level, indent); } 491 492 public String getIndent() { 493 return indent; 494 } 495 496 public void setIndent(String indent) { 497 this.indent = indent; 498 } 499 } 500 } 501 | Popular Tags |