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-2006 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:
042: package org.netbeans.modules.form.codestructure;
043:
044: import java.util.*;
045:
046: /**
047: * Default implementation class of CodeExpression interface. No other class
048: * should implement CodeExpression or extend this class. All extensibility
049: * is done through the CodeExpressionOrigin implementations. CodeExpression
050: * is kept as an interface for compatibility and usability reasons.
051: *
052: * @author Tomas Pavek
053: */
054:
055: final class DefaultCodeExpression implements CodeExpression {
056:
057: private CodeStructure codeStructure;
058:
059: private CodeExpressionOrigin expressionOrigin;
060:
061: private CodeObjectUsage expressionUsage;
062:
063: public DefaultCodeExpression(CodeStructure codeStructure,
064: CodeExpressionOrigin origin) {
065: this .codeStructure = codeStructure;
066: setOrigin(origin);
067: }
068:
069: DefaultCodeExpression(CodeStructure codeStructure) {
070: this .codeStructure = codeStructure;
071: }
072:
073: // -------
074:
075: public CodeStructure getCodeStructure() {
076: return codeStructure;
077: }
078:
079: public CodeVariable getVariable() {
080: return codeStructure.getVariable(this );
081: }
082:
083: public CodeExpressionOrigin getOrigin() {
084: return expressionOrigin;
085: }
086:
087: public void setOrigin(CodeExpressionOrigin newOrigin) {
088: CodeExpressionOrigin oldOrigin = expressionOrigin;
089: if (oldOrigin == newOrigin)
090: return;
091:
092: CodeExpression registerParent = null;
093: List<CodeExpression> registerParams = null;
094:
095: if (oldOrigin != null) {
096: if (newOrigin != null) { // changing one origin to another
097: CodeExpression oldParent = oldOrigin
098: .getParentExpression();
099: CodeExpression newParent = newOrigin
100: .getParentExpression();
101: if (oldParent != null && oldParent != newParent)
102: CodeStructure
103: .unregisterObjectUsage(this , oldParent);
104: if (newParent != null && newParent != oldParent)
105: registerParent = newParent;
106:
107: CodeExpression[] oldParams = oldOrigin
108: .getCreationParameters();
109: CodeExpression[] newParams = newOrigin
110: .getCreationParameters();
111:
112: for (int i = 0; i < oldParams.length; i++) {
113: CodeExpression oldPar = oldParams[i];
114: if (i < newParams.length && oldPar == newParams[i])
115: continue;
116: int j = 0;
117: while (j < newParams.length) {
118: if (oldPar == newParams[j])
119: break;
120: j++;
121: }
122: if (j == newParams.length)
123: CodeStructure.unregisterObjectUsage(this ,
124: oldPar);
125: }
126:
127: for (int i = 0; i < newParams.length; i++) {
128: CodeExpression newPar = newParams[i];
129: if (i < oldParams.length && newPar == oldParams[i])
130: continue;
131: int j = 0;
132: while (j < oldParams.length) {
133: if (newPar == oldParams[j])
134: break;
135: j++;
136: }
137: if (j == oldParams.length) {
138: if (registerParams == null)
139: registerParams = new ArrayList<CodeExpression>();
140: registerParams.add(newPar);
141: }
142: }
143: } else
144: CodeStructure.unregisterUsingCodeObject(this );
145: }
146:
147: expressionOrigin = newOrigin;
148:
149: if (codeStructure.isUndoRedoRecording())
150: codeStructure.logUndoableChange(new OriginChange(oldOrigin,
151: newOrigin));
152:
153: if (newOrigin != null) {
154: if (oldOrigin != null) {
155: if (registerParent != null)
156: registerParent.addUsingObject(this ,
157: UsedCodeObject.DEFINED,
158: CodeExpression.class);
159:
160: if (registerParams != null)
161: for (int i = 0, n = registerParams.size(); i < n; i++) {
162: CodeExpression param = registerParams.get(i);
163: param.addUsingObject(this ,
164: UsedCodeObject.USING,
165: CodeExpression.class);
166: }
167: } else
168: CodeStructure.registerUsingCodeObject(this );
169: }
170: }
171:
172: // --------
173: // UsedCodeObject implementation - registering objects that use
174: // this expression
175:
176: public void addUsingObject(UsingCodeObject usingObject,
177: int useType, Object useCategory) {
178: CodeStructureChange undoableChange = getExpressionUsage()
179: .addUsingObject(usingObject, useType, useCategory,
180: codeStructure.isUndoRedoRecording());
181: if (undoableChange != null)
182: codeStructure.logUndoableChange(undoableChange);
183: }
184:
185: public boolean removeUsingObject(UsingCodeObject usingObject) {
186: CodeStructureChange undoableChange = getExpressionUsage()
187: .removeUsingObject(usingObject,
188: codeStructure.isUndoRedoRecording());
189: if (undoableChange != null)
190: codeStructure.logUndoableChange(undoableChange);
191:
192: boolean stillUsed = !getExpressionUsage().isEmpty();
193: if (!stillUsed) // the elment is no longer used in the structure
194: codeStructure.removeExpressionFromVariable(this );
195: return stillUsed;
196: }
197:
198: public Iterator getUsingObjectsIterator(int useType,
199: Object useCategory) {
200: return getExpressionUsage().getUsingObjectsIterator(useType,
201: useCategory);
202: }
203:
204: private CodeObjectUsage getExpressionUsage() {
205: if (expressionUsage == null)
206: expressionUsage = new CodeObjectUsage(this );
207: return expressionUsage;
208: }
209:
210: // ---------
211: // UsingCodeObject implementation - handling objects used by this expression
212:
213: // notifying about registering this object in used object
214: public void usageRegistered(UsedCodeObject usedObject) {
215: }
216:
217: // notifying about removing the used object from structure
218: public boolean usedObjectRemoved(UsedCodeObject usedObject) {
219: // if (!(usedObject instanceof CodeExpression))
220: // return true;
221: // an used expression was removed - this expression will be too ...
222: codeStructure.removeExpressionFromVariable(this );
223: return false;
224: }
225:
226: public UsedCodeObject getDefiningObject() {
227: return getOrigin().getParentExpression();
228: }
229:
230: public Iterator getUsedObjectsIterator() {
231: return new UsedObjectsIterator();
232: }
233:
234: // --------
235:
236: private class OriginChange implements CodeStructureChange {
237: private CodeExpressionOrigin oldOrigin;
238: private CodeExpressionOrigin newOrigin;
239:
240: OriginChange(CodeExpressionOrigin oldOrigin,
241: CodeExpressionOrigin newOrigin) {
242: this .oldOrigin = oldOrigin;
243: this .newOrigin = newOrigin;
244: }
245:
246: public void undo() {
247: expressionOrigin = oldOrigin;
248: }
249:
250: public void redo() {
251: expressionOrigin = newOrigin;
252: }
253: }
254:
255: // --------
256:
257: private class UsedObjectsIterator implements Iterator {
258: int index;
259: CodeExpression[] parameters;
260:
261: UsedObjectsIterator() {
262: index = getOrigin().getParentExpression() != null ? -1 : 0;
263: parameters = getOrigin().getCreationParameters();
264: if (parameters == null)
265: parameters = CodeStructure.EMPTY_PARAMS;
266: }
267:
268: public boolean hasNext() {
269: return index < parameters.length;
270: }
271:
272: public Object next() {
273: if (!hasNext())
274: throw new java.util.NoSuchElementException();
275:
276: Object obj = index > -1 ? parameters[index] : getOrigin()
277: .getParentExpression();
278: index++;
279: return obj;
280: }
281:
282: public void remove() {
283: throw new UnsupportedOperationException();
284: }
285: }
286: }
|