package com.cfsoft.ofbiz; import com.cfsoft.ofbiz.dom.component.ComponentManager; import com.cfsoft.ofbiz.dom.component.ComponentUrl; import com.cfsoft.ofbiz.dom.component.api.Component; import com.cfsoft.ofbiz.dom.controller.api.Controller; import com.cfsoft.ofbiz.dom.controller.api.Event; import com.cfsoft.ofbiz.dom.controller.api.Handler; import com.cfsoft.ofbiz.dom.controller.model.ControllerManager; import com.cfsoft.ofbiz.dom.entity.api.Entity; import com.cfsoft.ofbiz.dom.entity.api.EntityModel; import com.cfsoft.ofbiz.dom.service.api.Service; import com.cfsoft.ofbiz.dom.service.api.Services; import com.cfsoft.ofbiz.dom.service.model.ServiceManager; import com.cfsoft.ofbiz.dom.service.model.ServiceModel; import com.cfsoft.ofbiz.dom.simplemethod.api.SimpleMethod; import com.cfsoft.ofbiz.dom.simplemethod.api.SimpleMethods; import com.intellij.codeInsight.lookup.LookupElementBuilder; import com.intellij.ide.highlighter.XmlFileType; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleUtil; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Condition; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.psi.*; import com.intellij.psi.search.FilenameIndex; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.xml.XmlElement; import com.intellij.psi.xml.XmlFile; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.xml.DomElement; import com.intellij.util.xml.DomFileElement; import com.intellij.util.xml.DomJavaUtil; import com.intellij.util.xml.DomService; import org.jetbrains.annotations.NotNull; import java.util.*; public class OfbizUtils { public static final String IDEA_POSTFIX = "IntellijIdeaRulezzz"; private OfbizUtils() { } public static PsiClass findEventClass(Event event) { String className = event.getPath().getStringValue(); Module module = ModuleUtil.findModuleForPsiElement(event.getXmlElement()); // resolve JAVA-class directly return DomJavaUtil.findClass(className, event.getXmlElement().getContainingFile(), module, GlobalSearchScope.allScope(event.getXmlElement().getProject())); } public static PsiClass findServiceClass(Service service) { String className = service.getLocation().getStringValue(); Module module = ModuleUtil.findModuleForPsiElement(service.getXmlElement()); // resolve JAVA-class directly return DomJavaUtil.findClass(className, service.getXmlElement().getContainingFile(), module, GlobalSearchScope.allScope(service.getXmlElement().getProject())); } private static boolean hasValidEventParameters(PsiMethod psiMethod) { // psiMethod.getParameterList().getParameters()[1].getTypeElement().getType().getCanonicalText() PsiParameter[] parameters = psiMethod.getParameterList().getParameters(); int count = psiMethod.getParameterList().getParametersCount(); if (count == 2) { boolean first = parameters[0].getTypeElement().getType().getCanonicalText().equals("javax.servlet.http.HttpServletRequest"); boolean second = parameters[1].getTypeElement().getType().getCanonicalText().equals("javax.servlet.http.HttpServletResponse"); return first && second; } return false; } public static boolean isEventMethod(@NotNull PsiMethod psiMethod) { PsiType returnType = psiMethod.getReturnType(); if (returnType != null && returnType.getCanonicalText().equals("java.lang.String") && hasValidEventParameters(psiMethod) && hasValidModifier(psiMethod)) return true; else return false; } public static boolean isServiceMethod(PsiMethod psiMethod) { return psiMethod.getReturnType() != null && psiMethod.getReturnType().getCanonicalText().startsWith("java.util.Map") && hasValidServiceParameters(psiMethod) && hasValidModifier(psiMethod); } private static boolean hasValidServiceParameters(PsiMethod psiMethod) { PsiParameter[] parameters = psiMethod.getParameterList().getParameters(); int count = psiMethod.getParameterList().getParametersCount(); if (count == 2) { boolean first = parameters[0].getTypeElement().getType().getCanonicalText().startsWith("org.ofbiz.service.DispatchContext"); boolean second = parameters[1].getTypeElement().getType().getCanonicalText().startsWith("java.util.Map"); return first && second; } return false; } public static boolean hasValidModifier(PsiMethod psiMethod) { PsiModifierList mlist = psiMethod.getModifierList(); return mlist.hasExplicitModifier("static") && mlist.hasExplicitModifier("public"); } public static PsiMethod getEventMethod(Event event) { if (event.getType().getStringValue().equals("java") && (event.getPath().getStringValue()) != null) { final PsiClass psiClass = findEventClass(event); if (psiClass != null) { for (PsiMethod psiMethod : psiClass.getAllMethods()) { if (psiMethod != null) { if (OfbizUtils.isEventMethod(psiMethod) && psiMethod.getName().equals(event.getInvoke().getStringValue())) { return psiMethod; } } } } } return null; } public static PsiMethod getServiceMethod(Service service) { if (service.getEngine().getStringValue().equals("java") && (service.getLocation().getStringValue()) != null) { final PsiClass psiClass = findServiceClass(service); if (psiClass != null) { for (PsiMethod psiMethod : psiClass.getAllMethods()) { if (OfbizUtils.isServiceMethod(psiMethod) && psiMethod.getName().equals(service.getInvoke().getStringValue())) { return psiMethod; } } } } return null; } public static XmlElement getEventServiceElememnt(Event event) { if (event.getType().getStringValue().equals("service") || event.getType().getStringValue().equals("service-multi")) { Module module = ModuleUtil.findModuleForPsiElement(event.getXmlElement()); final String path = event.getPath().getStringValue(); if (path == null || path.trim().equals("")) { ServiceModel serviceModel = ServiceManager.getInstance(event.getXmlElement().getProject()).getCombinedModel(module); for (Service service : serviceModel.getAllServices()) { if (service.getName().getStringValue().equals(event.getInvoke().getStringValue())) { return service.getXmlElement(); } } } else { List<DomFileElement<Services>> eles = DomService.getInstance().getFileElements(Services.class, event.getXmlElement().getProject(), new GlobalSearchScope() { @Override public boolean contains(VirtualFile virtualFile) { return virtualFile.getPath().endsWith(path); } @Override public int compare(VirtualFile virtualFile, VirtualFile virtualFile1) { return virtualFile.getPath().equals(virtualFile1.getPath()) ? 0 : 1; } @Override public boolean isSearchInModuleContent(@NotNull Module module) { return true; } @Override public boolean isSearchInLibraries() { return false; } }); for (DomFileElement<Services> ele : eles) { Services services = ele.getRootElement(); for (Service service : services.getServices()) { if (service.getName().getStringValue().equals(event.getInvoke())) { return service.getXmlElement(); } } } } } return null; } public static Set<String> getServiceCompleteMethodNames(Service service) { Set<String> psiMethods = new HashSet<String>(); if (service.getEngine().getStringValue().equals("java")) { PsiClass psiClass = OfbizUtils.findServiceClass(service); if (psiClass != null && psiClass.getAllMethods() != null) { for (PsiMethod psiMethod : psiClass.getAllMethods()) { if (OfbizUtils.isServiceMethod(psiMethod)) { psiMethods.add(psiMethod.getName()); } } } } return psiMethods; } public static Set<String> getEventCompleteMethodNames(Event event) { Set<String> psiMethods = new HashSet<String>(); if (event.getType().getStringValue().equals("java")) { PsiClass psiClass = OfbizUtils.findEventClass(event); if (psiClass != null) { for (PsiMethod psiMethod : psiClass.getAllMethods()) { if (OfbizUtils.isEventMethod(psiMethod)) { psiMethods.add(psiMethod.getName()); } } } } return psiMethods; } public static Set<Object> getEventCompleteServiceNames(Event event) { Set<Object> set = new HashSet<Object>(); if (event.getType().getStringValue().equals("service") || event.getType().getStringValue().equals("service-multi")) { Module module = ModuleUtil.findModuleForPsiElement(event.getXmlElement()); String path = event.getPath().getStringValue(); ServiceModel serviceModel = ServiceManager.getInstance(event.getXmlElement().getProject()).getCombinedModel(module); for (Service service : serviceModel.getAllServices()) { if (path != null && !path.trim().equals("") && service.getXmlElement().getContainingFile().getVirtualFile().getPath().endsWith(path)) { set.add(service.getName().getStringValue()); } else { // set.add(service.getName().getValue()); set.add(LookupElementBuilder.create(service.getName().getValue()).setTypeText(service.getXmlElement().getContainingFile().getVirtualFile().getPresentableName())); } } } return set; } public static PsiElement getServiceSimpleMethodElememnt(Service service) { if (service.getEngine().getStringValue().equals("simple")) { // Module module = ModuleUtil.findModuleForPsiElement(service.getXmlElement()); String path = service.getLocation().getStringValue(); if (path.startsWith("component://")) { path = path.substring("component://".length()); } if (path != null && !path.trim().equals("")) { List<DomFileElement<SimpleMethods>> eles = DomService.getInstance().getFileElements(SimpleMethods.class, service.getXmlElement().getProject(), GlobalSearchScope.allScope(service.getXmlElement().getProject())); for (DomFileElement<SimpleMethods> ele : eles) { if (ele.getFile().getVirtualFile().getPath().endsWith(path)) { for (SimpleMethod simpleMethod : ele.getRootElement().getSimpleMethods()) { if (simpleMethod.getMethodName().getStringValue().equals(service.getInvoke().getStringValue())) { return simpleMethod.getXmlElement(); } } } } } } return null; } public static Set<String> getServiceCompleteSimpleMethodNames(Service service) { Set<String> set = new HashSet<String>(); if (service.getEngine().getValue().equals("simple") && service.getInvoke() != null) { Module module = ModuleUtil.findModuleForPsiElement(service.getXmlElement()); String path = service.getLocation().getStringValue(); if (path.startsWith("component://")) { path = path.substring("component://".length()); } List<DomFileElement<SimpleMethods>> eles = DomService.getInstance().getFileElements(SimpleMethods.class, service.getXmlElement().getProject(), new ModulePsiFileTypeScope(module, XmlFileType.INSTANCE)); for (DomFileElement<SimpleMethods> ele : eles) { if (ele.getXmlElement().getContainingFile().getVirtualFile().getPath().endsWith(path)) { for (SimpleMethod simpleMethod : ele.getRootElement().getSimpleMethods()) { set.add(simpleMethod.getMethodName().getStringValue()); } } } } return set; } public static PsiElement getServiceLocation(Service service) { ComponentManager manager = ComponentManager.getInstance(service.getXmlElement().getProject()); if (service.getLocation() == null || service.getLocation().getValue() == null || !service.getEngine().getValue().equals("simple")) { return null; } String path = service.getLocation().getStringValue(); if (!path.startsWith("component://")) { Component component = manager.getComponent(service.getXmlElement()); path = String.format("file://%s/script/%s", component.getDirectory(), path); } else { path = "file://" + manager.getRealPath(path); } VirtualFile vf = VirtualFileManager.getInstance().findFileByUrl(path); if (vf != null) { return PsiManager.getInstance(service.getXmlElement().getProject()).findFile(vf); } return null; } public static Collection getServiceLocationNames(Service service) { ComponentManager componentManager = ComponentManager.getInstance(service.getXmlElement().getProject()); String location = service.getLocation().getStringValue(); if (service.getEngine().getValue().equals("simple")) { if (location.startsWith("comp")) { Component[] components = componentManager.getAllComponents(); ComponentUrl url = new ComponentUrl(location); if (url.getComponentName() == null) { return ContainerUtil.map(components, new Function<Component, Object>() { @Override public Object fun(Component component) { return String.format("component://%s/", component.getName().getValue()); } }); } else { final Component component = componentManager.getComponent(url.getComponentName(), components); List<SimpleMethods> list = getDomFileElements(SimpleMethods.class, service.getXmlElement().getProject(), component.getScope()); List<String> serviceLocations = ContainerUtil.map(list, new Function<SimpleMethods, String>() { @Override public String fun(SimpleMethods simpleMethods) { return ComponentUrl.buildComponentUrl(component, simpleMethods.getXmlElement().getContainingFile().getVirtualFile().getPath(), null); } }); return serviceLocations; } } else { Set<Object> set = new HashSet<Object>(); Module module = ModuleUtil.findModuleForPsiElement(service.getXmlElement()); List<DomFileElement<SimpleMethods>> eles = DomService.getInstance().getFileElements(SimpleMethods.class, service.getXmlElement().getProject(), new ModulePsiFileTypeScope(module, XmlFileType.INSTANCE)); String path; int pos; for (DomFileElement<SimpleMethods> ele : eles) { path = ele.getFile().getVirtualFile().getPath(); pos = path.lastIndexOf("/script/"); if (pos >= 0) { set.add(path.substring(pos + 8)); } } return set; } } else { return Collections.emptyList(); } } public static Entity findEntity(Project project, String entityName) { List<EntityModel> models = getDomFileElements(EntityModel.class, project, GlobalSearchScope.projectScope(project)); for (EntityModel model : models) { for (Entity entity : model.getEntities()) { if (entityName.equals(entity.getName().getValue())) { return entity; } } } return null; } public static PsiElement getEventTypeElement(Event event) { ControllerManager controllerManager = ControllerManager.getInstance(event.getXmlElement().getProject()); Controller controller = controllerManager.getController((XmlFile) event.getXmlElement().getContainingFile().getContainingFile()); for (Handler handler : controller.getAllHandlers()) { if (handler.getName().equals(event.getType())) { return handler.getXmlElement(); } } return null; } public static Set<String> getEventCompleteTypes(Event event, String type) { ControllerManager controllerManager = ControllerManager.getInstance(event.getXmlElement().getProject()); Controller controller = controllerManager.getController((XmlFile) event.getXmlElement().getContainingFile().getContainingFile()); Set<String> names = new HashSet<String>(); for (Handler handler : controller.getAllHandlers()) { if(handler.getType().getStringValue().equals(type)){ names.add(handler.getName().getStringValue()); } } return names; } public static class ModulePsiFileTypeScope extends GlobalSearchScope { private final Module module; public ModulePsiFileTypeScope(Module module, XmlFileType instance) { this.module = module; } @Override public boolean contains(VirtualFile virtualFile) { return XmlFileType.INSTANCE == virtualFile.getFileType(); } @Override public int compare(VirtualFile virtualFile, VirtualFile virtualFile1) { return virtualFile.getPath().equals(virtualFile1) ? 0 : 1; } @Override public boolean isSearchInModuleContent(@NotNull Module module) { return module == this.module; } @Override public boolean isSearchInLibraries() { return false; } } public static <T extends DomElement> List<T> getDomFileElements(Class<T> clazz, Project project, GlobalSearchScope scope) { List<T> list = new ArrayList<T>(); List<DomFileElement<T>> eles = DomService.getInstance().getFileElements(clazz, project, scope); for (DomFileElement<T> ele : eles) { list.add(ele.getRootElement()); } return list; } public static <T extends DomElement> T findXmlElement(Class<T> clazz, Project project, GlobalSearchScope scope, Condition<T> condition) { List<T> list = new ArrayList<T>(); List<DomFileElement<T>> eles = DomService.getInstance().getFileElements(clazz, project, scope); for (DomFileElement<T> ele : eles) { list.add(ele.getRootElement()); } return ContainerUtil.find(list, condition); } public static <T extends DomElement, R extends Object> List<R> lookupXmlElement(Class<T> clazz, Project project, GlobalSearchScope scope, Function<T, R> func) { List<T> list = new ArrayList<T>(); List<DomFileElement<T>> eles = DomService.getInstance().getFileElements(clazz, project, scope); for (DomFileElement<T> ele : eles) { list.add(ele.getRootElement()); } return ContainerUtil.map(list, func); } public static PsiFile findPsiFileByComponentUrl(@NotNull XmlElement xmlElement, @NotNull ComponentUrl url) { Project project = xmlElement.getProject(); ComponentManager manager = ComponentManager.getInstance(project); Component[] components = manager.getAllComponents(); Component currentComponent; if (url.getComponentName() == null) { currentComponent = manager.getComponent(xmlElement, components); if (currentComponent == null) { return null; } int pos = url.getUrl().indexOf("#"); String relativePath = url.getUrl().substring(0, pos >= 0 ? pos : url.getUrl().length()); String fileName = relativePath; pos = relativePath.lastIndexOf("/"); if (pos >= 0) { fileName = relativePath.substring(pos); } PsiFile[] files = FilenameIndex.getFilesByName(project, fileName, currentComponent.getScope()); for (PsiFile file : files) { if (file.getVirtualFile().getPath().endsWith(relativePath)) { return file; } } } else { currentComponent = manager.getComponent(url.getComponentName(), components); String path = url.getRealPath(project, components); VirtualFile vf = VirtualFileManager.getInstance().findFileByUrl("file://" + path); if (vf != null) { PsiFile psiFile = PsiManager.getInstance(project).findFile(vf); if (psiFile != null) { return psiFile; } } } return null; } public static PsiDirectory findPsiDirectoryByComponentUrl(@NotNull XmlElement xmlElement, @NotNull ComponentUrl url) { Project project = xmlElement.getProject(); ComponentManager manager = ComponentManager.getInstance(project); Component[] components = manager.getAllComponents(); if (url.getRelativeDirectory() != null) { String path = url.getRealDirectory(project, components); VirtualFile vf = VirtualFileManager.getInstance().findFileByUrl("file://" + path); if (vf != null && vf.isDirectory()) { return PsiManager.getInstance(project).findDirectory(vf); } }else if (url.getComponentName() != null) { VirtualFile vf = VirtualFileManager.getInstance().findFileByUrl("file://" + url.getComponentDirectory(project, components)); if (vf != null && vf.isDirectory()) { return PsiManager.getInstance(project).findDirectory(vf); } } return null; } public static String removeIdeaPostFix(String s) { if (s == null) { return s; } s = s.trim(); int pos = s.indexOf(IDEA_POSTFIX); if (pos >=0) { return s.substring(0, pos); } return s; } }