AbstractMVCGroupManager.java
001 /*
002  * Copyright 2009-2012 the original author or authors.
003  *
004  * Licensed under the Apache License, Version 2.0 (the "License");
005  * you may not use this file except in compliance with the License.
006  * You may obtain a copy of the License at
007  *
008  *      http://www.apache.org/licenses/LICENSE-2.0
009  *
010  * Unless required by applicable law or agreed to in writing, software
011  * distributed under the License is distributed on an "AS IS" BASIS,
012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013  * See the License for the specific language governing permissions and
014  * limitations under the License.
015  */
016 
017 package org.codehaus.griffon.runtime.core;
018 
019 import griffon.core.*;
020 import griffon.exceptions.MVCGroupConfigurationException;
021 import groovy.lang.Closure;
022 import groovy.util.FactoryBuilderSupport;
023 import org.slf4j.Logger;
024 import org.slf4j.LoggerFactory;
025 
026 import java.util.*;
027 
028 import static griffon.util.GriffonExceptionHandler.sanitize;
029 
030 /**
031  * Base implementation of the {@code MVCGroupManager} interface.
032  *
033  @author Andres Almiray
034  @since 0.9.4
035  */
036 public abstract class AbstractMVCGroupManager implements MVCGroupManager {
037     private static final Logger LOG = LoggerFactory.getLogger(AbstractMVCGroupManager.class);
038 
039     private final GriffonApplication app;
040 
041     private final Map<String, MVCGroupConfiguration> configurations = new LinkedHashMap<String, MVCGroupConfiguration>();
042     private final Map<String, MVCGroup> groups = new LinkedHashMap<String, MVCGroup>();
043     private final Object lock = new Object();
044     private boolean initialized;
045 
046     public AbstractMVCGroupManager(GriffonApplication app) {
047         this.app = app;
048     }
049 
050     public GriffonApplication getApp() {
051         return app;
052     }
053 
054     public Map<String, MVCGroupConfiguration> getConfigurations() {
055         synchronized (lock) {
056             return Collections.unmodifiableMap(configurations);
057         }
058     }
059 
060     public Map<String, MVCGroup> getGroups() {
061         synchronized (lock) {
062             return Collections.unmodifiableMap(groups);
063         }
064     }
065 
066     public MVCGroupConfiguration findConfiguration(String mvcType) {
067         MVCGroupConfiguration configuration = null;
068         synchronized (lock) {
069             configuration = configurations.get(mvcType);
070         }
071 
072         if (configuration == null) {
073             throw new MVCGroupConfigurationException("Unknown MVC type '" + mvcType + "'. Known types are " + configurations.keySet(), mvcType);
074         }
075         return configuration;
076     }
077 
078     public MVCGroup findGroup(String mvcId) {
079         synchronized (lock) {
080             if (LOG.isDebugEnabled()) {
081                 LOG.debug("Searching group " + mvcId);
082             }
083             return groups.get(mvcId);
084         }
085     }
086 
087     public MVCGroup getAt(String mvcId) {
088         return findGroup(mvcId);
089     }
090 
091     public final void initialize(Map<String, MVCGroupConfiguration> configurations) {
092         synchronized (lock) {
093             if (!initialized) {
094                 doInitialize(configurations);
095                 initialized = true;
096             }
097         }
098     }
099 
100     public void addConfiguration(MVCGroupConfiguration configuration) {
101         synchronized (lock) {
102             if (initialized && configurations.get(configuration.getMvcType()) != null) {
103                 return;
104             }
105             configurations.put(configuration.getMvcType(), configuration);
106         }
107     }
108 
109     protected void addGroup(MVCGroup group) {
110         synchronized (lock) {
111             if (group != null) {
112                 if (LOG.isDebugEnabled()) {
113                     LOG.debug("Adding group " + group.getMvcId() ":" + group);
114                 }
115                 groups.put(group.getMvcId(), group);
116             }
117         }
118     }
119 
120     protected void removeGroup(MVCGroup group) {
121         synchronized (lock) {
122             if (group != null) {
123                 if (LOG.isDebugEnabled()) {
124                     LOG.debug("Removing group " + group.getMvcId() ":" + group);
125                 }
126                 groups.remove(group.getMvcId());
127             }
128         }
129     }
130 
131     public MVCGroupConfiguration cloneMVCGroupConfiguration(String mvcType, Map<String, Object> config) {
132         MVCGroupConfiguration configuration = findConfiguration(mvcType);
133         Map<String, Object> configCopy = new LinkedHashMap<String, Object>();
134         configCopy.putAll(configuration.getConfig());
135         if (config != nullconfigCopy.putAll(config);
136         return newMVCGroupConfiguration(mvcType, configuration.getMembers(), configCopy);
137     }
138 
139     protected abstract void doInitialize(Map<String, MVCGroupConfiguration> configurations);
140 
141     public MVCGroup buildMVCGroup(String mvcType) {
142         return buildMVCGroup(findConfiguration(mvcType), mvcType, Collections.<String, Object>emptyMap());
143     }
144 
145     public MVCGroup buildMVCGroup(String mvcType, String mvcName) {
146         return buildMVCGroup(findConfiguration(mvcType), mvcName, Collections.<String, Object>emptyMap());
147     }
148 
149     public MVCGroup buildMVCGroup(Map<String, Object> args, String mvcType) {
150         return buildMVCGroup(findConfiguration(mvcType), mvcType, args);
151     }
152 
153     public MVCGroup buildMVCGroup(String mvcType, Map<String, Object> args) {
154         return buildMVCGroup(findConfiguration(mvcType), mvcType, args);
155     }
156 
157     public MVCGroup buildMVCGroup(Map<String, Object> args, String mvcType, String mvcName) {
158         return buildMVCGroup(findConfiguration(mvcType), mvcName, args);
159     }
160 
161     public MVCGroup buildMVCGroup(String mvcType, String mvcName, Map<String, Object> args) {
162         return buildMVCGroup(findConfiguration(mvcType), mvcName, args);
163     }
164 
165     public List<? extends GriffonMvcArtifact> createMVCGroup(String mvcType) {
166         return createMVCGroup(findConfiguration(mvcType), mvcType, Collections.<String, Object>emptyMap());
167     }
168 
169     public List<? extends GriffonMvcArtifact> createMVCGroup(Map<String, Object> args, String mvcType) {
170         return createMVCGroup(findConfiguration(mvcType), mvcType, args);
171     }
172 
173     public List<? extends GriffonMvcArtifact> createMVCGroup(String mvcType, Map<String, Object> args) {
174         return createMVCGroup(findConfiguration(mvcType), mvcType, args);
175     }
176 
177     public List<? extends GriffonMvcArtifact> createMVCGroup(String mvcType, String mvcName) {
178         return createMVCGroup(findConfiguration(mvcType), mvcName, Collections.<String, Object>emptyMap());
179     }
180 
181     public List<? extends GriffonMvcArtifact> createMVCGroup(Map<String, Object> args, String mvcType, String mvcName) {
182         return createMVCGroup(findConfiguration(mvcType), mvcName, args);
183     }
184 
185     public List<? extends GriffonMvcArtifact> createMVCGroup(String mvcType, String mvcName, Map<String, Object> args) {
186         return createMVCGroup(findConfiguration(mvcType), mvcName, args);
187     }
188 
189     public void withMVCGroup(String mvcType, Closure handler) {
190         withMVCGroup(findConfiguration(mvcType), mvcType, Collections.<String, Object>emptyMap(), handler);
191     }
192 
193     public void withMVCGroup(String mvcType, String mvcName, Closure handler) {
194         withMVCGroup(findConfiguration(mvcType), mvcName, Collections.<String, Object>emptyMap(), handler);
195     }
196 
197     public void withMVCGroup(String mvcType, Map<String, Object> args, Closure handler) {
198         withMVCGroup(findConfiguration(mvcType), mvcType, args, handler);
199     }
200 
201     public void withMVCGroup(Map<String, Object> args, String mvcType, Closure handler) {
202         withMVCGroup(findConfiguration(mvcType), mvcType, args, handler);
203     }
204 
205     public void withMVCGroup(Map<String, Object> args, String mvcType, String mvcName, Closure handler) {
206         withMVCGroup(findConfiguration(mvcType), mvcName, args, handler);
207     }
208 
209     public void withMVCGroup(String mvcType, String mvcName, Map<String, Object> args, Closure handler) {
210         withMVCGroup(findConfiguration(mvcType), mvcName, args, handler);
211     }
212 
213     public <M extends GriffonModel, V extends GriffonView, C extends GriffonController> void withMVCGroup(String mvcType, MVCClosure<M, V, C> handler) {
214         withMVCGroup(findConfiguration(mvcType), mvcType, Collections.<String, Object>emptyMap(), handler);
215     }
216 
217     public <M extends GriffonModel, V extends GriffonView, C extends GriffonController> void withMVCGroup(String mvcType, String mvcName, MVCClosure<M, V, C> handler) {
218         withMVCGroup(findConfiguration(mvcType), mvcName, Collections.<String, Object>emptyMap(), handler);
219     }
220 
221     public <M extends GriffonModel, V extends GriffonView, C extends GriffonController> void withMVCGroup(String mvcType, Map<String, Object> args, MVCClosure<M, V, C> handler) {
222         withMVCGroup(findConfiguration(mvcType), mvcType, args, handler);
223     }
224 
225     public <M extends GriffonModel, V extends GriffonView, C extends GriffonController> void withMVCGroup(Map<String, Object> args, String mvcType, MVCClosure<M, V, C> handler) {
226         withMVCGroup(findConfiguration(mvcType), mvcType, args, handler);
227     }
228 
229     public <M extends GriffonModel, V extends GriffonView, C extends GriffonController> void withMVCGroup(Map<String, Object> args, String mvcType, String mvcName, MVCClosure<M, V, C> handler) {
230         withMVCGroup(findConfiguration(mvcType), mvcName, args, handler);
231     }
232 
233     public <M extends GriffonModel, V extends GriffonView, C extends GriffonController> void withMVCGroup(String mvcType, String mvcName, Map<String, Object> args, MVCClosure<M, V, C> handler) {
234         withMVCGroup(findConfiguration(mvcType), mvcName, args, handler);
235     }
236 
237     protected List<? extends GriffonMvcArtifact> createMVCGroup(MVCGroupConfiguration configuration, String mvcName, Map<String, Object> args) {
238         MVCGroup group = buildMVCGroup(findConfiguration(configuration.getMvcType()), mvcName, args);
239         return Arrays.asList(group.getModel(), group.getView(), group.getController());
240     }
241 
242     protected void withMVCGroup(MVCGroupConfiguration configuration, String mvcId, Map<String, Object> args, Closure handler) {
243         MVCGroup group = null;
244         try {
245             group = buildMVCGroup(configuration, mvcId, args);
246             handler.call(group.getModel(), group.getView(), group.getController());
247         finally {
248             try {
249                 if (group != null) {
250                     destroyMVCGroup(group.getMvcId());
251                 }
252             catch (Exception x) {
253                 if (app.getLog().isWarnEnabled()) {
254                     app.getLog().warn("Could not destroy group [" + mvcId + "] of type " + configuration.getMvcType() ".", sanitize(x));
255                 }
256             }
257         }
258     }
259 
260     protected <M extends GriffonModel, V extends GriffonView, C extends GriffonController> void withMVCGroup(MVCGroupConfiguration configuration, String mvcId, Map<String, Object> args, MVCClosure<M, V, C> handler) {
261         MVCGroup group = null;
262         try {
263             group = buildMVCGroup(configuration, mvcId, args);
264             handler.call((Mgroup.getModel()(Vgroup.getView()(Cgroup.getController());
265         finally {
266             try {
267                 if (group != null) {
268                     destroyMVCGroup(group.getMvcId());
269                 }
270             catch (Exception x) {
271                 if (app.getLog().isWarnEnabled()) {
272                     app.getLog().warn("Could not destroy group [" + mvcId + "] of type " + configuration.getMvcType() ".", sanitize(x));
273                 }
274             }
275         }
276     }
277 
278     protected abstract MVCGroup buildMVCGroup(MVCGroupConfiguration configuration, String mvcId, Map<String, Object> args);
279 
280     public final Map<String, ? extends FactoryBuilderSupport> getBuilders() {
281         Map<String, FactoryBuilderSupport> builders = new LinkedHashMap<String, FactoryBuilderSupport>();
282         synchronized (lock) {
283             for (MVCGroup group : groups.values()) {
284                 FactoryBuilderSupport builder = group.getBuilder();
285                 if (builder != null) {
286                     builders.put(group.getMvcId(), builder);
287                 }
288             }
289         }
290         return Collections.unmodifiableMap(builders);
291     }
292 
293     public final Map<String, ? extends GriffonModel> getModels() {
294         Map<String, GriffonModel> models = new LinkedHashMap<String, GriffonModel>();
295         synchronized (lock) {
296             for (MVCGroup group : groups.values()) {
297                 GriffonModel model = group.getModel();
298                 if (model != null) {
299                     models.put(group.getMvcId(), model);
300                 }
301             }
302         }
303         return Collections.unmodifiableMap(models);
304     }
305 
306     public final Map<String, ? extends GriffonView> getViews() {
307         Map<String, GriffonView> views = new LinkedHashMap<String, GriffonView>();
308         synchronized (lock) {
309             for (MVCGroup group : groups.values()) {
310                 GriffonView view = group.getView();
311                 if (view != null) {
312                     views.put(group.getMvcId(), view);
313                 }
314             }
315         }
316         return Collections.unmodifiableMap(views);
317     }
318 
319     public final Map<String, ? extends GriffonController> getControllers() {
320         Map<String, GriffonController> controllers = new LinkedHashMap<String, GriffonController>();
321         synchronized (lock) {
322             for (MVCGroup group : groups.values()) {
323                 GriffonController controller = group.getController();
324                 if (controller != null) {
325                     controllers.put(group.getMvcId(), controller);
326                 }
327             }
328         }
329         return Collections.unmodifiableMap(controllers);
330     }
331 }