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