package org.jtheque.ui.utils; import org.jtheque.ui.Action; import org.jtheque.ui.ControllerException; import org.jtheque.ui.View; import org.jtheque.ui.Controller; import org.jtheque.utils.collections.CollectionUtils; import org.jtheque.utils.ui.SwingUtils; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Map; /* * Copyright JTheque (Baptiste Wicht) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * An abstract controller. It handles all the request, translate them into method name and then execute the method using * Reflection. * * @author Baptiste Wicht */ public abstract class AbstractController<T extends View> implements Controller<T>, ApplicationContextAware { private final Map<String, Method> methodCache = CollectionUtils.newHashMap(); private final Class<? extends T> viewType; private T view; private ApplicationContext applicationContext; /** * Construct a new AbstractController. We must pass the type of the view for the getView() method working * correctly. * * @param viewType The class of the view. Can be an interface. Will be getter from the application context. */ protected AbstractController(Class<? extends T> viewType) { super(); this.viewType = viewType; } /** * Handle the given action. Use the methods declared with the @Action annotation and execute the corresponding * method. * * @param actionName The i18n action name. * * @throws ControllerException If there is no method associated with the given action or if the action cannot be * accessed. */ @Override public void handleAction(String actionName) { Method method = getCachedMethod(actionName); if (method == null) { throw new ControllerException("There is no method for the action (" + actionName + ')'); } try { method.invoke(this); } catch (InvocationTargetException e) { throw new ControllerException("Unable to invoke the method (" + method + ')', e); } catch (IllegalAccessException e) { throw new ControllerException("Unable to invoke the method (" + method + ')', e); } } /** * Return the cached method corresponding the i18n action name. The methods are put in cache for later usages. * * @param action The i18n action name. * * @return The method corresponding to the i18n action name. */ private Method getCachedMethod(String action) { if (methodCache.isEmpty()) { generateCache(); } if (methodCache.containsKey(action)) { return methodCache.get(action); } else { throw new ControllerException("There is no method for the action (" + action + ')'); } } /** * Generate the cache of methods. */ private void generateCache() { Method[] methods = getClass().getMethods(); for (Method method : methods) { if (method.isAnnotationPresent(Action.class)) { Action action = method.getAnnotation(Action.class); methodCache.put(action.value(), method); } } } @Override public void setApplicationContext(ApplicationContext applicationContext) { this.applicationContext = applicationContext; } /** * Return the application context of the controller. * * @return The application context. */ protected ApplicationContext getContext() { return applicationContext; } @Override public T getView() { SwingUtils.assertEDT("Controller.getView()"); if (view == null) { view = applicationContext.getBean(viewType); } return view; } }