001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.isis.core.progmodel.facets;
018
019 import java.lang.reflect.Method;
020 import java.lang.reflect.Modifier;
021
022 import org.apache.isis.core.metamodel.facetapi.MethodRemover;
023 import org.apache.isis.core.metamodel.methodutils.MethodScope;
024
025 public final class MethodFinderUtils {
026
027 private MethodFinderUtils() {
028 }
029
030 public static Method findMethodWithOrWithoutParameters(final Class<?> type, final MethodScope classMethod,
031 final String name, final Class<?> returnType, final Class<?>[] paramTypes) {
032 Method method = MethodFinderUtils.findMethod(type, classMethod, name, returnType, paramTypes);
033 if (method == null) {
034 method =
035 MethodFinderUtils.findMethod(type, classMethod, name, returnType,
036 MethodPrefixBasedFacetFactoryAbstract.NO_PARAMETERS_TYPES);
037 }
038 return method;
039 }
040
041 /**
042 * Returns a specific public methods that: have the specified prefix; have the specified return type, or void, if
043 * canBeVoid is true; and has the specified number of parameters. If the returnType is specified as null then the
044 * return type is ignored.
045 *
046 * @param paramTypes
047 * the set of parameters the method should have, if null then is ignored
048 */
049 public static Method findMethod(final Class<?> type, final MethodScope methodScope, final String name,
050 final Class<?> returnType, final Class<?>[] paramTypes) {
051 Method method;
052 try {
053 method = type.getMethod(name, paramTypes);
054 } catch (final SecurityException e) {
055 return null;
056 } catch (final NoSuchMethodException e) {
057 return null;
058 }
059
060 final int modifiers = method.getModifiers();
061
062 // check for public modifier
063 if (!Modifier.isPublic(modifiers)) {
064 return null;
065 }
066
067 // check for scope modifier
068 if (!methodScope.matchesScopeOf(method)) {
069 return null;
070 }
071
072 // check for name
073 if (!method.getName().equals(name)) {
074 return null;
075 }
076
077 // check for return type
078 if (returnType != null && returnType != method.getReturnType()) {
079 return null;
080 }
081
082 // check params (if required)
083 if (paramTypes != null) {
084 final Class<?>[] parameterTypes = method.getParameterTypes();
085 if (paramTypes.length != parameterTypes.length) {
086 return null;
087 }
088
089 for (int c = 0; c < paramTypes.length; c++) {
090 if ((paramTypes[c] != null) && (paramTypes[c] != parameterTypes[c])) {
091 return null;
092 }
093 }
094 }
095
096 return method;
097 }
098
099 protected static boolean doesNotMatchScope(final MethodScope methodScope, final Method method) {
100 return methodScope.doesNotMatchScope(method);
101 }
102
103 public static Method findMethod(final Class<?> type, final MethodScope methodScope, final String name,
104 final Class<?> returnType) {
105 try {
106 final Method[] methods = type.getMethods();
107 for (final Method method2 : methods) {
108 final Method method = method2;
109 final int modifiers = method.getModifiers();
110 // check for public modifier
111 if (!Modifier.isPublic(modifiers)) {
112 continue;
113 }
114
115 // check correct scope (static vs instance)
116 if (!methodScope.matchesScopeOf(method)) {
117 continue;
118 }
119
120 // check for name
121 if (!method.getName().equals(name)) {
122 continue;
123 }
124
125 // check for return type
126 if (returnType != null && returnType != method.getReturnType()) {
127 continue;
128 }
129 return method;
130 }
131 } catch (final SecurityException e) {
132 return null;
133 }
134 return null;
135 }
136
137 public static void removeMethod(final MethodRemover methodRemover, final Method method) {
138 if (methodRemover != null && method != null) {
139 methodRemover.removeMethod(method);
140 }
141 }
142
143 public static Class<?>[] paramTypesOrNull(final Class<?> type) {
144 return type == null ? null : new Class[] { type };
145 }
146
147 public static boolean allParametersOfSameType(final Class<?>[] params) {
148 final Class<?> firstParam = params[0];
149 for (int i = 1; i < params.length; i++) {
150 if (params[i] != firstParam) {
151 return false;
152 }
153 }
154 return true;
155 }
156
157 }