View Javadoc
1   package org.andromda.core.common;
2   
3   import java.io.File;
4   import java.net.URL;
5   import java.util.ArrayList;
6   import java.util.Collection;
7   import java.util.LinkedHashMap;
8   import java.util.List;
9   import java.util.Map;
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.andromda.core.templateengine.TemplateEngine;
15  import org.apache.log4j.Logger;
16  
17  /**
18   * Represents the base plugin of AndroMDA. All Plugin instances inherit from this class.
19   *
20   * @author Chad Brandon
21   */
22  public abstract class BasePlugin
23      extends BaseNamespaceComponent
24      implements Plugin
25  {
26      /**
27       * Property references made available to the plugin
28       */
29      private final Collection<String> propertyReferences = new ArrayList<String>();
30  
31      /**
32       * The template objects made available to templates of this BasePlugin.
33       */
34      private final Collection<TemplateObject> templateObjects = new ArrayList<TemplateObject>();
35  
36      /**
37       * @see org.andromda.core.common.Plugin#initialize()
38       */
39      public void initialize()
40          throws Exception
41      {
42          // set the template engine merge location (this needs to be
43          // set before the template engine is initialized) so that the
44          // merge property can be set once on the template engine.
45          final Property mergeProperty =
46              Namespaces.instance().getProperty(
47                  this.getNamespace(),
48                  NamespaceProperties.MERGE_LOCATION,
49                  false);
50          this.mergeLocation = mergeProperty != null ? new File(mergeProperty.getValue()).toURI().toURL() : null;
51          if (this.mergeLocation != null)
52          {
53              this.getTemplateEngine().setMergeLocation(this.getMergeLocation().getFile());
54          }
55          this.getTemplateEngine().initialize(this.getNamespace());
56          for (final TemplateObject templateObject : this.templateObjects) {
57              templateObject.setResource(this.getResource());
58              templateObject.setNamespace(this.getNamespace());
59          }
60      }
61  
62      /**
63       * The current cartridge merge location.
64       */
65      private URL mergeLocation;
66  
67      /**
68       * Gets the current merge location for this plugin.
69       *
70       * @return the merge location (a file path).
71       */
72      protected URL getMergeLocation()
73      {
74          return this.mergeLocation;
75      }
76  
77      /**
78       * @see org.andromda.core.common.Plugin#shutdown()
79       */
80      public void shutdown()
81      {
82          this.getTemplateEngine().shutdown();
83      }
84  
85      /**
86       * Adds the <code>templateObject</code> to the collection of template objects that will be made available to the
87       * plugin during processing.
88       *
89       * @param templateObject the TemplateObject to add.
90       */
91      public void addTemplateObject(final TemplateObject templateObject)
92      {
93          if (templateObject != null)
94          {
95              this.templateObjects.add(templateObject);
96          }
97      }
98  
99      /**
100      * Adds a macro library to the TemplateEngine used by this BasePlugin.
101      *
102      * @param macrolibrary
103      */
104     public void addMacrolibrary(final String macrolibrary)
105     {
106         this.getTemplateEngine().addMacroLibrary(macrolibrary);
107     }
108 
109     /**
110      * @see org.andromda.core.common.Plugin#getTemplateObjects()
111      */
112     public Collection<TemplateObject> getTemplateObjects()
113     {
114         return this.templateObjects;
115     }
116 
117     private String templateEngineClass;
118 
119     /**
120      * Sets the template engine class for this cartridge.
121      *
122      * @param templateEngineClass the Class of the template engine implementation.
123      */
124     public void setTemplateEngineClass(final String templateEngineClass)
125     {
126         this.templateEngineClass = templateEngineClass;
127     }
128 
129     /**
130      * The template engine that this plugin will use.
131      */
132     private TemplateEngine templateEngine = null;
133 
134     /**
135      * @see org.andromda.core.common.Plugin#getTemplateEngine()
136      */
137     public TemplateEngine getTemplateEngine()
138     {
139         if (this.templateEngine == null)
140         {
141             this.templateEngine =
142                 (TemplateEngine)ComponentContainer.instance().newComponent(
143                     this.templateEngineClass, TemplateEngine.class);
144         }
145         return this.templateEngine;
146     }
147 
148     /**
149      * @see org.andromda.core.common.Plugin#getPropertyReferences()
150      */
151     public String[] getPropertyReferences()
152     {
153         return this.propertyReferences.toArray(new String[this.propertyReferences.size()]);
154     }
155 
156     /**
157      * Adds a property reference. Property references are those properties that are expected to be supplied by the
158      * calling client. These supplied properties are made available to the template during processing.
159      *
160      * @param reference the namespace of the reference.
161      */
162     public void addPropertyReference(final String reference)
163     {
164         this.propertyReferences.add(reference);
165     }
166 
167     /**
168      * Populates the <code>templateContext</code> with the properties and template objects defined in the
169      * <code>plugin</code>'s descriptor. If the <code>templateContext</code> is null, a new Map instance will be created
170      * before populating the context.
171      *
172      * @param templateContext the context of the template to populate.
173      */
174     protected void populateTemplateContext(Map<String, Object> templateContext)
175     {
176         if (templateContext == null)
177         {
178             templateContext = new LinkedHashMap<String, Object>();
179         }
180         this.addTemplateObjectsToContext(templateContext);
181         this.addPropertyReferencesToContext(templateContext);
182     }
183 
184     /**
185      * Takes all the template objects defined in the plugin's descriptor and places them in the
186      * <code>templateContext</code>.
187      *
188      * @param templateContext the template context
189      */
190     private void addTemplateObjectsToContext(final Map<String, Object> templateContext)
191     {
192         // add all the TemplateObject objects to the template context
193         final Collection<TemplateObject> templateObjects = this.getTemplateObjects();
194         if (templateObjects != null && !templateObjects.isEmpty())
195         {
196             for (TemplateObject templateObject : templateObjects)
197             {
198                 templateContext.put(
199                     templateObject.getName(),
200                     templateObject.getObject());
201             }
202         }
203     }
204 
205     /**
206      * Takes all the property references defined in the plugin's descriptor and looks up the corresponding values
207      * supplied by the calling client and supplies them to the <code>templateContext</code>.
208      *
209      * @param templateContext the template context
210      */
211     private void addPropertyReferencesToContext(final Map<String, Object> templateContext)
212     {
213         final String[] propertyReferences = this.getPropertyReferences();
214         if (propertyReferences != null && propertyReferences.length > 0)
215         {
216             final Namespaces namespaces = Namespaces.instance();
217             for (final String reference : propertyReferences) {
218                 templateContext.put(
219                         reference,
220                         namespaces.getPropertyValue(
221                                 this.getNamespace(),
222                                 reference));
223             }
224         }
225     }
226 
227     /**
228      * Stores the contents of the plugin.
229      */
230     private List<String> contents = null;
231 
232     /**
233      * @see org.andromda.core.common.Plugin#getContents()
234      */
235     public List<String> getContents()
236     {
237         if (this.contents == null)
238         {
239             if (ResourceUtils.isArchive(this.getResource()))
240             {
241                 this.contents = ResourceUtils.getClassPathArchiveContents(this.getResource());
242                 if (this.getMergeLocation() != null)
243                 {
244                     final Collection<String> mergeContents = ResourceUtils.getDirectoryContents(
245                             this.getMergeLocation(),
246                             0);
247                     if (mergeContents != null && !mergeContents.isEmpty())
248                     {
249                         this.contents.addAll(mergeContents);
250                     }
251                 }
252             }
253             else
254             {
255                 // we step down 1 level if its a directory (instead of an
256                 // archive since we get the contents relative to the plugin
257                 // resource which is in the META-INF directory
258                 this.contents = ResourceUtils.getDirectoryContents(
259                         this.getResource(),
260                         2);
261             }
262         }
263         return contents;
264     }
265 
266     /**
267      * Retrieves the logger instance that should be used for logging output for the plugin sub classes.
268      *
269      * @return the logger.
270      */
271     protected Logger getLogger()
272     {
273         return AndroMDALogger.getNamespaceLogger(this.getNamespace());
274     }
275 
276     /**
277      * @see Object#toString()
278      */
279     public String toString()
280     {
281         return super.toString() + '[' + this.getNamespace() + ']';
282     }
283 }