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: package org.netbeans.modules.uml.integration.ide.events;
043:
044: import java.util.ArrayList;
045: import java.util.HashSet;
046: import java.util.Iterator;
047: import java.util.List;
048:
049: import org.netbeans.modules.uml.core.metamodel.core.foundation.IElement;
050: import org.netbeans.modules.uml.core.metamodel.core.foundation.IMultiplicity;
051: import org.netbeans.modules.uml.core.metamodel.core.foundation.IMultiplicityRange;
052: import org.netbeans.modules.uml.core.metamodel.core.foundation.IPackage;
053: import org.netbeans.modules.uml.core.metamodel.infrastructure.coreinfrastructure.ClassifierTemplateParameter;
054: import org.netbeans.modules.uml.core.metamodel.infrastructure.coreinfrastructure.IClassifier;
055: import org.netbeans.modules.uml.core.metamodel.infrastructure.coreinfrastructure.IDerivation;
056: import org.netbeans.modules.uml.core.metamodel.infrastructure.coreinfrastructure.IUMLBinding;
057: import org.netbeans.modules.uml.core.metamodel.infrastructure.IDerivationClassifier;
058: import org.netbeans.modules.uml.core.metamodel.structure.IProject;
059: import org.netbeans.modules.uml.core.support.umlutils.ETList;
060: import org.netbeans.modules.uml.integration.ide.JavaClassUtils;
061: import org.netbeans.modules.uml.integration.ide.UMLSupport;
062:
063: /**
064: *
065: * @author Craig Conover, craig.conover@sun.com
066: */
067: public final class GenCodeUtil {
068: private GenCodeUtil() {
069: }
070:
071: public static boolean isValidClassType(String type) {
072: // valid class type are anything but:
073: // null, empty string, void, String, or a primitive
074: return !(type == null || type.length() == 0
075: || type.equals("void") || // NOI18N
076: type.equals("String") || // NOI18N
077: type.equals("java.lang.String") || // NOI18N
078: JavaClassUtils.isPrimitive(type));
079: }
080:
081: public static String getCodeGenType(IClassifier classType,
082: String[] collectionTypes, boolean useGenerics,
083: IMultiplicity mult, boolean fullyQualified,
084: ClassInfo container) {
085: ClassInfo ci = ClassInfo.getRefClassInfo(classType, true, true);
086: String classTypeName = ci.getCodeGenType(fullyQualified,
087: container);
088:
089: // if (mult != null && mult.getRangeCount() > 0)
090: if (mult != null && isMultiDim(mult)) {
091: return assembleMultiDimDataType(classTypeName,
092: collectionTypes, useGenerics, mult.getRangeCount(),
093: fullyQualified);
094: }
095: return classTypeName;
096:
097: }
098:
099: public static String assembleMultiDimDataType(String coreTypeName,
100: String[] collectionTypes, boolean useGenerics,
101: long dimCount, boolean fullyQualified) {
102: boolean isPrimitive = true;
103:
104: isPrimitive = JavaClassUtils.isPrimitive(coreTypeName);
105:
106: if (dimCount == 0)
107: return coreTypeName;
108:
109: if (isPrimitive
110: && collectionTypes[(int) dimCount - 1] != null
111: && !collectionTypes[(int) dimCount - 1]
112: .equals(IMultiplicityRange.AS_ARRAY)) {
113: String type = JavaClassUtils
114: .getPrimitiveWrapperType(coreTypeName);
115: if (fullyQualified)
116: coreTypeName = "java.lang." + type;
117: else
118: coreTypeName = type;
119:
120: isPrimitive = false;
121: }
122:
123: String leftPart = "";
124: String rightPart = "";
125:
126: for (int i = 0; i < dimCount; i++) {
127: String colType = collectionTypes[i];
128: if (((colType != null) && (!colType.trim().equals(
129: IMultiplicityRange.AS_ARRAY)))
130: && ((i != dimCount - 1) || (!isPrimitive))) {
131: leftPart += colType;
132: if (!useGenerics) {
133: return leftPart + rightPart;
134: } else {
135: leftPart += '<';
136: rightPart = '>' + rightPart;
137: }
138: } else {
139: rightPart = "[]" + rightPart;
140: }
141: }
142: return leftPart + coreTypeName + rightPart;
143: }
144:
145: public final static String ASTERIK = "*";
146:
147: public static boolean isMultiDim(IMultiplicity mult) {
148: if (mult == null || mult.getRanges().size() == 0)
149: return false;
150:
151: // if more than one dimension, even if all are upper limit of 1,
152: // we still want to use Collections
153: else if (mult.getRanges().size() > 1)
154: return true;
155:
156: String lowerStr = mult.getRanges().get(0).getLower();
157: String upperStr = mult.getRanges().get(0).getUpper();
158:
159: boolean result = upperStr.equals(ASTERIK)
160: || lowerStr.equals(ASTERIK);
161: if (!result) {
162: try {
163: result = Long.valueOf(upperStr).intValue() > 1;
164: } catch (NumberFormatException nfe) {
165: // do nothing as it is just happens to be not a number
166: }
167: }
168: return result;
169: }
170:
171: public static String removeGenericType(String type) {
172: return type.indexOf("<") == -1 ? type : type.substring(0, type
173: .indexOf('<'));
174: }
175:
176: //
177: // added for template codegen
178: //
179:
180: public static String[] getFullyQualifiedCodeGenType(
181: IClassifier classType) {
182: ClassInfo ci = ClassInfo.getRefClassInfo(classType, true, true);
183: String[] packAndName = ci.getFullyQualifiedCodeGenType();
184: return packAndName;
185: }
186:
187: public static String getTypeName(IClassifier clazz,
188: boolean fullyQualified) {
189: String fullClassName = "";
190: String[] packAndName = getFullyQualifiedCodeGenType(clazz);
191: if (packAndName != null && packAndName.length == 2) {
192: if (fullyQualified)
193: fullClassName = packAndName[0] + "." + packAndName[1];
194: else
195: fullClassName = packAndName[1];
196: }
197: return fullClassName;
198:
199: /*
200: String name = JavaClassUtils.getFullyQualifiedName(clazz);
201: name = JavaClassUtils.getFullInnerClassName(name);
202: if (! fullyQualified)
203: {
204: name = JavaClassUtils.getShortClassName(name);
205: }
206: return name;
207: */
208: }
209:
210: public static String getTypeCodeGenType(IClassifier classType,
211: boolean fullyQualified, ClassInfo container) {
212: IClassifier clazz = null;
213: String result = "";
214: if (classType instanceof IDerivationClassifier) {
215: IDerivation drv = classType.getDerivation();
216: if (drv != null) {
217: clazz = drv.getTemplate();
218: List<IUMLBinding> bindings = drv.getBindings();
219: if (bindings != null) {
220: boolean first = true;
221: for (IUMLBinding b : bindings) {
222: if (b.getActual() instanceof IClassifier) {
223: String name = getTypeCodeGenType(
224: (IClassifier) b.getActual(),
225: fullyQualified, container);
226: if (name != null && !name.trim().equals("")) {
227: if (JavaClassUtils.isPrimitive(name)) {
228: name = JavaClassUtils
229: .getPrimitiveWrapperType(name);
230: }
231: if (!first) {
232: result = result + ", ";
233: } else {
234: first = false;
235: }
236: result = result + name.trim();
237: }
238: }
239: }
240: if (result != null && !result.trim().equals("")) {
241: result = "<" + result + ">";
242: }
243: }
244: } else {
245: clazz = classType;
246: }
247: } else {
248: clazz = classType;
249: }
250:
251: String clazzTypeName;
252: if ((fullyQualified || isNameCodeGenConflict(container, clazz))
253: && !(clazz instanceof ClassifierTemplateParameter)) {
254: clazzTypeName = getTypeName(clazz, true);
255: } else {
256: clazzTypeName = getTypeName(clazz, false);
257: }
258: result = clazzTypeName + result;
259: return result;
260: }
261:
262: // see getCodeGenType()/assembleMultiDimDataType()
263: // for how the type string is formed
264: public static ArrayList<String[]> getReferredCodeGenTypes(
265: IClassifier classType, String[] collectionTypes,
266: boolean useGenerics, IMultiplicity mult, ClassInfo container) {
267: ArrayList<String[]> res = new ArrayList<String[]>();
268: boolean isPrimitive = false;
269:
270: ArrayList<String[]> refs;
271: if (classType instanceof IDerivationClassifier) {
272: refs = getReferredCodeGenTypes(classType, container);
273: } else {
274: IClassifier impClass = classType;
275: IElement owner = classType.getOwner();
276: while ((owner != null) && (owner instanceof IClassifier)) {
277: impClass = (IClassifier) owner;
278: owner = impClass.getOwner();
279: }
280: String[] fqType = GenCodeUtil
281: .getFullyQualifiedCodeGenType(impClass);
282: if (!(fqType != null && fqType.length == 2 && fqType[1] != null)) {
283: return null;
284: }
285:
286: refs = new ArrayList<String[]>();
287: if (!isNameCodeGenConflict(container, classType)) {
288: refs.add(fqType);
289: }
290: isPrimitive = JavaClassUtils.isPrimitive(fqType[1]);
291: }
292:
293: boolean reffersTheType = true;
294: if (mult != null && isMultiDim(mult)) {
295: int dimCount = (int) mult.getRangeCount();
296: if (isPrimitive
297: && collectionTypes[(int) dimCount - 1] != null
298: && !collectionTypes[(int) dimCount - 1]
299: .equals(IMultiplicityRange.AS_ARRAY)) {
300: isPrimitive = false;
301: }
302: for (int i = 0; i < dimCount; i++) {
303: String colType = collectionTypes[i];
304: if (((colType != null) && (!colType.trim().equals(
305: IMultiplicityRange.AS_ARRAY)))
306: && ((i != dimCount - 1) || (!isPrimitive))) {
307: res
308: .add(new String[] {
309: JavaClassUtils
310: .getPackageName(colType),
311: JavaClassUtils
312: .getShortClassName(colType) });
313: if (!useGenerics) {
314: reffersTheType = false;
315: break;
316: }
317: }
318: }
319: }
320:
321: if (reffersTheType) {
322: if (refs != null) {
323: res.addAll(refs);
324: }
325: }
326:
327: return res;
328: }
329:
330: public static ArrayList<String[]> getReferredCodeGenTypes(
331: IClassifier classType, ClassInfo container) {
332: ArrayList<String[]> res = new ArrayList<String[]>();
333:
334: IClassifier clazz = null;
335:
336: if (classType instanceof IDerivationClassifier) {
337: IDerivation drv = classType.getDerivation();
338: if (drv != null) {
339: clazz = drv.getTemplate();
340: List<IUMLBinding> bindings = drv.getBindings();
341: if (bindings != null) {
342: for (IUMLBinding b : bindings) {
343: if (b.getActual() instanceof IClassifier) {
344: ArrayList<String[]> refs = getReferredCodeGenTypes(
345: (IClassifier) b.getActual(),
346: container);
347: if (refs != null) {
348: res.addAll(refs);
349: }
350: }
351: }
352: }
353: } else {
354: // it is something like orphaned pack.clazz<type argument>,
355: // ie. there isn't derivation connecting it to pack.clazz;
356: // will try to extract "pack.clazz", though without the bindings
357: // there isn't enough info for "type argument"
358: String[] fqType = GenCodeUtil
359: .getFullyQualifiedCodeGenType(classType);
360: if ((fqType != null && fqType.length == 2)) {
361: String name = fqType[1];
362: if (name != null) {
363: int ind = name.indexOf('<');
364: if (ind > 1) {
365: name = name.substring(0, ind);
366: }
367: }
368: res.add(new String[] { fqType[0], name });
369: }
370: }
371: } else {
372: clazz = classType;
373: }
374:
375: if (clazz != null && !isNameCodeGenConflict(container, clazz)) {
376: String[] fqType = GenCodeUtil
377: .getFullyQualifiedCodeGenType(clazz);
378: if ((fqType != null && fqType.length == 2)) {
379: res.add(fqType);
380: }
381: }
382:
383: return res;
384: }
385:
386: // utility method merges 2 ArrayLists
387: // of String[2] with package and name of a class
388: public static void mergeReferredCodeGenTypes(
389: ArrayList<String[]> res, HashSet<String> fqNames,
390: ArrayList<String[]> refs) {
391: if (refs == null) {
392: return;
393: }
394: Iterator iter = refs.iterator();
395: while (iter.hasNext()) {
396: String[] pn = (String[]) iter.next();
397: if (pn != null && pn.length == 2) {
398: if (pn[0] != null && pn[1] != null) {
399: String fq = pn[1] + "." + pn[0];
400: if (!fqNames.contains(fq)) {
401: fqNames.add(fq);
402: res.add(pn);
403: }
404: }
405: }
406: }
407: }
408:
409: public static String[] getCollectionOverrideDataTypes(
410: IMultiplicity multiplicity, boolean fullyQualified) {
411:
412: if (multiplicity == null) {
413: return null;
414: }
415: List<IMultiplicityRange> ranges = multiplicity.getRanges();
416: if (ranges == null) {
417: return null;
418: }
419:
420: String[] res = new String[(int) multiplicity.getRangeCount()];
421: Iterator<IMultiplicityRange> iter = ranges.iterator();
422: for (int i = 0; i < res.length; i++) {
423: String type = null;
424: if (iter.hasNext()) {
425: IMultiplicityRange range = iter.next();
426: if (range != null) {
427: type = range.getCollectionTypeValue(true);
428: if (type == null || type.trim().equals("")) {
429: type = IMultiplicityRange.AS_ARRAY;
430: }
431: if (!IMultiplicityRange.AS_ARRAY.equals(type)) {
432: type = JavaClassUtils.convertUMLtoJava(type);
433: }
434: }
435: }
436: // as there is always a value set at the attribute/parameter level
437: // whereis empty means "AsArray"
438: // then there isn't need for the global one
439: //if (type == null || type.trim().equals("") ) {
440: // type = UMLSupport.getUMLSupport().getCollectionOverride();
441: //}
442: if (!fullyQualified
443: && !IMultiplicityRange.AS_ARRAY.equals(type)) {
444: type = JavaClassUtils.getShortClassName(type);
445: }
446: res[i] = type;
447: }
448: return res;
449:
450: }
451:
452: public static boolean isNameCodeGenConflict(ClassInfo container,
453: IClassifier classType) {
454: if (container == null) {
455: return false;
456: }
457: IClassifier cn = container.getClassElement();
458: if (cn == null) {
459: return false;
460: }
461: if (JavaClassUtils.isAnOwner(cn, classType)) {
462: return false;
463: }
464:
465: String typeName = getTypeName(classType, false);
466:
467: if (findConflictingByCodeGenName(container, typeName) != null) {
468: return true;
469: }
470:
471: ClassInfo owner = container.getOuterClass();
472: if (owner != null) {
473: return isNameCodeGenConflict(owner, classType);
474: } else {
475: String cnName = getTypeName(cn, false);
476: return cnName.equals(typeName);
477: }
478:
479: }
480:
481: public static ClassInfo findConflictingByCodeGenName(
482: ClassInfo container, String typeName) {
483: if (container == null || typeName == null) {
484: return null;
485: }
486: int ind = typeName.indexOf(".");
487: String nameToComp;
488: String restOfTypeName;
489: if (ind > -1) {
490: restOfTypeName = typeName.substring(ind + 1);
491: nameToComp = typeName.substring(0, ind);
492: } else {
493: nameToComp = typeName;
494: restOfTypeName = "";
495: }
496:
497: List<ClassInfo> children = container.getMemberTypes();
498: if (children != null) {
499: for (ClassInfo child : children) {
500: String chName = getTypeName(child.getClassElement(),
501: false);
502: int di = chName.lastIndexOf(".");
503: if (di > -1) {
504: chName = chName.substring(di + 1);
505: }
506: if (nameToComp.equals(chName)) {
507: if (!typeName.equals("")) {
508: return child;
509: } else {
510: ClassInfo cl = findConflictingByCodeGenName(
511: child, restOfTypeName);
512: if (cl != null) {
513: return cl;
514: }
515: }
516: }
517: }
518: }
519: ClassInfo owner = container.getOuterClass();
520: if (owner == null) {
521: if (typeName.equals(getTypeName(
522: container.getClassElement(), false))) {
523: return owner;
524: }
525: return null;
526: } else {
527: return findConflictingByCodeGenName(owner, typeName);
528: }
529: }
530:
531: }
|