/* * Copyright 2013-2016 Grzegorz Ligas <ligasgr@gmail.com> and other contributors * (see the CONTRIBUTORS file). * * 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 org.intellij.xquery.runner; import com.intellij.execution.Location; import com.intellij.execution.RunManagerEx; import com.intellij.execution.RunnerAndConfigurationSettings; import com.intellij.execution.actions.ConfigurationContext; import com.intellij.execution.actions.RunConfigurationProducer; import com.intellij.execution.configurations.ModuleBasedConfiguration; import com.intellij.execution.configurations.RunConfiguration; import com.intellij.openapi.module.Module; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import org.intellij.xquery.psi.*; import org.intellij.xquery.runner.state.run.XQueryRunConfiguration; import org.intellij.xquery.runner.state.run.XQueryRunVariable; import org.intellij.xquery.runner.state.run.XQueryRunVariables; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; import static org.intellij.xquery.util.StringUtils.EMPTY; import static org.intellij.xquery.util.StringUtils.removeQuotOrAposIfNeeded; public class XQueryRunConfigurationProducer extends RunConfigurationProducer implements Cloneable { public XQueryRunConfigurationProducer() { super(XQueryRunConfigurationType.getInstance()); } @Override protected boolean setupConfigurationFromContext(RunConfiguration configuration, ConfigurationContext context, Ref sourceElement) { if (!(configuration instanceof XQueryRunConfiguration)) return false; XQueryRunConfiguration appConfiguration = (XQueryRunConfiguration) configuration; Location location = context.getLocation(); PsiElement psiElement = location.getPsiElement(); PsiFile psiFile = psiElement.getContainingFile(); if (isUnsupportedFile(psiFile)) return false; XQueryFile containingFile = (XQueryFile) psiFile; if (containingFile.isLibraryModule()) return false; final VirtualFile vFile = location.getVirtualFile(); if (vFile == null) return false; prepareSettings(appConfiguration, context, vFile, containingFile); return true; } @Override public boolean isConfigurationFromContext(RunConfiguration configuration, ConfigurationContext context) { if (!(configuration instanceof XQueryRunConfiguration)) return false; XQueryRunConfiguration appConfiguration = (XQueryRunConfiguration) configuration; Location location = context.getLocation(); PsiFile psiFile = location.getPsiElement().getContainingFile(); if (isUnsupportedFile(psiFile) || ((XQueryFile) psiFile).isLibraryModule()) return false; return isForTheSameFile(psiFile, appConfiguration) && isForTheSameModule(location, appConfiguration) && appConfiguration.getDataSourceName() != null; } @Override protected RunnerAndConfigurationSettings cloneTemplateConfiguration(@NotNull ConfigurationContext context) { RunnerAndConfigurationSettings cloned = super.cloneTemplateConfiguration(context); cloned.setEditBeforeRun(true); return cloned; } private boolean isUnsupportedFile(PsiFile psiFile) { return !(psiFile instanceof XQueryFile); } private void prepareSettings(XQueryRunConfiguration configuration, ConfigurationContext context, VirtualFile vFile, XQueryFile containingFile) { setFileSpecificSettings(vFile, configuration, containingFile); setupConfigurationModule(context, configuration); } private void setFileSpecificSettings(VirtualFile vFile, XQueryRunConfiguration configuration, XQueryFile containingFile) { configuration.setMainFileName(FileUtil.toSystemIndependentName(vFile.getCanonicalPath())); configuration.setName(vFile.getPresentableName()); configuration.setVariables(getExternalVariables(containingFile)); configuration.setContextItemEnabled(containingFile.getContextItem() != null); String contextItemType = getContextItemType(containingFile); if (contextItemType != null) configuration.setContextItemType(contextItemType); } private String getContextItemType(XQueryFile containingFile) { XQueryContextItemDecl contextItem = containingFile.getContextItem(); if (contextItem != null && contextItem.getItemType() != null) return contextItem.getItemType().getText(); return null; } private XQueryRunVariables getExternalVariables(XQueryFile file) { List<XQueryRunVariable> variables = new ArrayList<XQueryRunVariable>(); for (XQueryVarDecl varDecl : file.getVariableDeclarations()) { if (varDecl.isExternal()) { String type = varDecl.getTypeDeclaration() != null ? varDecl.getTypeDeclaration().getSequenceType() .getText() : null; XQueryVarDefaultValue varDefaultValue = varDecl.getExternalVarPart().getVarDefaultValue(); String value = EMPTY; if (varDefaultValue != null && varDefaultValue.getExprSingle().getFirstChild() instanceof XQueryLiteral) { value = removeQuotOrAposIfNeeded(varDefaultValue.getExprSingle().getText()); } boolean isActive = varDefaultValue == null; String name = varDecl.getVarName().getText(); XQueryPrefix prefix = varDecl.getVarName().getPrefix(); String namespace = EMPTY; if (prefix != null) { PsiElement resolved = prefix.getReference().resolve(); if (resolved != null) { namespace = ((XQueryNamespaceSource) resolved.getParent()).getNamespace(); } } XQueryRunVariable variable = new XQueryRunVariable(name, namespace, type, value, isActive); variables.add(variable); } } return new XQueryRunVariables(variables); } private void setupConfigurationModule(@Nullable ConfigurationContext context, ModuleBasedConfiguration configuration) { if (context != null) { Module module = getModule(context, configuration); if (module != null) { configuration.setModule(module); } } } private Module getModule(ConfigurationContext context, ModuleBasedConfiguration configuration) { Module module = getPredefinedModule(context); if (module == null) module = getModuleForLocation(context, configuration); return module; } private Module getModuleForLocation(ConfigurationContext context, ModuleBasedConfiguration configuration) { final Module contextModule = context.getModule(); return findModule(configuration, contextModule); } private Module getPredefinedModule(ConfigurationContext context) { final RunnerAndConfigurationSettings template = getConfigurationTemplate(context); return getPredefinedModule(template); } private RunnerAndConfigurationSettings getConfigurationTemplate(ConfigurationContext context) { return context.getRunManager().getConfigurationTemplate(getConfigurationFactory()); } private Module findModule(ModuleBasedConfiguration configuration, Module contextModule) { if (configuration.getConfigurationModule().getModule() == null && contextModule != null) { return contextModule; } return null; } private boolean isForTheSameModule(Location location, XQueryRunConfiguration appConfiguration) { final Module configurationModule = appConfiguration.getConfigurationModule().getModule(); return Comparing.equal(location.getModule(), configurationModule) || Comparing.equal(getPredefinedModule(location), configurationModule); } private boolean isForTheSameFile(PsiFile psiFile, XQueryRunConfiguration appConfiguration) { String checkedFilePath = FileUtil.toSystemIndependentName(psiFile.getVirtualFile().getCanonicalPath()); String existingConfigFilePath = ""; if (appConfiguration.getMainFileName() != null) existingConfigFilePath = FileUtil.toSystemIndependentName(appConfiguration.getMainFileName()); return Comparing.equal(checkedFilePath, existingConfigFilePath); } private Module getPredefinedModule(Location location) { return ((XQueryRunConfiguration) RunManagerEx.getInstanceEx(location.getProject()) .getConfigurationTemplate(getConfigurationFactory()) .getConfiguration()).getConfigurationModule().getModule(); } private Module getPredefinedModule(RunnerAndConfigurationSettings template) { return ((ModuleBasedConfiguration) template.getConfiguration()).getConfigurationModule().getModule(); } }