1 package org.andromda.core.repository;
2
3 import org.andromda.core.common.AndroMDALogger;
4 import org.andromda.core.common.ComponentContainer;
5 import org.andromda.core.common.ExceptionUtils;
6 import org.andromda.core.common.Introspector;
7 import org.andromda.core.configuration.Model;
8 import org.andromda.core.configuration.Namespaces;
9 import org.andromda.core.namespace.PropertyDefinition;
10 import org.andromda.core.transformation.Transformer;
11 import org.apache.commons.lang.StringUtils;
12
13 import java.io.IOException;
14 import java.io.InputStream;
15 import java.util.Collection;
16 import java.util.Iterator;
17 import java.util.LinkedHashMap;
18 import java.util.Map;
19
20
21 /***
22 * This class provides access to all repositories available within the system (that
23 * is: any repository registered within a namespace).
24 *
25 * @author Chad Brandon
26 */
27 public class Repositories
28 {
29 /***
30 * The shared instance of this class
31 */
32 private static Repositories instance;
33
34 /***
35 * Retrieves the shared instance of this class.
36 *
37 * @return the shared instance.
38 */
39 public static Repositories instance()
40 {
41 if (instance == null)
42 {
43 instance = new Repositories();
44 }
45 return instance;
46 }
47
48 /***
49 * Stores all the repository implementations keyed by name.
50 */
51 private final Map repositories = new LinkedHashMap();
52
53 /***
54 * Discovers and initializes all repositories within this class.
55 */
56 public void initialize()
57 {
58
59 if (this.repositories.isEmpty())
60 {
61 final Namespaces namespaces = Namespaces.instance();
62 final Collection repositories = ComponentContainer.instance().findComponentsOfType(Repository.class);
63 for (final Iterator iterator = repositories.iterator(); iterator.hasNext();)
64 {
65 final Repository repository = (Repository)iterator.next();
66 final RepositoryFacade repositoryImplementation = repository.getImplementation();
67 final String namespace = repository.getNamespace();
68 final PropertyDefinition[] properties = namespaces.getPropertyDefinitions(namespace);
69 if (properties != null && properties.length > 0)
70 {
71 final int numberOfProperties = properties.length;
72 for (int ctr = 0; ctr < numberOfProperties; ctr++)
73 {
74 final PropertyDefinition property = properties[ctr];
75 final String propertyName = property.getName();
76 if (Introspector.instance().isWritable(repositoryImplementation, propertyName))
77 {
78 Introspector.instance().setProperty(
79 repositoryImplementation,
80 property.getName(),
81 namespaces.getPropertyValue(
82 namespace,
83 property.getName()));
84 }
85 }
86 }
87 repositoryImplementation.open();
88 this.repositories.put(
89 namespace,
90 repositoryImplementation);
91 }
92 }
93 }
94
95 /***
96 * Retrieves the repository implementation with the given name (i.e. namespace).
97 *
98 * @param name the name of the repository implementation to retrieve.
99 * @return the repository implementation.
100 */
101 public RepositoryFacade getImplementation(final String name)
102 {
103 final RepositoryFacade implementation = (RepositoryFacade)this.repositories.get(name);
104 if (implementation == null)
105 {
106 String message;
107 if (this.repositories.isEmpty())
108 {
109 message =
110 "No repository implementations have been registered, " +
111 "make sure you have at least one valid repository registered under a namespace on your classpath";
112 }
113 else
114 {
115 message =
116 "No repository implementation registered under namespace '" + name +
117 "', you must specify one of the following as your repository name: [" +
118 StringUtils.join(
119 this.repositories.keySet().iterator(),
120 ", ") + "]";
121 }
122 throw new RepositoryException(message);
123 }
124 return implementation;
125 }
126
127 /***
128 * Loads the model defined in the configuration model instance into the repository
129 * to which the model belongs.
130 *
131 * If the model has previously been loaded, this will only load the model
132 * if it needs to be re-loaded (i.e. it has been changed).
133 *
134 * @param model the configuration model instance that contains the information about the model to load.
135 * @return true if the model was loaded/re-loaded, false if the model was already loaded, and not re-loaded.
136 */
137 public boolean loadModel(final Model model)
138 {
139 ExceptionUtils.checkNull(
140 "model",
141 model);
142 boolean loaded = model.isChanged();
143 if (loaded)
144 {
145 final org.andromda.core.configuration.Repository repository = model.getRepository();
146 final String repositoryName = repository != null ? repository.getName() : null;
147 if (repositoryName == null)
148 {
149 throw new RepositoryException("Could not retrieve the repository to which the '" + model + "' belongs");
150 }
151
152
153 final Transformer transformer =
154 (Transformer)ComponentContainer.instance().findRequiredComponent(Transformer.class);
155 final String[] uris = model.getUris();
156 final int uriNumber = uris.length;
157 final InputStream[] streams = new InputStream[uriNumber];
158 for (int ctr = 0; ctr < uriNumber; ctr++)
159 {
160 streams[ctr] = transformer.transform(
161 uris[ctr],
162 model.getTransformations());
163 }
164
165
166 for (int ctr = 0; ctr < uriNumber; ctr++)
167 {
168 final String uri = uris[ctr];
169 AndroMDALogger.info("loading model --> '" + uri + "'");
170 }
171 final RepositoryFacade repositoryImplementation = this.getImplementation(repositoryName);
172 repositoryImplementation.readModel(
173 streams,
174 uris,
175 model.getModuleSearchLocationPaths());
176
177
178 repositoryImplementation.getModel().setPackageFilter(model.getPackages());
179 try
180 {
181 for (int ctr = 0; ctr < uriNumber; ctr++)
182 {
183 InputStream stream = streams[ctr];
184 stream.close();
185 stream = null;
186 }
187 }
188 catch (final IOException exception)
189 {
190
191 }
192 }
193 return loaded;
194 }
195
196 /***
197 * Clears out any resources used by this class.
198 */
199 public void clear()
200 {
201
202 if (!this.repositories.isEmpty())
203 {
204 for (final Iterator iterator = this.repositories.values().iterator(); iterator.hasNext();)
205 {
206 ((RepositoryFacade)iterator.next()).clear();
207 }
208 }
209 }
210 }