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 != null) configCopy.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((M) group.getModel(), (V) group.getView(), (C) group.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 }
|