/* * Copyright 2011 The authors * 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. */ package com.intellij.struts2.dom.struts.impl; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleUtil; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.PropertyUtil; import com.intellij.util.SmartList; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Collections; import java.util.List; import java.util.regex.Pattern; /** * Helper methods for {@link ActionImpl}. * * @author Yann Cébron */ final class ActionUtil { private ActionUtil() { } /** * Does the given path match the Action's path (including support for wildcards and bang notation). * * @param actionPath Path of Action. * @param checkPath Path to check. * @return true if matched. */ static boolean matchesPath(@NotNull @NonNls final String actionPath, @NotNull @NonNls final String checkPath) { // strip everything behind "!" final int bangIdx = StringUtil.indexOf(checkPath, '!'); final String strippedCheckPath = bangIdx == -1 ? checkPath : checkPath.substring(0, bangIdx); // do we have any wildcard-markers in our path? no --> exact compare if (StringUtil.indexOf(actionPath, '*') == -1) { return Comparing.equal(strippedCheckPath, actionPath); } return Pattern.matches(StringUtil.replace(actionPath, "*", "[^/]*"), strippedCheckPath); } /** * Returns all suitable action methods for the given Action class. * * @param actionClass Action class to search for action methods. * @param methodName (Optional) Method name. * @return Methods suitable for action execution. */ static List<PsiMethod> findActionMethods(@NotNull final PsiClass actionClass, @Nullable final String methodName) { final Module module = ModuleUtil.findModuleForPsiElement(actionClass); if (module == null) { return Collections.emptyList(); } final GlobalSearchScope scope = GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module, false); final PsiElementFactory psiElementFactory = JavaPsiFacade.getInstance(actionClass.getProject()).getElementFactory(); final PsiClassType stringType = psiElementFactory.createTypeByFQClassName(CommonClassNames.JAVA_LANG_STRING, scope); final PsiClassType resultType = psiElementFactory.createTypeByFQClassName("com.opensymphony.xwork2.Result", scope); final boolean searchForMethod = methodName != null; final List<PsiMethod> actionMethods = new SmartList<PsiMethod>(); for (final PsiMethod psiMethod : actionClass.getAllMethods()) { final String psiMethodName = psiMethod.getName(); if (searchForMethod && !Comparing.equal(psiMethodName, methodName)) { continue; } if (psiMethod.isConstructor()) { continue; } // only public non-static concrete methods final PsiModifierList modifiers = psiMethod.getModifierList(); if (!modifiers.hasModifierProperty(PsiModifier.PUBLIC) || modifiers.hasModifierProperty(PsiModifier.STATIC) || modifiers.hasModifierProperty(PsiModifier.ABSTRACT)) { continue; } // no parameters if (psiMethod.getParameterList().getParametersCount() != 0) { continue; } // skip "toString()" if (Comparing.equal(psiMethodName, "toString")) { continue; } // do not include simple getters (with underlying field) if (PropertyUtil.isSimplePropertyGetter(psiMethod) && actionClass.findFieldByName(PropertyUtil.getPropertyName(psiMethod), true) != null) { continue; } // return type "java.lang.String" or "com.opensymphony.xwork2.Result" final PsiType type = psiMethod.getReturnType(); if (type != null && type instanceof PsiClassType && (type.equals(stringType) || type.equals(resultType))) { actionMethods.add(psiMethod); // stop on first hit when searching for name if (searchForMethod) { return actionMethods; } } } return actionMethods; } }