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.bpel.model.api.support;
020:
021: import java.util.ArrayList;
022: import java.util.HashSet;
023: import java.util.Iterator;
024: import java.util.LinkedList;
025: import java.util.List;
026: import java.util.ListIterator;
027: import java.util.Set;
028: import org.netbeans.modules.bpel.model.api.ActivityHolder;
029: import org.netbeans.modules.bpel.model.api.BaseScope;
030: import org.netbeans.modules.bpel.model.api.Process;
031: import org.netbeans.modules.bpel.model.api.BpelEntity;
032: import org.netbeans.modules.bpel.model.api.CompositeActivity;
033: import org.netbeans.modules.bpel.model.api.ExtendableActivity;
034: import org.netbeans.modules.bpel.model.api.Scope;
035: import org.netbeans.modules.bpel.model.api.Variable;
036: import org.netbeans.modules.bpel.model.api.VariableContainer;
037: import org.netbeans.modules.bpel.model.api.VariableDeclaration;
038: import org.netbeans.modules.bpel.model.api.VariableDeclarationScope;
039: import org.netbeans.modules.bpel.model.spi.FindHelper;
040: import org.openide.util.Lookup;
041:
042: /**
043: * Describes a visibility scope for a bpel element.
044: * There are 2 different kind of visibility scope: for activities and for variables.
045: * Activities are visible inside of Scope elements.
046: * Variables are visible inside of VariableDeclarationScope elements.
047: * The visibility scope is the chain of such elements. This chain is calculated
048: * relative the certain target BPEL element and defines the containers
049: * with elements visible to the target element.
050: * <p>
051: * The Scopes has particular order in the chain.
052: * The first element of visibility zone is the Process.
053: * The most nested scope is at the end of the chain.
054: *
055: * ATTENTION!
056: * TODO: It necessary to check if using of this class is safe.
057: * The matter is that the scope list is cached here and can be chenged after it.
058: * So the cached value can be obsolete.
059: *
060: * @author nk160297
061: */
062: public class VisibilityScope {
063:
064: /**
065: * This model element has been used to construct the current instance
066: */
067: private BpelEntity baseModelElement;
068:
069: private List<BaseScope> myScopeList;
070: private List<VariableDeclarationScope> myVarScopeList;
071:
072: public VisibilityScope(BpelEntity modelElement, Lookup lookup) {
073: baseModelElement = modelElement;
074: }
075:
076: public VisibilityScope(BpelEntity modelElement) {
077: baseModelElement = modelElement;
078: }
079:
080: private void calculateScopeList(final BpelEntity modelElement) {
081: myScopeList = new LinkedList<BaseScope>();
082: FindHelper helper = (FindHelper) Lookup.getDefault().lookup(
083: FindHelper.class);
084: Iterator<BaseScope> itr = helper.scopeIterator(modelElement);
085: while (itr.hasNext()) {
086: BaseScope baseScope = itr.next();
087: // Put new element to the top of list to provide the sorting contract.
088: myScopeList.add(0, baseScope);
089: }
090: //
091: if (modelElement instanceof Process && myScopeList.isEmpty()) {
092: myScopeList.add((BaseScope) modelElement);
093: }
094: }
095:
096: private void calculateVarScopeList(final BpelEntity modelElement) {
097: myVarScopeList = new LinkedList<VariableDeclarationScope>();
098: FindHelper helper = (FindHelper) Lookup.getDefault().lookup(
099: FindHelper.class);
100: Iterator<VariableDeclarationScope> itr = helper
101: .varaibleDeclarationScopes(modelElement);
102: while (itr.hasNext()) {
103: VariableDeclarationScope vdScope = itr.next();
104: // Put new element to the top of list to provide the sorting contract.
105: myVarScopeList.add(0, vdScope);
106: }
107: //
108: if (modelElement instanceof Process && myVarScopeList.isEmpty()) {
109: myVarScopeList.add((BaseScope) modelElement);
110: }
111: }
112:
113: /**
114: * Returns the Bpel element relative to which the visibility scope was constructed.
115: */
116: public BpelEntity getBaseModelElement() {
117: return baseModelElement;
118: }
119:
120: public List<BaseScope> getScopeChain() {
121: if (myScopeList == null) {
122: calculateScopeList(baseModelElement);
123: }
124: return myScopeList;
125: }
126:
127: public BaseScope getClosestScope() {
128: List<BaseScope> scopeList = getScopeChain();
129: assert !scopeList.isEmpty() : "The VisibilityScope should never be empty";
130: return scopeList.get(scopeList.size() - 1);
131: }
132:
133: public List<VariableDeclarationScope> getVarScopeChain() {
134: if (myVarScopeList == null) {
135: calculateVarScopeList(baseModelElement);
136: }
137: return myVarScopeList;
138: }
139:
140: public VariableDeclarationScope getClosestVarScope() {
141: List<VariableDeclarationScope> varScopeList = getVarScopeChain();
142: assert !varScopeList.isEmpty() : "The VisibilityScope should never be empty";
143: return varScopeList.get(varScopeList.size() - 1);
144: }
145:
146: /**
147: * Looks for a variable by name in the visibility scope
148: * @param varName
149: * @return variable or null
150: */
151: public VariableDeclaration lookForVariable(String varName) {
152: VariableDeclaration result = null;
153: //
154: List<VariableDeclarationScope> scopeList = getVarScopeChain();
155: ListIterator<VariableDeclarationScope> itr = scopeList
156: .listIterator(scopeList.size());
157: while (itr.hasPrevious()) {
158: VariableDeclarationScope varScope = itr.previous();
159: List<VariableDeclaration> varDeclList = Utils
160: .getVarDeclInScope(varScope);
161: if (varDeclList != null) {
162: for (VariableDeclaration varDecl : varDeclList) {
163: if (varDecl.getVariableName().equals(varName)) {
164: return varDecl;
165: }
166: }
167: }
168: }
169: //
170: return null;
171: }
172:
173: public static class Utils {
174:
175: public static List<Scope> getNestedScopes(BpelEntity startFrom) {
176: List<Scope> scopes = new ArrayList<Scope>();
177: addNestedScopes(startFrom, scopes);
178: return scopes;
179: }
180:
181: public static List<VariableDeclarationScope> getNestedVarScopes(
182: BpelEntity startFrom) {
183: List<VariableDeclarationScope> scopes = new ArrayList<VariableDeclarationScope>();
184: addNestedVarScopes(startFrom, scopes);
185: return scopes;
186: }
187:
188: /**
189: * Iterate recursively over the BPEL Object model and looking for
190: * nested Scope elements. Searching goes on only to the nearest Scopes.
191: */
192: private static void addNestedScopes(BpelEntity startFrom,
193: List<Scope> scopeList) {
194: if (startFrom == null || scopeList == null) {
195: return;
196: } else if (startFrom instanceof Scope) {
197: // Check to Scope should be the first to catch only the nearest Scopes!!!
198: scopeList.add((Scope) startFrom);
199: } else if (startFrom instanceof ActivityHolder) {
200: addNestedScopes(((ActivityHolder) startFrom)
201: .getActivity(), scopeList);
202: } else if (startFrom instanceof CompositeActivity) {
203: ExtendableActivity[] actArr = ((CompositeActivity) startFrom)
204: .getActivities();
205: for (ExtendableActivity act : actArr) {
206: addNestedScopes(act, scopeList);
207: }
208: }
209: }
210:
211: /**
212: * Iterate recursively over the BPEL Object model and looking for
213: * nested VariableDeclarationScope elements.
214: * Searching goes on only to the nearest VariableDeclarationScopes.
215: */
216: private static void addNestedVarScopes(BpelEntity startFrom,
217: List<VariableDeclarationScope> scopeList) {
218: if (startFrom == null || scopeList == null) {
219: return;
220: } else if (startFrom instanceof VariableDeclarationScope) {
221: // Check to VariableDeclarationScope should be the first
222: // in order to catch only the nearest Scopes!!!
223: scopeList.add((VariableDeclarationScope) startFrom);
224: } else if (startFrom instanceof ActivityHolder) {
225: addNestedVarScopes(((ActivityHolder) startFrom)
226: .getActivity(), scopeList);
227: } else if (startFrom instanceof CompositeActivity) {
228: ExtendableActivity[] actArr = ((CompositeActivity) startFrom)
229: .getActivities();
230: for (ExtendableActivity act : actArr) {
231: addNestedVarScopes(act, scopeList);
232: }
233: }
234: }
235:
236: /**
237: * Obtains the list of variables accessible from the specifid
238: * variable declaration scope.
239: *
240: * @param vdScope
241: * @return
242: */
243: public static List<VariableDeclaration> getVarDeclInScope(
244: VariableDeclarationScope vdScope) {
245: List<VariableDeclaration> result = new ArrayList<VariableDeclaration>();
246: //
247: // Create variable nodes
248: if (vdScope instanceof BaseScope) {
249: VariableContainer vc = ((BaseScope) vdScope)
250: .getVariableContainer();
251: if (vc != null) {
252: Variable[] varArr = vc.getVariables();
253: for (Variable var : varArr) {
254: result.add(var);
255: }
256: }
257: } else if (vdScope instanceof VariableDeclaration) {
258: VariableDeclaration varDecl = (VariableDeclaration) vdScope;
259: String varName = varDecl.getVariableName();
260: if (varName != null && varName.length() != 0) {
261: Object varTypeRef = null;
262: varTypeRef = varDecl.getMessageType();
263: if (varTypeRef == null) {
264: varTypeRef = varDecl.getType();
265: if (varTypeRef == null) {
266: varTypeRef = varDecl.getElement();
267: }
268: }
269: if (varTypeRef != null) {
270: // Ignore variable declaration without a name or type
271: result.add(varDecl);
272: }
273: }
274: } else if (vdScope instanceof VariableContainer) {
275: VariableContainer vc = (VariableContainer) vdScope;
276: Variable[] varArr = vc.getVariables();
277: for (Variable var : varArr) {
278: result.add(var);
279: }
280: }
281: //
282: return result;
283: }
284:
285: /**
286: * Traverses the specified visibility scope and collects all
287: * overridden variables.
288: * @param visScope to travrse over
289: * @return the set of overridden variables
290: */
291: public static Set<VariableDeclaration> getAllOverridenVariables(
292: VisibilityScope visScope) {
293: HashSet<VariableDeclaration> result = new HashSet<VariableDeclaration>();
294: HashSet<String> visibleNames = new HashSet<String>();
295: //
296: List<VariableDeclarationScope> vdScopeList = visScope
297: .getVarScopeChain();
298: for (int index = vdScopeList.size() - 1; index >= 0; index--) {
299: VariableDeclarationScope vdScope = vdScopeList
300: .get(index);
301: List<VariableDeclaration> varList = getVarDeclInScope(vdScope);
302: for (VariableDeclaration varDecl : varList) {
303: String varName = varDecl.getVariableName();
304: //
305: if (visibleNames.contains(varName)) {
306: result.add(varDecl);
307: } else {
308: visibleNames.add(varName);
309: }
310: }
311: }
312: //
313: return result;
314: }
315:
316: }
317:
318: }
|