001: package org.andromda.core.repository;
002:
003: import org.andromda.core.common.AndroMDALogger;
004: import org.andromda.core.common.ComponentContainer;
005: import org.andromda.core.common.ExceptionUtils;
006: import org.andromda.core.common.Introspector;
007: import org.andromda.core.configuration.Model;
008: import org.andromda.core.configuration.Namespaces;
009: import org.andromda.core.namespace.PropertyDefinition;
010: import org.andromda.core.transformation.Transformer;
011: import org.apache.commons.lang.StringUtils;
012:
013: import java.io.IOException;
014: import java.io.InputStream;
015: import java.util.Collection;
016: import java.util.Iterator;
017: import java.util.LinkedHashMap;
018: import java.util.Map;
019:
020: /**
021: * This class provides access to all repositories available within the system (that
022: * is: any repository registered within a namespace).
023: *
024: * @author Chad Brandon
025: */
026: public class Repositories {
027: /**
028: * The shared instance of this class
029: */
030: private static Repositories instance;
031:
032: /**
033: * Retrieves the shared instance of this class.
034: *
035: * @return the shared instance.
036: */
037: public static Repositories instance() {
038: if (instance == null) {
039: instance = new Repositories();
040: }
041: return instance;
042: }
043:
044: /**
045: * Stores all the repository implementations keyed by name.
046: */
047: private final Map repositories = new LinkedHashMap();
048:
049: /**
050: * Discovers and initializes all repositories within this class.
051: */
052: public void initialize() {
053: // - find and open any repositories
054: if (this .repositories.isEmpty()) {
055: final Namespaces namespaces = Namespaces.instance();
056: final Collection repositories = ComponentContainer
057: .instance().findComponentsOfType(Repository.class);
058: for (final Iterator iterator = repositories.iterator(); iterator
059: .hasNext();) {
060: final Repository repository = (Repository) iterator
061: .next();
062: final RepositoryFacade repositoryImplementation = repository
063: .getImplementation();
064: final String namespace = repository.getNamespace();
065: final PropertyDefinition[] properties = namespaces
066: .getPropertyDefinitions(namespace);
067: if (properties != null && properties.length > 0) {
068: final int numberOfProperties = properties.length;
069: for (int ctr = 0; ctr < numberOfProperties; ctr++) {
070: final PropertyDefinition property = properties[ctr];
071: final String propertyName = property.getName();
072: if (Introspector.instance().isWritable(
073: repositoryImplementation, propertyName)) {
074: Introspector.instance().setProperty(
075: repositoryImplementation,
076: property.getName(),
077: namespaces.getPropertyValue(
078: namespace, property
079: .getName()));
080: }
081: }
082: }
083: repositoryImplementation.open();
084: this .repositories.put(namespace,
085: repositoryImplementation);
086: }
087: }
088: }
089:
090: /**
091: * Retrieves the repository implementation with the given name (i.e. namespace).
092: *
093: * @param name the name of the repository implementation to retrieve.
094: * @return the repository implementation.
095: */
096: public RepositoryFacade getImplementation(final String name) {
097: final RepositoryFacade implementation = (RepositoryFacade) this .repositories
098: .get(name);
099: if (implementation == null) {
100: String message;
101: if (this .repositories.isEmpty()) {
102: message = "No repository implementations have been registered, "
103: + "make sure you have at least one valid repository registered under a namespace on your classpath";
104: } else {
105: message = "No repository implementation registered under namespace '"
106: + name
107: + "', you must specify one of the following as your repository name: ["
108: + StringUtils.join(this .repositories.keySet()
109: .iterator(), ", ") + "]";
110: }
111: throw new RepositoryException(message);
112: }
113: return implementation;
114: }
115:
116: /**
117: * Loads the model defined in the configuration model instance into the repository
118: * to which the model belongs.
119: *
120: * If the model has previously been loaded, this will only load the model
121: * if it needs to be re-loaded (i.e. it has been changed).
122: *
123: * @param model the configuration model instance that contains the information about the model to load.
124: * @return true if the model was loaded/re-loaded, false if the model was already loaded, and not re-loaded.
125: */
126: public boolean loadModel(final Model model) {
127: ExceptionUtils.checkNull("model", model);
128: boolean loaded = model.isChanged();
129: if (loaded) {
130: final org.andromda.core.configuration.Repository repository = model
131: .getRepository();
132: final String repositoryName = repository != null ? repository
133: .getName()
134: : null;
135: if (repositoryName == null) {
136: throw new RepositoryException(
137: "Could not retrieve the repository to which the '"
138: + model + "' belongs");
139: }
140:
141: // - first perform any transformations
142: final Transformer transformer = (Transformer) ComponentContainer
143: .instance()
144: .findRequiredComponent(Transformer.class);
145: final String[] uris = model.getUris();
146: final int uriNumber = uris.length;
147: final InputStream[] streams = new InputStream[uriNumber];
148: for (int ctr = 0; ctr < uriNumber; ctr++) {
149: streams[ctr] = transformer.transform(uris[ctr], model
150: .getTransformations());
151: }
152:
153: // - now load the models into the repository
154: for (int ctr = 0; ctr < uriNumber; ctr++) {
155: final String uri = uris[ctr];
156: AndroMDALogger.info("loading model --> '" + uri + "'");
157: }
158: final RepositoryFacade repositoryImplementation = this
159: .getImplementation(repositoryName);
160: repositoryImplementation.readModel(streams, uris, model
161: .getModuleSearchLocationPaths());
162:
163: // - set the package filter
164: repositoryImplementation.getModel().setPackageFilter(
165: model.getPackages());
166: try {
167: for (int ctr = 0; ctr < uriNumber; ctr++) {
168: InputStream stream = streams[ctr];
169: stream.close();
170: stream = null;
171: }
172: } catch (final IOException exception) {
173: // ignore since the stream just couldn't be closed
174: }
175: }
176: return loaded;
177: }
178:
179: /**
180: * Clears out any resources used by this class.
181: */
182: public void clear() {
183: // - clear out any repositories
184: if (!this .repositories.isEmpty()) {
185: for (final Iterator iterator = this .repositories.values()
186: .iterator(); iterator.hasNext();) {
187: ((RepositoryFacade) iterator.next()).clear();
188: }
189: }
190: }
191: }
|