View Javadoc

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          // - find and open any repositories
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             // - first perform any transformations
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             // - now load the models into the repository
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             // - set the package filter
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                 // ignore since the stream just couldn't be closed
191             }
192         }
193         return loaded;
194     }
195 
196     /***
197      * Clears out any resources used by this class.
198      */
199     public void clear()
200     {
201         // - clear out any repositories
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 }