View Javadoc
1   package org.andromda.core.profile;
2   
3   import java.io.Serializable;
4   import java.net.URL;
5   import java.util.Collection;
6   import java.util.LinkedHashMap;
7   import java.util.Map;
8   import org.andromda.core.common.ComponentContainer;
9   import org.andromda.core.common.XmlObjectFactory;
10  import org.andromda.core.configuration.NamespaceProperties;
11  import org.andromda.core.configuration.Namespaces;
12  import org.andromda.core.configuration.Property;
13  import org.andromda.core.namespace.BaseNamespaceComponent;
14  import org.apache.commons.lang.StringUtils;
15  
16  /**
17   * Represents an AndroMDA profile applied to a model.
18   * Profiles allow us to extend aspects of a model.
19   *
20   * @author Chad Brandon
21   * @author Bob Fields
22   */
23  public class Profile
24      extends BaseNamespaceComponent
25      implements Serializable
26  {
27      private static final long serialVersionUID = 34L;
28  
29      /**
30       * The shared instance of this class.
31       */
32      private static Profile instance;
33  
34      /**
35       * Gets the shared instance of this class.
36       *
37       * @return the shared instance.
38       */
39      public static Profile instance()
40      {
41          if (instance == null)
42          {
43              instance = new Profile();
44          }
45          return instance;
46      }
47  
48      /**
49       * Stores the elements for the profile (by name).
50       */
51      private final Map<String, String> elements = new LinkedHashMap<String, String>();
52  
53      /**
54       * Adds a new element to this namespace registry.
55       * @param name
56       * @param value
57       */
58      public void addElement(
59          final String name,
60          final String value)
61      {
62          this.elements.put(
63              name,
64              value);
65      }
66  
67      /**
68       * Gets the profile value (if one is available)
69       * for the given name, otherwise returns name.
70       *
71       * @param name the profile name to retrieve.
72       * @return the value.
73       */
74      public String get(String name)
75      {
76          name = StringUtils.trim(name);
77          // - attempt to get the profile value from the profile defined
78          //   by the profile mappings uri first
79          String value = this.elements.get(name);
80  
81          // - if we can't get any profile value from an the override profile
82          //   mapping, then we resort to the ones defined in the namespace
83          if (StringUtils.isBlank(value))
84          {
85              Map<String, String> namespaceElements = this.getNamespaceElements(this.getNamespace());
86              if (namespaceElements != null)
87              {
88                  value = namespaceElements.get(name);
89              }
90              if (value == null)
91              {
92                  namespaceElements = this.getNamespaceElements(Namespaces.DEFAULT);
93                  if (namespaceElements != null)
94                  {
95                      value = namespaceElements.get(name);
96                  }
97              }
98          }
99          return value != null ? value : name;
100     }
101 
102     /**
103      * Initializes this profile instance.
104      */
105     public void initialize()
106     {
107         final Collection<Profile> profiles = ComponentContainer.instance().findComponentsOfType(Profile.class);
108         for (final Profile profile : profiles)
109         {
110             String namespace = profile.getNamespace();
111             if (Namespaces.instance().isShared(namespace))
112             {
113                 profile.setNamespace(Namespaces.DEFAULT);
114             }
115             this.addElements(profile);
116         }
117     }
118 
119     /**
120      * Refreshes the profile instance.
121      */
122     public void refresh()
123     {
124         // - clear out the instance's elements
125         this.elements.clear();
126         try
127         {
128             final Property mappingsUri =
129                 Namespaces.instance().getProperty(
130                     Namespaces.DEFAULT,
131                     NamespaceProperties.PROFILE_MAPPINGS_URI,
132                     false);
133             final String mappingsUriValue = mappingsUri != null ? mappingsUri.getValue() : null;
134             if (mappingsUriValue != null)
135             {
136                 final XmlObjectFactory factory = XmlObjectFactory.getInstance(Profile.class);
137                 final Profile profile = (Profile)factory.getObject(new URL(mappingsUriValue.trim()));
138                 this.elements.putAll(profile.elements);
139             }
140         }
141         catch (final Throwable throwable)
142         {
143             throw new ProfileException(throwable);
144         }
145     }
146 
147     /**
148      * Stores all elements.
149      */
150     private final Map<String, Map<String, String>> allElements = new LinkedHashMap<String, Map<String, String>>();
151 
152     /**
153      * Adds the elements to the internal elements map.
154      * @param profile Profile
155      */
156     private void addElements(final Profile profile)
157     {
158         final Collection<String> elements = profile != null ? profile.elements.keySet() : null;
159         if (elements != null && profile != null)
160         {
161             final String namespace = profile.getNamespace();
162             final Map<String, String> namespaceElements = this.getNamespaceElements(namespace);
163             for (final String name : elements)
164             {
165                 namespaceElements.put(
166                     name,
167                     profile.elements.get(name));
168             }
169         }
170     }
171 
172     /**
173      * Adds a namespace element for the given namespace with the given name and
174      * value.
175      * @param namespace the namespace for which to add the namespace element.
176      * @param name the element name.
177      * @param value the element value.
178      */
179     public void addElement(
180         final String namespace,
181         final String name,
182         final String value)
183     {
184         final Map<String, String> namespaceElements = this.getNamespaceElements(namespace);
185         namespaceElements.put(
186             name,
187             value);
188     }
189 
190     /**
191      * Retrieves the namespace elements map for the given namespace.
192      * If one doesn't exist, then a new one is created.
193      * @param namespace the namespace for which to retrieve the namespace elements
194      * @return the namespace element map
195      */
196     private Map<String, String> getNamespaceElements(final String namespace)
197     {
198         Map<String, String> namespaceElements = this.allElements.get(namespace);
199         if (namespaceElements == null)
200         {
201             namespaceElements = new LinkedHashMap<String, String>();
202             this.allElements.put(
203                 namespace,
204                 namespaceElements);
205         }
206         return namespaceElements;
207     }
208 
209     /**
210      * Shuts down the shared instance and releases any used resources.
211      */
212     public void shutdown()
213     {
214         Profile.instance = null;
215     }
216 }