package com.seventh7.mybatis.generate; import com.google.common.base.Function; import com.google.common.base.Optional; import com.google.common.collect.Collections2; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.collect.Sets; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiMethod; import com.intellij.psi.PsiPrimitiveType; import com.intellij.psi.PsiType; import com.intellij.psi.impl.source.PsiClassReferenceType; import com.intellij.psi.xml.XmlTag; import com.intellij.util.CommonProcessors; import com.seventh7.mybatis.dom.model.GroupTwo; import com.seventh7.mybatis.dom.model.Mapper; import com.seventh7.mybatis.service.EditorService; import com.seventh7.mybatis.service.JavaService; import com.seventh7.mybatis.setting.MybatisSetting; import com.seventh7.mybatis.ui.ListSelectionListener; import com.seventh7.mybatis.ui.UiComponentFacade; import com.seventh7.mybatis.util.CollectionUtils; import com.seventh7.mybatis.util.JavaUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Collection; import java.util.List; import java.util.Set; /** * @author yanglin */ public abstract class StatementGenerator { public static final StatementGenerator UPDATE_GENERATOR = new UpdateGenerator("update", "modify", "set"); public static final StatementGenerator SELECT_GENERATOR = new SelectGenerator("select", "get", "look", "find", "list", "search", "count", "query"); public static final StatementGenerator DELETE_GENERATOR = new DeleteGenerator("del", "cancel"); public static final StatementGenerator INSERT_GENERATOR = new InsertGenerator("insert", "add", "new"); public static final Set<StatementGenerator> ALL = ImmutableSet.of(UPDATE_GENERATOR, SELECT_GENERATOR, DELETE_GENERATOR, INSERT_GENERATOR); private static final Function<Mapper, String> FUN = new Function<Mapper, String>() { @Override public String apply(Mapper mapper) { VirtualFile vf = mapper.getXmlTag().getContainingFile().getVirtualFile(); if (null == vf) return ""; return vf.getCanonicalPath(); } }; public static Optional<PsiClass> getSelectResultType(@Nullable PsiMethod method) { if (null == method) { return Optional.absent(); } PsiType returnType = method.getReturnType(); if (returnType instanceof PsiPrimitiveType && returnType != PsiType.VOID) { return JavaUtils.findClazz(method.getProject(), ((PsiPrimitiveType) returnType).getBoxedTypeName()); } else if (returnType instanceof PsiClassReferenceType) { PsiClassReferenceType type = (PsiClassReferenceType)returnType; if (type.hasParameters()) { PsiType[] parameters = type.getParameters(); if (parameters.length == 1) { type = (PsiClassReferenceType)parameters[0]; } } return Optional.fromNullable(type.resolve()); } return Optional.absent(); } public static void applyGenerate(@Nullable final PsiMethod method) { if (null == method) return; final StatementGenerator[] generators = getGenerators(method); if (1 == generators.length) { generators[0].execute(method); } else { UiComponentFacade.getInstance(method.getProject()).showListPopup("[ Select target statement ]", new ListSelectionListener() { @Override public void selected(int index) { generators[index].execute(method); } @Override public boolean isWriteAction() { return true; } }, generators); } } @NotNull public static StatementGenerator[] getGenerators(@NotNull PsiMethod method) { GenerateModel model = MybatisSetting.getInstance().getStatementGenerateModel(); String target = method.getName(); List<StatementGenerator> result = Lists.newArrayList(); for (StatementGenerator generator : ALL) { if (model.matchesAny(generator.getPatterns(), target)) { result.add(generator); } } return CollectionUtils.isNotEmpty(result) ? result.toArray(new StatementGenerator[result.size()]) : ALL.toArray(new StatementGenerator[ALL.size()]); } private Set<String> patterns; public StatementGenerator(@NotNull String... patterns) { this.patterns = Sets.newHashSet(patterns); } public void execute(@NotNull final PsiMethod method) { PsiClass psiClass = method.getContainingClass(); if (null == psiClass) return; CommonProcessors.CollectProcessor<Mapper> processor = new CommonProcessors.CollectProcessor<Mapper>(); JavaService.getInstance(method.getProject()).process(psiClass, processor); final List<Mapper> mappers = Lists.newArrayList(processor.getResults()); if (1 == mappers.size()) { setupTag(method, Iterables.getOnlyElement(mappers, null)); } else if (mappers.size() > 1) { Collection<String> paths = Collections2.transform(mappers, FUN); UiComponentFacade.getInstance(method.getProject()).showListPopup("Choose target mapper xml to generate", new ListSelectionListener() { @Override public void selected(int index) { setupTag(method, mappers.get(index)); } @Override public boolean isWriteAction() { return true; } }, paths.toArray(new String[paths.size()])); } } private void setupTag(PsiMethod method, Mapper mapper) { GroupTwo target = getTarget(mapper, method); target.getId().setStringValue(method.getName()); target.setValue(" "); XmlTag tag = target.getXmlTag(); int offset = tag.getTextOffset() + tag.getTextLength() - tag.getName().length() + 1; EditorService editorService = EditorService.getInstance(method.getProject()); editorService.format(tag.getContainingFile(), tag); editorService.scrollTo(tag, offset); } @Override public String toString() { return this.getDisplayText(); } @NotNull protected abstract GroupTwo getTarget(@NotNull Mapper mapper, @NotNull PsiMethod method); @NotNull public abstract String getId(); @NotNull public abstract String getDisplayText(); public Set<String> getPatterns() { return patterns; } public void setPatterns(Set<String> patterns) { this.patterns = patterns; } }