View Javadoc
1   /*
2    * #%L
3    * EUGene :: EUGene
4    * %%
5    * Copyright (C) 2004 - 2010 CodeLutin
6    * %%
7    * This program is free software: you can redistribute it and/or modify
8    * it under the terms of the GNU Lesser General Public License as 
9    * published by the Free Software Foundation, either version 3 of the 
10   * License, or (at your option) any later version.
11   * 
12   * This program is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   * GNU General Lesser Public License for more details.
16   * 
17   * You should have received a copy of the GNU General Lesser Public 
18   * License along with this program.  If not, see
19   * <http://www.gnu.org/licenses/lgpl-3.0.html>.
20   * #L%
21   */
22  
23  package org.nuiton.eugene.models.object.xml;
24  
25  import com.google.common.collect.ImmutableSet;
26  import com.google.common.collect.Iterables;
27  import com.google.common.collect.Sets;
28  import org.apache.commons.lang3.StringUtils;
29  import org.nuiton.eugene.EugeneCoreTagValues;
30  import org.nuiton.eugene.GeneratorUtil;
31  import org.nuiton.eugene.models.object.ObjectModelAttribute;
32  import org.nuiton.eugene.models.object.ObjectModelClass;
33  import org.nuiton.eugene.models.object.ObjectModelClassifier;
34  import org.nuiton.eugene.models.object.ObjectModelJavaModifier;
35  import org.nuiton.eugene.models.object.ObjectModelModifier;
36  import org.nuiton.eugene.models.object.ObjectModelUMLModifier;
37  
38  import java.util.Set;
39  
40  /**
41   * ObjectModelAttributeImpl.
42   *
43   * Created: 14 janv. 2004
44   *
45   * @author Cédric Pineau - pineau@codelutin.com Copyright Code Lutin
46   */
47  public class ObjectModelAttributeImpl extends ObjectModelParameterImpl
48          implements ObjectModelAttribute {
49  
50      public static final String ATTRIBUTE_TYPE_AGGREGATE = "aggregate";
51  
52      public static final String ATTRIBUTE_TYPE_SHARED = "shared";
53  
54      public static final String ATTRIBUTE_TYPE_COMPOSITE = "composite";
55  
56      public static final ObjectModelJavaModifier DEFAULT_VISIBILITY = ObjectModelJavaModifier.PROTECTED;
57  
58      protected String reverseAttributeName;
59  
60      protected int reverseMaxMultiplicity = -1;
61  
62      protected ObjectModelClassifier reference;
63  
64      protected String associationClassName;
65  
66      private static Set<ObjectModelModifier> authorizedModifiers;
67  
68      public ObjectModelAttributeImpl() {
69          addModifier(ObjectModelUMLModifier.NAVIGABLE); // Navigable by default
70      }
71  
72      public void postInit() {
73          if (name == null) {
74              name = GeneratorUtil.toLowerCaseFirstLetter(GeneratorUtil.getClassNameFromQualifiedName(type));
75          }
76          super.postInit();
77      }
78  
79      public void setReverseAttributeName(String reverseAttributeName) {
80          this.reverseAttributeName = reverseAttributeName;
81      }
82  
83      public void setAssociationType(String associationType) {
84          removeModifiers(ObjectModelUMLModifier.associationTypes);
85          if (ATTRIBUTE_TYPE_SHARED.equals(associationType) || ATTRIBUTE_TYPE_AGGREGATE.equals(associationType)) {
86              addModifier(ObjectModelUMLModifier.AGGREGATE);
87          } else if (ATTRIBUTE_TYPE_COMPOSITE.equals(associationType)) {
88              addModifier(ObjectModelUMLModifier.COMPOSITE);
89          } else {
90              throw new IllegalArgumentException("Unexpected association type: " + associationType);
91          }
92      }
93  
94      public void setReverseMaxMultiplicity(int reverseMaxMultiplicity) {
95          this.reverseMaxMultiplicity = reverseMaxMultiplicity;
96      }
97  
98      public void setVisibility(String visibility) {
99          ObjectModelModifier modifier = ObjectModelJavaModifier.fromVisibility(visibility);
100         removeModifiers(ObjectModelJavaModifier.visibilityModifiers);
101         if (modifier == null) {
102             modifier = DEFAULT_VISIBILITY; // default visibility
103         }
104         addModifier(modifier);
105     }
106 
107     public void setFinal(boolean isFinal) {
108         addOrRemoveModifier(ObjectModelJavaModifier.FINAL, isFinal);
109     }
110 
111     public void setTransient(boolean isTransient) {
112         addOrRemoveModifier(ObjectModelJavaModifier.TRANSIENT, isTransient);
113     }
114 
115     public void setStatic(boolean isStatic) {
116         super.setStatic(isStatic);
117     }
118 
119     @Override
120     protected Set<ObjectModelModifier> getAuthorizedModifiers() {
121         if (authorizedModifiers == null) {
122             // http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.3.1
123             // static final transient volatile
124             Set<ObjectModelModifier> modifiers = Sets.newHashSet(
125                     (ObjectModelModifier) ObjectModelJavaModifier.STATIC, // Force cast because of generics limitation
126                     ObjectModelJavaModifier.FINAL,
127                     ObjectModelJavaModifier.TRANSIENT,
128                     ObjectModelJavaModifier.VOLATILE,
129                     ObjectModelUMLModifier.AGGREGATE,
130                     ObjectModelUMLModifier.COMPOSITE,
131                     ObjectModelUMLModifier.NAVIGABLE,
132                     ObjectModelUMLModifier.ORDERED,
133                     ObjectModelUMLModifier.UNIQUE
134             );
135             Iterables.addAll(modifiers, ObjectModelJavaModifier.visibilityModifiers);
136             authorizedModifiers = ImmutableSet.copyOf(modifiers);
137         }
138         return authorizedModifiers;
139     }
140 
141     public void setNavigable(boolean navigable) {
142         addOrRemoveModifier(ObjectModelUMLModifier.NAVIGABLE, navigable);
143     }
144 
145     @Override
146     public void setUnique(boolean isUnique) {
147         super.setUnique(isUnique);
148     }
149 
150     /**
151      * Returns whether this attribute is an aggregate or not.
152      *
153      * @return a boolean indicating whether this attribute is an aggregate or
154      * not.
155      */
156     @Override
157     public boolean isAggregate() {
158         return modifiers.contains(ObjectModelUMLModifier.AGGREGATE);
159     }
160 
161     /**
162      * Returns whether this attribute is an composite or not.
163      *
164      * @return a boolean indicating whether this attribute is an composite or
165      * not.
166      */
167     @Override
168     public boolean isComposite() {
169         return modifiers.contains(ObjectModelUMLModifier.COMPOSITE);
170     }
171 
172     @Override
173     public String getVisibility() {
174         String visibility = DEFAULT_VISIBILITY.toString(); // default
175         if (modifiers.contains(ObjectModelJavaModifier.PUBLIC)) {
176             visibility = ObjectModelJavaModifier.PUBLIC.toString();
177         } else if (modifiers.contains(ObjectModelJavaModifier.PRIVATE)) {
178             visibility = ObjectModelJavaModifier.PRIVATE.toString();
179         }
180         if (modifiers.contains(ObjectModelJavaModifier.PACKAGE)) {
181             visibility = ObjectModelJavaModifier.PACKAGE.toString();
182         }
183         return visibility;
184     }
185 
186     public void setAssociationClassName(String associationClassName) {
187         this.associationClassName = associationClassName;
188     }
189 
190     /**
191      * Returns whether this attribute reference a model classifier or not.
192      *
193      * @return a boolean indicating whether this attribute reference a model
194      * classifier or not.
195      */
196     @Override
197     public boolean referenceClassifier() {
198         return getClassifier() != null;
199     }
200 
201     /**
202      * Returns the classifier referenced by this attribute or null if it does
203      * not reference a model classifier.
204      *
205      * @return the ObjectModelClassfifier referenced by this attribute or null
206      * if it does not reference a model classifier.
207      */
208     @Override
209     public ObjectModelClassifier getClassifier() {
210         return getModel().getClassifier(type);
211     }
212 
213     /**
214      * Returns the attribute used to reference this class at the other end of
215      * the association or null if this is not an association, or if it is not
216      * bi-directionnal. @ see #getClassifier()
217      *
218      * @return the ObjectModelAttribute used to reference this class at the
219      * other end of the association or null if this is not an
220      * association, or if it is not bi-directionnal.
221      */
222     @Override
223     public ObjectModelAttribute getReverseAttribute() {
224         ObjectModelAttribute reverseAttribute = null;
225         ObjectModelClassifier classifier = getClassifier();
226         if (classifier instanceof ObjectModelClass) {
227             reverseAttribute = classifier.getAttribute(getReverseAttributeName());
228         }
229         return reverseAttribute;
230     }
231 
232     @Override
233     public String getReverseAttributeName() {
234         if (StringUtils.isEmpty(reverseAttributeName)) {
235             reverseAttributeName = GeneratorUtil
236                     .toLowerCaseFirstLetter(getDeclaringElement().getName());
237         }
238         return reverseAttributeName;
239     }
240 
241     @Override
242     public String getName() {
243         if (StringUtils.isEmpty(name) && getClassifier() != null) {
244             name = GeneratorUtil.toLowerCaseFirstLetter(getClassifier()
245                                                                 .getName());
246         }
247         return name;
248     }
249 
250     @Override
251     public int getReverseMaxMultiplicity() {
252         return reverseMaxMultiplicity;
253     }
254 
255     /**
256      * Returns the association class associated with this association, or null
257      * if there is none.
258      *
259      * @return a ObjectModelClass corresponding to the association class
260      * associated with this association, or null if there is none.
261      */
262     @Override
263     public ObjectModelClass getAssociationClass() {
264         return getModel().getClass(associationClassName);
265     }
266 
267     /**
268      * Returns whether this association has an associated association class, ot
269      * not.
270      *
271      * @return a boolean indicating whether this association has an associated
272      * association class, ot not.
273      */
274     @Override
275     public boolean hasAssociationClass() {
276         return getAssociationClass() != null;
277     }
278 
279     /**
280      * Returns whether this attribute is final or not.
281      *
282      * @return a boolean indicating whether this attribute is final or not.
283      */
284     @Override
285     public boolean isFinal() {
286         return modifiers.contains(ObjectModelJavaModifier.FINAL);
287     }
288 
289     public boolean isTransient() {
290         return modifiers.contains(ObjectModelJavaModifier.TRANSIENT);
291     }
292 
293     @Override
294     public boolean isNavigable() {
295         return modifiers.contains(ObjectModelUMLModifier.NAVIGABLE);
296     }
297 
298     @Override
299     public ObjectModelImplRef addStereotype(ObjectModelImplRef stereotype) {
300         String stereotypeName = stereotype.getName();
301         if (EugeneCoreTagValues.Store.ordered.getName().equals(stereotypeName)) {
302             setOrdered(true);
303         }
304         return super.addStereotype(stereotype);
305     }
306 }