001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package org.netbeans.modules.xml.axi.util;
042:
043: import java.io.FileReader;
044: import java.net.URL;
045: import java.util.ArrayList;
046: import java.util.Collection;
047: import java.util.Iterator;
048: import javax.xml.xpath.XPath;
049: import javax.xml.xpath.XPathConstants;
050: import javax.xml.xpath.XPathFactory;
051: import org.netbeans.modules.xml.axi.AXIComponent;
052: import org.netbeans.modules.xml.axi.AXIDocument;
053: import org.netbeans.modules.xml.axi.AnyAttribute;
054: import org.netbeans.modules.xml.axi.Attribute;
055: import org.netbeans.modules.xml.axi.Element;
056: import org.netbeans.modules.xml.axi.visitor.PrintAXITreeVisitor;
057: import org.w3c.dom.Node;
058: import org.w3c.dom.NodeList;
059: import org.xml.sax.InputSource;
060:
061: /**
062: * Test visitor to visit all children in the AXI tree.
063: * @author Samaresh
064: */
065: public class ModelValidator extends PrintAXITreeVisitor {
066:
067: private String errorMessage;
068: private boolean success;
069: private URL expectedFileURL;
070: private FileReader expectedFileReader;
071:
072: /**
073: * Creates a new instance of AXITreeVisitor
074: */
075: public ModelValidator(URL url) {
076: this .success = true;
077: this .expectedFileURL = url;
078: }
079:
080: public boolean visitAndCompareAgainstDOMElement(Element element) {
081: this .visit(element);
082: return success;
083: }
084:
085: public void visit(Attribute attr) {
086: //do nothing
087: }
088:
089: public void visit(AnyAttribute attr) {
090: //do nothing
091: }
092:
093: protected void visitChildren(AXIComponent component) {
094: if (canCompare()) {
095: if (!compare(component))
096: return;
097: }
098: super .visitChildren(component);
099: }
100:
101: public String getErrorMessage() {
102: return errorMessage;
103: }
104:
105: private boolean canCompare() {
106: if (expectedFileURL == null)
107: return false;
108:
109: return true;
110: }
111:
112: /**
113: * Compares AXI component against corresponding DOM element.
114: */
115: private boolean compare(AXIComponent axiNode) {
116: FileUtil util = FileUtil.getInstance();
117: try {
118: InputSource inputSource = util.openFile(expectedFileURL);
119: if (inputSource == null) {
120: success = false;
121: return false;
122: }
123: String expression = getExpression(axiNode);
124: XPath xpath = XPathFactory.newInstance().newXPath();
125: Node domNode = (Node) xpath.evaluate(expression,
126: inputSource, XPathConstants.NODE);
127: if (!axiNode.toString().equals(domNode.getNodeName())) {
128: success = false;
129: errorMessage = "Expected AXI node " + axiNode
130: + ", but found DOM node "
131: + domNode.getNodeName();
132: return false;
133: }
134:
135: if (!compareChildren(axiNode, domNode)) {
136: return false;
137: }
138:
139: } catch (Exception ex) {
140: ex.printStackTrace();
141: success = false;
142: errorMessage = "Exception: " + ex.getMessage();
143: return false;
144: } finally {
145: util.closeFile();
146: }
147:
148: return true;
149: }
150:
151: /**
152: * Compares each child of an AXI component against
153: * corresponding DOM element's child.
154: */
155: private boolean compareChildren(AXIComponent axiNode, Node domNode) {
156: //compare sizes
157: Collection<AXIComponent> axiChildren = getChildren(axiNode);
158: Collection<Node> domChildren = getChildren(domNode);
159: if (axiChildren.size() != domChildren.size()) {
160: success = false;
161: errorMessage = "For AXI node " + axiNode
162: + ", expected child count is " + axiChildren.size()
163: + " where as, actual count is "
164: + domChildren.size();
165: return success;
166: }
167:
168: Collection<Attribute> attrs = axiNode
169: .getChildren(Attribute.class);
170: if (attrs.size() != domNode.getAttributes().getLength()) {
171: success = false;
172: errorMessage = "For AXI node " + axiNode
173: + ", expected attribute count is " + attrs.size()
174: + " where as, actual count is "
175: + domNode.getAttributes().getLength();
176: return success;
177: }
178:
179: Iterator<AXIComponent> axiIterator = axiChildren.iterator();
180: Iterator<Node> domIterator = domChildren.iterator();
181: while (axiIterator.hasNext() && domIterator.hasNext()) {
182: AXIComponent axiChild = axiIterator.next();
183: Node domChild = domIterator.next();
184: if (!axiChild.toString().equals(domChild.getNodeName())) {
185: success = false;
186: errorMessage = "For AXI node " + axiNode
187: + ", expecting child " + axiChild
188: + " where as, found child "
189: + domChild.getNodeName();
190: return success;
191: }
192: }
193:
194: return true;
195: }
196:
197: private String getExpression(AXIComponent component) {
198: if (component.getParent() instanceof AXIDocument)
199: return "/" + component;
200:
201: return getExpression(component.getParent()) + "/" + component;
202: }
203:
204: private Collection<Node> getChildren(Node node) {
205: Collection<Node> nodes = new ArrayList<Node>();
206: NodeList children = node.getChildNodes();
207: for (int i = 0; i < children.getLength(); i++) {
208: Node child = children.item(i);
209: if (child.getNodeType() != Node.ELEMENT_NODE)
210: continue;
211: nodes.add(child);
212: }
213: return nodes;
214: }
215:
216: private Collection<AXIComponent> getChildren(AXIComponent component) {
217: Collection<AXIComponent> children = new ArrayList<AXIComponent>();
218: for (AXIComponent child : component.getChildren()) {
219: if (child instanceof Attribute)
220: continue;
221: children.add(child);
222: }
223: return children;
224: }
225:
226: }
|