/* * Copyright 2012-2017 the original author or authors. * * 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 io.spring.initializr.metadata; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import io.spring.initializr.util.Version; import io.spring.initializr.util.VersionParser; import io.spring.initializr.util.VersionProperty; /** * Meta-data used to generate a project. * * @author Stephane Nicoll * @see ServiceCapability */ public class InitializrMetadata { private final InitializrConfiguration configuration; private final DependenciesCapability dependencies = new DependenciesCapability(); private final TypeCapability types = new TypeCapability(); private final SingleSelectCapability bootVersions = new SingleSelectCapability("bootVersion", "Spring Boot Version", "spring boot version"); private final SingleSelectCapability packagings = new SingleSelectCapability("packaging", "Packaging", "project packaging"); private final SingleSelectCapability javaVersions = new SingleSelectCapability("javaVersion", "Java Version", "language level"); private final SingleSelectCapability languages = new SingleSelectCapability("language", "Language", "programming language"); private final TextCapability name = new TextCapability("name", "Name", "project name (infer application name)"); private final TextCapability description = new TextCapability("description", "Description", "project description"); private final TextCapability groupId = new TextCapability("groupId", "Group", "project coordinates"); private final TextCapability artifactId = new ArtifactIdCapability(name); private final TextCapability version = new TextCapability("version", "Version", "project version"); private final TextCapability packageName = new PackageCapability(groupId, artifactId); public InitializrMetadata() { this(new InitializrConfiguration()); } protected InitializrMetadata(InitializrConfiguration configuration) { this.configuration = configuration; } public InitializrConfiguration getConfiguration() { return configuration; } public DependenciesCapability getDependencies() { return dependencies; } public TypeCapability getTypes() { return types; } public SingleSelectCapability getBootVersions() { return bootVersions; } public SingleSelectCapability getPackagings() { return packagings; } public SingleSelectCapability getJavaVersions() { return javaVersions; } public SingleSelectCapability getLanguages() { return languages; } public TextCapability getName() { return name; } public TextCapability getDescription() { return description; } public TextCapability getGroupId() { return groupId; } public TextCapability getArtifactId() { return artifactId; } public TextCapability getVersion() { return version; } public TextCapability getPackageName() { return packageName; } /** * Merge this instance with the specified argument * @param other the other instance */ public void merge(InitializrMetadata other) { this.configuration.merge(other.configuration); this.dependencies.merge(other.dependencies); this.types.merge(other.types); this.bootVersions.merge(other.bootVersions); this.packagings.merge(other.packagings); this.javaVersions.merge(other.javaVersions); this.languages.merge(other.languages); this.name.merge(other.name); this.description.merge(other.description); this.groupId.merge(other.groupId); this.artifactId.merge(other.artifactId); this.version.merge(other.version); this.packageName.merge(other.packageName); } /** * Validate the metadata. */ public void validate() { this.configuration.validate(); dependencies.validate(); Map<String, Repository> repositories = configuration.getEnv().getRepositories(); Map<String, BillOfMaterials> boms = configuration.getEnv().getBoms(); for (Dependency dependency : dependencies.getAll()) { if (dependency.getBom() != null && !boms.containsKey(dependency.getBom())) { throw new InvalidInitializrMetadataException( "Dependency " + dependency + "defines an invalid BOM id " + dependency.getBom() + ", available boms " + boms); } if (dependency.getRepository() != null && !repositories.containsKey(dependency.getRepository())) { throw new InvalidInitializrMetadataException("Dependency " + dependency + "defines an invalid repository id " + dependency.getRepository() + ", available repositories " + repositories); } } for (BillOfMaterials bom : boms.values()) { for (String r : bom.getRepositories()) { if (!repositories.containsKey(r)) { throw new InvalidInitializrMetadataException( bom + "defines an invalid repository id " + r + ", available repositories " + repositories); } } for (String b : bom.getAdditionalBoms()) { if (!boms.containsKey(b)) { throw new InvalidInitializrMetadataException( bom + " defines an invalid " + "additional bom id " + b + ", available boms " + boms); } } for (BillOfMaterials.Mapping m : bom.getMappings()) { for (String r : m.getRepositories()) { if (!repositories.containsKey(r)) { throw new InvalidInitializrMetadataException( m + " of " + bom + "defines an invalid repository id " + r + ", available repositories " + repositories); } } for (String b : m.getAdditionalBoms()) { if (!boms.containsKey(b)) { throw new InvalidInitializrMetadataException(m + " of " + bom + " defines " + "an invalid additional bom id " + b + ", available boms " + boms); } } } } } /** * Update the available Spring Boot versions with the specified capabilities. * @param versionsMetadata the Spring Boot boot versions metadata to use */ public void updateSpringBootVersions(List<DefaultMetadataElement> versionsMetadata) { this.bootVersions.getContent().clear(); this.bootVersions.getContent().addAll(versionsMetadata); List<Version> bootVersions = this.bootVersions.getContent().stream() .map(it -> Version.parse(it.getId())).collect(Collectors.toList()); VersionParser parser = new VersionParser(bootVersions); dependencies.updateVersionRange(parser); configuration.getEnv().getBoms().values() .forEach(it -> it.updateVersionRange(parser)); } /** * Create an URL suitable to download Spring Boot cli for the specified version and * extension. */ public String createCliDistributionURl(String extension) { String bootVersion = defaultId(bootVersions); return configuration.getEnv().getArtifactRepository() + "org/springframework/boot/spring-boot-cli/" + bootVersion + "/spring-boot-cli-" + bootVersion + "-bin." + extension; } /** * Create a {@link BillOfMaterials} for the spring boot BOM. */ public BillOfMaterials createSpringBootBom(String bootVersion, String versionProperty) { BillOfMaterials bom = BillOfMaterials.create("org.springframework.boot", "spring-boot-dependencies", bootVersion); bom.setVersionProperty(new VersionProperty(versionProperty)); bom.setOrder(100); return bom; } /** * Return the defaults for the capabilities defined on this instance. */ public Map<String, Object> defaults() { Map<String, Object> defaults = new LinkedHashMap<>(); defaults.put("type", defaultId(types)); defaults.put("bootVersion", defaultId(bootVersions)); defaults.put("packaging", defaultId(packagings)); defaults.put("javaVersion", defaultId(javaVersions)); defaults.put("language", defaultId(languages)); defaults.put("groupId", groupId.getContent()); defaults.put("artifactId", artifactId.getContent()); defaults.put("version", version.getContent()); defaults.put("name", name.getContent()); defaults.put("description", description.getContent()); defaults.put("packageName", packageName.getContent()); return defaults; } private static String defaultId(Defaultable<? extends DefaultMetadataElement> element) { DefaultMetadataElement defaultValue = element.getDefault(); return defaultValue != null ? defaultValue.getId() : null; } private static class ArtifactIdCapability extends TextCapability { private final TextCapability nameCapability; ArtifactIdCapability(TextCapability nameCapability) { super("artifactId", "Artifact", "project coordinates (infer archive name)"); this.nameCapability = nameCapability; } @Override public String getContent() { String value = super.getContent(); return value == null ? nameCapability.getContent() : value; } } private static class PackageCapability extends TextCapability { private final TextCapability groupId; private final TextCapability artifactId; PackageCapability(TextCapability groupId, TextCapability artifactId) { super("packageName", "Package Name", "root package"); this.groupId = groupId; this.artifactId = artifactId; } @Override public String getContent() { String value = super.getContent(); if (value != null) { return value; } else if (this.groupId.getContent() != null && this.artifactId.getContent() != null) { return InitializrConfiguration.cleanPackageName( this.groupId.getContent() + "." + this.artifactId.getContent()); } return null; } } }