/******************************************************************************* * Copyright (c) 2012-2017 Codenvy, S.A. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Codenvy, S.A. - initial API and implementation *******************************************************************************/ package org.eclipse.che.ide.maven.tools; import org.eclipse.che.commons.xml.Element; import org.eclipse.che.commons.xml.ElementMapper; import org.eclipse.che.commons.xml.NewElement; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import static com.google.common.base.Strings.isNullOrEmpty; import static java.util.Collections.emptyList; import static java.util.Collections.emptyMap; import static org.eclipse.che.commons.xml.NewElement.createElement; import static org.eclipse.che.commons.xml.XMLTreeLocation.before; import static org.eclipse.che.commons.xml.XMLTreeLocation.beforeAnyOf; import static org.eclipse.che.commons.xml.XMLTreeLocation.inTheBegin; import static org.eclipse.che.commons.xml.XMLTreeLocation.inTheEnd; /** * Describes profile for <i>/project/profiles/</i> * <p/> * Supports next data: * <ul> * <li>id</li> * <li>activation</li> * <li>build</li> * <li>properties</li> * <li>modules</li> * <li>repositories</li> * <li>dependencies</li> * <li>dependencyManagement</li> * </ul> */ public class Profile { public static final String SOURCE_POM = "pom"; private static final ElementMapper<String> TEXT_MAPPER = new ElementTextMapper(); private static final RepositoryMapper REPOSITORY_MAPPER = new RepositoryMapper(); private static final ToDependencyMapper TO_DEPENDENCY_MAPPER = new ToDependencyMapper(); public Element element; private String id; private Activation activation; private List<String> modules; private Build build; private List<Repository> repositories; private Map<String, String> properties; private Dependencies dependencies; private DependencyManagement dependencyManagement; Profile(Element element) { this.element = element; this.id = element.getChildText("id"); final Element modules = element.getSingleChild("modules"); if (element.hasSingleChild("modules") && modules != null) { this.modules = modules.getChildren(TEXT_MAPPER); } if (element.hasSingleChild("activation")) { activation = new Activation(element.getSingleChild("activation")); } if (element.hasSingleChild("build")) { build = new Build(element.getSingleChild("build")); } final Element repositories = element.getSingleChild("repositories"); if (element.hasSingleChild("repositories") && repositories != null) { this.repositories = repositories.getChildren(REPOSITORY_MAPPER); } final Element elementDependencies = element.getSingleChild("dependencies"); if (element.hasSingleChild("dependencies") && elementDependencies != null) { final List<Dependency> dependencies = elementDependencies.getChildren(TO_DEPENDENCY_MAPPER); this.dependencies = new Dependencies(element, dependencies); } final Element properties = element.getSingleChild("properties"); if (element.hasSingleChild("properties") && properties != null) { this.properties = fetchProperties(properties); } final Element dependencyManagementDependencies = element.getSingleChild("dependencyManagement/dependencies"); if (element.hasSingleChild("dependencyManagement") && dependencyManagementDependencies != null) { final Element dm = element.getSingleChild("dependencyManagement"); final List<Dependency> dependencies = dependencyManagementDependencies.getChildren(TO_DEPENDENCY_MAPPER); this.dependencyManagement = new DependencyManagement(dm, dependencies); } } /** * Returns profile identifier. */ public String getId() { return id; } /** * Sets profile identifier. * * @param id * new profile identifier, if it is {@code null} then <i>id</i> element will be removed from xml if exists */ public Profile setId(String id) { this.id = id; if (!isNew()) { if (isNullOrEmpty(id)) { element.removeChild("id"); } else { final Element idElement = element.getSingleChild("id"); if (element.hasSingleChild("id") && idElement != null) { idElement.setText(id); } else { element.insertChild(createElement("id", id), inTheBegin()); } } } return this; } public Activation getActivation() { return activation; } /** * Sets activation configuration, see {@link Activation} * * @param activation * new activation * @return this profile instance */ public Profile setActivation(Activation activation) { this.activation = activation; if (!isNew()) { if (activation == null) { element.removeChild("activation"); } else if (element.hasSingleChild("activation")) { element.removeChild("activation"); element.appendChild(activation.asXMLElement()); } else { element.appendChild(activation.asXMLElement()); } } return this; } /** * Returns profile properties or empty map when the profile * doesn't have properties * <p/> * <b>Note: update methods should not be used on returned map</b> */ public Map<String, String> getProperties() { if (properties == null) { return emptyMap(); } return new HashMap<>(properties); } public List<Repository> getRepositories() { if (repositories == null) { return emptyList(); } return new ArrayList<>(repositories); } /** * Sets collection of repositories. * <p/> * <b>Note: all existing repositories will be removed from profile and xml as well</b> * * @param repositories * new plugin repositories */ public Profile setRepositories(Collection<? extends Repository> repositories) { for (Repository repository : repositories()) { repository.remove(); } if (repositories != null && !repositories.isEmpty()) { for (Repository repository : repositories) { addRepository(repository); } } else { element.removeChild("repositories"); this.repositories = null; } return this; } public List<Dependency> getDependencies() { return dependencies == null ? emptyList() : dependencies.get(); } public Profile setDependencies(List<Dependency> dependencies) { this.dependencies = new Dependencies(element, dependencies); return this; } public DependencyManagement getDependencyManagement() { return dependencyManagement; } /** * Sets default dependency information for projects that inherit from this one. * If new dependency management is {@code null} removes old dependency management * from profile and from xml as well * * @param dependencyManagement * new project dependency management * @return this profile instance */ public Profile setDependencyManagement(DependencyManagement dependencyManagement) { this.dependencyManagement = dependencyManagement; if (dependencyManagement == null) { element.removeChild("dependencyManagement"); } else { final Element dependencyManagementElement = element.getSingleChild("dependencyManagement"); if (element.hasSingleChild("dependencyManagement") && dependencyManagementElement != null) { dependencyManagement.dmElement = dependencyManagementElement .replaceWith(dependencyManagement.asXMLElement()); } else { element.insertChild(this.dependencyManagement.asXMLElement(), beforeAnyOf("dependencies").or(inTheEnd())); dependencyManagement.dmElement = dependencyManagementElement; } } return this; } public Build getBuild() { return build; } /** * Sets build configuration, see {@link Activation} * * @param build * new build * @return this profile instance */ public Profile setBuild(Build build) { this.build = build; if (!isNew()) { if (build == null) { element.removeChild("build"); } else if (element.hasSingleChild("build")) { element.removeChild("build"); element.appendChild(build.asXMLElement()); } else { element.appendChild(build.asXMLElement()); } } return this; } /** * Returns list of modules. */ public List<String> getModules() { if (modules == null) { return emptyList(); } return new ArrayList<>(modules); } /** * Specifies list of modules. */ public Profile setModules(Collection<String> modules) { if (modules == null || modules.isEmpty()) { removeModules(); } else { setModules0(modules); } return this; } public void remove() { if (element != null) { element.remove(); element = null; } } /** Returns profile element as XML element. */ public NewElement asXMLElement() { final NewElement profile = createElement("profile"); if (!isNullOrEmpty(id)) { profile.appendChild(createElement("id", id)); } if (modules != null && !modules.isEmpty()) { profile.appendChild(newModulesXMLElement(modules)); } if (activation != null) { profile.appendChild(activation.asXMLElement()); } if (build != null) { profile.appendChild(build.asXMLElement()); } if (repositories != null && !repositories.isEmpty()) { profile.appendChild(newRepositoryElement(repositories)); } if (dependencies != null && !dependencies.get().isEmpty()) { profile.appendChild(newDependencyElement(dependencies.get())); } if (properties != null && !properties.isEmpty()) { profile.appendChild(newPropertiesElement(properties)); } if (dependencyManagement != null && !dependencyManagement.getDependencies().isEmpty()) { profile.appendChild(newDependencyManagementElement(dependencies.get())); } return profile; } private Profile addRepository(Repository repository) { repositories().add(repository); final Element repositoriesElement = element.getSingleChild("repositories"); if (element.hasSingleChild("repositories") && repositoriesElement != null) { repositoriesElement.appendChild(repository.asXMLElement()); repository.element = element.getLastChild(); } else { element.insertChild(createElement("repositories", repository.asXMLElement()), beforeAnyOf("pluginRepositories", "activation", "build").or(inTheEnd())); if (repositoriesElement != null) { repository.element = repositoriesElement.getFirstChild(); } } return this; } private static Map<String, String> fetchProperties(Element propertiesElement) { final Map<String, String> properties = new HashMap<>(); for (Element property : propertiesElement.getChildren()) { properties.put(property.getName(), property.getText()); } return properties; } private Map<String, String> properties() { return properties == null ? properties = new HashMap<>() : properties; } private List<Repository> repositories() { return repositories == null ? repositories = new ArrayList<>() : repositories; } private void setModules0(Collection<String> modules) { this.modules = new ArrayList<>(modules); if (isNew()) return; //if modules element exists we should replace it children //with new set of modules, otherwise create element for it if (element.hasSingleChild("modules")) { final Element modulesElement = element.getSingleChild("modules"); if (modulesElement == null) { return; } //remove all modules from element for (Element module : modulesElement.getChildren()) { module.remove(); } //append each new module to "modules" element for (String module : modules) { element.appendChild(createElement("module", module)); } } else { element.insertChild(newModulesXMLElement(this.modules), before("build").or(inTheEnd())); } } private NewElement newRepositoryElement(List<Repository> repositories) { final NewElement repositoriesElement = createElement("repositories"); for (Repository repository : repositories) { repositoriesElement.appendChild(repository.asXMLElement()); } return repositoriesElement; } private NewElement newDependencyElement(List<Dependency> dependencies) { final NewElement dependenciesElement = createElement("dependencies"); for (Dependency dependency : dependencies) { dependenciesElement.appendChild(dependency.asXMLElement()); } return dependenciesElement; } private NewElement newPropertiesElement(Map<String, String> properties) { final NewElement propertiesElement = createElement("properties"); for (String key : properties.keySet()) { propertiesElement.appendChild(createElement(key, properties.get(key))); } return propertiesElement; } private NewElement newDependencyManagementElement(List<Dependency> dependencies) { final NewElement dependenciesElement = createElement("dependencies"); for (Dependency dependency : dependencies) { dependenciesElement.appendChild(dependency.asXMLElement()); } final NewElement dependencyManagement = createElement("dependencyManagement"); dependencyManagement.appendChild(dependenciesElement); return dependencyManagement; } private NewElement newModulesXMLElement(List<String> text) { final NewElement element = createElement("modules"); for (String line : text) { element.appendChild(createElement("module", line)); } return element; } private void removeModules() { if (!isNew()) { element.removeChild("modules"); } modules = null; } private boolean isNew() { return element == null; } private static class ElementTextMapper implements ElementMapper<String> { @Override public String map(Element element) { return element.getText(); } } private static class RepositoryMapper implements ElementMapper<Repository> { @Override public Repository map(Element element) { return new Repository(element); } } private static class ToDependencyMapper implements ElementMapper<Dependency> { @Override public Dependency map(Element element) { return new Dependency(element); } } }