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:
042: /*
043: * File : ConstructorInfo.java
044: * Version : 1.6
045: * Description : Describes a constructor
046: * Author : Trey Spiva
047: */
048: package org.netbeans.modules.uml.integration.ide.events;
049:
050: import org.netbeans.modules.uml.core.metamodel.core.foundation.FactoryRetriever;
051: import org.netbeans.modules.uml.core.metamodel.core.foundation.IElement;
052: import org.netbeans.modules.uml.core.metamodel.infrastructure.IDerivationClassifier;
053: import org.netbeans.modules.uml.core.roundtripframework.requestprocessors.javarpcomponent.JavaMethodChangeFacility;
054: import org.netbeans.modules.uml.core.support.umlutils.ElementLocator;
055: import java.lang.reflect.Modifier;
056: import java.util.Arrays;
057: import java.util.LinkedList;
058: import java.util.ListIterator;
059:
060: import org.netbeans.modules.uml.integration.ide.ChangeUtils;
061: import org.netbeans.modules.uml.integration.ide.JavaClassUtils;
062: import org.netbeans.modules.uml.core.metamodel.infrastructure.coreinfrastructure.IClassifier;
063: import org.netbeans.modules.uml.core.metamodel.infrastructure.coreinfrastructure.IOperation;
064: import org.netbeans.modules.uml.core.metamodel.infrastructure.coreinfrastructure.IParameter;
065: import org.netbeans.modules.uml.core.support.umlsupport.Log;
066: import org.netbeans.modules.uml.core.support.umlutils.ETArrayList;
067: import org.netbeans.modules.uml.core.support.umlutils.ETList;
068: import org.netbeans.modules.uml.integration.ide.UMLSupport;
069:
070: //import org.netbeans.modules.uml.integration.netbeans.NBEventProcessor;
071:
072: /**
073: * The ConstructorInfo communicates with the EventManager to update Describe.
074: * ConstructorInfo is still a high level class. It knows how to communicate
075: * with the EventMangaer to update Describe, but it does not know any of the
076: * details of how to update Describe.
077: * <br>
078: * Because ConstructorInfo contains both before and after data, ConstructorInfo
079: * is able to search for the constructor and update it to how the source file
080: * current represents the constructor.
081: * <br>
082: * For Wolverine, the ConstructorInfo may also carry data for model-source
083: * roundtrip events. In such cases, only the 'before' data fields are used.
084: *
085: * Revision History
086: * No. Date Who What
087: * --- ---- --- ----
088: * 1 2002-05-03 Darshan Added methods to manipulate parameters using
089: * IParameters. These are needed because of the
090: * changes to Wolverine's method-parameter-change
091: * event mechanism in build 64.
092: * Also reformatted to use 4-space tabs and Java
093: * style brace positioning.
094: * 2 2002-05-06 Darshan Added constructor to take a ClassInfo and an
095: * IOperation for model-source work.
096: *
097: * @see EventManager
098: * @see MethodInfo
099: * @author Trey Spiva
100: */
101: public class ConstructorInfo extends ElementInfo {
102: private ClassInfo mContainer = null;
103: private LinkedList mOrigParameters = null;
104: private LinkedList mNewParameters = null;
105: private LinkedList mExceptions = null;
106: private String mSource = null;
107: private JavaMethodChangeFacility facility = new JavaMethodChangeFacility();
108:
109: /**
110: * Intiailizes a new ConstructorInfo.
111: * @param container The class that contains the data member.
112: * @param type The transaction type.
113: * @see ElementInfo
114: */
115: public ConstructorInfo(ClassInfo container, int type) {
116: super (type);
117: setContainingClass(container);
118: }
119:
120: public ConstructorInfo(ClassInfo container, IOperation op) {
121: super (op);
122: setContainingClass(container);
123: }
124:
125: /**
126: * Retrieves the containing clas of the data member.
127: * @return The containing class.
128: */
129: public ClassInfo getContainingClass() {
130: return mContainer;
131: }
132:
133: /**
134: * Sets the containing clas of the data member.
135: * @param container The containing class.
136: */
137: public void setContainingClass(ClassInfo container) {
138: mContainer = container;
139: }
140:
141: public void syncFields() {
142: super .syncFields();
143: if (getNewParameters() != null) {
144: setParameters(getNewParameters());
145: setNewParameters(null);
146: }
147: }
148:
149: /**
150: * Retrieves all of the constructor's parameters.
151: * @return An array of MethodParameterInfo objects.
152: */
153: public MethodParameterInfo[] getParameters() {
154: // D: The caller had better set the parameters correctly!
155: if (mOrigParameters == null)
156: return null;
157:
158: // Convert to an array
159: MethodParameterInfo[] retVal = new MethodParameterInfo[mOrigParameters
160: .size()];
161: for (int i = 0; i < retVal.length; i++)
162: retVal[i] = (MethodParameterInfo) mOrigParameters.get(i);
163:
164: return retVal;
165: }
166:
167: /**
168: * Retrieves a specific parameter information.
169: * @return A MethodParameterInfo object.
170: * @throws IndexOutOfBoundsException
171: */
172: public MethodParameterInfo getParameters(int index)
173: throws IndexOutOfBoundsException {
174: if (mOrigParameters == null)
175: throw new IndexOutOfBoundsException();
176:
177: return (MethodParameterInfo) mOrigParameters.get(index);
178: }
179:
180: /**
181: * Sets the constructors parameters. This is setting the original parameters.
182: * @param params All the parameters.
183: */
184: public void setParameters(MethodParameterInfo[] params) {
185: if (params != null)
186: mOrigParameters = new LinkedList(Arrays.asList(params));
187: else
188: mOrigParameters = null;
189: }
190:
191: /**
192: * Adds a parameters to a specific location in the parameters list. This is
193: * setting the original parameters.
194: * @param index The position that the parameter should fill.
195: * @param param The parameter.
196: */
197: public void addParameter(int index, MethodParameterInfo param)
198: throws IndexOutOfBoundsException {
199: if (mOrigParameters == null)
200: mOrigParameters = new LinkedList();
201:
202: mOrigParameters.add(index, param);
203: }
204:
205: /**
206: * Removes all the parameter from the parameter list. This does not mean
207: * that the parameters will be removed from Describe, only from the
208: * ConstructorInfo.
209: *
210: * This is setting the original parameters.
211: */
212: public void clearParameters() {
213: mOrigParameters = null;
214: }
215:
216: /**
217: * Remove a specific parameter from the collection of parameters. This does
218: * not mean that the parameter will be removed from Describe, only from
219: * the ConstructorInfo. This is setting the original parameters.
220: * @param index The parameter to be removed.
221: */
222: public void removeParameter(int index) {
223: if (mOrigParameters != null)
224: mOrigParameters.remove(index);
225: }
226:
227: public MethodParameterInfo getParameter(IParameter param) {
228: // EARLY EXIT
229: if (mOrigParameters == null)
230: return null;
231:
232: ListIterator i = mOrigParameters.listIterator();
233:
234: if (i == null)
235: return null;
236:
237: while (i.hasNext()) {
238: MethodParameterInfo mpi = (MethodParameterInfo) i.next();
239: if (mpi.getName().equals(param.getName())
240: && JavaClassUtils.getInnerClassName(mpi.getType())
241: .equals(param.getTypeName()))
242: return mpi;
243: }
244: return null;
245: }
246:
247: public void removeParameter(IParameter param) {
248: MethodParameterInfo mpi = getParameter(param);
249: if (mpi != null)
250: mOrigParameters.remove(mpi);
251: }
252:
253: public void changeParameter(IParameter orig, IParameter newp) {
254: MethodParameterInfo mpi = getParameter(orig);
255: if (mpi != null) {
256: mpi.setName(newp.getName());
257: mpi.setType(newp.getTypeName());
258: }
259: }
260:
261: // New Parameters
262: public MethodParameterInfo[] getNewParameters() {
263: MethodParameterInfo[] retVal = null;
264: if (mNewParameters != null) {
265: // Convert to an array
266: retVal = new MethodParameterInfo[mNewParameters.size()];
267: for (int i = 0; i < retVal.length; i++)
268: retVal[i] = (MethodParameterInfo) mNewParameters.get(i);
269: }
270:
271: return retVal;
272: }
273:
274: /**
275: * Sets the constructors parameters. This is setting the new parameters.
276: * @param params All the parameters.
277: */
278: public MethodParameterInfo getNewParameters(int index)
279: throws IndexOutOfBoundsException {
280: if (mNewParameters == null)
281: throw new IndexOutOfBoundsException();
282:
283: return (MethodParameterInfo) mNewParameters.get(index);
284: }
285:
286: /**
287: * Sets the constructors parameters. This is setting the new parameters.
288: * @param params All the parameters.
289: */
290: public void setNewParameters(MethodParameterInfo[] params) {
291: if (params != null)
292: mNewParameters = new LinkedList(Arrays.asList(params));
293: else
294: mNewParameters = null;
295: }
296:
297: /**
298: * Adds a parameters to a specific location in the parameters list. This is
299: * setting the new parameters.
300: * @param index The position that the parameter should fill.
301: * @param param The parameter.
302: */
303: public void addNewParameter(int index, MethodParameterInfo param)
304: throws IndexOutOfBoundsException {
305: if (mNewParameters == null)
306: mNewParameters = new LinkedList();
307:
308: mNewParameters.add(index, param);
309: }
310:
311: /**
312: * Removes all the parameter from the parameter list. This does not mean that
313: * the parameters will be removed from Describe, only from the ConstructorInfo.
314: * This is setting the new parameters.
315: */
316: public void clearNewParameters() {
317: mNewParameters = null;
318: }
319:
320: /**
321: * Remove a specific parameter from the collection of parameters. This does
322: * not mean that the parameter will be removed from Describe, only from
323: * the ConstructorInfo. This is setting the new parameters.
324: * @param index The parameter to be removed.
325: */
326: public void removeNewParameter(int index) {
327: mNewParameters.remove(index);
328: }
329:
330: /**
331: * Retrieves the exceptions that can be thrown by the constructor.
332: * @return The list of thrown exceptions.
333: */
334: public String[] getExceptions() {
335: String[] retVal = null;
336: if ((mExceptions != null) && (mExceptions.size() > 0)) {
337: // Convert to an array
338: retVal = new String[mExceptions.size()];
339: for (int i = 0; i < retVal.length; i++)
340: retVal[i] = (String) mExceptions.get(i);
341: }
342:
343: return retVal;
344: }
345:
346: /**
347: * Sets the exceptions that can be thrown by the constructor.
348: * @param value The list of thrown exceptions.
349: */
350: public void setExceptions(String[] value) {
351: mExceptions = null;
352: mExceptions = new LinkedList(Arrays.asList(value));
353: }
354:
355: /**
356: * Adds a exceptions that can be thrown by the constructor.
357: * @param An exception that can be thrown.
358: */
359: public void addException(String value) {
360: if (mExceptions == null)
361: mExceptions = new LinkedList();
362:
363: mExceptions.add(value);
364: }
365:
366: /**
367: * Removes a exceptions that can be thrown by the constructor.
368: * @param An exception that can be thrown.
369: */
370: public void removeException(String exception) {
371: mExceptions.remove(exception);
372: }
373:
374: /**
375: * Updates the constructor. A Class Transaction is began and {@link #update(GDSymbolTransaction trans) update}
376: * is called.
377: */
378: public void update() {
379: if (getContainingClass() != null) {
380: SymbolTransaction trans = new SymbolTransaction(
381: getContainingClass());
382: update(trans);
383: }
384: }
385:
386: protected void checkSanity() {
387: if (getChangeType() == MODIFY && mNewParameters != null
388: && mNewParameters.size() > 0) {
389: // Check whether parameter lists are the same
390: MethodParameterInfo[] oldP = getParameters(), newP = getNewParameters();
391: if (Arrays.equals(oldP, newP))
392: setNewParameters(null);
393: }
394: }
395:
396: /**
397: * Returns whether the parameter list of this constructor needs to be
398: * updated to the Describe model.
399: *
400: * @return <code>true</code> if the model needs to be updated.
401: */
402: protected boolean needParameterUpdate() {
403: return getNewParameters() != null;
404: }
405:
406: /**
407: * Updates the constructor using the specified Symbol transaction.
408: * @param trans The transaction that is to be used to update the correct symbol.
409: * @return The method transaction that was created to update the data member.
410: */
411: public MethodTransaction update(SymbolTransaction trans) {
412: checkSanity();
413:
414: Log.out("GDMethodTransaction.update(): Updating " + this );
415: MethodTransaction retVal = null;
416: EventManager manager = EventManager.getEventManager();
417: Log
418: .out("GDMethodTransaction.update(): Creating GDMethodTransaction");
419: retVal = new MethodTransaction(trans, this );
420: Log
421: .out("GDMethodTransaction.update(): Done Creating GDMethodTransaction");
422: IOperation op = retVal.getOperation();
423:
424: Log.out("GDMethodTransaction.update(): IOperation is " + op);
425:
426: if (retVal != null && op != null) {
427: if (getChangeType() == ElementInfo.DELETE) {
428: Log.out("About to delete the method ..");
429: facility.deleted(op, op.getFeaturingClassifier(), true); //JM added this
430: manager.deleteMethod(retVal);
431: return null;
432: }
433:
434: if (op.getRaisedExceptions() != null) {
435: ETList<IClassifier> existingExceptions = op
436: .getRaisedExceptions();
437: for (int i = 0; i < existingExceptions.getCount(); i++)
438: op
439: .removeRaisedException(existingExceptions
440: .item(i));
441: }
442: if (getExceptions() != null) {
443: Log.out("Setting raised exceptions for the method....");
444: String[] exceptions = getExceptions();
445: for (int i = 0; i < exceptions.length; i++) {
446: IClassifier clazz = JavaClassUtils
447: .findClassSymbol(exceptions[i]);
448: if (clazz == null)
449: clazz = JavaClassUtils
450: .createDataType(exceptions[i]);
451: op.addRaisedException(clazz);
452: }
453: }
454:
455: if (isCommentSet()) {
456: Log.out("Setting the comment for method to ========="
457: + getComment());
458: op.setDocumentation(getComment());
459: }
460:
461: if (getModifiers() != null) {
462: Log.out(" Updating modifiers........");
463: manager.updateMethodModifers(retVal, getModifiers()
464: .intValue());
465: }
466:
467: if (getNewName() != null && !getNewName().equals(getName())) {
468: // op.setName(getNewName());
469: facility.changeName(op, getNewName(), false, true);
470: }
471:
472: if (needParameterUpdate())
473: updateParameters(retVal);
474:
475: if (getChangeType() == ElementInfo.MODIFY) {
476: if (needParameterUpdate()) {
477: facility.typeChanged(op, true);
478: }
479: }
480:
481: IClassifier sym = trans.getSymbol();
482: if (sym != null && !(sym.findMatchingOperation(op) == op)) {
483: // add newly created operation to class, when all stuff related to it (like parameters, modifiers, etc.) is set
484: facility.added(op, true);
485: sym.addOperation(op);
486: }
487: }
488: return retVal;
489: }
490:
491: protected ETList<IParameter> getParameterCollection(IOperation op) {
492: return new ETArrayList<IParameter>();
493: }
494:
495: protected void updateParameters(MethodTransaction trans) {
496: // Create the IParameter for each new parameter added and add it to the
497: // IOperation
498: EventManager.getEventManager().getEventFilter().blockEventType(
499: ChangeUtils.RDT_DEPENDENCY_ADDED);
500: try {
501: IOperation op = trans.getOperation();
502: if (getNewParameters() != null) {
503: ETList<IParameter> pars = getParameterCollection(op);
504: MethodParameterInfo[] params = getNewParameters();
505: for (int i = 0; i < params.length; i++) {
506: MethodParameterInfo param = params[i];
507:
508: String type = param.getType();
509: int mul = MemberInfo.getMultiplicity(type);
510: type = MemberInfo.getTypeName(type);
511:
512: IParameter ip = null;
513: IDerivationClassifier derivation = getDerivationClassifer(
514: op, type);
515: if (derivation != null) {
516: ip = op.createParameter2(derivation, param
517: .getName());
518: } else {
519: String typename = JavaClassUtils
520: .convertJavaToUML(type);
521: ip = op.createParameter(typename, param
522: .getName());
523: }
524: MemberInfo.setMultiplicity(ip, mul, 0);
525: Log
526: .out("Adding new param: "
527: + JavaClassUtils
528: .convertJavaToUML(param
529: .getType()) + " "
530: + param.getName());
531:
532: pars.add(ip);
533: }
534: Log.out("Calling setParameters() for operation "
535: + getName());
536: try {
537: UMLSupport.setRoundTripEnabled(true);
538: /* NB60TBD NBEventProcessor.setUpdatingModel(true); */
539: op.setParameters(pars);
540: } finally {
541: UMLSupport.setRoundTripEnabled(false);
542: /* NB60TBD NBEventProcessor.setUpdatingModel(false); */
543: }
544:
545: Log.out("Done calling setParameters() for operation "
546: + getName());
547: }
548: } finally {
549: EventManager.getEventManager().getEventFilter()
550: .unblockEventType(ChangeUtils.RDT_DEPENDENCY_ADDED);
551: }
552: }
553:
554: protected IDerivationClassifier getDerivationClassifer(
555: IElement owner, String name) {
556: IDerivationClassifier retVal = null;
557:
558: if (name.indexOf('<') > 0) {
559: // We have a template instance. We should create a derived
560: // classifier instead of a DataType.
561: ElementLocator pLocator = new ElementLocator();
562: ETList<IElement> elements = pLocator.findScopedElements(
563: owner, name);
564: if ((elements != null) && (elements.size() > 0)) {
565: retVal = (IDerivationClassifier) elements.get(0);
566: } else {
567: FactoryRetriever fact = FactoryRetriever.instance();
568: Object obj = fact.createType("DerivationClassifier",
569: null);
570: if (obj != null && obj instanceof IDerivationClassifier) {
571: IDerivationClassifier nEle = (IDerivationClassifier) obj;
572: nEle.setName(name);
573: owner.getProject().addOwnedElement(nEle);
574: retVal = nEle;
575: }
576: }
577: }
578:
579: return retVal;
580: }
581:
582: public String getCode() {
583: return "I";
584: }
585:
586: public Object clone() {
587: ConstructorInfo ci = (ConstructorInfo) super .clone();
588: if (mOrigParameters != null) {
589: ci.mOrigParameters = (LinkedList) mOrigParameters.clone();
590: deepClone(ci.mOrigParameters);
591: }
592: if (mNewParameters != null) {
593: ci.mNewParameters = (LinkedList) mNewParameters.clone();
594: deepClone(ci.mNewParameters);
595: }
596: if (mExceptions != null)
597: ci.mExceptions = (LinkedList) mExceptions.clone();
598: return ci;
599: }
600:
601: protected void deepClone(LinkedList l) {
602: ListIterator li = l.listIterator();
603: while (li.hasNext()) {
604: Object obj = li.next();
605: if (obj instanceof MethodParameterInfo) {
606: MethodParameterInfo mpi = (MethodParameterInfo) obj, oth = (MethodParameterInfo) mpi
607: .clone();
608:
609: li.remove();
610: li.add(oth);
611: }
612: }
613: }
614:
615: protected String getDisplayString(String fnName,
616: MethodParameterInfo[] mpi) {
617: StringBuffer text = new StringBuffer(fnName);
618: text.append('(');
619:
620: for (int i = 0; mpi != null && i < mpi.length; ++i) {
621: if (i > 0)
622: text.append(", ");
623: text.append(mpi[i].getName()).append(": ").append(
624: mpi[i].getType());
625: }
626: text.append(')');
627: return text.toString();
628: }
629:
630: public String toString() {
631: int mods = getModifiers() != null ? getModifiers().intValue()
632: : 0;
633: String original = getDisplayString(getName(), getParameters());
634: if (getNewName() != null || getNewParameters() != null) {
635: String newName = getNewName() != null ? getNewName()
636: : getName();
637: MethodParameterInfo[] mpi = getNewParameters() != null ? getNewParameters()
638: : getParameters();
639: original += " -> " + getDisplayString(newName, mpi);
640: }
641: return "(" + getChangeName() + ") " + Modifier.toString(mods)
642: + " " + original + getExceptionString();
643: }
644:
645: public void setSource(String src) {
646: mSource = src;
647: }
648:
649: public String getSource() {
650: return mSource;
651: }
652:
653: private String getExceptionString() {
654: StringBuffer excStr = new StringBuffer();
655: String[] ex = getExceptions();
656: if (ex != null && ex.length > 0) {
657: excStr.append(" throws ");
658: for (int i = 0; i < ex.length; ++i) {
659: if (i > 0)
660: excStr.append(", ");
661: excStr.append(ex[i]);
662: }
663: }
664: return excStr.toString();
665: }
666: }
|