001: /*
002: * The contents of this file are subject to the terms of the Common Development
003: * and Distribution License (the License). You may not use this file except in
004: * compliance with the License.
005: *
006: * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
007: * or http://www.netbeans.org/cddl.txt.
008: *
009: * When distributing Covered Code, include this CDDL Header Notice in each file
010: * and include the License file at http://www.netbeans.org/cddl.txt.
011: * If applicable, add the following below the CDDL Header, with the fields
012: * enclosed by brackets [] replaced by your own identifying information:
013: * "Portions Copyrighted [year] [name of copyright owner]"
014: *
015: * The Original Software is NetBeans. The Initial Developer of the Original
016: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
017: * Microsystems, Inc. All Rights Reserved.
018: */
019:
020: package org.netbeans.modules.xslt.mapper.view;
021:
022: import java.util.LinkedList;
023: import java.util.List;
024: import org.netbeans.modules.soa.ui.axinodes.AxiomUtils;
025: import org.netbeans.modules.xml.axi.AXIComponent;
026: import org.netbeans.modules.xml.axi.AXIType;
027: import org.netbeans.modules.xml.axi.AbstractElement;
028: import org.netbeans.modules.xml.xam.dom.AbstractDocumentComponent;
029: import org.netbeans.modules.xml.xpath.LocationStep;
030: import org.netbeans.modules.xml.xpath.XPathCoreFunction;
031: import org.netbeans.modules.xml.xpath.XPathCoreOperation;
032: import org.netbeans.modules.xml.xpath.XPathExpression;
033: import org.netbeans.modules.xml.xpath.XPathExpressionPath;
034: import org.netbeans.modules.xml.xpath.XPathExtensionFunction;
035: import org.netbeans.modules.xml.xpath.XPathLocationPath;
036: import org.netbeans.modules.xml.xpath.XPathPredicateExpression;
037: import org.netbeans.modules.xml.xpath.XPathVariableReference;
038: import org.netbeans.modules.xml.xpath.visitor.AbstractXPathVisitor;
039: import org.netbeans.modules.xslt.mapper.model.PredicatedAxiComponent;
040: import org.netbeans.modules.xslt.model.XslComponent;
041:
042: /**
043: * The visitor is intended to look for predicate expressions
044: * inside of an XPath.
045: *
046: * @author nk160297
047: */
048: public class PredicateFinderVisitor extends AbstractXPathVisitor {
049:
050: private XsltMapper mapper;
051: private XPathLocationPath myLocationPath;
052: private XslComponent contextXslComp;
053:
054: public PredicateFinderVisitor(XsltMapper mapper) {
055: this .mapper = mapper;
056: }
057:
058: public void setContextXslComponent(XslComponent xslc) {
059: contextXslComp = xslc;
060: }
061:
062: //---------------------------------------------------
063:
064: public void visit(XPathLocationPath expr) {
065: myLocationPath = expr;
066: //
067: // if (!expr.getAbsolute()) {
068: // assert false : "Only absolute location pathes are supported now."; // NOI18N
069: // }
070: //
071: LocationPathConverter converter = new LocationPathConverter();
072: converter.processLocationPath(expr.getSteps());
073: }
074:
075: public void visit(XPathExpressionPath expressionPath) {
076: XPathExpression rootExpr = expressionPath.getRootExpression();
077: rootExpr.accept(this );
078: //
079: LocationPathConverter converter = new LocationPathConverter();
080: converter.processLocationPath(expressionPath.getSteps());
081: // assert false : "Variables are not supported in the XSLT mapper yet"; // NOI18N
082: }
083:
084: public void visit(XPathVariableReference vReference) {
085: }
086:
087: //---------------------------------------------------
088:
089: public void visit(XPathCoreOperation expr) {
090: visitChildren(expr);
091: }
092:
093: public void visit(XPathCoreFunction expr) {
094: visitChildren(expr);
095: }
096:
097: public void visit(XPathExtensionFunction expr) {
098: visitChildren(expr);
099: }
100:
101: //---------------------------------------------------
102:
103: /**
104: * See the description of the method "processLocationPath"
105: */
106: private class LocationPathConverter {
107: // The list can contain objects of either AXIComponent
108: // or PredicatedAxiComponent type.
109: private transient LinkedList objLocationPath = new LinkedList();
110: private boolean processingAborted = false;
111:
112: public List getObjLocationPath() {
113: if (processingAborted) {
114: return null;
115: } else {
116: return objLocationPath;
117: }
118: }
119:
120: /**
121: * Resolves each LocationStep to object form and registers new
122: * predicates in the PredicateManager.
123: */
124: public void processLocationPath(LocationStep[] stepArr) {
125: processingAborted = false;
126: //
127: for (LocationStep step : stepArr) {
128: if (!processingAborted) {
129: // ignore attributes. Process only subelements
130: if (LocationStep.AXIS_CHILD == step.getAxis()) {
131: processStep(step);
132: }
133: }
134: }
135: }
136:
137: private void processStep(LocationStep step) {
138: //
139: // Extract the namespace and name of the step
140: String name = "";
141: String namespace = null;
142: //
143: String nameTest = step.getNodeTest().toString();
144: //
145: int pos = nameTest.indexOf(':');
146: //
147: if (pos != -1) {
148: String prefix = nameTest.substring(0, pos);
149: assert contextXslComp != null
150: && contextXslComp instanceof AbstractDocumentComponent;
151: namespace = ((AbstractDocumentComponent) contextXslComp)
152: .lookupNamespaceURI(prefix, true);
153: name = nameTest.substring(pos + 1);
154: } else {
155: namespace = "";
156: name = nameTest;
157: }
158: //
159: // Look for the corresponding child AXIOM component
160: AXIComponent soughtChildComp = null;
161: if (objLocationPath.isEmpty()) {
162: // Need look for a root element
163: AXIComponent rootComp = mapper.getContext()
164: .getSourceType();
165: if (isCorresponding(rootComp, name, namespace)) {
166: soughtChildComp = rootComp;
167: } else {
168: // Error. The location step has inconsistent type
169: processingAborted = true;
170: return;
171: }
172: } else {
173: Object lastPathItem = objLocationPath.getLast();
174: AXIComponent parentAxiComp = null;
175: if (lastPathItem instanceof AXIComponent) {
176: parentAxiComp = (AXIComponent) lastPathItem;
177: } else if (lastPathItem instanceof PredicatedAxiComponent) {
178: parentAxiComp = ((PredicatedAxiComponent) lastPathItem)
179: .getType();
180: } else {
181: // Error. The list can contain only objects of the following types:
182: // AXIComponent, PredicatedAxiComponent.
183: processingAborted = true;
184: return;
185: }
186: //
187: assert parentAxiComp != null;
188: List<AbstractElement> children = parentAxiComp
189: .getChildElements();
190: for (AbstractElement childAxiComp : children) {
191: if (isCorresponding(childAxiComp, name, namespace)) {
192: soughtChildComp = childAxiComp;
193: break;
194: }
195: }
196: }
197: //
198: if (soughtChildComp == null) {
199: // Error. The location path contains a step with unknown AXIOM type
200: // The predicate manager can't continue analysing the path!
201: processingAborted = true;
202: return;
203: }
204: //
205: XPathPredicateExpression[] predArr = step.getPredicates();
206: if (predArr == null || predArr.length == 0) {
207: objLocationPath.add(soughtChildComp);
208: } else {
209: PredicatedAxiComponent newPAxiComp = new PredicatedAxiComponent(
210: soughtChildComp, predArr);
211: //
212: objLocationPath.add(newPAxiComp);
213: //
214: LinkedList currentLocationPathList = new LinkedList();
215: currentLocationPathList.addAll(objLocationPath);
216: //
217: PredicateManager pm = mapper.getPredicateManager();
218: pm.addPredicate(currentLocationPathList);
219: }
220: }
221:
222: /**
223: * Check if the specidied AXIOM component has the specified name and namespace.
224: */
225: private boolean isCorresponding(AXIComponent axiComp,
226: String name, String namespace) {
227: // Extract the namespace and name of the current Tree Node
228: assert axiComp instanceof AXIType;
229: String typeName = ((AXIType) axiComp).getName();
230: String typeNamespace = AxiomUtils.isUnqualified(axiComp) ? ""
231: : axiComp.getTargetNamespace();
232: //
233: if (typeName.equals(name)
234: && namespace.equals(typeNamespace)) {
235: return true;
236: } else {
237: return false;
238: }
239: }
240:
241: }
242:
243: }
|