001: package org.andromda.core.common;
002:
003: import java.io.File;
004: import java.net.URL;
005: import java.util.ArrayList;
006: import java.util.Collection;
007: import java.util.Iterator;
008: import java.util.LinkedHashMap;
009: import java.util.List;
010: import java.util.Map;
011:
012: import org.andromda.core.configuration.NamespaceProperties;
013: import org.andromda.core.configuration.Namespaces;
014: import org.andromda.core.configuration.Property;
015: import org.andromda.core.namespace.BaseNamespaceComponent;
016: import org.andromda.core.templateengine.TemplateEngine;
017: import org.apache.log4j.Logger;
018:
019: /**
020: * Represents the base plugin of AndroMDA. All Plugin instances inherit from this class.
021: *
022: * @author Chad Brandon
023: */
024: public abstract class BasePlugin extends BaseNamespaceComponent
025: implements Plugin {
026: /**
027: * Property references made available to the plugin
028: */
029: private final Collection propertyReferences = new ArrayList();
030:
031: /**
032: * The template objects made available to templates of this BasePlugin.
033: */
034: private final Collection templateObjects = new ArrayList();
035:
036: /**
037: * @see org.andromda.core.common.Plugin#initialize()
038: */
039: public void initialize() throws Exception {
040: // set the template engine merge location (this needs to be
041: // set before the template engine is initialized) so that the
042: // merge property can be set once on the template engine.
043: final Property mergeProperty = Namespaces.instance()
044: .getProperty(this .getNamespace(),
045: NamespaceProperties.MERGE_LOCATION, false);
046: this .mergeLocation = mergeProperty != null ? new File(
047: mergeProperty.getValue()).toURL() : null;
048: if (this .mergeLocation != null) {
049: this .getTemplateEngine().setMergeLocation(
050: this .getMergeLocation().getFile());
051: }
052: this .getTemplateEngine().initialize(this .getNamespace());
053: for (final Iterator iterator = this .templateObjects.iterator(); iterator
054: .hasNext();) {
055: final TemplateObject templateObject = (TemplateObject) iterator
056: .next();
057: templateObject.setResource(this .getResource());
058: templateObject.setNamespace(this .getNamespace());
059: }
060: }
061:
062: /**
063: * The current cartridge merge location.
064: */
065: private URL mergeLocation;
066:
067: /**
068: * Gets the current merge location for this plugin.
069: *
070: * @return the merge location (a file path).
071: */
072: protected URL getMergeLocation() {
073: return this .mergeLocation;
074: }
075:
076: /**
077: * @see org.andromda.core.common.Plugin#shutdown()
078: */
079: public void shutdown() {
080: this .getTemplateEngine().shutdown();
081: }
082:
083: /**
084: * Adds the <code>templateObject</code> to the collection of template objects that will be made available to the
085: * plugin during processing.
086: *
087: * @param templateObject the TemplateObject to add.
088: */
089: public void addTemplateObject(final TemplateObject templateObject) {
090: if (templateObject != null) {
091: this .templateObjects.add(templateObject);
092: }
093: }
094:
095: /**
096: * Adds a macro library to the TemplateEngine used by this BasePlugin.
097: *
098: * @param macrolibrary
099: */
100: public void addMacrolibrary(final String macrolibrary) {
101: this .getTemplateEngine().addMacroLibrary(macrolibrary);
102: }
103:
104: /**
105: * @see org.andromda.core.common.Plugin#getTemplateObjects()
106: */
107: public Collection getTemplateObjects() {
108: return this .templateObjects;
109: }
110:
111: private String templateEngineClass;
112:
113: /**
114: * Sets the template engine class for this cartridge.
115: *
116: * @param templateEngineClass the Class of the template engine implementation.
117: */
118: public void setTemplateEngineClass(final String templateEngineClass) {
119: this .templateEngineClass = templateEngineClass;
120: }
121:
122: /**
123: * The template engine that this plugin will use.
124: */
125: private TemplateEngine templateEngine = null;
126:
127: /**
128: * @see org.andromda.core.common.Plugin#getTemplateEngine()
129: */
130: public TemplateEngine getTemplateEngine() {
131: if (this .templateEngine == null) {
132: this .templateEngine = (TemplateEngine) ComponentContainer
133: .instance().newComponent(this .templateEngineClass,
134: TemplateEngine.class);
135: }
136: return this .templateEngine;
137: }
138:
139: /**
140: * @see org.andromda.core.common.Plugin#getPropertyReferences()
141: */
142: public String[] getPropertyReferences() {
143: return (String[]) this .propertyReferences
144: .toArray(new String[0]);
145: }
146:
147: /**
148: * Adds a property reference. Property references are those properties that are expected to be supplied by the
149: * calling client. These supplied properties are made available to the template during processing.
150: *
151: * @param reference the namespace of the reference.
152: */
153: public void addPropertyReference(final String reference) {
154: this .propertyReferences.add(reference);
155: }
156:
157: /**
158: * Populates the <code>templateContext</code> with the properties and template objects defined in the
159: * <code>plugin</code>'s descriptor. If the <code>templateContext</code> is null, a new Map instance will be created
160: * before populating the context.
161: *
162: * @param templateContext the context of the template to populate.
163: */
164: protected void populateTemplateContext(Map templateContext) {
165: if (templateContext == null) {
166: templateContext = new LinkedHashMap();
167: }
168: this .addTemplateObjectsToContext(templateContext);
169: this .addPropertyReferencesToContext(templateContext);
170: }
171:
172: /**
173: * Takes all the template objects defined in the plugin's descriptor and places them in the
174: * <code>templateContext</code>.
175: *
176: * @param templateContext the template context
177: */
178: private void addTemplateObjectsToContext(final Map templateContext) {
179: // add all the TemplateObject objects to the template context
180: final Collection templateObjects = this .getTemplateObjects();
181: if (templateObjects != null && !templateObjects.isEmpty()) {
182: for (final Iterator iterator = templateObjects.iterator(); iterator
183: .hasNext();) {
184: final TemplateObject templateObject = (TemplateObject) iterator
185: .next();
186: templateContext.put(templateObject.getName(),
187: templateObject.getObject());
188: }
189: }
190: }
191:
192: /**
193: * Takes all the property references defined in the plugin's descriptor and looks up the corresponding values
194: * supplied by the calling client and supplies them to the <code>templateContext</code>.
195: *
196: * @param templateContext the template context
197: */
198: private void addPropertyReferencesToContext(
199: final Map templateContext) {
200: final String[] propertyReferences = this
201: .getPropertyReferences();
202: if (propertyReferences != null && propertyReferences.length > 0) {
203: final Namespaces namespaces = Namespaces.instance();
204: for (int ctr = 0; ctr < propertyReferences.length; ctr++) {
205: final String reference = propertyReferences[ctr];
206: templateContext.put(reference, namespaces
207: .getPropertyValue(this .getNamespace(),
208: reference));
209: }
210: }
211: }
212:
213: /**
214: * Stores the contents of the plugin.
215: */
216: private List contents = null;
217:
218: /**
219: * @see org.andromda.core.common.Plugin#getContents()
220: */
221: public List getContents() {
222: if (this .contents == null) {
223: if (ResourceUtils.isArchive(this .getResource())) {
224: this .contents = ResourceUtils
225: .getClassPathArchiveContents(this .getResource());
226: if (this .getMergeLocation() != null) {
227: final Collection mergeContents = ResourceUtils
228: .getDirectoryContents(this
229: .getMergeLocation(), 0);
230: if (mergeContents != null
231: && !mergeContents.isEmpty()) {
232: this .contents.addAll(mergeContents);
233: }
234: }
235: } else {
236: // we step down 1 level if its a directory (instead of an
237: // archive since we get the contents relative to the plugin
238: // resource which is in the META-INF directory
239: this .contents = ResourceUtils.getDirectoryContents(this
240: .getResource(), 2);
241: }
242: }
243: return contents;
244: }
245:
246: /**
247: * Retrieves the logger instance that should be used for logging output for the plugin sub classes.
248: *
249: * @return the logger.
250: */
251: protected Logger getLogger() {
252: return AndroMDALogger.getNamespaceLogger(this .getNamespace());
253: }
254:
255: /**
256: * @see java.lang.Object#toString()
257: */
258: public String toString() {
259: return super .toString() + "[" + this .getNamespace() + "]";
260: }
261: }
|