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: package org.netbeans.modules.xslt.mapper.view;
020:
021: import java.util.List;
022: import org.netbeans.modules.soa.mapper.common.IMapperLink;
023: import org.netbeans.modules.soa.mapper.common.IMapperNode;
024: import org.netbeans.modules.soa.mapper.common.basicmapper.IBasicViewModel;
025: import org.netbeans.modules.soa.mapper.common.basicmapper.methoid.IFieldNode;
026: import org.netbeans.modules.soa.mapper.common.basicmapper.methoid.IMethoid;
027: import org.netbeans.modules.soa.mapper.common.basicmapper.methoid.IMethoidNode;
028: import org.netbeans.modules.soa.mapper.common.basicmapper.tree.IMapperTreeNode;
029: import org.netbeans.modules.xml.xpath.XPathExpression;
030: import org.netbeans.modules.xml.xpath.XPathOperationOrFuntion;
031: import org.netbeans.modules.xslt.mapper.model.BuildExpressionVisitor;
032: import org.netbeans.modules.xslt.mapper.model.nodes.LiteralCanvasNode;
033: import org.netbeans.modules.xslt.mapper.model.nodes.Node;
034: import org.netbeans.modules.xslt.mapper.model.nodes.TreeNode;
035: import org.netbeans.modules.xslt.mapper.model.targettree.StylesheetNode;
036: import org.netbeans.modules.xslt.model.XslComponent;
037: import org.netbeans.modules.xslt.model.XslComponent;
038:
039: /**
040: *
041: * @author Alexey
042: */
043: public class DiagramBuilder {
044:
045: boolean updating = false;
046: private XsltMapper mapper;
047: private boolean relayoutRequired;
048: private PredicateFinderVisitor pfv;
049:
050: public DiagramBuilder(XsltMapper mapper) {
051: this .mapper = mapper;
052: pfv = new PredicateFinderVisitor(mapper);
053: }
054:
055: public void updateDiagram(boolean reuse) {
056: TreeNode root = (TreeNode) mapper.getMapperViewManager()
057: .getDestView().getTree().getModel().getRoot();
058:
059: if (root != null) {
060: relayoutRequired = false;
061: try {
062: updating = true;
063: updateDiagramRecursive(root, reuse);
064: } finally {
065: updating = false;
066: }
067: if (relayoutRequired) {
068: //this flag indicates that at least 1 node was added to diagram
069: mapper.getMapperViewManager().getCanvasView()
070: .getAutoLayout().autoLayout();
071: }
072: }
073: //
074: // Remove old automatically created predicates.
075: mapper.getPredicateManager().clearTemporaryPredicates();
076: }
077:
078: public boolean isUpdating() {
079: return this .updating;
080: }
081:
082: /**
083: * Detects if given target tree node contains xpath expression.
084: * If so, builds expression node graph starting from this tree node
085: **/
086: public void updateDiagram(TreeNode tree_node, boolean reuse) {
087:
088: Object data = tree_node.getDataObject();
089:
090: if (!(data instanceof XslComponent)) {
091: return;
092: }
093:
094: XslComponent xslc = (XslComponent) data;
095:
096: GetExpressionVisitor visitor_ge = new GetExpressionVisitor();
097:
098: xslc.accept(visitor_ge);
099: XPathExpression new_expr = visitor_ge.getExpression();
100:
101: // Look for predicates in the specified XPath expression
102: if (new_expr != null) {
103: pfv.setContextXslComponent(xslc);
104: new_expr.accept(pfv);
105: }
106:
107: //first check, if current node is already connected to any graph
108: List<Node> upstreams = tree_node.getPreviousNodes();
109:
110: XPathExpression current_expr = null;
111:
112: if (reuse) {
113: if (!upstreams.isEmpty() && reuse) {
114: Node upstream = upstreams.get(0);
115: if (upstream != null) {
116: BuildExpressionVisitor visitor_be = new BuildExpressionVisitor(
117: mapper.getContext());
118:
119: upstream.accept(visitor_be);
120: current_expr = visitor_be.getResult();
121: }
122: }
123:
124: if (current_expr != null) {
125: if (new_expr == null
126: || !current_expr.toString().equals(
127: new_expr.toString())) {
128: destroyDiagramRecursive(tree_node);
129: }
130: }
131: } else {
132: destroyDiagramRecursive(tree_node);
133: }
134:
135: if (new_expr != null) {
136: if (current_expr == null
137: || !new_expr.toString().equals(
138: current_expr.toString())) {
139:
140: relayoutRequired = true;
141:
142: Node graph_root = buildDiagramRecursive(new_expr);
143: if (graph_root != null) {
144: mapper.addLink(graph_root, tree_node);
145: }
146: }
147: }
148: }
149:
150: public void destroyDiagramRecursive(Node node) {
151:
152: List<Node> upstreams = node.getPreviousNodes();
153:
154: for (Node upstream : upstreams) {
155: if (upstream == null) {
156: continue;
157: }
158:
159: IBasicViewModel model = mapper.getMapperViewManager()
160: .getMapperModel().getSelectedViewModel();
161:
162: mapper.removeDirectedChain(upstream.getMapperNode(), model);
163: }
164:
165: List links = node.getMapperNode().getLinks();
166: for (int i = 0; i < links.size(); i++) {
167: mapper.removeLink((IMapperLink) links.get(i));
168: }
169:
170: // List<Node> upstreams = node.getPreviousNodes();
171: // List links = node.getOutputNode().getLinks();
172: //
173: // mapper.removeNode(node.getMapperNode());
174: // for(Object link: links){
175: // mapper.removeLink((IMapperLink) link);
176: // }
177: // for (Node upstream: upstreams){
178: // destroyDiagramRecursive(upstream);
179: // }
180: //
181: }
182:
183: /**
184: * Perform recursion deep into expression.
185: * Create mapper nodes for all subexpressions and add them to canvas
186: **/
187: private Node buildDiagramRecursive(XPathExpression expression) {
188: NodeCreatorVisitor visitor_cn = new NodeCreatorVisitor(mapper);
189:
190: expression.accept(visitor_cn);
191:
192: Node node = visitor_cn.getResult();
193:
194: if (node == null) {
195: return null;
196: }
197:
198: IMapperNode mapper_node = (IMapperNode) node.getMapperNode();
199:
200: if (!(mapper_node instanceof IMapperTreeNode)) {
201: mapper.addNode(mapper_node);
202: //hack required by stupid Mapper framework.
203: //aaddNode resets the literalName.
204: if (node instanceof LiteralCanvasNode) {
205: IFieldNode field0 = (IFieldNode) node.getOutputNode();
206: field0.setLiteralName(expression.toString());
207: }
208:
209: if (mapper_node instanceof IMethoidNode
210: && expression instanceof XPathOperationOrFuntion) {
211: IMethoidNode methoidNode = (IMethoidNode) mapper_node;
212: IMethoid methoid = (IMethoid) methoidNode
213: .getMethoidObject();
214: boolean isAccumulative = methoid.isAccumulative();
215: int fieldIndex = 0;
216: //
217: for (Object expr : ((XPathOperationOrFuntion) expression)
218: .getChildren()) {
219: List inputFields = methoidNode.getInputFieldNodes();
220: if (fieldIndex >= inputFields.size()) {
221: break;
222: }
223: IFieldNode fn = (IFieldNode) inputFields
224: .get(fieldIndex);
225: assert fn != null : "Filed shouldn't be null anyway"; // NOI18N
226: if (!expr.toString().startsWith(
227: BuildExpressionVisitor.UNCONNECTED_INPUT)) {
228: Node upstream_node = buildDiagramRecursive((XPathExpression) expr);
229:
230: fn.setNodeObject(upstream_node);
231:
232: if (upstream_node != null) {
233: mapper.addLink(upstream_node, node);
234: }
235: }
236: fieldIndex++;
237: }
238: }
239: }
240: return node;
241: }
242:
243: private boolean methoidHasField(IMethoidNode methoidNode,
244: String fieldName) {
245: for (Object fieldObj : methoidNode.getInputFieldNodes()) {
246: if (fieldObj instanceof IFieldNode) {
247: IFieldNode tempFieldNode = (IFieldNode) fieldObj;
248: String tempFieldName = tempFieldNode.getName();
249: if (fieldName.equals(tempFieldName)) {
250: return true;
251: }
252: }
253: }
254: return false;
255: }
256:
257: /**
258: * Iterates over target tree nodes
259: * calls updateDiagram() for each node
260: **/
261: private void updateDiagramRecursive(TreeNode node, boolean reuse) {
262: if (node instanceof StylesheetNode) {
263: updateDiagram(node, reuse);
264: for (TreeNode n : node.getChildren()) {
265: updateDiagramRecursive(n, reuse);
266: }
267: }
268: }
269: }
|