001 /*
002 * Copyright 2007-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 */
015
016 package org.codehaus.griffon.runtime.core.controller;
017
018 import griffon.core.GriffonApplication;
019 import griffon.core.GriffonController;
020 import griffon.core.GriffonControllerClass;
021 import griffon.core.controller.GriffonControllerAction;
022 import griffon.core.controller.GriffonControllerActionManager;
023 import griffon.core.i18n.NoSuchMessageException;
024 import org.slf4j.Logger;
025 import org.slf4j.LoggerFactory;
026
027 import java.lang.ref.WeakReference;
028 import java.util.Collections;
029 import java.util.LinkedHashMap;
030 import java.util.Map;
031
032 import static griffon.util.GriffonApplicationUtils.isMacOSX;
033 import static griffon.util.GriffonNameUtils.*;
034 import static org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation.castToBoolean;
035
036 /**
037 * @author Andres Almiray
038 * @since 1.1.0
039 */
040 public abstract class AbstractGriffonControllerActionManager implements GriffonControllerActionManager {
041 private static final Logger LOG = LoggerFactory.getLogger(AbstractGriffonControllerActionManager.class);
042 private final ActionCache actionCache = new ActionCache();
043 private GriffonApplication app;
044
045 protected AbstractGriffonControllerActionManager(GriffonApplication app) {
046 this.app = app;
047 }
048
049 public GriffonApplication getApp() {
050 return app;
051 }
052
053 public Map<String, GriffonControllerAction> actionsFor(GriffonController controller) {
054 if (controller == null) {
055 throw new IllegalArgumentException("controller parameter is null!");
056 }
057 Map<String, GriffonControllerAction> actions = actionCache.get(controller);
058 if (actions.isEmpty()) {
059 if (LOG.isTraceEnabled()) {
060 LOG.trace("No actions defined for controller " + controller);
061 }
062 }
063 return actions;
064 }
065
066 public GriffonControllerAction actionFor(GriffonController controller, String actionName) {
067 if (controller == null) {
068 throw new IllegalArgumentException("controller parameter is null!");
069 }
070 if (isBlank(actionName)) {
071 throw new IllegalArgumentException("actionName parameter is null!");
072 }
073
074 return actionCache.get(controller).get(normalizeName(actionName));
075 }
076
077 public void createActions(GriffonController controller) {
078 GriffonControllerClass griffonClass = (GriffonControllerClass) controller.getGriffonClass();
079 for (String actionName : griffonClass.getActionNames()) {
080 GriffonControllerAction action = createAndConfigureAction(controller, actionName);
081 Map<String, GriffonControllerAction> actions = actionCache.get(controller);
082 if (actions.isEmpty()) {
083 actions = new LinkedHashMap<String, GriffonControllerAction>();
084 actionCache.set(controller, actions);
085 }
086 String actionKey = normalizeName(actionName);
087 if (LOG.isTraceEnabled()) {
088 LOG.trace("Action for " + controller.getClass().getName() + "." + actionName + " stored as " + actionKey);
089 }
090 actions.put(actionKey, action);
091 }
092 }
093
094 protected GriffonControllerAction createAndConfigureAction(GriffonController controller, String actionName) {
095 GriffonControllerAction action = createControllerAction(controller, actionName);
096
097 String normalizeNamed = capitalize(normalizeName(actionName));
098 String keyPrefix = controller.getClass().getName() + ".action.";
099
100 String rsActionName = msg(keyPrefix, normalizeNamed, "name", getNaturalName(normalizeNamed));
101 if (!isBlank(rsActionName)) {
102 if (LOG.isTraceEnabled()) {
103 LOG.trace(keyPrefix + normalizeNamed + ".name = " + rsActionName);
104 }
105 action.setName(rsActionName);
106 }
107
108 String rsAccelerator = msg(keyPrefix, normalizeNamed, "accelerator", "");
109 if (!isBlank(rsAccelerator)) {
110 if (!isMacOSX() && rsAccelerator.contains("meta") && !rsAccelerator.contains("ctrl")) {
111 rsAccelerator = rsAccelerator.replace("meta", "ctrl");
112 }
113 if (LOG.isTraceEnabled()) {
114 LOG.trace(keyPrefix + normalizeNamed + ".accelerator = " + rsAccelerator);
115 }
116 action.setAccelerator(rsAccelerator);
117 }
118
119 /*
120 String rsCommand = msg(keyPrefix, normalizeNamed, "command", "");
121 if (!isBlank(rsCommand)) {
122 if (LOG.isTraceEnabled()) {
123 LOG.trace(keyPrefix + normalizeNamed + ".command = " + rsCommand);
124 }
125 action.setCommand(rsCommand);
126 }
127 */
128
129 String rsShortDescription = msg(keyPrefix, normalizeNamed, "short_description", "");
130 if (!isBlank(rsShortDescription)) {
131 if (LOG.isTraceEnabled()) {
132 LOG.trace(keyPrefix + normalizeNamed + ".short_description = " + rsShortDescription);
133 }
134 action.setShortDescription(rsShortDescription);
135 }
136
137 String rsLongDescription = msg(keyPrefix, normalizeNamed, "long_description", "");
138 if (!isBlank(rsLongDescription)) {
139 if (LOG.isTraceEnabled()) {
140 LOG.trace(keyPrefix + normalizeNamed + ".long_description = " + rsLongDescription);
141 }
142 action.setLongDescription(rsLongDescription);
143 }
144
145 String rsMnemonic = msg(keyPrefix, normalizeNamed, "mnemonic", "");
146 if (!isBlank(rsMnemonic)) {
147 if (LOG.isTraceEnabled()) {
148 LOG.trace(keyPrefix + normalizeNamed + ".mnemonic = " + rsMnemonic);
149 }
150 action.setMnemonic(rsMnemonic);
151 }
152
153 String rsSmallIcon = msg(keyPrefix, normalizeNamed, "small_icon", "");
154 if (!isBlank(rsSmallIcon)) {
155 if (LOG.isTraceEnabled()) {
156 LOG.trace(keyPrefix + normalizeNamed + ".small_icon = " + rsSmallIcon);
157 }
158 action.setSmallIcon(rsSmallIcon);
159 }
160
161 String rsLargeIcon = msg(keyPrefix, normalizeNamed, "large_icon", "");
162 if (!isBlank(rsLargeIcon)) {
163 if (LOG.isTraceEnabled()) {
164 LOG.trace(keyPrefix + normalizeNamed + ".large_icon = " + rsLargeIcon);
165 }
166 action.setLargeIcon(rsLargeIcon);
167 }
168
169 String rsEnabled = msg(keyPrefix, normalizeNamed, "enabled", "true");
170 if (!isBlank(rsEnabled)) {
171 if (LOG.isTraceEnabled()) {
172 LOG.trace(keyPrefix + normalizeNamed + ".enabled = " + rsEnabled);
173 }
174 action.setEnabled(castToBoolean(rsEnabled));
175 }
176
177 String rsSelected = msg(keyPrefix, normalizeNamed, "selected", "false");
178 if (!isBlank(rsSelected)) {
179 if (LOG.isTraceEnabled()) {
180 LOG.trace(keyPrefix + normalizeNamed + ".selected = " + rsSelected);
181 }
182 action.setSelected(castToBoolean(rsSelected));
183 }
184
185 return action;
186 }
187
188 protected abstract GriffonControllerAction createControllerAction(GriffonController controller, String actionName);
189
190 public String normalizeName(String actionName) {
191 if (actionName.endsWith(ACTION)) {
192 actionName = actionName.substring(0, actionName.length() - ACTION.length());
193 }
194 return uncapitalize(actionName);
195 }
196
197 protected String msg(String key, String actionName, String subkey, String defaultValue) {
198 try {
199 return app.getMessage(key + actionName + "." + subkey);
200 } catch (NoSuchMessageException nsme) {
201 return app.getMessage("application.action." + actionName + "." + subkey, defaultValue);
202 }
203 }
204
205 private static class ActionCache {
206 private final Map<WeakReference<GriffonController>, Map<String, GriffonControllerAction>> cache = Collections.synchronizedMap(new LinkedHashMap<WeakReference<GriffonController>, Map<String, GriffonControllerAction>>());
207
208 public Map<String, GriffonControllerAction> get(GriffonController controller) {
209 synchronized (cache) {
210 for (Map.Entry<WeakReference<GriffonController>, Map<String, GriffonControllerAction>> entry : cache.entrySet()) {
211 GriffonController test = entry.getKey().get();
212 if (test == controller) {
213 return entry.getValue();
214 }
215 }
216 }
217 return Collections.emptyMap();
218 }
219
220 public void set(GriffonController controller, Map<String, GriffonControllerAction> actions) {
221 WeakReference<GriffonController> existingController = null;
222 synchronized (cache) {
223 for (WeakReference<GriffonController> key : cache.keySet()) {
224 if (key.get() == controller) {
225 existingController = key;
226 break;
227 }
228 }
229 }
230
231 if (null != existingController) {
232 cache.remove(existingController);
233 }
234
235 cache.put(new WeakReference<GriffonController>(controller), actions);
236 }
237 }
238 }
|