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.bpel.mapper.predicates;
021:
022: import java.util.ArrayList;
023: import java.util.Iterator;
024: import java.util.LinkedList;
025: import java.util.List;
026: import java.util.ListIterator;
027: import org.netbeans.modules.bpel.mapper.predicates.editor.PathConverter;
028: import org.netbeans.modules.bpel.mapper.tree.spi.RestartableIterator;
029: import org.netbeans.modules.xml.schema.model.SchemaComponent;
030: import org.netbeans.modules.xml.xpath.ext.XPathPredicateExpression;
031: import org.netbeans.modules.xml.xpath.ext.XPathUtils;
032:
033: /**
034: * The class collects all predicate expressions which are in the edited
035: * XPath expression. Each predicate is declared in the XPath location step.
036: * The location step is bound to the specific schema element or attribute.
037: * The predicate manager keeps the location of predicate in term of
038: * schema components' path.
039: *
040: * The main intention of the predicate manager is to provide showing of
041: * predicates in the mapper source and destination trees.
042: *
043: * @author nk160297
044: */
045: public class PredicateManager {
046:
047: // The cache of predicates.
048: private LinkedList<CachedPredicate> mPredicates;
049:
050: public PredicateManager() {
051: mPredicates = new LinkedList<CachedPredicate>();
052: }
053:
054: public List<AbstractPredicate> getPredicates(
055: RestartableIterator<Object> parentPath,
056: SchemaComponent sComp) {
057: //
058: ArrayList<AbstractPredicate> result = new ArrayList<AbstractPredicate>();
059:
060: for (CachedPredicate cPred : mPredicates) {
061: if (cPred.hasSameBase(sComp)
062: && cPred.hasSameLocation(parentPath)) {
063: result.add(cPred.getPredicate());
064: }
065: }
066: //
067: return result;
068: }
069:
070: public boolean addPredicate(List<Object> parentPath,
071: AbstractPredicate pred) {
072: for (CachedPredicate cPred : mPredicates) {
073: if (cPred.hasSameLocation(parentPath)
074: && cPred.hasSamePredicate(pred)) {
075: // the same predicate already in cache
076: return false;
077: }
078: }
079: //
080: CachedPredicate cPredicate = new CachedPredicate(parentPath,
081: pred);
082: mPredicates.add(cPredicate);
083: return true;
084: }
085:
086: public boolean addPredicate(RestartableIterator<Object> parentItr,
087: AbstractPredicate pred) {
088: //
089: List<Object> parentPath = PathConverter
090: .constructPredicateLocationtList(parentItr);
091: //
092: if (parentPath != null) {
093: return addPredicate(parentPath, pred);
094: }
095: //
096: return false;
097: }
098:
099: public void removePredicate(AbstractPredicate predToDelete) {
100: for (CachedPredicate cPred : mPredicates) {
101: AbstractPredicate pred = cPred.getPredicate();
102: if (pred.equals(predToDelete)) {
103: mPredicates.remove(pred);
104: break;
105: }
106: }
107: }
108:
109: public static String toString(
110: XPathPredicateExpression[] predicatesArr) {
111: if (predicatesArr != null && predicatesArr.length != 0) {
112: StringBuilder sb = new StringBuilder();
113: for (XPathPredicateExpression predicate : predicatesArr) {
114: sb.append(predicate.getExpressionString());
115: }
116: return sb.toString();
117: } else {
118: return "";
119: }
120: }
121:
122: /**
123: * This class holds the predicate itself (PredicatedSchemaComp) +
124: * its location and the flag persistent.
125: *
126: * ATTENTION!
127: * The location is the different notion relative to the XPathSchemaContext.
128: * The schema context consists from SchemaComponent objects only.
129: * The location can contain a Variable, a Part, SchemaComponent and
130: * PredicatedSchemaComp objects.
131: */
132: public static class CachedPredicate {
133: // The list contains data objects from which a tree path consists of
134: // It is implied that it can contain a set of SchemaComponents and
135: // PredicatedSchemaComp. And there is either a variable or
136: // a variable with a part at the end.
137: // The first element is the parent of the predicate!
138: // The predicated schema component isn't in the list itself.
139: // It it held in the separate attribute mPredSComp.
140: private List<Object> mParentPath;
141:
142: // The Schema component which is the base for the predicate.
143: private AbstractPredicate mPred;
144:
145: // Persistense means that the instance should not be automatically
146: // deleted from the cache if it is not used.
147: // The predicates which are not persistent will be removed from
148: // the cache automatically.
149: private boolean isPersistent;
150:
151: public CachedPredicate(List<Object> parentPath,
152: AbstractPredicate pred) {
153: mParentPath = parentPath;
154: mPred = pred;
155: }
156:
157: public boolean isPersistent() {
158: return isPersistent;
159: }
160:
161: public void setPersistent(boolean newValue) {
162: isPersistent = newValue;
163: }
164:
165: public SchemaComponent getBaseType() {
166: return mPred.getSComponent();
167: }
168:
169: public AbstractPredicate getPredicate() {
170: return mPred;
171: }
172:
173: /**
174: * Returns the list of data objects which indicate the location of
175: * the predicate in the tree. The first element of the list points
176: * to the parent element of the predicate.
177: */
178: public List getParentPath() {
179: return mParentPath;
180: }
181:
182: public boolean hasSameBase(SchemaComponent baseSchemaComp) {
183: return getPredicate().getSComponent()
184: .equals(baseSchemaComp);
185: }
186:
187: /**
188: * Check if the cached predicate has the same schema component
189: * and the same predicates.
190: */
191: public boolean hasSameParams(SchemaComponent schemaComp,
192: XPathPredicateExpression[] predArr) {
193: AbstractPredicate pComp = getPredicate();
194: return pComp.getSComponent().equals(schemaComp)
195: && XPathUtils.samePredicatesArr(pComp
196: .getPredicates(), predArr);
197: }
198:
199: public boolean hasSamePredicate(AbstractPredicate pred) {
200: AbstractPredicate pComp = getPredicate();
201: return pComp.equals(pred);
202: }
203:
204: public boolean hasSameLocation(RestartableIterator parentPathItr) {
205: parentPathItr.restart();
206: return hasSameLocationImpl(parentPathItr);
207: }
208:
209: public boolean hasSameLocation(List<Object> parentPath) {
210: Iterator externalItr = parentPath.iterator();
211: return hasSameLocationImpl(externalItr);
212: }
213:
214: private boolean hasSameLocationImpl(Iterator externalItr) {
215: //
216: Iterator internalItr = mParentPath.iterator();
217: boolean theSame = true;
218: while (externalItr.hasNext() && internalItr.hasNext()) {
219: Object externalPathStep = externalItr.next();
220: Object internalPathStep = internalItr.next();
221: if (!externalPathStep.equals(internalPathStep)) {
222: theSame = false;
223: break;
224: }
225: }
226: //
227: if (theSame && internalItr.hasNext()) {
228: // internal location path longer then required.
229: // It isn't allowed. It can be shorter only.
230: return false;
231: }
232: //
233: return theSame;
234: }
235:
236: @Override
237: public String toString() {
238: String endText = mPred.toString() + " persistent="
239: + isPersistent; // NOI18N
240: //
241: String parentPath = locationToString();
242: if (parentPath == null || parentPath.length() == 0) {
243: return endText;
244: } else {
245: return parentPath + " " + endText;
246: }
247: }
248:
249: private String locationToString() {
250: StringBuilder sb = new StringBuilder();
251: ListIterator itr = mParentPath.listIterator(mParentPath
252: .size());
253: boolean isFirst = true;
254: while (itr.hasPrevious()) {
255: if (isFirst) {
256: isFirst = false;
257: } else {
258: sb.append("/");
259: }
260: //
261: Object stepObj = itr.previous();
262: sb.append(stepObj.toString());
263: }
264: return sb.toString();
265: }
266:
267: @Override
268: public boolean equals(Object obj2) {
269: if (!(obj2 instanceof CachedPredicate)) {
270: return false;
271: }
272: //
273: CachedPredicate pred2 = (CachedPredicate) obj2;
274: if (!pred2.getPredicate().equals(mPred)) {
275: return false;
276: }
277: //
278: List path2 = pred2.getParentPath();
279: if (path2.size() != mParentPath.size()) {
280: // Pathes have diferrent length
281: return false;
282: }
283: //
284: Iterator itr = mParentPath.listIterator();
285: Iterator itr2 = path2.listIterator();
286: //
287: while (itr.hasNext()) { // Pathes have the same length!
288: Object dataObj = itr.next();
289: Object dataObj2 = itr2.next();
290: if (!(dataObj.equals(dataObj2))) {
291: return false;
292: }
293: }
294: //
295: return true;
296: }
297: }
298:
299: }
|