blob: f2c5f78be98e136de6c6af88311d67196d97d903 [file] [log] [blame]
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* 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.jetbrains.idea.maven.dom;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.CommonClassNames;
import com.intellij.psi.PsiElement;
import com.intellij.psi.codeStyle.NameUtil;
import com.intellij.psi.xml.XmlElement;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.xml.DomElement;
import com.intellij.util.xml.GenericDomValue;
import com.intellij.util.xml.Required;
import com.intellij.util.xml.XmlName;
import com.intellij.util.xml.reflect.DomExtender;
import com.intellij.util.xml.reflect.DomExtension;
import com.intellij.util.xml.reflect.DomExtensionsRegistrar;
import gnu.trove.THashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.maven.dom.converters.MavenDomConvertersRegistry;
import org.jetbrains.idea.maven.dom.converters.MavenPluginCustomParameterValueConverter;
import org.jetbrains.idea.maven.dom.model.MavenDomConfiguration;
import org.jetbrains.idea.maven.dom.model.MavenDomConfigurationParameter;
import org.jetbrains.idea.maven.dom.model.MavenDomPluginExecution;
import org.jetbrains.idea.maven.dom.plugin.MavenDomMojo;
import org.jetbrains.idea.maven.dom.plugin.MavenDomParameter;
import org.jetbrains.idea.maven.dom.plugin.MavenDomPluginModel;
import java.lang.annotation.Annotation;
import java.util.*;
public class MavenPluginConfigurationDomExtender extends DomExtender<MavenDomConfiguration> {
public static final Key<ParameterData> PLUGIN_PARAMETER_KEY = Key.create("MavenPluginConfigurationDomExtender.PLUGIN_PARAMETER_KEY");
private static final Set<String> COLLECTIONS_TYPE_NAMES = ContainerUtil.immutableSet("java.util.Collection", CommonClassNames.JAVA_UTIL_SET,
CommonClassNames.JAVA_UTIL_LIST,
"java.util.ArrayList", "java.util.HashSet",
"java.util.LinkedList");
@Override
public void registerExtensions(@NotNull MavenDomConfiguration config, @NotNull DomExtensionsRegistrar r) {
MavenDomPluginModel pluginModel = MavenPluginDomUtil.getMavenPluginModel(config);
if (pluginModel == null) {
r.registerCustomChildrenExtension(MavenDomConfigurationParameter.class);
return;
}
boolean isInPluginManagement = isInPluginManagement(config);
for (ParameterData each : collectParameters(pluginModel, config)) {
registerPluginParameter(isInPluginManagement, r, each);
}
}
private static boolean isInPluginManagement(MavenDomConfiguration pluginNode) {
XmlElement xmlElement = pluginNode.getXmlElement();
if (xmlElement == null) return false;
PsiElement pluginTag = xmlElement.getParent();
if (pluginTag == null) return false;
PsiElement pluginsTag = pluginTag.getParent();
if (pluginsTag == null) return false;
PsiElement pluginManagementTag = pluginsTag.getParent();
return pluginManagementTag instanceof XmlTag && "pluginManagement".equals(((XmlTag)pluginManagementTag).getName());
}
private static Collection<ParameterData> collectParameters(MavenDomPluginModel pluginModel, MavenDomConfiguration config) {
List<String> selectedGoals = null;
MavenDomPluginExecution executionElement = config.getParentOfType(MavenDomPluginExecution.class, false);
if (executionElement != null) {
selectedGoals = new ArrayList<String>();
String id = executionElement.getId().getStringValue();
String defaultPrefix = "default-";
if (id != null && id.startsWith(defaultPrefix)) {
String goal = id.substring(defaultPrefix.length());
if (!StringUtil.isEmptyOrSpaces(goal)) selectedGoals.add(goal);
}
for (GenericDomValue<String> goal : executionElement.getGoals().getGoals()) {
selectedGoals.add(goal.getStringValue());
}
}
Map<String, ParameterData> namesWithParameters = new THashMap<String, ParameterData>();
for (MavenDomMojo eachMojo : pluginModel.getMojos().getMojos()) {
String goal = eachMojo.getGoal().getStringValue();
if (goal == null) continue;
if (selectedGoals == null || selectedGoals.contains(goal)) {
for (MavenDomParameter eachParameter : eachMojo.getParameters().getParameters()) {
if (eachParameter.getEditable().getValue() == Boolean.FALSE) continue;
String name = eachParameter.getName().getStringValue();
if (name == null) continue;
ParameterData data = new ParameterData(eachParameter);
fillParameterData(name, data, eachMojo);
ParameterData oldParameter = namesWithParameters.get(name);
if (oldParameter == null || hasMorePriority(data, oldParameter, executionElement != null)) {
namesWithParameters.put(name, data);
}
}
}
}
return namesWithParameters.values();
}
private static boolean hasMorePriority(ParameterData d1, ParameterData d2, boolean isForExecutionSection) {
if (!isForExecutionSection) {
if (StringUtil.isEmptyOrSpaces(d1.getMojo().getPhase().getStringValue())) return false;
if (StringUtil.isEmptyOrSpaces(d2.getMojo().getPhase().getStringValue())) return true;
}
return d1.getRequiringLevel() > d2.getRequiringLevel();
}
private static void fillParameterData(String name, ParameterData data, MavenDomMojo mojo) {
XmlTag config = mojo.getConfiguration().getXmlTag();
if (config == null) return;
for (XmlTag each : config.getSubTags()) {
if (!name.equals(each.getName())) continue;
data.defaultValue = each.getAttributeValue("default-value");
data.expression = each.getValue().getTrimmedText();
}
}
private static void registerPluginParameter(boolean isInPluginManagement, DomExtensionsRegistrar r, final ParameterData parameter) {
String paramName = parameter.parameter.getName().getStringValue();
String alias = parameter.parameter.getAlias().getStringValue();
registerPluginParameter(isInPluginManagement, r, parameter, paramName);
if (alias != null) registerPluginParameter(isInPluginManagement, r, parameter, alias);
}
private static void registerPluginParameter(boolean isInPluginManagement, DomExtensionsRegistrar r, final ParameterData data, final String parameterName) {
DomExtension e = r.registerFixedNumberChildExtension(new XmlName(parameterName), MavenDomConfigurationParameter.class);
if (isCollection(data.parameter)) {
e.addExtender(new DomExtender() {
public void registerExtensions(@NotNull DomElement domElement, @NotNull DomExtensionsRegistrar registrar) {
for (String each : collectPossibleNameForCollectionParameter(parameterName)) {
DomExtension inner = registrar.registerCollectionChildrenExtension(new XmlName(each), MavenDomConfigurationParameter.class);
inner.setDeclaringElement(data.parameter);
}
}
});
}
else {
addValueConverter(e, data.parameter);
if (!isInPluginManagement) {
addRequiredAnnotation(e, data);
}
}
e.setDeclaringElement(data.parameter);
data.parameter.getXmlElement().putUserData(PLUGIN_PARAMETER_KEY, data);
}
private static void addValueConverter(DomExtension e, MavenDomParameter parameter) {
String type = parameter.getType().getStringValue();
if (!StringUtil.isEmptyOrSpaces(type)) {
e.setConverter(new MavenPluginCustomParameterValueConverter(type), MavenDomConvertersRegistry.getInstance().isSoft(type));
}
}
private static void addRequiredAnnotation(DomExtension e, final ParameterData data) {
if (Boolean.parseBoolean(data.parameter.getRequired().getStringValue())
&& StringUtil.isEmptyOrSpaces(data.defaultValue)
&& StringUtil.isEmptyOrSpaces(data.expression)) {
e.addCustomAnnotation(new Required(){
@Override
public boolean value() {
return true;
}
@Override
public boolean nonEmpty() {
return false;
}
@Override
public boolean identifier() {
return false;
}
public Class<? extends Annotation> annotationType() {
return Required.class;
}
});
}
}
public static List<String> collectPossibleNameForCollectionParameter(String parameterName) {
String singularName = StringUtil.unpluralize(parameterName);
if (singularName == null) singularName = parameterName;
List<String> result = new ArrayList<String>();
String[] parts = NameUtil.splitNameIntoWords(singularName);
for (int i = 0; i < parts.length; i++) {
result.add(StringUtil.decapitalize(StringUtil.join(parts, i, parts.length, "")));
}
return result;
}
private static boolean isCollection(MavenDomParameter parameter) {
String type = parameter.getType().getStringValue();
if (type == null) return false;
return type.endsWith("[]") || COLLECTIONS_TYPE_NAMES.contains(type);
}
public static class ParameterData {
public final MavenDomParameter parameter;
public @Nullable String defaultValue;
public @Nullable String expression;
private ParameterData(MavenDomParameter parameter) {
this.parameter = parameter;
}
@NotNull
public MavenDomMojo getMojo() {
return (MavenDomMojo)parameter.getParent().getParent();
}
public int getRequiringLevel() {
if (!Boolean.parseBoolean(parameter.getRequired().getStringValue())) return 0;
if (!StringUtil.isEmptyOrSpaces(defaultValue) || !StringUtil.isEmptyOrSpaces(expression)) {
return 1;
}
return 2;
}
}
}