001: package org.andromda.metafacades.uml14;
002:
003: import java.util.Collection;
004: import java.util.Iterator;
005:
006: import org.andromda.metafacades.uml.ClassifierFacade;
007: import org.andromda.metafacades.uml.NameMasker;
008: import org.andromda.metafacades.uml.TypeMappings;
009: import org.andromda.metafacades.uml.UMLMetafacadeProperties;
010: import org.andromda.metafacades.uml.UMLMetafacadeUtils;
011: import org.andromda.metafacades.uml.UMLProfile;
012: import org.andromda.utils.StringUtilsHelper;
013: import org.apache.commons.lang.BooleanUtils;
014: import org.apache.commons.lang.ObjectUtils;
015: import org.apache.commons.lang.StringUtils;
016: import org.omg.uml.foundation.core.AssociationEnd;
017: import org.omg.uml.foundation.datatypes.AggregationKindEnum;
018: import org.omg.uml.foundation.datatypes.ChangeableKindEnum;
019: import org.omg.uml.foundation.datatypes.Multiplicity;
020: import org.omg.uml.foundation.datatypes.MultiplicityRange;
021: import org.omg.uml.foundation.datatypes.OrderingKind;
022: import org.omg.uml.foundation.datatypes.OrderingKindEnum;
023:
024: /**
025: * Metaclass facade implementation.
026: */
027: public class AssociationEndFacadeLogicImpl extends
028: AssociationEndFacadeLogic implements
029: org.andromda.metafacades.uml.AssociationEndFacade {
030: public AssociationEndFacadeLogicImpl(
031: org.omg.uml.foundation.core.AssociationEnd metaObject,
032: String context) {
033: super (metaObject, context);
034: }
035:
036: /**
037: * @see org.andromda.core.metafacade.MetafacadeBase#getValidationOwner()
038: */
039: public Object getValidationOwner() {
040: return this .getType();
041: }
042:
043: /**
044: * @see org.andromda.metafacades.uml.AssociationEndFacade#getOtherEnd()
045: */
046: protected Object handleGetOtherEnd() {
047: final Collection ends = metaObject.getAssociation()
048: .getConnection();
049: for (final Iterator endIt = ends.iterator(); endIt.hasNext();) {
050: final AssociationEnd end = (AssociationEnd) endIt.next();
051: if (!metaObject.equals(end)) {
052: return end;
053: }
054: }
055: return null;
056: }
057:
058: /**
059: * @see org.andromda.metafacades.uml14.ModelElementFacadeLogic#handleGetName()
060: */
061: protected String handleGetName() {
062: String name = super .handleGetName();
063:
064: // if name is empty, then get the name from the type
065: if (StringUtils.isEmpty(name)) {
066: final ClassifierFacade type = this .getType();
067: if (type != null) {
068: name = StringUtils.uncapitalize(StringUtils
069: .trimToEmpty(type.getName()));
070: }
071: if (this .isMany() && this .isPluralizeAssociationEndNames()) {
072: name = StringUtilsHelper.pluralize(name);
073: }
074: }
075: final String nameMask = String
076: .valueOf(this
077: .getConfiguredProperty(UMLMetafacadeProperties.CLASSIFIER_PROPERTY_NAME_MASK));
078: return NameMasker.mask(name, nameMask);
079: }
080:
081: /**
082: * Indicates whether or not we should pluralize association end names.
083: *
084: * @return true/false
085: */
086: private boolean isPluralizeAssociationEndNames() {
087: final Object value = this
088: .getConfiguredProperty(UMLMetafacadeProperties.PLURALIZE_ASSOCIATION_END_NAMES);
089: return value != null
090: && Boolean.valueOf(String.valueOf(value))
091: .booleanValue();
092: }
093:
094: /**
095: * @see org.andromda.metafacades.uml.AssociationEndFacade#getType()
096: */
097: protected Object handleGetType() {
098: return metaObject.getParticipant();
099: }
100:
101: /**
102: * @see org.andromda.metafacades.uml.AssociationEndFacade#isOne2Many()
103: */
104: protected boolean handleIsOne2Many() {
105: return !this .isMany() && this .getOtherEnd().isMany();
106: }
107:
108: /**
109: * @see org.andromda.metafacades.uml.AssociationEndFacade#isMany2Many()
110: */
111: protected boolean handleIsMany2Many() {
112: return this .isMany() && this .getOtherEnd().isMany();
113: }
114:
115: /**
116: * @see org.andromda.metafacades.uml.AssociationEndFacade#isOne2One()
117: */
118: protected boolean handleIsOne2One() {
119: return !this .isMany() && !this .getOtherEnd().isMany();
120: }
121:
122: /**
123: * @see org.andromda.metafacades.uml.AssociationEndFacade#isMany2One()
124: */
125: protected boolean handleIsMany2One() {
126: return this .isMany() && !this .getOtherEnd().isMany();
127: }
128:
129: /**
130: * @see org.andromda.metafacades.uml.AssociationEndFacade#isMany()
131: */
132: protected boolean handleIsMany() {
133: boolean isMany = false;
134: final Multiplicity multiplicity = this .metaObject
135: .getMultiplicity();
136:
137: // we'll say a null multiplicity is 1
138: if (multiplicity != null) {
139: final Collection ranges = multiplicity.getRange();
140: if (ranges != null && !ranges.isEmpty()) {
141: final Iterator rangeIt = ranges.iterator();
142: while (rangeIt.hasNext()) {
143: final MultiplicityRange multiplicityRange = (MultiplicityRange) rangeIt
144: .next();
145: final int upper = multiplicityRange.getUpper();
146: isMany = upper > 1 || upper < 0;
147: }
148: }
149: }
150: return isMany;
151: }
152:
153: /**
154: * @see org.andromda.metafacades.uml.AssociationEndFacade#isOrdered()
155: */
156: protected boolean handleIsOrdered() {
157: boolean ordered = false;
158:
159: final OrderingKind ordering = metaObject.getOrdering();
160:
161: // no ordering is 'unordered'
162: if (ordering != null) {
163: ordered = ordering.equals(OrderingKindEnum.OK_ORDERED);
164: }
165:
166: return ordered;
167: }
168:
169: /**
170: * @see org.andromda.metafacades.uml.AssociationEndFacade#isAggregation()
171: */
172: protected boolean handleIsAggregation() {
173: return AggregationKindEnum.AK_AGGREGATE.equals(metaObject
174: .getAggregation());
175: }
176:
177: /**
178: * @see org.andromda.metafacades.uml.AssociationEndFacade#isComposition()
179: */
180: protected boolean handleIsComposition() {
181: return AggregationKindEnum.AK_COMPOSITE.equals(metaObject
182: .getAggregation());
183: }
184:
185: /**
186: * @see org.andromda.metafacades.uml.AssociationEndFacade#isReadOnly()
187: */
188: protected boolean handleIsReadOnly() {
189: return ChangeableKindEnum.CK_FROZEN.equals(metaObject
190: .getChangeability());
191: }
192:
193: /**
194: * @see org.andromda.metafacades.uml.AssociationEndFacade#isNavigable()
195: */
196: protected boolean handleIsNavigable() {
197: return metaObject.isNavigable();
198: }
199:
200: /**
201: * @see org.andromda.metafacades.uml.AssociationEndFacade#getGetterName()
202: */
203: protected java.lang.String handleGetGetterName() {
204: return UMLMetafacadeUtils.getGetterPrefix(this .getType())
205: + StringUtilsHelper.capitalize(this .getName());
206: }
207:
208: /**
209: * @see org.andromda.metafacades.uml.AssociationEndFacade#getSetterName()
210: */
211: protected java.lang.String handleGetSetterName() {
212: return "set" + StringUtils.capitalize(this .getName());
213: }
214:
215: /**
216: * @see org.andromda.metafacades.uml.AssociationEndFacade#getAssociation()
217: */
218: protected Object handleGetAssociation() {
219: return metaObject.getAssociation();
220: }
221:
222: /**
223: * @see org.andromda.metafacades.uml.AssociationEndFacade#getGetterSetterTypeName()
224: */
225: protected String handleGetGetterSetterTypeName() {
226: String name = null;
227: if (this .isMany()) {
228: final TypeMappings mappings = this .getLanguageMappings();
229: if (mappings != null) {
230: name = this .isOrdered() ? mappings
231: .getTo(UMLProfile.LIST_TYPE_NAME) : mappings
232: .getTo(UMLProfile.COLLECTION_TYPE_NAME);
233: }
234:
235: // set this association end's type as a template parameter if required
236: if (BooleanUtils
237: .toBoolean(ObjectUtils
238: .toString(this
239: .getConfiguredProperty(UMLMetafacadeProperties.ENABLE_TEMPLATING)))) {
240: name = name + "<"
241: + this .getType().getFullyQualifiedName() + ">";
242: }
243: }
244: if (name == null && this .getType() != null) {
245: name = this .getType().getFullyQualifiedName();
246: }
247: return name;
248: }
249:
250: /**
251: * @see org.andromda.metafacades.uml.AssociationEndFacade#isRequired()
252: */
253: protected boolean handleIsRequired() {
254: final int lower = this .getMultiplicityRangeLower();
255: return lower >= 1;
256: }
257:
258: /**
259: * @see org.andromda.metafacades.uml.AssociationEndFacade#isChild()
260: */
261: protected boolean handleIsChild() {
262: return this .getOtherEnd() != null
263: && this .getOtherEnd().isComposition();
264: }
265:
266: /**
267: * Returns the lower range of the multiplicty for the passed in associationEnd
268: *
269: * @return int the lower range of the multiplicty or 1 if it isn't defined.
270: */
271: private int getMultiplicityRangeLower() {
272: Integer lower = null;
273: final Multiplicity multiplicity = this .metaObject
274: .getMultiplicity();
275: if (multiplicity != null) {
276: final Collection ranges = multiplicity.getRange();
277: if (ranges != null && !ranges.isEmpty()) {
278: final Iterator rangeIt = ranges.iterator();
279: while (rangeIt.hasNext()) {
280: final MultiplicityRange multiplicityRange = (MultiplicityRange) rangeIt
281: .next();
282: lower = new Integer(multiplicityRange.getLower());
283: }
284: }
285: }
286: if (lower == null) {
287: final String defaultMultiplicity = this
288: .getDefaultMultiplicity();
289: if (defaultMultiplicity.startsWith("0")) {
290: lower = new Integer(0);
291: } else {
292: lower = new Integer(1);
293: }
294: }
295: return lower.intValue();
296: }
297:
298: /**
299: * Gets the default multiplicity for this attribute (the
300: * multiplicity if none is defined).
301: *
302: * @return the defautl multiplicity as a String.
303: */
304: private String getDefaultMultiplicity() {
305: return ObjectUtils
306: .toString(this
307: .getConfiguredProperty(UMLMetafacadeProperties.DEFAULT_MULTIPLICITY));
308: }
309:
310: /**
311: * Get the UML upper multiplicity
312: * Not implemented for UML1.4
313: */
314: protected int handleGetUpper() {
315: throw new java.lang.UnsupportedOperationException(
316: "'upper' is not a UML1.4 feature");
317: }
318:
319: /**
320: * Get the UML lower multiplicity
321: */
322: protected int handleGetLower() {
323: return this.getMultiplicityRangeLower();
324: }
325: }
|