DefaultGriffonControllerClass.java
001 /*
002  * Copyright 2010-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 package org.codehaus.griffon.runtime.core;
017 
018 import griffon.core.GriffonApplication;
019 import griffon.core.GriffonControllerClass;
020 import griffon.util.GriffonClassUtils;
021 import griffon.util.GriffonNameUtils;
022 import groovy.lang.Closure;
023 import groovy.lang.MetaMethod;
024 import groovy.lang.MetaProperty;
025 import org.codehaus.groovy.ast.ClassHelper;
026 
027 import java.lang.reflect.Method;
028 import java.util.LinkedHashSet;
029 import java.util.Set;
030 
031 /**
032  @author Andres Almiray
033  @since 0.9.1
034  */
035 public class DefaultGriffonControllerClass extends DefaultGriffonClass implements GriffonControllerClass {
036     protected final Set<String> actionsCache = new LinkedHashSet<String>();
037 
038     public DefaultGriffonControllerClass(GriffonApplication app, Class<?> clazz) {
039         super(app, clazz, TYPE, TRAILING);
040     }
041 
042     public void resetCaches() {
043         super.resetCaches();
044         actionsCache.clear();
045     }
046 
047     public String[] getActionNames() {
048         if (actionsCache.isEmpty()) {
049             for (String propertyName : getPropertiesWithFields()) {
050                 if (!STANDARD_PROPERTIES.contains(propertyName&&
051                         !actionsCache.contains(propertyName&&
052                         !GriffonClassUtils.isEventHandler(propertyName&&
053                         getPropertyValue(propertyName, Closure.class!= null) {
054                     actionsCache.add(propertyName);
055                 }
056             }
057             for (Method method : getClazz().getMethods()) {
058                 String methodName = method.getName();
059                 if (!actionsCache.contains(methodName&&
060                         GriffonClassUtils.isPlainMethod(method&&
061                         !GriffonClassUtils.isEventHandler(methodName&&
062                         hasVoidOrDefAsReturnType(method)) {
063                     actionsCache.add(methodName);
064                 }
065             }
066             for (MetaProperty p : getMetaProperties()) {
067                 String propertyName = p.getName();
068                 if (GriffonClassUtils.isGetter(p, true)) {
069                     propertyName = GriffonNameUtils.uncapitalize(propertyName.substring(3));
070                 }
071                 if (!STANDARD_PROPERTIES.contains(propertyName&&
072                         !actionsCache.contains(propertyName&&
073                         !GriffonClassUtils.isEventHandler(propertyName&&
074                         isClosureMetaProperty(p)) {
075                     actionsCache.add(propertyName);
076                 }
077             }
078             for (MetaMethod method : getMetaClass().getMethods()) {
079                 String methodName = method.getName();
080                 if (!actionsCache.contains(methodName&&
081                         GriffonClassUtils.isPlainMethod(method&&
082                         !GriffonClassUtils.isEventHandler(methodName&&
083                         hasVoidOrDefAsReturnType(method)) {
084                     actionsCache.add(methodName);
085                 }
086             }
087         }
088 
089         return actionsCache.toArray(new String[actionsCache.size()]);
090     }
091 
092     private boolean hasVoidOrDefAsReturnType(Method method) {
093         Class<?> returnType = method.getReturnType();
094         return returnType == ClassHelper.DYNAMIC_TYPE.getTypeClass() ||
095                 returnType == ClassHelper.VOID_TYPE.getTypeClass();
096     }
097 
098     private boolean hasVoidOrDefAsReturnType(MetaMethod method) {
099         Class<?> returnType = method.getReturnType();
100         return returnType == ClassHelper.DYNAMIC_TYPE.getTypeClass() ||
101                 returnType == ClassHelper.VOID_TYPE.getTypeClass();
102     }
103 }