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 : MemberInfo.java
044: * Version : 1.4
045: * Description : Information about the changes to an attribute.
046: * Author : Trey Spiva
047: */
048: package org.netbeans.modules.uml.integration.ide.events;
049:
050: import java.lang.reflect.Modifier;
051: import java.util.StringTokenizer;
052: import java.util.ArrayList;
053:
054: import org.netbeans.modules.uml.common.Util;
055: import org.netbeans.modules.uml.core.roundtripframework.RTMode;
056: import org.netbeans.modules.uml.core.roundtripframework.RoundTripModeRestorer;
057: import org.netbeans.modules.uml.core.roundtripframework.requestprocessors.javarpcomponent.JavaAttributeChangeFacility;
058: import org.netbeans.modules.uml.core.roundtripframework.requestprocessors.javarpcomponent.JavaChangeHandlerUtilities;
059: import org.netbeans.modules.uml.integration.ide.ChangeUtils;
060: import org.netbeans.modules.uml.integration.ide.JavaClassUtils;
061: import org.netbeans.modules.uml.core.support.umlsupport.Log;
062: import org.netbeans.modules.uml.core.metamodel.core.foundation.IElement;
063: import org.netbeans.modules.uml.core.metamodel.core.foundation.IMultiplicity;
064: import org.netbeans.modules.uml.core.metamodel.core.foundation.IMultiplicityRange;
065: import org.netbeans.modules.uml.core.metamodel.infrastructure.coreinfrastructure.IAttribute;
066: import org.netbeans.modules.uml.core.metamodel.infrastructure.coreinfrastructure.IClassifier;
067: import org.netbeans.modules.uml.core.metamodel.infrastructure.coreinfrastructure.INavigableEnd;
068: import org.netbeans.modules.uml.core.metamodel.infrastructure.coreinfrastructure.IStructuralFeature;
069: import org.netbeans.modules.uml.core.metamodel.infrastructure.coreinfrastructure.ITypedElement;
070: import org.netbeans.modules.uml.core.metamodel.structure.IProject;
071: import org.netbeans.modules.uml.core.support.umlutils.ETList;
072: import org.netbeans.modules.uml.util.DummyCorePreference;
073: import org.openide.util.NbPreferences;
074:
075: /**
076: * The MemberInfo communicates with the EventManager to update Describe.
077: * MemberInfo is still a high level class. It knows how to communicate with
078: * the EventMangaer to update Describe, but it does not know any of the details
079: * of how to update Describe.
080: * <br>
081: * Because MemberInfo contains both before and after data, MemberInfo is able
082: * to search for the data member and update it to how the source file current
083: * represents the member.
084: *
085: * Revision History
086: * No. Date Who What
087: * --- ---- --- ----
088: * 1 2002-04-25 Darshan Added (currently empty) constructors to
089: * create a MemberInfo given an IAttribute.
090: * 2 2002-04-26 Darshan Added constructor to create a MemberInfo off
091: * an IAttribute and reformatted the file to
092: * 4-space tabs.
093: * 3 2002-04-30 Darshan Used JavaClassUtils to map Describe's modifiers
094: * to Java modifiers.
095: * 4 2002-05-06 Darshan Changed MemberInfo(ClassInfo, IAttribute) to
096: * call the ElementInfo(INamedElement) constructor.
097: * 5 2002-05-29 Darshan Added check for navigable ends.
098: * 6 2002-06-05 Darshan Allow creation of MemberInfo from an
099: * IStructuralFeature instead of an IAttribute,
100: * since this allows us to construct MemberInfos
101: * from INavigableEnds (so that we can navigate
102: * to the attribute for a navigable end).
103: * 7 2002-06-21 Darshan Expanded check for the parent class for an
104: * INavigableEnd, fixed attribute delete and
105: * initializer bugs.
106: * 8 2002-06-22 Darshan Included code suggested by Sumitabh to find the
107: * referencing classifier of an INavigableEnd.
108: *
109: * @see EventManager
110: */
111: public class MemberInfo extends ElementInfo {
112: /** The containing class information. */
113: private ClassInfo mContainer = null;
114:
115: /** The original data type of the data member. */
116: private String mOrigType = null;
117:
118: /** The fully qualified name of the original type of the data member. */
119: private String mOrigQualType = null;
120:
121: /**
122: * The data type of this data member as should be created in the source,
123: * assuming that the source does not already contain a member of type
124: * mOrigType or mOrigQualType. If null, this can be ignored.
125: */
126: private String collectionType = null;
127:
128: /** A global option that specifies whether or not to use generics when
129: * Collection data types are generated in code
130: */
131: private boolean useGenerics = false;
132:
133: /** The new data type of the data member. */
134: private String mNewType = null;
135:
136: /** The fully qualified name of the new type of the data member. */
137: private String mNewQualType = null;
138:
139: /** The initializer for the data member. */
140: private String mInitializer = null;
141:
142: private int modifierMask;
143:
144: /**
145: * The IAttribute from which this MemberInfo was constructed. If the
146: * MemberInfo was constructed by an IDE integration, this should be null.
147: */
148: private IStructuralFeature attribute = null;
149:
150: public IAttribute getAttribute() {
151: return (IAttribute) attribute;
152: }
153:
154: /**
155: * Intiailizes a new MemberInfo.
156: * @param container The class that contains the data member.
157: * @param type The transaction type.
158: * @see ElementInfo
159: */
160: public MemberInfo(ClassInfo container, int type) {
161: super (type);
162: setContainingClass(container);
163: }
164:
165: public MemberInfo(ClassInfo container, IStructuralFeature attr) {
166: super (attr);
167: setContainingClass(container);
168:
169: // Remember the attribute we're created from. This should not be
170: // used beyond the lifetime of the thread in which this MemberInfo
171: // is created.
172: attribute = attr;
173: setFromAttribute(attribute);
174: }
175:
176: /* (non-Javadoc)
177: * @see com.embarcadero.integration.events.ElementInfo#getOwningProject()
178: */
179: public IProject getOwningProject() {
180: return attribute != null ? (IProject) attribute.getProject()
181: : getContainingClass() != null ? getContainingClass()
182: .getOwningProject() : null;
183: }
184:
185: public void syncFields() {
186: super .syncFields();
187: if (getNewType() != null) {
188: setType(getQualifiedType(), getNewType());
189: setNewType(getNewQualifiedType(), null);
190: }
191:
192: if (getNewQualifiedType() != null) {
193: setType(getNewQualifiedType(), getType());
194: setNewType(null, getNewType());
195: }
196: }
197:
198: public String getFilename() {
199: return (mContainer != null ? mContainer.getFilename() : null);
200: }
201:
202: public IProject getProject() {
203: return attribute != null ? (IProject) attribute.getProject()
204: : null;
205: }
206:
207: /**
208: * Set all properties for this MemberInfo using info from the given
209: * IStructuralFeature.
210: * @param attr An <code>IStructuralFeature</code> for the attribute (or
211: * navigable association).
212: */
213: public void setFromAttribute(IStructuralFeature attr) {
214: setName(attr.getName());
215: int mods = JavaClassUtils.getJavaModifier(attr.getVisibility());
216:
217: if (attr.getIsFinal())
218: mods |= Modifier.FINAL;
219:
220: if (attr.getIsStatic())
221: mods |= Modifier.STATIC;
222:
223: if (attr.getIsTransient())
224: mods |= Modifier.TRANSIENT;
225:
226: if (attr.getIsVolatile())
227: mods |= Modifier.VOLATILE;
228:
229: setModifiers(new Integer(mods));
230:
231: setType(JavaClassUtils.getFullyQualifiedName(attr.getType()),
232: attr.getTypeName());
233:
234: collectionType = null;
235: int mul = getMultiplicity(attr);
236:
237: if (mul > 0) {
238: collectionType = getCollectionOverrideDataType();
239: StringBuffer collectionLeft = new StringBuffer();
240: StringBuffer collectionRight = new StringBuffer();
241: StringBuffer arr = new StringBuffer(mul * 2);
242:
243: for (int i = 0; i < mul; ++i) {
244: arr.append("[]"); // NOI18N
245:
246: if (isUseGenerics()) {
247: if (i == 0) {
248: collectionLeft.append('<');
249:
250: if (mul == 1)
251: collectionLeft.append(mOrigType);
252:
253: else
254: collectionLeft.append(collectionType)
255: .append('<');
256: }
257:
258: else if (i == mul - 1)
259: collectionLeft.append(mOrigType);
260:
261: else
262: collectionLeft.append(collectionType).append(
263: '<');
264:
265: collectionRight.append('>');
266: }
267: }
268:
269: mOrigType += arr.toString();
270: mOrigQualType += arr.toString();
271: collectionType += collectionLeft.append(collectionRight)
272: .toString();
273:
274: // cvc - CR 6286610
275: // disabled because nothing else gets an initial value
276: // in code generation and this is messing with array/collection
277: // mulitiplicity settings in RoundTrip
278: // setInitializer("new " + collectionType + "()");
279: }
280:
281: if (attr instanceof IAttribute) {
282: IAttribute at = (IAttribute) attr;
283: String init = at.getDefault().getBody();
284:
285: if (init != null && init.trim().length() == 0)
286: init = null;
287:
288: // cvc - CR 6286610
289: // disabled because nothing else gets an initial value
290: // in code generation and this is messing with array/collection
291: // mulitiplicity settings in RoundTrip
292: // if (init == null && collectionType != null)
293: // init = "new " + collectionType + "()";
294:
295: setInitializer(init);
296: }
297:
298: // Assuming the container hasn't been set, attempt to create a
299: // ClassInfo for it.
300: if (getContainingClass() == null) {
301: IElement owner = attr.getOwner();
302:
303: if (owner instanceof IClassifier) {
304: IClassifier cp = (IClassifier) owner;
305: ClassInfo inf = ClassInfo.getRefClassInfo(cp, true);
306: setContainingClass(inf);
307: }
308:
309: else {
310: // Might this be a navigable end?
311: if (attr instanceof INavigableEnd) {
312: INavigableEnd nav = (INavigableEnd) attr;
313: IClassifier feat = null;
314:
315: if (nav.getOtherEnd2() != null)
316: feat = nav.getOtherEnd2().getParticipant();
317:
318: else {
319: // Do we have a referencing IClassifier?
320: feat = nav.getReferencingClassifier();
321: }
322:
323: if (feat != null) {
324: Log.out("Found participant classifier "
325: + feat.getName());
326:
327: ClassInfo inf = ClassInfo.getRefClassInfo(feat,
328: true);
329: setContainingClass(inf);
330: }
331: }
332: }
333: }
334: }
335:
336: public MemberInfo(IStructuralFeature attr) {
337: this (null, attr);
338: }
339:
340: /**
341: * Retrieves the containing clas of the data member.
342: * @return The containing class.
343: */
344: public ClassInfo getContainingClass() {
345: return mContainer;
346: }
347:
348: /**
349: * Sets the containing clas of the data member.
350: * @param container The containing class.
351: */
352: public void setContainingClass(ClassInfo container) {
353: mContainer = container;
354: }
355:
356: /**
357: * Sets the original type of the data member.
358: * @param fullName The fully qualified type data member
359: * @param value The data types simple name.
360: */
361: public void setType(String fullName, String value) {
362: mOrigType = value;
363: mOrigQualType = fullName;
364: }
365:
366: /**
367: * Retrieves the simple name for the data member's original type.
368: * @return The data types simple name.
369: */
370: public String getType() {
371: return mOrigType;
372: }
373:
374: /**
375: * Retrieves the full name for the data member's original type.
376: * @return The fully qualified type data member.
377: */
378: public String getQualifiedType() {
379: return mOrigQualType;
380: }
381:
382: public String getCollectionOverrideDataType() {
383: // TODO: conover - change this to use attribute level property
384: // rather than the global preference
385: //kris richards - made change to nbpreferences
386: return NbPreferences.forModule(DummyCorePreference.class).get(
387: "UML_COLLECTION_OVERRIDE_DEFAULT",
388: "java.util.ArrayList"); // NOI18N
389: }
390:
391: public boolean isCollectionType() {
392: return Util.isValidCollectionDataType(getQualifiedType());
393: }
394:
395: public boolean isUseCollectionOverride() {
396: // TODO: conover - change this to use attribute level property
397: // rather than the global preference
398: return getAttribute().getMultiplicity().getRangeCount() > 0
399: && Util
400: .isValidCollectionDataType(getCollectionOverrideDataType());
401: }
402:
403: public boolean isUseGenerics() {
404: // TODO: conover - eventually, use the atribute level property
405: // instead of this global preference
406: //kris richards - made change to nbpreferences
407: return NbPreferences.forModule(DummyCorePreference.class)
408: .getBoolean("UML_USE_GENERICS_DEFAULT", true); // NOI18N
409:
410: }
411:
412: /**
413: * Sets the new type of the data member.
414: * @param fullName The fully qualified type data member
415: * @param value The data types simple name.
416: */
417: public void setNewType(String fullName, String value) {
418: mNewType = value;
419: mNewQualType = fullName;
420: }
421:
422: /**
423: * Retrieves the simple name for the data member's new type.
424: * @return The data types simple name.
425: */
426: public String getNewType() {
427: return mNewType;
428: }
429:
430: /**
431: * Retrieves the full name for the data member's new type.
432: * @return The fully qualified type data member.
433: */
434: public String getNewQualifiedType() {
435: return mNewQualType;
436: }
437:
438: /**
439: * Checks if the data type of the attribute is primitive
440: * @return true if data type is non primitive or not a String
441: */
442: public boolean isNonPrimitive() {
443: return "String".equals(mOrigQualType) && // NOI18N
444: !JavaClassUtils.isPrimitive(mOrigQualType);
445: }
446:
447: /**
448: * Retrieves the initailizer for the data member.
449: * @return The data members initailizer.
450: */
451: public String getInitializer() {
452: return mInitializer;
453: }
454:
455: /**
456: * Sets the initailizer for the data member.
457: * @return The data members initailizer.
458: */
459: public void setInitializer(String value) {
460: mInitializer = value;
461: }
462:
463: /**
464: * Updates the data member. A Class Transaction is began and {@link #update(GDSymbolTransaction trans) update}
465: * is called.
466: */
467: public void update() {
468: if (getContainingClass() != null) {
469: SymbolTransaction trans = new SymbolTransaction(
470: getContainingClass());
471: update(trans);
472: }
473: }
474:
475: public String getCodeGenType() {
476: return getCodeGenType(false);
477: }
478:
479: public String getCodeGenType(boolean fullyQualified) {
480: // if no return param, probably a Constructor; return empty string
481: if (getAttribute() == null)
482: return ""; // NOI18N
483:
484: if (fullyQualified) {
485: if (codeGenTypeFullyQualified == null) {
486: codeGenTypeFullyQualified = GenCodeUtil.getCodeGenType(
487: getAttribute().getType(), GenCodeUtil
488: .getCollectionOverrideDataTypes(
489: getAttribute()
490: .getMultiplicity(),
491: fullyQualified),
492: isUseGenerics(), getAttribute()
493: .getMultiplicity(), fullyQualified,
494: getContainingClass());
495: }
496: return codeGenTypeFullyQualified;
497: } else {
498: if (codeGenTypeShort == null) {
499: codeGenTypeShort = GenCodeUtil.getCodeGenType(
500: getAttribute().getType(), GenCodeUtil
501: .getCollectionOverrideDataTypes(
502: getAttribute()
503: .getMultiplicity(),
504: fullyQualified),
505: isUseGenerics(), getAttribute()
506: .getMultiplicity(), fullyQualified,
507: getContainingClass());
508: }
509: return codeGenTypeShort;
510: }
511: }
512:
513: private String codeGenTypeFullyQualified = null;
514: private String codeGenTypeShort = null;
515:
516: /**
517: * Updates the data member using the specified Symbol transaction.
518: * @param trans The transaction that is to be used to update the correct symbol.
519: * @return The member transaction that was created to update the data member.
520: */
521: public MemberTransaction update(SymbolTransaction trans) {
522: EventManager manager = EventManager.getEventManager();
523:
524: MemberTransaction retVal = new MemberTransaction(trans, this );
525: IStructuralFeature attribute = retVal.getAttribute();
526:
527: if (attribute == null)
528: return null;
529:
530: manager.getEventFilter().blockEventType(
531: ChangeUtils.RDT_DEPENDENCY_ADDED);
532:
533: try {
534: if (retVal != null) {
535: JavaAttributeChangeFacility facility = new JavaAttributeChangeFacility();
536:
537: if (getChangeType() == ElementInfo.DELETE) {
538: // if (attribute instanceof INavigableEnd)
539: // {
540: // IAssociation assoc =
541: // ((INavigableEnd)attribute).getAssociation();
542: //
543: // ETList<IAssociationEnd> ends = assoc.getEnds();
544: //
545: // for(int i = 0 ; i < ends.size() ; i++)
546: // {
547: // ends.get(i).delete();
548: // }
549: // assoc.delete();
550: // }
551: //
552: // else if (attribute instanceof IAttribute)
553: // {
554: // attribute.delete();
555: // }
556:
557: if (attribute instanceof IAttribute) {
558: facility.delete((IAttribute) attribute, false,
559: false);
560: }
561: } else {
562: if (isCommentSet()) {
563: Log.out("Setting the comment ===============" // NOI18N
564: + getComment());
565:
566: attribute.setDocumentation(getComment());
567: }
568:
569: if (getModifiers() != null) {
570: manager.updateMemberModifers(retVal,
571: getModifiers().intValue());
572: }
573:
574: if (getNewName() != null) {
575: if (attribute instanceof IAttribute) {
576: facility.changeName((IAttribute) attribute,
577: getNewName(), false, true);
578: }
579: }
580:
581: if (getNewType() != null) {
582: Log.out("Setting the new member type ....."); // NOI18N
583:
584: // CR 6435621 - cvc
585: // this was added because when an attibute's type
586: // was changed (in source code) from an object to a
587: // primitive (Integer to int for example), the
588: // NavigableEnd link from the parent class to the
589: // associated class was not being removed in the model,
590: // and the attribute was not added to the parent class
591: EventManager
592: .getAttributeFacility()
593: .changeAttributeType(
594: (IAttribute) attribute,
595: trans.getSymbol(),
596: getName(),
597: JavaClassUtils
598: .convertJavaToUML(getNewQualifiedType()));
599:
600: manager.updateMemberType(retVal,
601: getNewQualifiedType(), getNewType());
602: //attribute.setType2(getNewType());
603:
604: if (attribute instanceof IAttribute) {
605: RoundTripModeRestorer restorer = new RoundTripModeRestorer();
606:
607: restorer.setMode(RTMode.RTM_LIVE);
608: facility
609: .typeChanged((IAttribute) attribute);
610: // IZ 80035: conover
611: // if there was a type change, there might
612: // have been a multiplicity change
613: facility
614: .multiplicityChanged((IAttribute) attribute);
615: restorer.restoreOriginalMode();
616: }
617: }
618:
619: if (getInitializer() != null) {
620: // Downcasting is okay for the attribute, because whoever
621: // sets it will have set it as either an IAttribute or an
622: // INavigableEnd, not a simple IStructuralFeature.
623: Log
624: .out("setting default value for attribute to : " // NOI18N
625: + getInitializer());
626:
627: String initializer = getInitializer();
628:
629: Log.out("initializer : " + initializer); // NOI18N
630:
631: IAttribute att = null;
632:
633: if (attribute instanceof IAttribute)
634: att = (IAttribute) attribute;
635:
636: else if (attribute instanceof INavigableEnd)
637: att = (IAttribute) attribute;
638:
639: if (att != null) {
640: IMultiplicity mul = att.getMultiplicity();
641:
642: Log.out("range count : " // NOI18N
643: + mul.getRangeCount());
644:
645: ETList<IMultiplicityRange> ranges = mul
646: .getRanges();
647: int count = ranges.getCount();
648:
649: if (count > 0)
650: setMultiplicityRanges(ranges,
651: initializer);
652:
653: att.setDefault2(initializer);
654: }
655: }
656: }
657: }
658: }
659:
660: catch (Exception ex) {
661: Log.stackTrace(ex);
662: }
663:
664: finally {
665: manager.getEventFilter().unblockEventType(
666: ChangeUtils.RDT_DEPENDENCY_ADDED);
667: }
668:
669: return retVal;
670: }
671:
672: public String getCode() {
673: return "F"; // NOI18N
674: }
675:
676: public String toString() {
677: StringBuffer str = new StringBuffer("" + getType()); // NOI18N
678:
679: if (isCollectionType())
680: str.append(" (").append(getCollectionOverrideDataType())
681: .append(")"); // NOI18N
682:
683: str.append(" ").append(getName()); // NOI18N
684:
685: if (getInitializer() != null)
686: str.append(" = ").append(getInitializer()); // NOI18N
687:
688: if (getModifiers() != null) {
689: str.insert(0, " "); // NOI18N
690: str.insert(0, Modifier.toString(getModifiers().intValue()));
691: }
692:
693: return str.toString();
694: }
695:
696: /**
697: * Strips out array specifiers from a given type name.
698: * @param name The type name (possibly including array specifiers)
699: * @return For "int[][]" returns "int"
700: * For "String" returns "String"
701: */
702: public static String getTypeName(String name) {
703: if (name == null)
704: return null;
705: int arrPos = name.indexOf('[');
706: return (arrPos == -1) ? name : name.substring(0, arrPos).trim();
707: }
708:
709: /**
710: * Returns the number of array specifiers that qualify the type name given.
711: * @param name The type name (including array specifiers)
712: * @return The number of array specifiers. Ex: For "int[][]", returns 2.
713: */
714: public static int getMultiplicity(String name) {
715: int count = 0, pos = -1;
716: if (name != null) {
717: while ((pos = name.indexOf('[', pos + 1)) != -1)
718: count++;
719: }
720: return count;
721: }
722:
723: public static int getMultiplicity(ITypedElement attr) {
724: if (attr == null)
725: return 0;
726: return getMultiplicity(attr.getMultiplicity());
727: }
728:
729: public static int getMultiplicity(IMultiplicity mul) {
730: if (mul != null) {
731: ETList<IMultiplicityRange> ranges = mul.getRanges();
732: if (ranges != null) {
733: if (ranges.size() == 1) {
734: IMultiplicityRange range = ranges.get(0);
735: String lower = range.getLower();
736: String upper = range.getUpper();
737: if (lower != null && lower.equals("1")
738: && upper != null && upper.equals("1")) {
739: return 0;
740: }
741: }
742: return ranges.getCount();
743: }
744: }
745: return 0;
746: }
747:
748: public static void setMultiplicity(ITypedElement attr,
749: int newmultiplicity, int oldmultiplicity) {
750: if (newmultiplicity == oldmultiplicity)
751: return;
752:
753: IMultiplicity mul = attr.getMultiplicity();
754: int diff = newmultiplicity - oldmultiplicity;
755: if (diff < 0) {
756: ETList<IMultiplicityRange> ranges = mul.getRanges();
757: if (ranges == null)
758: return;
759: int count = ranges.getCount();
760:
761: for (int i = count - 1; i >= count + diff; --i) {
762: Log.out("Removing multiplicity range: "
763: + ranges.item(i));
764: mul.removeRange(ranges.item(i));
765: }
766: } else {
767: StringBuffer range = new StringBuffer(diff * 7);
768: for (int i = 0; i < newmultiplicity; ++i) {
769: if (i > 0)
770: range.append(",");
771: range.append("0..*");
772: }
773: Log.out("Setting multiplicity range to '"
774: + range.toString() + "'");
775: mul.setRangeThroughString(range.toString());
776:
777: // <drumroll> Horrible kludge warning #8913891231 </drumroll>
778: // Now go back through the ranges and explicitly set the upper bound
779: // for each, since we still have not got a fix for the above code
780: // not working.
781: ETList<IMultiplicityRange> ranges = mul.getRanges();
782: if (ranges != null && ranges.getCount() == newmultiplicity) {
783: for (int i = 0; i < newmultiplicity; ++i) {
784: ranges.item(i).setUpper("*");
785: }
786: }
787: }
788: }
789:
790: public static String getArrayType(String type, int mul) {
791: if (mul <= 0)
792: return type;
793:
794: StringBuffer buf = (mul < cache.length) ? cache[mul] : null;
795: if (buf == null) {
796: buf = new StringBuffer(mul * 2);
797: for (int i = 0; i < mul; ++i)
798: buf.append("[]");
799: if (mul < cache.length)
800: cache[mul] = buf;
801: }
802: return type += buf.toString();
803: }
804:
805: public static String getArrayTypeName(ITypedElement el) {
806: String type = el.getType().getName();
807: int mul = getMultiplicity(el);
808: if (mul > 0) {
809: StringBuffer arr = new StringBuffer(mul * 2);
810: for (int i = 0; i < mul; ++i)
811: arr.append("[]");
812: type += arr;
813: }
814: return type;
815: }
816:
817: private static void setMultiplicityRanges(
818: ETList<IMultiplicityRange> ranges, String initializer) {
819: if (initializer.indexOf("[") == -1) {
820: for (int i = 0; i < ranges.getCount(); i++) {
821: ranges.item(i).setLower("0");
822: ranges.item(i).setUpper("*");
823: }
824: return;
825: }
826: String r = initializer.substring(initializer.indexOf("["));
827: StringTokenizer tok = new StringTokenizer(r, "]");
828: String range = null, nextTok = null;
829: for (int i = 0; i < ranges.getCount(); i++) {
830: try {
831: nextTok = tok.nextToken();
832: } catch (Exception ex) {
833: }
834: if (nextTok == null)
835: ranges.remove(i);
836: else {
837: range = nextTok.substring(nextTok.indexOf("[") + 1,
838: nextTok.length()); // NOI18N
839: Log.out("range val : " + range); // NOI18N
840: Log.out("Lower val : " + ranges.item(i).getLower()); // NOI18N
841: Log.out("Upper val : " + ranges.item(i).getUpper()); // NOI18N
842: int lower = 0, upper = 0, rangeVal = 0;
843: try {
844: lower = Integer.parseInt(ranges.item(i).getLower());
845: } catch (Exception ex) {
846: }
847:
848: try {
849: upper = Integer.parseInt(ranges.item(i).getUpper());
850: } catch (Exception ex) {
851: }
852:
853: try {
854: rangeVal = Integer.parseInt(range);
855: } catch (Exception ex) {
856: ranges.item(i).setLower("0"); // NOI18N
857: ranges.item(i).setUpper("*"); // NOI18N
858: }
859:
860: if ((upper - lower) != rangeVal)
861: upper = rangeVal + lower;
862:
863: if (upper > 0 && rangeVal != 0) {
864: upper--;
865: ranges.item(i).setLower(Integer.toString(lower));
866: ranges.item(i).setUpper(Integer.toString(upper));
867: }
868: }
869: }
870: }
871:
872: private static StringBuffer[] cache = new StringBuffer[4];
873:
874: public int getmodifierMask() {
875: return modifierMask;
876: }
877:
878: public void setmodifierMask(int modifierMask) {
879: this .modifierMask = modifierMask;
880: }
881:
882: public static String stripBrackets(String val) {
883: return val.substring(0, val.indexOf('['));
884: }
885:
886: //
887: // added for template codegen
888: //
889:
890: void checkGenerateName() {
891: String name = getName();
892: if (name != null && !name.trim().equals("")) {
893: return;
894: }
895: String attrName = "";
896: IAttribute attr = getAttribute();
897: if (attr instanceof INavigableEnd) {
898: INavigableEnd nav = (INavigableEnd) attr;
899: IClassifier pClass = nav.getParticipant();
900: if (pClass != null) {
901: String typeName = pClass.getName();
902: String prefix = new JavaChangeHandlerUtilities()
903: .attributePrefix();
904: attrName = prefix + stripGenericBrackets(typeName);
905: ClassInfo owner = getContainingClass();
906: if (owner != null) {
907: String aName = attrName;
908: int i = 0;
909: while (!owner.checkAddAttributeName(aName)) {
910: aName = attrName + (++i);
911: }
912: attrName = aName;
913: }
914: }
915: }
916: setName(attrName);
917: }
918:
919: private String stripGenericBrackets(String type) {
920: int begin = type.indexOf("<");
921: if (begin > -1)
922: return type.substring(0, begin).trim();
923: return type;
924: }
925:
926: // see getCodeGenType() for how the type string is formed
927: public ArrayList<String[]> getReferredCodeGenTypes() {
928: return GenCodeUtil.getReferredCodeGenTypes(getAttribute()
929: .getType(), GenCodeUtil.getCollectionOverrideDataTypes(
930: getAttribute().getMultiplicity(), true),
931: isUseGenerics(), getAttribute().getMultiplicity(),
932: getContainingClass());
933:
934: }
935:
936: }
|