KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > schema2beans > Schema2BeansUtil


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.schema2beans;
21
22 import org.w3c.dom.Node JavaDoc;
23 import org.w3c.dom.Document JavaDoc;
24 import org.w3c.dom.NodeList JavaDoc;
25 import org.w3c.dom.NamedNodeMap JavaDoc;
26
27 import java.util.Map JavaDoc;
28 import java.util.HashMap JavaDoc;
29 import java.util.List JavaDoc;
30 import java.util.LinkedList JavaDoc;
31 import java.util.Iterator JavaDoc;
32 import java.beans.PropertyChangeListener JavaDoc;
33 import java.beans.PropertyChangeEvent JavaDoc;
34 import java.io.Writer JavaDoc;
35 import java.io.IOException JavaDoc;
36 import java.io.OutputStream JavaDoc;
37
38 /**
39  * @author pfiala
40  */

41 public class Schema2BeansUtil {
42
43     /**
44      * Write the current schema2beans graph as an XML document without reformating
45      *
46      * @param bean
47      * @param writer
48      * @throws IOException
49      */

50     public static void write(BaseBean bean, Writer JavaDoc writer) throws IOException JavaDoc {
51         GraphManager graphManager = bean.graphManager();
52         if (graphManager != null) {
53             graphManager.write(writer);
54         } else {
55             throw new IllegalStateException JavaDoc(Common.getMessage("CantWriteBeanNotInDOMTree_msg"));
56         }
57     }
58
59     /**
60      * Write the current schema2beans graph as an XML document without reformating
61      *
62      * @param bean
63      * @param outputStream
64      * @throws IOException
65      */

66     public static void write(BaseBean bean, OutputStream JavaDoc outputStream) throws IOException JavaDoc {
67         try {
68             GraphManager graphManager = bean.graphManager();
69             if (graphManager != null) {
70                 graphManager.write(outputStream);
71             } else {
72                 throw new IllegalStateException JavaDoc(Common.getMessage("CantWriteBeanNotInDOMTree_msg"));
73             }
74         } catch (Schema2BeansException e) {
75             throw new Schema2BeansRuntimeException(e);
76         }
77     }
78
79     /**
80      * Merge "unsupported" elements - elements which are not represented
81      * in model (whitespaces, comments, unknown atributes and tags),
82      * but they should be merged to DOMBinding
83      *
84      * @param patternBean
85      */

86     public static void mergeUnsupportedElements(BaseBean bean, BaseBean patternBean) {
87         Map JavaDoc nodeMap = new HashMap JavaDoc();
88         List JavaDoc l = new LinkedList JavaDoc();
89         l.add(bean);
90         bean.childBeans(true, l);
91         l.add(patternBean);
92         patternBean.childBeans(true, l);
93         for (Iterator JavaDoc 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 JavaDoc nodeMap, BaseBean bean, BaseBean patternBean) {
104         if (bean.binding != null && patternBean.binding != null) {
105             Node JavaDoc node = bean. binding.getNode();
106             Node JavaDoc otherNode = patternBean.binding.getNode();
107             if (node != null && otherNode != null) {
108                 mergeNode(nodeMap, node, otherNode);
109             }
110         }
111     }
112
113     /**
114      * Retrieves owner document of a node
115      *
116      * @param node
117      * @return the owner document
118      */

119     private static Document JavaDoc getOwnerDocument(Node JavaDoc node) {
120         return node instanceof Document JavaDoc ? (Document JavaDoc) node : node.getOwnerDocument();
121     }
122
123     /**
124      * Merge "unsupported" attributes and child elements of node
125      *
126      * @param nodeMap
127      * @param node
128      * @param patternNode
129      */

130     private static void mergeNode(Map JavaDoc nodeMap, Node JavaDoc node, Node JavaDoc patternNode) {
131         mergeAttributes(node, patternNode);
132         NodeList JavaDoc childNodes = node.getChildNodes();
133         List JavaDoc children = relevantNodes(childNodes);
134         Document JavaDoc document = getOwnerDocument(node);
135         for (int i = childNodes.getLength() - 1; i >= 0; i--) {
136             Node JavaDoc childNode = childNodes.item(i);
137             if (!isRelevantNode(childNode)) {
138                 node.removeChild(childNode);
139             }
140         }
141         NodeList JavaDoc patternChildNodes = patternNode.getChildNodes();
142         for (int i = 0; i < patternChildNodes.getLength(); i++) {
143             Node JavaDoc patternChild = patternChildNodes.item(i);
144             Node JavaDoc currentChild = childNodes.item(i);
145             if (isRelevantNode(patternChild)) {
146                 BaseBean patternBean = (BaseBean) nodeMap.get(patternChild);
147                 BaseBean foundBean;
148                 Node JavaDoc 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 JavaDoc child = document.importNode(patternChild, true);
173                     node.insertBefore(child, currentChild);
174                 }
175             } else {
176                 Node JavaDoc child = document.importNode(patternChild, true);
177                 node.insertBefore(child, currentChild);
178             }
179         }
180     }
181
182     /**
183      * Merge "unsupported" attributes of a node
184      *
185      * @param node
186      * @param otherNode
187      */

188     private static void mergeAttributes(Node JavaDoc node, Node JavaDoc otherNode) {
189         NamedNodeMap JavaDoc attributes = node.getAttributes();
190         NamedNodeMap JavaDoc 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 JavaDoc names = new LinkedList JavaDoc();
201         for (int i = 0; i < attributes.getLength(); i++) {
202             names.add(attributes.item(i).getNodeName());
203         }
204         for (Iterator JavaDoc it = names.iterator(); it.hasNext();) {
205             String JavaDoc name = (String JavaDoc) it.next();
206             if (otherAttributes.getNamedItem(name) == null) {
207                 attributes.removeNamedItem(name);
208             }
209         }
210         Document JavaDoc document = getOwnerDocument(node);
211         for (int i = 0; i < otherAttributes.getLength(); i++) {
212             Node JavaDoc newAttribute = otherAttributes.item(i);
213             String JavaDoc name = newAttribute.getNodeName();
214             String JavaDoc value = newAttribute.getNodeValue();
215             Node JavaDoc 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     /**
225      * Search list of nodes for related bean that is equivalent of given pattern
226      *
227      * @param nodeMap
228      * @param nodes
229      * @param patternBean
230      * @return the bean
231      */

232     private static BaseBean takeEqualBean(Map JavaDoc nodeMap, List JavaDoc nodes, BaseBean patternBean) {
233         for (Iterator JavaDoc it = nodes.iterator(); it.hasNext();) {
234             Node JavaDoc node = (Node JavaDoc) 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     /**
245      * Search list of nodes for node that is equivalent of given pattern
246      *
247      * @param nodes
248      * @param patternNode
249      * @return the node if found otherwise null
250      */

251     private static Node JavaDoc takeEqualNode(List JavaDoc nodes, Node JavaDoc patternNode) {
252         List JavaDoc result = filterNodes(nodes, patternNode);
253         if (result.size() == 0) {
254             return null;
255         } else {
256             Node JavaDoc node = (Node JavaDoc) result.get(0);
257             nodes.remove(node);
258             return node;
259         }
260     }
261
262     private static List JavaDoc filterNodes(List JavaDoc nodes, Node JavaDoc patternNode) {
263         List JavaDoc trueList = new LinkedList JavaDoc();
264         String JavaDoc name = patternNode.getNodeName();
265         for (Iterator JavaDoc it = nodes.iterator(); it.hasNext();) {
266             Node JavaDoc node = (Node JavaDoc) 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 JavaDoc falseList = new LinkedList JavaDoc();
276         for (Iterator JavaDoc it = trueList.iterator(); it.hasNext();) {
277             Node JavaDoc node = (Node JavaDoc) 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 JavaDoc();
290         String JavaDoc value = patternNode.getNodeValue();
291         for (Iterator JavaDoc it = trueList.iterator(); it.hasNext();) {
292             Node JavaDoc node = (Node JavaDoc) 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 JavaDoc();
305         NamedNodeMap JavaDoc attributes = patternNode.getAttributes();
306         for (Iterator JavaDoc it = trueList.iterator(); it.hasNext();) {
307             Node JavaDoc node = (Node JavaDoc) 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     /**
321      * Test strings for equivalency
322      *
323      * @param s1
324      * @param s2
325      * @return true if they are equivalent, otherwise false
326      */

327     private static boolean equals(String JavaDoc s1, String JavaDoc s2) {
328         return s1 == null ? s2 == null : !(s2 == null) && s1.trim().equals(s2.trim());
329
330     }
331
332     /**
333      * Test attributes for equivalency
334      *
335      * @param attributes1
336      * @param attributes2
337      * @return true if they are equivalent, otherwise false
338      */

339     private static boolean equals(NamedNodeMap JavaDoc attributes1, NamedNodeMap JavaDoc 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 JavaDoc attr1 = attributes1.item(i);
349                 Node JavaDoc 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     /**
359      * Provides list of relevant nodes
360      *
361      * @param nodeList
362      * @return list of relevant nodes
363      */

364     private static List JavaDoc relevantNodes(NodeList JavaDoc nodeList) {
365         List JavaDoc list = new LinkedList JavaDoc();
366         if (nodeList != null) {
367             for (int i = 0; i < nodeList.getLength(); i++) {
368                 Node JavaDoc node = nodeList.item(i);
369                 if (isRelevantNode(node)) {
370                     list.add(node);
371                 }
372             }
373         }
374         return list;
375     }
376
377     /**
378      * Tests whether the node is relevant - not comment nor text node containing white spaces solely
379      *
380      * @param node
381      * @return true if the node is relevant
382      */

383     private static boolean isRelevantNode(Node JavaDoc node) {
384         short type = node.getNodeType();
385         return type != Node.COMMENT_NODE && !isWhiteSpaceNode(node);
386     }
387
388     /**
389      * Tests whether the node contains white spaces solely
390      *
391      * @param node
392      * @return true if node contains only white spaces, otherwise false
393      */

394     private static boolean isWhiteSpaceNode(Node JavaDoc node) {
395         short type = node.getNodeType();
396         return (type == Node.TEXT_NODE && node.getNodeValue().trim().length() == 0);
397     }
398
399     /**
400      * Searches node corresponding to the path
401      * @param bean
402      * @param path
403      * @return the node if found, otherwise null
404      */

405     private static Node JavaDoc findNode(BaseBean bean, String JavaDoc 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 JavaDoc 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     /**
440      * The listener processes property changes caused by adding a new element of graph
441      * Then the new element in DOM binding is properly reformated
442      */

443     public static class ReindentationListener implements PropertyChangeListener JavaDoc {
444         String JavaDoc indent = " ";
445
446         public void propertyChange(PropertyChangeEvent JavaDoc evt) {
447             Object JavaDoc oldValue = evt.getOldValue();
448             Object JavaDoc newValue = evt.getNewValue();
449             if (oldValue == null && newValue != null) {
450                 String JavaDoc path = evt.getPropertyName();
451                 BaseBean bean = (BaseBean) evt.getSource();
452                 Node JavaDoc node = findNode(bean, path);
453                 if (node != null) {
454                     reindentNode(node);
455                 }
456             }
457         }
458
459         private void reindentNode(Node JavaDoc node) {
460             Document JavaDoc document = node.getOwnerDocument();
461             int level = 0;
462             StringBuffer JavaDoc sb = new StringBuffer JavaDoc("\n");
463             for (Node JavaDoc parent = node.getParentNode(); parent != document; parent = parent.getParentNode()) {
464                 level++;
465                 sb.append(indent);
466             }
467             String JavaDoc indentString = sb.toString();
468
469             Node JavaDoc parentNode = node.getParentNode();
470             Node JavaDoc previousNode = node.getPreviousSibling();
471             if (previousNode != null && isWhiteSpaceNode(previousNode)) {
472                 String JavaDoc s = previousNode.getNodeValue();
473                 int i = s.lastIndexOf('\n');
474                 s = i > 0 ? s.substring(0, i) + indentString : indentString;
475                 previousNode.setNodeValue(s); //set proper indent
476
} else {
477                 parentNode.insertBefore(document.createTextNode(indentString), node); //break line
478
}
479             Node JavaDoc nextNode = node.getNextSibling();
480             if (nextNode != null && isWhiteSpaceNode(nextNode)) {
481                 String JavaDoc s = nextNode.getNodeValue();
482                 int i = s.indexOf('\n');
483                 if (i == -1) {
484                     nextNode.setNodeValue(indentString); //set proper indent
485
}
486             } else {
487                 parentNode.insertBefore(document.createTextNode(indentString), nextNode); //break line
488
}
489             XMLUtil.reindent(document, node, level, indent); // reindent the new node
490
}
491
492         public String JavaDoc getIndent() {
493             return indent;
494         }
495
496         public void setIndent(String JavaDoc indent) {
497             this.indent = indent;
498         }
499     }
500 }
501
Popular Tags