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-2007 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.bpel.refactoring;
042:
043: import java.util.Collection;
044: import java.util.Iterator;
045: import java.util.LinkedList;
046: import java.util.List;
047: import javax.xml.namespace.QName;
048:
049: import org.netbeans.modules.bpel.model.api.BpelEntity;
050: import org.netbeans.modules.bpel.model.api.BpelModel;
051: import org.netbeans.modules.bpel.model.api.Variable;
052:
053: import org.netbeans.modules.xml.schema.model.Choice;
054: import org.netbeans.modules.xml.schema.model.ComplexContent;
055: import org.netbeans.modules.xml.schema.model.ComplexContentDefinition;
056: import org.netbeans.modules.xml.schema.model.ComplexExtension;
057: import org.netbeans.modules.xml.schema.model.ComplexType;
058: import org.netbeans.modules.xml.schema.model.ComplexTypeDefinition;
059: import org.netbeans.modules.xml.schema.model.Element;
060: import org.netbeans.modules.xml.schema.model.ElementReference;
061: import org.netbeans.modules.xml.schema.model.GlobalType;
062: import org.netbeans.modules.xml.schema.model.LocalAttribute;
063: import org.netbeans.modules.xml.schema.model.LocalElement;
064: import org.netbeans.modules.xml.schema.model.Sequence;
065: import org.netbeans.modules.xml.schema.model.SequenceDefinition;
066: import org.netbeans.modules.xml.schema.model.SimpleType;
067: import org.netbeans.modules.xml.schema.model.TypeContainer;
068: import org.netbeans.modules.xml.schema.model.visitor.DeepSchemaVisitor;
069:
070: import org.netbeans.modules.xml.wsdl.model.Message;
071: import org.netbeans.modules.xml.wsdl.model.Part;
072: import org.netbeans.modules.xml.xam.Component;
073: import org.netbeans.modules.xml.xam.Named;
074: import org.netbeans.modules.xml.xam.dom.NamedComponentReference;
075:
076: import org.netbeans.modules.xml.xpath.AbstractXPathModelHelper;
077: import org.netbeans.modules.xml.xpath.LocationStep;
078: import org.netbeans.modules.xml.xpath.StepNodeNameTest;
079: import org.netbeans.modules.xml.xpath.XPathCoreFunction;
080: import org.netbeans.modules.xml.xpath.XPathCoreOperation;
081: import org.netbeans.modules.xml.xpath.XPathException;
082: import org.netbeans.modules.xml.xpath.XPathExpression;
083: import org.netbeans.modules.xml.xpath.XPathExpressionPath;
084: import org.netbeans.modules.xml.xpath.XPathExtensionFunction;
085: import org.netbeans.modules.xml.xpath.XPathLocationPath;
086: import org.netbeans.modules.xml.xpath.XPathModel;
087: import org.netbeans.modules.xml.xpath.XPathPredicateExpression;
088: import org.netbeans.modules.xml.xpath.XPathVariableReference;
089: import org.netbeans.modules.xml.xpath.visitor.AbstractXPathVisitor;
090: import static org.netbeans.modules.soa.ui.util.UI.*;
091:
092: /**
093: * @author Vladimir Yaroslavskiy
094: * @version 2006.06.30
095: */
096: final class XPath extends AbstractXPathVisitor {
097:
098: XPath(List<Component> usage, Named target, String oldName) {
099: myOldName = oldName;
100: myTarget = target;
101: myUsage = usage;
102: }
103:
104: void visit(String content, Component component) {
105: //out();
106: //out("XPATH visit: " + content);
107: //out("XPATH visit: '" + content + "' " + component);
108: visit(content, component, false);
109: }
110:
111: String rename(String content, Component component) {
112: //out();
113: //out("XPATH rename");
114: return visit(content, component, true);
115: }
116:
117: private String visit(String content, Component component,
118: boolean doRename) {
119: if (content == null || content.length() == 0) {
120: return content;
121: }
122: //out();
123: //out("visit: " + content);
124: XPathModel model = AbstractXPathModelHelper.getInstance()
125: .newXPathModel();
126: myVisitedComplexType = new LinkedList<ComplexType>();
127: myExpressions = new LinkedList<XPathExpression>();
128: myComponent = component;
129: myDoRename = doRename;
130:
131: try {
132: XPathExpression expression = model.parseExpression(content);
133: expression.accept(this );
134: //out();
135: //out();
136: if (myDoRename) {
137: //out(" do rename: " + myTarget.getName());
138: rename(myTarget.getName());
139: }
140: //out(" new content: " + expression.getExpressionString());
141: return expression.getExpressionString();
142: } catch (XPathException e) {
143: //out(" !!!! exception: " + e.getMessage());
144: return content;
145: }
146: }
147:
148: private void rename(String newName) {
149: //out();
150: //out("----------------------------------");
151: //out();
152: //out("To rename:");
153:
154: for (XPathExpression expression : myExpressions) {
155: //out("See: " + expression);
156: if (expression instanceof LocationStep) {
157: LocationStep step = (LocationStep) expression;
158: step.setNodeTest(new StepNodeNameTest(createName(step
159: .getString(), newName)));
160: } else if (expression instanceof XPathVariableReference) {
161: XPathVariableReference reference = (XPathVariableReference) expression;
162: reference.setVariableName(createName(reference
163: .getVariableName(), newName));
164: }
165: }
166: //out();
167: //out("----------------------------------");
168: //out();
169: }
170:
171: private String createName(String oldName, String newName) {
172: int k = oldName.indexOf(":"); // NOI18N
173:
174: if (k == -1) {
175: return newName;
176: }
177: return oldName.substring(0, k + 1) + newName;
178: }
179:
180: private String createName(QName qName, String part) {
181: String name = qName.getLocalPart();
182: int k = name.indexOf("."); // NOI18N
183:
184: if (k == -1) {
185: return name;
186: }
187: return name.substring(0, k + 1) + part;
188: }
189:
190: @Override
191: public void visit(XPathExpressionPath expressionPath) {
192: //out();
193: //out("EXPRESION: " + expressionPath);
194: XPathExpression rootExpression = expressionPath
195: .getRootExpression();
196: myVariable = null;
197: myVariableReference = null;
198:
199: if (!expressionPath.equals(rootExpression)) {
200: //out(" root: " + rootExpression);
201: rootExpression.accept(this );
202: }
203: if (myVariable == null) {
204: //out("Variable is not found");
205: return;
206: }
207: //out("Variable: " + myVariable.getName());
208:
209: if (myVariable == myTarget) {
210: //out(" variable is target: " + myVariable.getName());
211: return;
212: }
213: LocationStep[] locations = expressionPath.getSteps();
214: List<LocationStep> steps = new LinkedList<LocationStep>();
215: steps.add(null); // first step is fake
216:
217: if (locations == null) {
218: return;
219: }
220: for (LocationStep location : locations) {
221: steps.add(location);
222: }
223: visit(steps);
224: visit(locations);
225: }
226:
227: private void visit(LocationStep[] locations) {
228: if (locations == null) {
229: return;
230: }
231: for (LocationStep location : locations) {
232: location.accept(this );
233: }
234: }
235:
236: private void visit(List<LocationStep> steps) {
237: visitReference(myVariable.getMessageType(), createList(steps),
238: ""); // NOI18N
239: visitReference(myVariable.getElement(), createList(steps), ""); // NOI18N
240: visitReference(myVariable.getType(), createList(steps), ""); // NOI18N
241: }
242:
243: private List<LocationStep> createList(List<LocationStep> steps) {
244: List<LocationStep> list = new LinkedList<LocationStep>();
245:
246: for (LocationStep step : steps) {
247: list.add(step);
248: }
249: return list;
250: }
251:
252: private void visitPart(Part part, List<LocationStep> steps) {
253: visitReference(part.getElement(), createList(steps), ""); // NOI18N
254: visitReference(part.getType(), createList(steps), ""); // NOI18N
255: }
256:
257: private void visitReference(NamedComponentReference reference,
258: List<LocationStep> steps, String indent) {
259: if (reference != null) {
260: visitComponent(reference.get(), steps, indent);
261: }
262: }
263:
264: private void visitComponent(Object object,
265: List<LocationStep> steps, String indent) {
266: if (object instanceof ComplexType) {
267: //out(" visit complex");
268: visitComplexType((ComplexType) object, steps, indent);
269: } else if (object instanceof SimpleType) {
270: //out(" visit simple");
271: visitSimpleType((SimpleType) object, steps, indent);
272: } else if (object instanceof Element) {
273: visitElement((Element) object, steps, indent);
274: } else if (object instanceof Message) {
275: visitMessage((Message) object, steps, indent);
276: } else {
277: if (object == null) {
278: return;
279: }
280: //out(indent + " unknown !!!: " + object);
281: }
282: }
283:
284: private void visitMessage(Message message,
285: List<LocationStep> steps, String indent) {
286: Iterator<Part> parts = message.getParts().iterator();
287:
288: while (parts.hasNext()) {
289: Part part = parts.next();
290: //out();
291: //out(" see part: " + part.getName());
292: //out(" part: " + myPartName);
293: if (part.equals(myTarget)) {
294: addItem();
295:
296: if (myDoRename) {
297: myExpressions.add(myVariableReference);
298: }
299: }
300: if (myPartName.equals(part.getName())) {
301: //out("==== PART: " + myPartName);
302: //out();
303: visitPart(part, createList(steps));
304: }
305: }
306: }
307:
308: private void visitElement(Element element,
309: List<LocationStep> steps, String indent) {
310: //out(indent + "ELEMENT: " + Util.getName(element));
311: if (checkUsages(element, steps, false)) {
312: return;
313: }
314: myTypeReference = null;
315:
316: element.accept(new DeepSchemaVisitor() {
317: @Override
318: public void visit(ComplexExtension extension) {
319: myTypeReference = extension.getBase();
320: }
321: });
322: visitReference(myTypeReference, steps, indent + INDENT);
323:
324: if (element instanceof TypeContainer) {
325: TypeContainer container = (TypeContainer) element;
326:
327: visitReference(container.getType(), createList(steps),
328: indent + INDENT);
329:
330: visitComponent(container.getInlineType(),
331: createList(steps), indent + INDENT);
332: }
333: }
334:
335: private void visitComplexType(ComplexType type,
336: List<LocationStep> steps, String indent) {
337: //out(indent + "COMPLEX.TYPE: " + Util.getName(type));
338: if (myVisitedComplexType.contains(type)) {
339: return;
340: }
341: myVisitedComplexType.add(type);
342:
343: if (checkUsages(type, steps, true)) {
344: return;
345: }
346: ComplexTypeDefinition definition = type.getDefinition();
347:
348: if (definition instanceof Sequence) {
349: visitSequence((Sequence) definition, steps, indent + INDENT);
350: } else if (definition instanceof Choice) {
351: visitChoice((Choice) definition, steps, indent);
352: } else if (definition instanceof ComplexContent) {
353: visitComplexContent((ComplexContent) definition, steps,
354: indent);
355: }
356: // else {
357: //out(indent + "unknown !!: " + definition);
358: // }
359: Collection<LocalAttribute> attributes = type
360: .getLocalAttributes();
361:
362: for (LocalAttribute attribute : attributes) {
363: visitAttribute(attribute, steps, indent);
364: }
365: }
366:
367: private void visitAttribute(LocalAttribute attribute,
368: List<LocationStep> steps, String indent) {
369: //out(indent + "ATTRIBUTE: " + Util.getName(attribute));
370: checkUsages(attribute, steps, true);
371: }
372:
373: private void visitComplexContent(ComplexContent content,
374: List<LocationStep> steps, String indent) {
375: ComplexContentDefinition definition = content
376: .getLocalDefinition();
377:
378: if (definition instanceof ComplexExtension) {
379: visitReference(((ComplexExtension) definition).getBase(),
380: steps, indent);
381: }
382: }
383:
384: private void visitChoice(Choice choice, List<LocationStep> steps,
385: String indent) {
386: //out(indent + " [choice] ===================");
387: Iterator<Choice> choices = choice.getChoices().iterator();
388:
389: while (choices.hasNext()) {
390: visitChoice(choices.next(), createList(steps), indent
391: + INDENT);
392: }
393: Iterator<Sequence> sequences = choice.getSequences().iterator();
394:
395: while (sequences.hasNext()) {
396: visitSequence(sequences.next(), createList(steps), indent
397: + INDENT);
398: }
399: Iterator<LocalElement> elements = choice.getLocalElements()
400: .iterator();
401:
402: while (elements.hasNext()) {
403: visitElement(elements.next(), createList(steps), indent
404: + INDENT);
405: }
406: Iterator<ElementReference> references = choice
407: .getElementReferences().iterator();
408:
409: while (references.hasNext()) {
410: visitReference(references.next().getRef(),
411: createList(steps), indent + INDENT);
412: }
413: //out(indent + " [===========================");
414: }
415:
416: private void visitSequence(Sequence sequence,
417: List<LocationStep> steps, String indent) {
418: //out(indent + " [sequnce] ==================");
419: List<SequenceDefinition> content = sequence.getContent();
420:
421: if (content == null) {
422: return;
423: }
424: for (SequenceDefinition definition : content) {
425: ////out(indent + " see: " + Util.getName(definition));
426: if (definition instanceof Element) {
427: visitElement((Element) definition, createList(steps),
428: indent + INDENT);
429: } else if (definition instanceof ComplexType) {
430: visitComplexType((ComplexType) definition,
431: createList(steps), indent + INDENT);
432: } else if (definition instanceof SimpleType) {
433: visitSimpleType((SimpleType) definition,
434: createList(steps), indent + INDENT);
435: } else if (definition instanceof ElementReference) {
436: visitReference(
437: ((ElementReference) definition).getRef(),
438: createList(steps), indent + INDENT);
439: } else {
440: //out(indent + " error !!!: " + definition);
441: return;
442: }
443: }
444: //out(indent + " [===========================");
445: }
446:
447: private void visitSimpleType(SimpleType type,
448: List<LocationStep> steps, String indent) {
449: //out(indent + "SIMPLE.TYPE: " + Util.getName(type));
450: checkUsages(type, steps, true);
451: }
452:
453: @Override
454: public void visit(XPathVariableReference reference) {
455: QName qName = reference.getVariableName();
456: //out("VAR REFER: " + qName);
457: String name = qName.getLocalPart();
458: String part = ""; // NOI18N
459: int k = name.indexOf("."); // NOI18N
460:
461: if (k != -1) {
462: part = name.substring(k + 1);
463: name = name.substring(0, k);
464: }
465: if (!(myComponent instanceof BpelEntity)) {
466: return;
467: }
468: Variable[] variables = ((BpelModel) ((BpelEntity) myComponent)
469: .getModel()).getProcess().getVariableContainer()
470: .getVariables();
471:
472: if (variables == null) {
473: return;
474: }
475: for (Variable variable : variables) {
476: //out(" see: " + variable.getName());
477:
478: if (variable.getName().equals(name)) {
479: //out(" this.");
480: myVariable = variable;
481: myVariableReference = reference;
482: myPartName = part;
483:
484: if (myVariable == myTarget) {
485: //out(" add variable: " + myVariable.getName());
486: addItem();
487: }
488: break;
489: }
490: }
491: }
492:
493: @Override
494: public void visit(LocationStep locationStep) {
495: //out("=== LOCATION STEP: " + locationStep);
496: XPathPredicateExpression[] predicates = locationStep
497: .getPredicates();
498: //out(" predicates: " + predicates);
499:
500: if (predicates == null) {
501: return;
502: }
503: for (XPathPredicateExpression predicate : predicates) {
504: predicate.accept(this );
505: }
506: }
507:
508: @Override
509: public void visit(XPathCoreFunction coreFunction) {
510: //out("CORE FUNC: " + coreFunction);
511: visitChildren(coreFunction);
512: }
513:
514: @Override
515: public void visit(XPathCoreOperation coreOperation) {
516: //out("CORE OPER: " + coreOperation);
517: visitChildren(coreOperation);
518: }
519:
520: @Override
521: public void visit(XPathExtensionFunction extensionFunction) {
522: //out("EXT FUNC: " + extensionFunction);
523: visitChildren(extensionFunction);
524: }
525:
526: @Override
527: public void visit(XPathLocationPath locationPath) {
528: //out("LOCAL PATH: " + locationPath);
529: visit(locationPath.getSteps());
530: }
531:
532: private boolean checkUsages(Component component,
533: List<LocationStep> steps, boolean nextStep) {
534: if (component == null) {
535: return false;
536: }
537: //out();
538: //out(" chk compnt: "+ Util.getName(component));
539: //out(" target: "+ myTarget.getName());
540: //out(" step: "+ (steps.size() == 0 ? null : steps.get(0)));
541:
542: if (steps.size() == 0) {
543: //out(" size: 0");
544: //out(" return: false");
545: //out();
546: return false;
547: }
548: LocationStep step = steps.get(0);
549:
550: if (myTarget.equals(component)) {
551: //out();
552: //out("name: " + myOldName);
553: //out("step: " + step.getString());
554: if (step != null
555: && equalsIgnorePrefixAndAmpersand(myOldName, step
556: .getString())) {
557: addItem();
558:
559: if (myDoRename) {
560: myExpressions.add(step);
561: //out("!! ==== STEP: " + step.getString());
562: }
563: //out(" return: true");
564: //out();
565: return true;
566: }
567: } else {
568: if (nextStep) {
569: //out(" remove: " + step);
570: steps.remove(0);
571: }
572: }
573: //out(" return: false");
574: //out();
575: return false;
576: }
577:
578: private boolean equalsIgnorePrefixAndAmpersand(String name,
579: String step) {
580: if (name == null || step == null) {
581: return false;
582: }
583: if (step.startsWith("@")) {
584: step = step.substring(1);
585: }
586: int k = step.indexOf(":"); // NOI18N
587:
588: if (k == -1) {
589: return name.equals(step);
590: }
591: return name.equals(step.substring(k + 1));
592: }
593:
594: private void addItem() {
595: if (myUsage != null) {
596: myUsage.add(myComponent);
597: //out("!! ===== ADD: " + Util.getName(myComponent));
598: }
599: }
600:
601: private Named myTarget;
602: private String myOldName;
603: private String myPartName;
604: private boolean myDoRename;
605: private Variable myVariable;
606: private Component myComponent;
607: private List<XPathExpression> myExpressions;
608: private List<ComplexType> myVisitedComplexType;
609: private XPathVariableReference myVariableReference;
610: private NamedComponentReference<GlobalType> myTypeReference;
611: private List<Component> myUsage;
612: private static final String INDENT = " "; // NOI18N
613: }
|