AbstractMVCGroupManager.java
001 /*
002  * Copyright 2009-2013 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 import static griffon.util.GriffonNameUtils.isBlank;
030 
031 /**
032  * Base implementation of the {@code MVCGroupManager} interface.
033  *
034  @author Andres Almiray
035  @since 0.9.4
036  */
037 public abstract class AbstractMVCGroupManager implements MVCGroupManager {
038     private static final Logger LOG = LoggerFactory.getLogger(AbstractMVCGroupManager.class);
039 
040     private final GriffonApplication app;
041 
042     private final Map<String, MVCGroupConfiguration> configurations = new LinkedHashMap<String, MVCGroupConfiguration>();
043     private final Map<String, MVCGroup> groups = new LinkedHashMap<String, MVCGroup>();
044     private final Object lock = new Object();
045     private boolean initialized;
046 
047     public AbstractMVCGroupManager(GriffonApplication app) {
048         this.app = app;
049     }
050 
051     public GriffonApplication getApp() {
052         return app;
053     }
054 
055     public Map<String, MVCGroupConfiguration> getConfigurations() {
056         synchronized (lock) {
057             return Collections.unmodifiableMap(configurations);
058         }
059     }
060 
061     public Map<String, MVCGroup> getGroups() {
062         synchronized (lock) {
063             return Collections.unmodifiableMap(groups);
064         }
065     }
066 
067     public MVCGroupConfiguration findConfiguration(String mvcType) {
068         MVCGroupConfiguration configuration = null;
069         synchronized (lock) {
070             configuration = configurations.get(mvcType);
071         }
072 
073         if (configuration == null) {
074             throw new MVCGroupConfigurationException("Unknown MVC type '" + mvcType + "'. Known types are " + configurations.keySet(), mvcType);
075         }
076         return configuration;
077     }
078 
079     public MVCGroup findGroup(String mvcId) {
080         synchronized (lock) {
081             if (LOG.isDebugEnabled()) {
082                 LOG.debug("Searching group " + mvcId);
083             }
084             return groups.get(mvcId);
085         }
086     }
087 
088     public MVCGroup getAt(String mvcId) {
089         return findGroup(mvcId);
090     }
091 
092     public final void initialize(Map<String, MVCGroupConfiguration> configurations) {
093         synchronized (lock) {
094             if (!initialized) {
095                 doInitialize(configurations);
096                 initialized = true;
097             }
098         }
099     }
100 
101     public void addConfiguration(MVCGroupConfiguration configuration) {
102         synchronized (lock) {
103             if (initialized && configurations.get(configuration.getMvcType()) != null) {
104                 return;
105             }
106             configurations.put(configuration.getMvcType(), configuration);
107         }
108     }
109 
110     public void removeConfiguration(MVCGroupConfiguration configuration) {
111         if (configuration != null) {
112             removeConfiguration(configuration.getMvcType());
113         }
114     }
115 
116     public void removeConfiguration(String name) {
117         if (!isBlank(name)) {
118             synchronized (lock) {
119                 configurations.remove(name);
120             }
121         }
122     }
123 
124     protected void addGroup(MVCGroup group) {
125         synchronized (lock) {
126             if (group != null) {
127                 if (LOG.isDebugEnabled()) {
128                     LOG.debug("Adding group " + group.getMvcId() ":" + group);
129                 }
130                 groups.put(group.getMvcId(), group);
131             }
132         }
133     }
134 
135     protected void removeGroup(MVCGroup group) {
136         synchronized (lock) {
137             if (group != null) {
138                 if (LOG.isDebugEnabled()) {
139                     LOG.debug("Removing group " + group.getMvcId() ":" + group);
140                 }
141                 groups.remove(group.getMvcId());
142             }
143         }
144     }
145 
146     public MVCGroupConfiguration cloneMVCGroupConfiguration(String mvcType, Map<String, Object> config) {
147         MVCGroupConfiguration configuration = findConfiguration(mvcType);
148         Map<String, Object> configCopy = new LinkedHashMap<String, Object>();
149         configCopy.putAll(configuration.getConfig());
150         if (config != nullconfigCopy.putAll(config);
151         return newMVCGroupConfiguration(mvcType, configuration.getMembers(), configCopy);
152     }
153 
154     protected abstract void doInitialize(Map<String, MVCGroupConfiguration> configurations);
155 
156     public MVCGroup buildMVCGroup(String mvcType) {
157         return buildMVCGroup(findConfiguration(mvcType), null, Collections.<String, Object>emptyMap());
158     }
159 
160     public MVCGroup buildMVCGroup(String mvcType, String mvcName) {
161         return buildMVCGroup(findConfiguration(mvcType), mvcName, Collections.<String, Object>emptyMap());
162     }
163 
164     public MVCGroup buildMVCGroup(Map<String, Object> args, String mvcType) {
165         return buildMVCGroup(findConfiguration(mvcType), null, args);
166     }
167 
168     public MVCGroup buildMVCGroup(String mvcType, Map<String, Object> args) {
169         return buildMVCGroup(findConfiguration(mvcType), null, args);
170     }
171 
172     public MVCGroup buildMVCGroup(Map<String, Object> args, String mvcType, String mvcName) {
173         return buildMVCGroup(findConfiguration(mvcType), mvcName, args);
174     }
175 
176     public MVCGroup buildMVCGroup(String mvcType, String mvcName, Map<String, Object> args) {
177         return buildMVCGroup(findConfiguration(mvcType), mvcName, args);
178     }
179 
180     public List<? extends GriffonMvcArtifact> createMVCGroup(String mvcType) {
181         return createMVCGroup(findConfiguration(mvcType), null, Collections.<String, Object>emptyMap());
182     }
183 
184     public List<? extends GriffonMvcArtifact> createMVCGroup(Map<String, Object> args, String mvcType) {
185         return createMVCGroup(findConfiguration(mvcType), null, args);
186     }
187 
188     public List<? extends GriffonMvcArtifact> createMVCGroup(String mvcType, Map<String, Object> args) {
189         return createMVCGroup(findConfiguration(mvcType), null, args);
190     }
191 
192     public List<? extends GriffonMvcArtifact> createMVCGroup(String mvcType, String mvcName) {
193         return createMVCGroup(findConfiguration(mvcType), mvcName, Collections.<String, Object>emptyMap());
194     }
195 
196     public List<? extends GriffonMvcArtifact> createMVCGroup(Map<String, Object> args, String mvcType, String mvcName) {
197         return createMVCGroup(findConfiguration(mvcType), mvcName, args);
198     }
199 
200     public List<? extends GriffonMvcArtifact> createMVCGroup(String mvcType, String mvcName, Map<String, Object> args) {
201         return createMVCGroup(findConfiguration(mvcType), mvcName, args);
202     }
203 
204     public void withMVCGroup(String mvcType, Closure handler) {
205         withMVCGroup(findConfiguration(mvcType), null, Collections.<String, Object>emptyMap(), handler);
206     }
207 
208     public void withMVCGroup(String mvcType, String mvcName, Closure handler) {
209         withMVCGroup(findConfiguration(mvcType), mvcName, Collections.<String, Object>emptyMap(), handler);
210     }
211 
212     public void withMVCGroup(String mvcType, Map<String, Object> args, Closure handler) {
213         withMVCGroup(findConfiguration(mvcType), null, args, handler);
214     }
215 
216     public void withMVCGroup(Map<String, Object> args, String mvcType, Closure handler) {
217         withMVCGroup(findConfiguration(mvcType), null, args, handler);
218     }
219 
220     public void withMVCGroup(Map<String, Object> args, String mvcType, String mvcName, Closure handler) {
221         withMVCGroup(findConfiguration(mvcType), mvcName, args, handler);
222     }
223 
224     public void withMVCGroup(String mvcType, String mvcName, Map<String, Object> args, Closure handler) {
225         withMVCGroup(findConfiguration(mvcType), mvcName, args, handler);
226     }
227 
228     public <M extends GriffonModel, V extends GriffonView, C extends GriffonController> void withMVCGroup(String mvcType, MVCClosure<M, V, C> handler) {
229         withMVCGroup(findConfiguration(mvcType), null, Collections.<String, Object>emptyMap(), handler);
230     }
231 
232     public <M extends GriffonModel, V extends GriffonView, C extends GriffonController> void withMVCGroup(String mvcType, String mvcName, MVCClosure<M, V, C> handler) {
233         withMVCGroup(findConfiguration(mvcType), mvcName, Collections.<String, Object>emptyMap(), handler);
234     }
235 
236     public <M extends GriffonModel, V extends GriffonView, C extends GriffonController> void withMVCGroup(String mvcType, Map<String, Object> args, MVCClosure<M, V, C> handler) {
237         withMVCGroup(findConfiguration(mvcType), null, args, handler);
238     }
239 
240     public <M extends GriffonModel, V extends GriffonView, C extends GriffonController> void withMVCGroup(Map<String, Object> args, String mvcType, MVCClosure<M, V, C> handler) {
241         withMVCGroup(findConfiguration(mvcType), null, args, handler);
242     }
243 
244     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) {
245         withMVCGroup(findConfiguration(mvcType), mvcName, args, handler);
246     }
247 
248     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) {
249         withMVCGroup(findConfiguration(mvcType), mvcName, args, handler);
250     }
251 
252     protected List<? extends GriffonMvcArtifact> createMVCGroup(MVCGroupConfiguration configuration, String mvcName, Map<String, Object> args) {
253         MVCGroup group = buildMVCGroup(findConfiguration(configuration.getMvcType()), mvcName, args);
254         return Arrays.asList(group.getModel(), group.getView(), group.getController());
255     }
256 
257     protected void withMVCGroup(MVCGroupConfiguration configuration, String mvcId, Map<String, Object> args, Closure handler) {
258         MVCGroup group = null;
259         try {
260             group = buildMVCGroup(configuration, mvcId, args);
261             handler.call(group.getModel(), group.getView(), group.getController());
262         finally {
263             try {
264                 if (group != null) {
265                     destroyMVCGroup(group.getMvcId());
266                 }
267             catch (Exception x) {
268                 if (app.getLog().isWarnEnabled()) {
269                     app.getLog().warn("Could not destroy group [" + mvcId + "] of type " + configuration.getMvcType() ".", sanitize(x));
270                 }
271             }
272         }
273     }
274 
275     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) {
276         MVCGroup group = null;
277         try {
278             group = buildMVCGroup(configuration, mvcId, args);
279             handler.call((Mgroup.getModel()(Vgroup.getView()(Cgroup.getController());
280         finally {
281             try {
282                 if (group != null) {
283                     destroyMVCGroup(group.getMvcId());
284                 }
285             catch (Exception x) {
286                 if (app.getLog().isWarnEnabled()) {
287                     app.getLog().warn("Could not destroy group [" + mvcId + "] of type " + configuration.getMvcType() ".", sanitize(x));
288                 }
289             }
290         }
291     }
292 
293     protected abstract MVCGroup buildMVCGroup(MVCGroupConfiguration configuration, String mvcId, Map<String, Object> args);
294 
295     public final Map<String, ? extends FactoryBuilderSupport> getBuilders() {
296         Map<String, FactoryBuilderSupport> builders = new LinkedHashMap<String, FactoryBuilderSupport>();
297         synchronized (lock) {
298             for (MVCGroup group : groups.values()) {
299                 FactoryBuilderSupport builder = group.getBuilder();
300                 if (builder != null) {
301                     builders.put(group.getMvcId(), builder);
302                 }
303             }
304         }
305         return Collections.unmodifiableMap(builders);
306     }
307 
308     public final Map<String, ? extends GriffonModel> getModels() {
309         Map<String, GriffonModel> models = new LinkedHashMap<String, GriffonModel>();
310         synchronized (lock) {
311             for (MVCGroup group : groups.values()) {
312                 GriffonModel model = group.getModel();
313                 if (model != null) {
314                     models.put(group.getMvcId(), model);
315                 }
316             }
317         }
318         return Collections.unmodifiableMap(models);
319     }
320 
321     public final Map<String, ? extends GriffonView> getViews() {
322         Map<String, GriffonView> views = new LinkedHashMap<String, GriffonView>();
323         synchronized (lock) {
324             for (MVCGroup group : groups.values()) {
325                 GriffonView view = group.getView();
326                 if (view != null) {
327                     views.put(group.getMvcId(), view);
328                 }
329             }
330         }
331         return Collections.unmodifiableMap(views);
332     }
333 
334     public final Map<String, ? extends GriffonController> getControllers() {
335         Map<String, GriffonController> controllers = new LinkedHashMap<String, GriffonController>();
336         synchronized (lock) {
337             for (MVCGroup group : groups.values()) {
338                 GriffonController controller = group.getController();
339                 if (controller != null) {
340                     controllers.put(group.getMvcId(), controller);
341                 }
342             }
343         }
344         return Collections.unmodifiableMap(controllers);
345     }
346 }