package com.seventh7.mybatis.service;
import com.google.common.base.Optional;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.project.Project;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementFactory;
import com.intellij.psi.PsiField;
import com.intellij.psi.PsiImportList;
import com.intellij.psi.PsiImportStatement;
import com.intellij.psi.PsiJavaFile;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiType;
import com.intellij.psi.impl.source.PsiClassReferenceType;
import com.intellij.util.CommonProcessors;
import com.intellij.util.Processor;
import com.intellij.util.xml.DomElement;
import com.seventh7.mybatis.dom.model.IdDomElement;
import com.seventh7.mybatis.dom.model.Mapper;
import com.seventh7.mybatis.util.JavaUtils;
import com.seventh7.mybatis.util.MapperUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author yanglin
*/
public class JavaService {
private Project project;
private JavaPsiFacade javaPsiFacade;
private EditorService editorService;
public JavaService(Project project) {
this.project = project;
this.javaPsiFacade = JavaPsiFacade.getInstance(project);
this.editorService = EditorService.getInstance(project);
}
public static JavaService getInstance(@NotNull Project project) {
return ServiceManager.getService(project, JavaService.class);
}
public Optional<PsiClass> getReferenceClazzOfPsiField(@NotNull PsiElement field) {
if (!(field instanceof PsiField)) {
return Optional.absent();
}
PsiType type = ((PsiField)field).getType();
return type instanceof PsiClassReferenceType ? Optional.fromNullable(((PsiClassReferenceType) type).resolve()) : Optional.<PsiClass>absent();
}
public Optional<DomElement> findStatement(@Nullable PsiMethod method) {
CommonProcessors.FindFirstProcessor<DomElement> processor = new CommonProcessors.FindFirstProcessor<DomElement>();
process(method, processor);
return processor.isFound() ? Optional.fromNullable(processor.getFoundValue()) : Optional.<DomElement>absent();
}
@SuppressWarnings("unchecked")
public void process(@NotNull PsiMethod psiMethod, @NotNull Processor<IdDomElement> processor) {
PsiClass psiClass = psiMethod.getContainingClass();
if (null == psiClass) return;
String id = psiClass.getQualifiedName() + "." + psiMethod.getName();
for (Mapper mapper : MapperUtils.findMappers(psiMethod.getProject())) {
for (IdDomElement idDomElement : mapper.getDaoElements()) {
if (MapperUtils.getIdSignature(idDomElement).equals(id)) {
processor.process(idDomElement);
}
}
}
}
@SuppressWarnings("unchecked")
public void process(@NotNull PsiClass clazz, @NotNull Processor<Mapper> processor) {
String ns = clazz.getQualifiedName();
for (Mapper mapper : MapperUtils.findMappers(clazz.getProject())) {
if (MapperUtils.getNamespace(mapper).equals(ns)) {
processor.process(mapper);
}
}
}
public void process(@NotNull PsiElement target, @NotNull Processor processor) {
if (target instanceof PsiMethod) {
process((PsiMethod) target, processor);
} else if (target instanceof PsiClass){
process((PsiClass)target, processor);
}
}
public <T> Optional<T> findWithFindFirstProcessor(@NotNull PsiElement target) {
CommonProcessors.FindFirstProcessor<T> processor = new CommonProcessors.FindFirstProcessor<T>();
process(target, processor);
return Optional.fromNullable(processor.getFoundValue());
}
public void importClazz(PsiJavaFile file, String clazzName) {
if (!JavaUtils.hasImportClazz(file, clazzName)) {
Optional<PsiClass> clazz = JavaUtils.findClazz(project, clazzName);
PsiImportList importList = file.getImportList();
if (clazz.isPresent() && null != importList) {
PsiElementFactory elementFactory = javaPsiFacade.getElementFactory();
PsiImportStatement statement = elementFactory.createImportStatement(clazz.get());
importList.add(statement);
editorService.format(file, statement);
}
}
}
}