More flexible meta-data

Provide a more flexible meta-data contract and clearly separate the
service configuration from the options used to generate a project.

The meta-data now defines a fixed set of core service capabilities. Each
capability has an id, a type, a description and a 'content'. The
following capability types are supported:

* text: single value
* single-select: a list of values, one value should be chosen
* hierarchical-multi-select: values of values, many values can be chosen
* action: a specific single-select that defines the action to invoke

An extension can now build its own meta-data instance more easily.

Closes gh-87
This commit is contained in:
Stephane Nicoll
2015-02-27 14:35:12 +01:00
parent 146c1489b1
commit d0985d3cc5
64 changed files with 2061 additions and 1256 deletions

View File

@@ -0,0 +1,120 @@
/*
* Copyright 2012-2015 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
/**
* Various configuration options used by the service.
*
* @author Stephane Nicoll
* @since 1.0
*/
class InitializrConfiguration {
final Env env = new Env()
/**
* Generate a suitable application mame based on the specified name. If no suitable
* application name can be generated from the specified {@code name}, the
* {@link Env#fallbackApplicationName} is used instead.
* <p>No suitable application name can be generated if the name is {@code null} or
* if it contains an invalid character for a class identifier.
* @see Env#fallbackApplicationName
* @see Env#invalidApplicationNames
*/
String generateApplicationName(String name) {
if (!name) {
return env.fallbackApplicationName
}
String text = splitCamelCase(name.trim())
String result = text.replaceAll("(_|-| |:)+([A-Za-z0-9])", { Object[] it ->
it[2].toUpperCase()
})
if (!result.endsWith('Application')) {
result += 'Application'
}
String candidate = result.capitalize();
if (hasInvalidChar(candidate) || env.invalidApplicationNames.contains(candidate)) {
return env.fallbackApplicationName
} else {
return candidate
}
}
private static String splitCamelCase(String text) {
text.split('(?<!(^|[A-Z]))(?=[A-Z])|(?<!^)(?=[A-Z][a-z])').collect {
String s = it.toLowerCase()
s.capitalize()
}.join("")
}
private static boolean hasInvalidChar(String text) {
if (!Character.isJavaIdentifierStart(text.charAt(0))) {
return true
}
if (text.length() > 1) {
for (int i = 1; i < text.length(); i++) {
if (!Character.isJavaIdentifierPart(text.charAt(i))) {
return true
}
}
}
return false
}
/**
* Defines additional environment settings
*/
static class Env {
/**
* The url of the repository servicing distribution bundle
*/
String artifactRepository = 'https://repo.spring.io/release/'
/**
* The meta-data url of the Spring Boot project
*/
String springBootMetadataUrl = 'https://spring.io/project_metadata/spring-boot'
/**
* The application name to use if none could be generated.
*/
String fallbackApplicationName = 'Application'
/**
* The list of invalid application names. If such name is chosen or generated,
* the {@link #fallbackApplicationName} should be used instead.
*/
List<String> invalidApplicationNames = [
'SpringApplication',
'SpringBootApplication'
]
/**
* Force SSL support. When enabled, any access using http generate https links.
*/
boolean forceSsl = true
void setArtifactRepository(String artifactRepository) {
if (!artifactRepository.endsWith('/')) {
artifactRepository = artifactRepository + '/'
}
this.artifactRepository = artifactRepository
}
}
}

View File

@@ -1,480 +0,0 @@
/*
* Copyright 2012-2015 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
import javax.annotation.PostConstruct
import groovy.transform.ToString
import groovy.util.logging.Slf4j
import io.spring.initializr.mapper.InitializrMetadataJsonMapper
import io.spring.initializr.mapper.InitializrMetadataV21JsonMapper
import io.spring.initializr.mapper.InitializrMetadataV2JsonMapper
import io.spring.initializr.support.InvalidVersionException
import io.spring.initializr.support.VersionRange
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties
/**
* The metadata using by the initializr, that is:
*
* <ul>
* <li>Known dependencies gathered in group</li>
* <li>The build types supported by the service</li>
* <li>Supported Java versions</li>
* <li>Supported language</li>
* <li>Supported Spring Boot versions</li>
* <li>Default settings used to generate the project</li>
* <li>Environment related settings</li>
* </ul>
*
* @author Stephane Nicoll
* @since 1.0
*/
@ConfigurationProperties(prefix = 'initializr', ignoreUnknownFields = false)
@Slf4j
class InitializrMetadata {
final List<DependencyGroup> dependencies = []
final List<Type> types = []
final List<Packaging> packagings = []
final List<JavaVersion> javaVersions = []
final List<Language> languages = []
final List<BootVersion> bootVersions = []
final Defaults defaults = new Defaults()
final Env env = new Env()
private final Map<String, Dependency> indexedDependencies = [:]
@Autowired(required = false)
List<InitializrMetadataCustomizer> customizers = []
/**
* Return the {@link Dependency} with the specified id or {@code null} if
* no such dependency exists.
*/
Dependency getDependency(String id) {
indexedDependencies[id]
}
/**
* Return all dependencies as a flat collection
*/
Collection<Dependency> getAllDependencies() {
indexedDependencies.values()
}
/**
* Return the {@link Type} with the specified id or {@code null} if no
* such type exists.
*/
Type getType(String id) {
for (it in this.types) {
if (id.equals(it.id) || id.equals(it.stsId)) {
return it
}
}
return null
}
/**
* Create an URL suitable to download Spring Boot cli for the specified version and extension.
*/
String createCliDistributionURl(String extension) {
env.artifactRepository + "org/springframework/boot/spring-boot-cli/" +
"$defaults.bootVersion/spring-boot-cli-$defaults.bootVersion-bin.$extension"
}
/**
* Generate a suitable application mame based on the specified name. If no suitable
* application name can be generated from the specified {@code name}, the
* {@link Env#fallbackApplicationName} is used instead.
* <p>No suitable application name can be generated if the name is {@code null} or
* if it contains an invalid character for a class identifier.
* @see Env#fallbackApplicationName
* @see Env#invalidApplicationNames
*/
String generateApplicationName(String name) {
if (!name) {
return env.fallbackApplicationName
}
String text = splitCamelCase(name.trim())
String result = text.replaceAll("(_|-| |:)+([A-Za-z0-9])", { Object[] it ->
it[2].toUpperCase()
})
if (!result.endsWith('Application')) {
result += 'Application'
}
String candidate = result.capitalize();
if (hasInvalidChar(candidate) || env.invalidApplicationNames.contains(candidate)) {
return env.fallbackApplicationName
} else {
return candidate
}
}
/**
* Initializes a {@link ProjectRequest} instance with the defaults
* defined in this instance.
*/
void initializeProjectRequest(ProjectRequest request) {
defaults.properties.each { key, value ->
if (request.hasProperty(key) && !(key in ['class', 'metaClass'])) {
request[key] = value
}
}
request
}
/**
* Merge this instance with the specified content.
*/
void merge(List<BootVersion> bootVersions) {
if (bootVersions) {
synchronized (this.bootVersions) {
this.bootVersions.clear()
this.bootVersions.addAll(bootVersions)
}
}
refreshDefaults()
}
/**
* Generate a JSON representation of the current metadata
* @param version the meta-data version
* @param appUrl the application url
*/
String generateJson(InitializrMetadataVersion version, String appUrl) {
getJsonMapper(version).write(this, appUrl)
}
/**
* Initialize and validate the configuration.
*/
@PostConstruct
void validate() {
customizers.each { customizer ->
customizer.customize(this)
}
dependencies.each { group ->
group.content.each { dependency ->
validateDependency(dependency)
indexDependency(dependency.id, dependency)
for (String alias : dependency.aliases) {
indexDependency(alias, dependency)
}
}
}
env.validate()
refreshDefaults()
}
private void refreshDefaults() {
defaults.type = getDefault(types)
defaults.packaging = getDefault(packagings)
defaults.javaVersion = getDefault(javaVersions)
defaults.language = getDefault(languages)
defaults.bootVersion = getDefault(bootVersions)
}
private void indexDependency(String id, Dependency dependency) {
def existing = indexedDependencies[id]
if (existing) {
throw new IllegalArgumentException("Could not register $dependency another dependency has also the '$id' id $existing");
}
indexedDependencies[id] = dependency
}
static void validateDependency(Dependency dependency) {
def id = dependency.id
if (id == null) {
if (!dependency.hasCoordinates()) {
throw new InvalidInitializrMetadataException(
'Invalid dependency, should have at least an id or a groupId/artifactId pair.')
}
dependency.generateId()
} else if (!dependency.hasCoordinates()) {
// Let's build the coordinates from the id
def st = new StringTokenizer(id, ':')
if (st.countTokens() == 1) { // assume spring-boot-starter
dependency.asSpringBootStarter(id)
} else if (st.countTokens() == 2 || st.countTokens() == 3) {
dependency.groupId = st.nextToken()
dependency.artifactId = st.nextToken()
if (st.hasMoreTokens()) {
dependency.version = st.nextToken()
}
} else {
throw new InvalidInitializrMetadataException(
"Invalid dependency, id should have the form groupId:artifactId[:version] but got $id")
}
}
if (dependency.versionRange) {
try {
VersionRange.parse(dependency.versionRange)
} catch (InvalidVersionException ex) {
throw new InvalidInitializrMetadataException("Invalid version range '$dependency.versionRange' for " +
"dependency with id '$dependency.id'")
}
}
}
static def getDefault(List elements) {
for (DefaultIdentifiableElement element : elements) {
if (element.default) {
return element.id
}
}
log.warn("No default found amongst $elements")
return (elements.isEmpty() ? null : elements.get(0).id)
}
private static InitializrMetadataJsonMapper getJsonMapper(InitializrMetadataVersion version) {
switch(version) {
case InitializrMetadataVersion.V2: return new InitializrMetadataV2JsonMapper();
default: return new InitializrMetadataV21JsonMapper();
}
}
private static String splitCamelCase(String text) {
text.split('(?<!(^|[A-Z]))(?=[A-Z])|(?<!^)(?=[A-Z][a-z])').collect {
String s = it.toLowerCase()
s.capitalize()
}.join("")
}
private static boolean hasInvalidChar(String text) {
if (!Character.isJavaIdentifierStart(text.charAt(0))) {
return true
}
if (text.length() > 1) {
for (int i = 1; i < text.length(); i++) {
if (!Character.isJavaIdentifierPart(text.charAt(i))) {
return true
}
}
}
return false
}
static class DependencyGroup {
String name
final List<Dependency> content = []
}
@ToString(ignoreNulls = true, includePackage = false)
static class Dependency extends IdentifiableElement {
static final String SCOPE_COMPILE = 'compile'
static final String SCOPE_RUNTIME = 'runtime'
static final String SCOPE_PROVIDED = 'provided'
static final String SCOPE_TEST = 'test'
static final List<String> SCOPE_ALL = [SCOPE_COMPILE, SCOPE_RUNTIME, SCOPE_PROVIDED, SCOPE_TEST]
List<String> aliases = []
List<String> facets = []
String groupId
String artifactId
String version
String scope = SCOPE_COMPILE
String description
String versionRange
void setScope(String scope) {
if (!SCOPE_ALL.contains(scope)) {
throw new InvalidInitializrMetadataException("Invalid scope $scope must be one of $SCOPE_ALL")
}
this.scope = scope
}
void setVersionRange(String versionRange) {
this.versionRange = versionRange ? versionRange.trim() : null
}
/**
* Specify if the dependency has its coordinates set, i.e. {@code groupId}
* and {@code artifactId}.
*/
boolean hasCoordinates() {
groupId && artifactId
}
/**
* Define this dependency as a standard spring boot starter with the specified name
* <p>If no name is specified, the root 'spring-boot-starter' is assumed.
*/
Dependency asSpringBootStarter(String name) {
groupId = 'org.springframework.boot'
artifactId = name ? 'spring-boot-starter-' + name : 'spring-boot-starter'
if (name) {
id = name
}
this
}
/**
* Generate an id using the groupId and artifactId
*/
def generateId() {
if (groupId == null || artifactId == null) {
throw new IllegalArgumentException(
"Could not generate id for $this: at least groupId and artifactId must be set.")
}
StringBuilder sb = new StringBuilder()
sb.append(groupId).append(':').append(artifactId)
id = sb.toString()
}
}
static class Type extends DefaultIdentifiableElement {
String description
@Deprecated
String stsId
String action
void setAction(String action) {
String actionToUse = action
if (!actionToUse.startsWith("/")) {
actionToUse = "/" + actionToUse
}
this.action = actionToUse
}
final Map<String, String> tags = [:]
}
static class Packaging extends DefaultIdentifiableElement {
}
static class JavaVersion extends DefaultIdentifiableElement {
}
static class Language extends DefaultIdentifiableElement {
}
static class BootVersion extends DefaultIdentifiableElement {
}
static class Defaults {
static final String DEFAULT_NAME = 'demo'
String groupId = 'org.test'
String artifactId
String version = '0.0.1-SNAPSHOT'
String name = DEFAULT_NAME
String description = 'Demo project for Spring Boot'
String packageName
String type
String packaging
String javaVersion
String language
String bootVersion
/**
* Return the artifactId or the name of the project if none is set.
*/
String getArtifactId() {
artifactId == null ? name : artifactId
}
/**
* Return the package name or the name of the project if none is set
*/
String getPackageName() {
packageName == null ? name.replace('-', '.') : packageName
}
}
/**
* Defines additional environment settings
*/
static class Env {
String artifactRepository = 'https://repo.spring.io/release/'
String springBootMetadataUrl = 'https://spring.io/project_metadata/spring-boot'
/**
* The application name to use if none could be generated.
*/
String fallbackApplicationName = 'Application'
/**
* The list of invalid application names. If such name is chosen or generated,
* the {@link #fallbackApplicationName} should be used instead.
*/
List<String> invalidApplicationNames = ['SpringApplication', 'SpringBootApplication']
boolean forceSsl = true
void validate() {
if (!artifactRepository.endsWith('/')) {
artifactRepository = artifactRepository + '/'
}
}
}
static class DefaultIdentifiableElement extends IdentifiableElement {
private boolean defaultValue
void setDefault(boolean defaultValue) {
this.defaultValue = defaultValue
}
boolean isDefault() {
this.defaultValue
}
}
static class IdentifiableElement {
String name
String id
String getName() {
(name ?: id)
}
}
}

View File

@@ -14,11 +14,18 @@
* limitations under the License.
*/
package io.spring.initializr
package io.spring.initializr.config
import java.util.concurrent.TimeUnit
import com.google.common.cache.CacheBuilder
import io.spring.initializr.generator.ProjectGenerationMetricsListener
import io.spring.initializr.generator.ProjectGenerator
import io.spring.initializr.metadata.InitializrMetadata
import io.spring.initializr.metadata.InitializrMetadataBuilder
import io.spring.initializr.metadata.InitializrMetadataProvider
import io.spring.initializr.metadata.InitializrProperties
import io.spring.initializr.support.DefaultInitializrMetadataProvider
import io.spring.initializr.web.MainController
import io.spring.initializr.web.WebConfig
@@ -47,7 +54,7 @@ import org.springframework.context.annotation.Configuration
*/
@Configuration
@EnableCaching
@EnableConfigurationProperties(InitializrMetadata)
@EnableConfigurationProperties(InitializrProperties)
class InitializrAutoConfiguration {
@Autowired
@@ -72,6 +79,12 @@ class InitializrAutoConfiguration {
generator
}
@Bean
@ConditionalOnMissingBean
InitializrMetadata initializrMetadata(InitializrProperties properties) {
new InitializrMetadataBuilder().fromConfiguration(properties).build()
}
@Bean
@ConditionalOnMissingBean(InitializrMetadataProvider)
InitializrMetadataProvider initializrMetadataProvider(InitializrMetadata metadata) {

View File

@@ -14,11 +14,13 @@
* limitations under the License.
*/
package io.spring.initializr
package io.spring.initializr.generator
import io.spring.initializr.support.VersionRange
import io.spring.initializr.metadata.InitializrMetadata
import io.spring.initializr.metadata.Type
import io.spring.initializr.util.VersionRange
import static io.spring.initializr.support.GroovyTemplate.template
import static io.spring.initializr.util.GroovyTemplate.template
/**
* Generate help pages for command-line clients.
@@ -86,13 +88,8 @@ class CommandLineHelpGenerator {
model['dependencies'] = generateDependencyTable(metadata)
model['types'] = generateTypeTable(metadata, 'Rel', false)
Map defaults = [:]
metadata.defaults.properties.each {
if (!(it.key in ['class', 'metaClass', 'DEFAULT_NAME'])) {
defaults[it.key] = it.value
}
}
defaults['applicationName'] = metadata.generateApplicationName(metadata.defaults.name)
Map defaults = metadata.defaults()
defaults['applicationName'] = metadata.configuration.generateApplicationName(metadata.name.content)
defaults['baseDir'] = 'no base dir'
defaults['dependencies'] = 'none'
@@ -119,12 +116,7 @@ class CommandLineHelpGenerator {
model['types'] = generateTypeTable(metadata, 'Id', true)
Map defaults = [:]
metadata.defaults.properties.sort().each {
if (!(it.key in ['class', 'metaClass', 'DEFAULT_NAME'])) {
defaults[it.key] = it.value
}
}
Map defaults = metadata.defaults()
Map parametersDescription = buildParametersDescription()
String[][] parameterTable = new String[defaults.size() + 1][];
parameterTable[0] = ["Id", "Description", "Default value"]
@@ -140,9 +132,9 @@ class CommandLineHelpGenerator {
}
protected String generateDependencyTable(InitializrMetadata metadata) {
String[][] dependencyTable = new String[metadata.allDependencies.size() + 1][];
String[][] dependencyTable = new String[metadata.dependencies.all.size() + 1][];
dependencyTable[0] = ["Id", "Description", "Required version"]
new ArrayList(metadata.allDependencies).sort { a, b -> a.id <=> b.id }
new ArrayList(metadata.dependencies.all).sort { a, b -> a.id <=> b.id }
.eachWithIndex { dep, i ->
String[] data = new String[3]
data[0] = dep.id
@@ -154,16 +146,16 @@ class CommandLineHelpGenerator {
}
protected String generateTypeTable(InitializrMetadata metadata, String linkHeader, boolean addTags) {
String[][] typeTable = new String[metadata.types.size() + 1][];
String[][] typeTable = new String[metadata.types.content.size() + 1][];
if (addTags) {
typeTable[0] = [linkHeader, "Description", "Tags"]
}
else {
typeTable[0] = [linkHeader, "Description"]
}
new ArrayList<>(metadata.types).sort { a, b -> a.id <=> b.id }.eachWithIndex { type, i ->
new ArrayList<>(metadata.types.content).sort { a, b -> a.id <=> b.id }.eachWithIndex { type, i ->
String[] data = new String[typeTable[0].length]
data[0] = (metadata.defaults.type.equals(type.id) ? type.id + " *" : type.id)
data[0] = (type.default ? type.id + " *" : type.id)
data[1] = type.description ?: type.name
if (addTags) {
data[2] = buildTagRepresentation(type)
@@ -205,7 +197,7 @@ class CommandLineHelpGenerator {
}
}
private static String buildTagRepresentation(InitializrMetadata.Type type) {
private static String buildTagRepresentation(Type type) {
if (type.tags.isEmpty()) {
return "";
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2014 the original author or authors.
* Copyright 2012-2015 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.
@@ -14,9 +14,10 @@
* limitations under the License.
*/
package io.spring.initializr
package io.spring.initializr.generator
import groovy.transform.InheritConstructors
import io.spring.initializr.InitializrException
import org.springframework.http.HttpStatus
import org.springframework.web.bind.annotation.ResponseStatus

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2014 the original author or authors.
* Copyright 2012-2015 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package io.spring.initializr
package io.spring.initializr.generator
/**
* Interface to be implemented by components that need to be aware of project generation

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2014 the original author or authors.
* Copyright 2012-2015 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package io.spring.initializr
package io.spring.initializr.generator
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.actuate.metrics.CounterService

View File

@@ -14,17 +14,18 @@
* limitations under the License.
*/
package io.spring.initializr
package io.spring.initializr.generator
import groovy.util.logging.Slf4j
import io.spring.initializr.support.Version
import io.spring.initializr.metadata.Dependency
import io.spring.initializr.metadata.InitializrMetadata
import io.spring.initializr.util.Version
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Value
import org.springframework.util.Assert
import static io.spring.initializr.InitializrMetadata.Dependency.*
import static io.spring.initializr.support.GroovyTemplate.template
import static io.spring.initializr.util.GroovyTemplate.template
/**
* Generate a project based on the configured metadata.
@@ -174,10 +175,10 @@ class ProjectGenerator {
request.properties.each { model[it.key] = it.value }
model['compileDependencies'] = filterDependencies(dependencies, SCOPE_COMPILE)
model['runtimeDependencies'] = filterDependencies(dependencies, SCOPE_RUNTIME)
model['providedDependencies'] = filterDependencies(dependencies, SCOPE_PROVIDED)
model['testDependencies'] = filterDependencies(dependencies, SCOPE_TEST)
model['compileDependencies'] = filterDependencies(dependencies, Dependency.SCOPE_COMPILE)
model['runtimeDependencies'] = filterDependencies(dependencies, Dependency.SCOPE_RUNTIME)
model['providedDependencies'] = filterDependencies(dependencies, Dependency.SCOPE_PROVIDED)
model['testDependencies'] = filterDependencies(dependencies, Dependency.SCOPE_TEST)
// @SpringBootApplication available as from 1.2.0.RC1
model['useSpringBootApplication'] = VERSION_1_2_0_RC1

View File

@@ -14,11 +14,14 @@
* limitations under the License.
*/
package io.spring.initializr
package io.spring.initializr.generator
import groovy.util.logging.Slf4j
import io.spring.initializr.support.Version
import io.spring.initializr.support.VersionRange
import io.spring.initializr.metadata.Dependency
import io.spring.initializr.metadata.InitializrMetadata
import io.spring.initializr.metadata.Type
import io.spring.initializr.util.Version
import io.spring.initializr.util.VersionRange
/**
* A request to generate a project.
@@ -54,29 +57,40 @@ class ProjectRequest {
String baseDir
// Resolved dependencies based on the ids provided by either "style" or "dependencies"
List<InitializrMetadata.Dependency> resolvedDependencies
List<Dependency> resolvedDependencies
def facets = []
def build
/**
* Initializes this instance with the defaults defined in the specified {@link InitializrMetadata}.
*/
void initialize(InitializrMetadata metadata) {
metadata.defaults().forEach { key, value ->
if (owner.hasProperty(key)) {
owner.setProperty(key, value)
}
}
}
/**
* Resolve this instance against the specified {@link InitializrMetadata}
*/
void resolve(InitializrMetadata metadata) {
List<String> depIds = style ? style : dependencies
resolvedDependencies = depIds.collect {
def dependency = metadata.getDependency(it)
def dependency = metadata.dependencies.get(it)
if (dependency == null) {
if (it.contains(':')) {
throw new InvalidProjectRequestException("Unknown dependency '$it' check project metadata")
}
log.warn("No known dependency for style '$it' assuming spring-boot-starter")
dependency = new InitializrMetadata.Dependency()
dependency = new Dependency()
dependency.asSpringBootStarter(it)
}
dependency
}
String actualBootVersion = bootVersion ?: metadata.defaults.bootVersion
String actualBootVersion = bootVersion ?: metadata.bootVersions.default.id
Version requestedVersion = Version.parse(actualBootVersion)
resolvedDependencies.each {
it.facets.each {
@@ -94,7 +108,7 @@ class ProjectRequest {
}
if (this.type) {
InitializrMetadata.Type type = metadata.getType(this.type)
Type type = metadata.types.get(this.type)
if (!type) {
throw new InvalidProjectRequestException("Unknown type '${this.type}' check project metadata")
}
@@ -105,7 +119,7 @@ class ProjectRequest {
}
if (!applicationName) {
this.applicationName = metadata.generateApplicationName(this.name)
this.applicationName = metadata.configuration.generateApplicationName(this.name)
}
afterResolution(metadata)
@@ -117,7 +131,7 @@ class ProjectRequest {
protected afterResolution(InitializrMetadata metadata) {
if (packaging == 'war' && !hasWebFacet()) {
// Need to be able to bootstrap the web app
resolvedDependencies << metadata.getDependency('web')
resolvedDependencies << metadata.dependencies.get('web')
facets << 'web'
}
if (resolvedDependencies.isEmpty()) {
@@ -130,7 +144,7 @@ class ProjectRequest {
* dependency
*/
protected addDefaultDependency() {
def root = new InitializrMetadata.Dependency()
def root = new Dependency()
root.id = DEFAULT_STARTER
root.asSpringBootStarter('')
resolvedDependencies << root

View File

@@ -16,7 +16,7 @@
package io.spring.initializr.mapper
import io.spring.initializr.InitializrMetadata
import io.spring.initializr.metadata.InitializrMetadata
/**
* Generate a JSON representation of the metadata.

View File

@@ -1,14 +1,14 @@
/*
* Copyright 2012-2014 the original author or authors.
* Copyright 2012-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the 'License');
* 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,
* 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.
@@ -17,12 +17,12 @@
package io.spring.initializr.mapper
import groovy.json.JsonBuilder
import io.spring.initializr.InitializrMetadata
import io.spring.initializr.metadata.InitializrMetadata
import io.spring.initializr.metadata.SingleSelectCapability
import org.springframework.hateoas.TemplateVariable
import org.springframework.hateoas.TemplateVariables
import org.springframework.hateoas.UriTemplate
import org.springframework.util.StringUtils
/**
* A {@link InitializrMetadataJsonMapper} handling the meta-data format for v2.
@@ -54,19 +54,19 @@ class InitializrMetadataV2JsonMapper implements InitializrMetadataJsonMapper {
String write(InitializrMetadata metadata, String appUrl) {
JsonBuilder json = new JsonBuilder()
json {
links(delegate, metadata.types, appUrl)
links(delegate, metadata.types.content, appUrl)
dependencies(delegate, metadata.dependencies)
type(delegate, metadata.defaults.type, metadata.types)
singleSelect(delegate, 'packaging', metadata.defaults.packaging, metadata.packagings)
singleSelect(delegate, 'javaVersion', metadata.defaults.javaVersion, metadata.javaVersions)
singleSelect(delegate, 'language', metadata.defaults.language, metadata.languages)
singleSelect(delegate, 'bootVersion', metadata.defaults.bootVersion, metadata.bootVersions)
text(delegate, 'groupId', metadata.defaults.groupId)
text(delegate, 'artifactId', metadata.defaults.artifactId)
text(delegate, 'version', metadata.defaults.version)
text(delegate, 'name', metadata.defaults.name)
text(delegate, 'description', metadata.defaults.description)
text(delegate, 'packageName', metadata.defaults.packageName)
type(delegate, metadata.types)
singleSelect(delegate, metadata.packagings)
singleSelect(delegate, metadata.javaVersions)
singleSelect(delegate, metadata.languages)
singleSelect(delegate, metadata.bootVersions)
text(delegate, metadata.groupId)
text(delegate, metadata.artifactId)
text(delegate, metadata.version)
text(delegate, metadata.name)
text(delegate, metadata.description)
text(delegate, metadata.packageName)
}
json.toString()
}
@@ -94,44 +94,47 @@ class InitializrMetadataV2JsonMapper implements InitializrMetadataJsonMapper {
}
protected dependencies(parent, groups) {
parent.dependencies {
type 'hierarchical-multi-select'
values groups.collect {
protected dependencies(parent, capability) {
parent."$capability.id" {
type "$capability.type.name"
values capability.content.collect {
mapDependencyGroup(it)
}
}
}
protected type(parent, defaultValue, dependencies) {
protected type(parent, capability) {
parent.type {
type 'action'
if (defaultValue) {
'default' defaultValue
def defaultType = capability.default
if (defaultType) {
'default' defaultType.id
}
values dependencies.collect {
values capability.content.collect {
mapType(it)
}
}
}
protected singleSelect(parent, name, defaultValue, itemValues) {
parent."$name" {
type 'single-select'
protected singleSelect(parent, SingleSelectCapability capability) {
parent."$capability.id" {
type "$capability.type.name"
def defaultValue = capability.default
if (defaultValue) {
'default' defaultValue
'default' defaultValue.id
}
values itemValues.collect {
values capability.content.collect {
mapValue(it)
}
}
}
protected text(parent, name, value) {
parent."$name" {
type 'text'
if (value) {
'default' value
protected text(parent, capability) {
parent."$capability.id" {
type "$capability.type.name"
def defaultValue = capability.content
if (defaultValue) {
'default' defaultValue
}
}
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package io.spring.initializr
package io.spring.initializr.mapper
import org.springframework.http.MediaType

View File

@@ -0,0 +1,37 @@
/*
* Copyright 2012-2015 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
/**
* A {@link MetadataElement} that specifies if its
* the default for a given capability.
*
* @author Stephane Nicoll
* @since 1.0
*/
class DefaultMetadataElement extends MetadataElement {
private boolean defaultValue
void setDefault(boolean defaultValue) {
this.defaultValue = defaultValue
}
boolean isDefault() {
this.defaultValue
}
}

View File

@@ -0,0 +1,73 @@
/*
* Copyright 2012-2015 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
/**
* A {@link ServiceCapability} listing the available dependencies defined as a
* {@link ServiceCapabilityType#HIERARCHICAL_MULTI_SELECT} capability.
*
* @author Stephane Nicoll
* @since 1.0
*/
class DependenciesCapability extends ServiceCapability<List<DependencyGroup>> {
final List<DependencyGroup> content = []
private final Map<String, Dependency> indexedDependencies = [:]
DependenciesCapability() {
super('dependencies', ServiceCapabilityType.HIERARCHICAL_MULTI_SELECT)
}
/**
* Return the {@link Dependency} with the specified id or {@code null} if
* no such dependency exists.
*/
Dependency get(String id) {
indexedDependencies[id]
}
/**
* Return all dependencies as a flat collection
*/
Collection<Dependency> getAll() {
Collections.unmodifiableCollection(indexedDependencies.values())
}
void validate() {
indexedDependencies.clear()
content.each { group ->
group.content.each { dependency ->
dependency.resolve()
indexDependency(dependency.id, dependency)
for (String alias : dependency.aliases) {
indexDependency(alias, dependency)
}
}
}
}
private void indexDependency(String id, Dependency dependency) {
def existing = indexedDependencies[id]
if (existing) {
throw new IllegalArgumentException("Could not register $dependency another dependency " +
"has also the '$id' id $existing");
}
indexedDependencies[id] = dependency
}
}

View File

@@ -0,0 +1,142 @@
/*
* Copyright 2012-2015 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 groovy.transform.ToString
import io.spring.initializr.util.InvalidVersionException
import io.spring.initializr.util.VersionRange
/**
* Meta-data for a dependency. Each dependency has a primary identifier and an
* arbitrary number of {@code aliases}.
*
* @author Stephane Nicoll
* @since 1.0
*/
@ToString(ignoreNulls = true, includePackage = false)
class Dependency extends MetadataElement {
static final String SCOPE_COMPILE = 'compile'
static final String SCOPE_RUNTIME = 'runtime'
static final String SCOPE_PROVIDED = 'provided'
static final String SCOPE_TEST = 'test'
static final List<String> SCOPE_ALL = [
SCOPE_COMPILE,
SCOPE_RUNTIME,
SCOPE_PROVIDED,
SCOPE_TEST
]
List<String> aliases = []
List<String> facets = []
String groupId
String artifactId
String version
String scope = SCOPE_COMPILE
String description
String versionRange
void setScope(String scope) {
if (!SCOPE_ALL.contains(scope)) {
throw new InvalidInitializrMetadataException("Invalid scope $scope must be one of $SCOPE_ALL")
}
this.scope = scope
}
void setVersionRange(String versionRange) {
this.versionRange = versionRange ? versionRange.trim() : null
}
/**
* Specify if the dependency has its coordinates set, i.e. {@code groupId}
* and {@code artifactId}.
*/
boolean hasCoordinates() {
groupId && artifactId
}
/**
* Define this dependency as a standard spring boot starter with the specified name
* <p>If no name is specified, the root 'spring-boot-starter' is assumed.
*/
Dependency asSpringBootStarter(String name) {
groupId = 'org.springframework.boot'
artifactId = name ? 'spring-boot-starter-' + name : 'spring-boot-starter'
if (name) {
id = name
}
this
}
/**
* Validate the dependency and complete its state based on the
* available information.
*/
def resolve() {
if (id == null) {
if (!hasCoordinates()) {
throw new InvalidInitializrMetadataException(
'Invalid dependency, should have at least an id or a groupId/artifactId pair.')
}
generateId()
} else if (!hasCoordinates()) {
// Let's build the coordinates from the id
def st = new StringTokenizer(id, ':')
if (st.countTokens() == 1) { // assume spring-boot-starter
asSpringBootStarter(id)
} else if (st.countTokens() == 2 || st.countTokens() == 3) {
groupId = st.nextToken()
artifactId = st.nextToken()
if (st.hasMoreTokens()) {
version = st.nextToken()
}
} else {
throw new InvalidInitializrMetadataException(
"Invalid dependency, id should have the form groupId:artifactId[:version] but got $id")
}
}
if (versionRange) {
try {
VersionRange.parse(versionRange)
} catch (InvalidVersionException ex) {
throw new InvalidInitializrMetadataException("Invalid version range '$versionRange' for " +
"dependency with id '$id'")
}
}
}
/**
* Generate an id using the groupId and artifactId
*/
def generateId() {
if (groupId == null || artifactId == null) {
throw new IllegalArgumentException(
"Could not generate id for $this: at least groupId and artifactId must be set.")
}
StringBuilder sb = new StringBuilder()
sb.append(groupId).append(':').append(artifactId)
id = sb.toString()
}
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright 2012-2015 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
/**
* A group of {@link Dependency} instances identified by a name.
*
* @author Stephane Nicoll
* @since 1.0
*/
class DependencyGroup {
String name
final List<Dependency> content = []
}

View File

@@ -0,0 +1,130 @@
/*
* Copyright 2012-2015 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 io.spring.initializr.InitializrConfiguration
/**
* Meta-data used to generate a project.
*
* @author Stephane Nicoll
* @since 1.0
* @see ServiceCapability
*/
class InitializrMetadata {
final InitializrConfiguration configuration
final DependenciesCapability dependencies = new DependenciesCapability()
final TypeCapability types = new TypeCapability()
final SingleSelectCapability bootVersions = new SingleSelectCapability('bootVersion')
final SingleSelectCapability packagings = new SingleSelectCapability('packaging')
final SingleSelectCapability javaVersions = new SingleSelectCapability('javaVersion')
final SingleSelectCapability languages = new SingleSelectCapability('language')
final TextCapability name = new TextCapability('name', 'demo')
final TextCapability description = new TextCapability('description', 'Demo project for Spring Boot')
final TextCapability groupId = new TextCapability('groupId', 'org.test')
final TextCapability artifactId = new ArtifactIdCapability(name)
final TextCapability version = new TextCapability('version', '0.0.1-SNAPSHOT')
final TextCapability packageName = new PackageCapability(name)
InitializrMetadata(InitializrConfiguration configuration) {
this.configuration = configuration
}
/**
* Validate the meta-data.
*/
void validate() {
dependencies.validate()
}
/**
* Create an URL suitable to download Spring Boot cli for the specified version and extension.
*/
String createCliDistributionURl(String extension) {
String bootVersion = defaultId(bootVersions)
configuration.env.artifactRepository + "org/springframework/boot/spring-boot-cli/" +
"$bootVersion/spring-boot-cli-$bootVersion-bin.$extension"
}
/**
* Return the defaults for the capabilities defined on this instance.
*/
Map<String, ?> defaults() {
def defaults = [:]
defaults['type'] = defaultId(types)
defaults['bootVersion'] = defaultId(bootVersions)
defaults['packaging'] = defaultId(packagings)
defaults['javaVersion'] = defaultId(javaVersions)
defaults['language'] = defaultId(languages)
defaults['groupId'] = groupId.content
defaults['artifactId'] = artifactId.content
defaults['version'] = version.content
defaults['name'] = name.content
defaults['description'] = description.content
defaults['packageName'] = packageName.content
defaults
}
private static String defaultId(def element) {
def defaultValue = element.default
defaultValue ? defaultValue.id : null
}
private static class ArtifactIdCapability extends TextCapability {
private final TextCapability nameCapability
ArtifactIdCapability(TextCapability nameCapability) {
super('artifactId')
this.nameCapability = nameCapability
}
@Override
String getContent() {
String value = super.getContent()
value == null ? nameCapability.content : value
}
}
private static class PackageCapability extends TextCapability {
private final TextCapability nameCapability
PackageCapability(TextCapability nameCapability) {
super('packageName')
this.nameCapability = nameCapability
}
@Override
String getContent() {
String value = super.getContent()
value == null ? nameCapability.content.replace('-', '.') : value
}
}
}

View File

@@ -0,0 +1,98 @@
/*
* Copyright 2012-2015 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 io.spring.initializr.InitializrConfiguration
/**
* Builder for {@link InitializrMetadata}.
*
* @author Stephane Nicoll
* @since 1.0
* @see InitializrMetadataCustomizer
*/
class InitializrMetadataBuilder {
private final List<InitializrMetadataCustomizer> customizers = []
private InitializrConfiguration configuration
/**
* Adds the specified configuration.
* @see InitializrProperties
*/
InitializrMetadataBuilder fromConfiguration(InitializrProperties configuration) {
this.configuration = configuration
withCustomizer(new InitializerPropertiesCustomizer(configuration))
}
/**
* Adds a {@link InitializrMetadataCustomizer}. customizers are invoked in their
* order of addition.
* @see InitializrMetadataCustomizer
*/
InitializrMetadataBuilder withCustomizer(InitializrMetadataCustomizer customizer) {
customizers << customizer
this
}
/**
* Build a {@link InitializrMetadata} baed on the state of this builder.
*/
InitializrMetadata build() {
InitializrConfiguration config = this.configuration ?: new InitializrConfiguration()
InitializrMetadata instance = createInstance(config)
for (InitializrMetadataCustomizer customizer : customizers) {
customizer.customize(instance)
}
instance.validate()
instance
}
/**
* Creates an empty instance based on the specified {@link InitializrConfiguration}
*/
protected InitializrMetadata createInstance(InitializrConfiguration configuration) {
new InitializrMetadata(configuration)
}
static class InitializerPropertiesCustomizer implements InitializrMetadataCustomizer {
private final InitializrProperties properties
InitializerPropertiesCustomizer(InitializrProperties properties) {
this.properties = properties
}
@Override
void customize(InitializrMetadata metadata) { // NICE: merge
metadata.dependencies.content.addAll(properties.dependencies)
metadata.types.content.addAll(properties.types)
metadata.bootVersions.content.addAll(properties.bootVersions)
metadata.packagings.content.addAll(properties.packagings)
metadata.javaVersions.content.addAll(properties.javaVersions)
metadata.languages.content.addAll(properties.languages)
metadata.groupId.content = properties.defaults.groupId
metadata.artifactId.content = properties.defaults.artifactId
metadata.version.content = properties.defaults.version
metadata.name.content = properties.defaults.name
metadata.description.content = properties.defaults.description
metadata.packageName.content = properties.defaults.packageName
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2015 the original author or authors.
* Copyright 2012-2015 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.
@@ -14,12 +14,20 @@
* limitations under the License.
*/
package io.spring.initializr
package io.spring.initializr.metadata
/**
* @author Dave Syer
* Strategy interface used to customize the {@link InitializrMetadata}.
*
* @author Dave Syer
* @since 1.0
*/
interface InitializrMetadataCustomizer {
/**
* Customize the {@link InitializrMetadata}, updating or moving around
* capabilities before they are validated.
*/
void customize(InitializrMetadata metadata)
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2014 the original author or authors.
* Copyright 2012-2015 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package io.spring.initializr
package io.spring.initializr.metadata
/**
* Provide the {@link InitializrMetadata} to use.

View File

@@ -0,0 +1,57 @@
/*
* Copyright 2012-2015 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 io.spring.initializr.InitializrConfiguration
import org.springframework.boot.context.properties.ConfigurationProperties
/**
* Configuration of the initializr service.
*
* @author Stephane Nicoll
* @since 1.0
*/
@ConfigurationProperties(prefix = 'initializr', ignoreUnknownFields = false)
class InitializrProperties extends InitializrConfiguration {
final List<DependencyGroup> dependencies = []
final List<Type> types = []
final List<DefaultMetadataElement> packagings = []
final List<DefaultMetadataElement> javaVersions = []
final List<DefaultMetadataElement> languages = []
final List<DefaultMetadataElement> bootVersions = []
final Defaults defaults = new Defaults()
static class Defaults {
String groupId = 'org.test'
String artifactId
String version = '0.0.1-SNAPSHOT'
String name = 'demo'
String description = 'Demo project for Spring Boot'
String packageName
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2014 the original author or authors.
* Copyright 2012-2015 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.
@@ -14,9 +14,10 @@
* limitations under the License.
*/
package io.spring.initializr
package io.spring.initializr.metadata
import groovy.transform.InheritConstructors
import io.spring.initializr.InitializrException
/**
* Thrown when the configuration defines invalid metadata.

View File

@@ -0,0 +1,40 @@
/*
* Copyright 2012-2015 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
/**
* A basic meta-data element
*
* @author Stephane Nicoll
* @since 1.0
*/
class MetadataElement {
/**
* A visual representation of this element.
*/
String name
/**
* The unique id of this element for a given capability.
*/
String id
String getName() {
(name ?: id)
}
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright 2012-2015 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
/**
* Defines a capability of the initializr service. Each capability
* is defined by a id and a {@link ServiceCapabilityType type}.
*
* @author Stephane Nicoll
* @since 1.0
*/
abstract class ServiceCapability<T> {
final String id
final ServiceCapabilityType type
String description
protected ServiceCapability(String id, ServiceCapabilityType type) {
this.id = id
this.type = type
}
/**
* Return the "content" of this capability. The structure of the content
* vastly depends on the {@link ServiceCapability type} of the capability.
*/
abstract T getContent()
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright 2012-2015 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
/**
* Defines the supported service capability type.
*
* @author Stephane Nicoll
* @since 1.0
*/
enum ServiceCapabilityType {
/**
* A special type that defines the action to use.
*/
ACTION('action'),
/**
* A simple text value with no option.
*/
TEXT('text'),
/**
* A simple value to be chosen amongst the specified options.
*/
SINGLE_SELECT('single-select'),
/**
* A hierarchical set of values (values in values) with the ability to
* select multiple values.
*/
HIERARCHICAL_MULTI_SELECT('hierarchical-multi-select')
final String name
ServiceCapabilityType(String name) {
this.name = name
}
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright 2012-2015 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
/**
* A {@link ServiceCapabilityType#SINGLE_SELECT single select} capability.
*
* @author Stephane Nicoll
* @since 1.0
*/
class SingleSelectCapability extends ServiceCapability<List<DefaultMetadataElement>> {
final List<DefaultMetadataElement> content = []
SingleSelectCapability(String id) {
super(id, ServiceCapabilityType.SINGLE_SELECT)
}
/**
* Return the default element of this capability.
*/
DefaultMetadataElement getDefault() {
return content.find { it.default }
}
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright 2012-2015 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
/**
* A {@link ServiceCapabilityType#TEXT text} capability.
*
* @author Stephane Nicoll
* @since 1.0
*/
class TextCapability extends ServiceCapability<String> {
String content
TextCapability(String id) {
super(id, ServiceCapabilityType.TEXT);
}
TextCapability(String id, String content) {
this(id)
this.content = content
}
}

View File

@@ -0,0 +1,45 @@
/*
* Copyright 2012-2015 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
/**
* Defines a particular project type. Each type is associated to a concrete
* action that should be invoked to generate the content of that type.
*
* @author Stephane Nicoll
* @since 1.0
*/
class Type extends DefaultMetadataElement {
String description
@Deprecated
String stsId
String action
final Map<String, String> tags = [:]
void setAction(String action) {
String actionToUse = action
if (!actionToUse.startsWith("/")) {
actionToUse = "/" + actionToUse
}
this.action = actionToUse
}
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright 2012-2015 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
/**
* An {@link ServiceCapabilityType#ACTION action} capability.
*
* @author Stephane Nicoll
* @since 1.0
*/
class TypeCapability extends ServiceCapability<List<Type>> {
final List<Type> content = []
TypeCapability() {
super('type', ServiceCapabilityType.ACTION)
}
/**
* Return the {@link Type} with the specified id or {@code null} if no
* such type exists.
*/
Type get(String id) {
return content.find { id.equals(it.id) || id.equals(it.stsId) }
}
/**
* Return the default {@link Type}.
*/
Type getDefault() {
return content.find { it.default }
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2014 the original author or authors.
* Copyright 2012-2015 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.
@@ -14,9 +14,12 @@
* limitations under the License.
*/
package io.spring.initializr
package io.spring.initializr.support
import groovy.util.logging.Slf4j
import io.spring.initializr.metadata.DefaultMetadataElement
import io.spring.initializr.metadata.InitializrMetadata
import io.spring.initializr.metadata.InitializrMetadataProvider
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.cache.annotation.Cacheable
@@ -43,17 +46,18 @@ class DefaultInitializrMetadataProvider implements InitializrMetadataProvider {
InitializrMetadata get() {
def bootVersions = fetchBootVersions()
if (bootVersions) {
metadata.merge(bootVersions)
metadata.bootVersions.content.clear()
metadata.bootVersions.content.addAll(bootVersions)
}
metadata
}
protected List<InitializrMetadata.BootVersion> fetchBootVersions() {
def url = metadata.env.springBootMetadataUrl
protected List<DefaultMetadataElement> fetchBootVersions() {
def url = metadata.configuration.env.springBootMetadataUrl
if (url) {
try {
log.info("Fetching boot metadata from $url")
return new SpringBootMetadataReader(url).getBootVersions()
return new SpringBootMetadataReader(url).bootVersions
} catch (Exception e) {
log.warn('Failed to fetch spring boot metadata', e)
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2014 the original author or authors.
* Copyright 2012-2015 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.
@@ -14,9 +14,10 @@
* limitations under the License.
*/
package io.spring.initializr
package io.spring.initializr.support
import groovy.json.JsonSlurper
import io.spring.initializr.metadata.DefaultMetadataElement
import org.springframework.web.client.RestTemplate
@@ -44,9 +45,9 @@ class SpringBootMetadataReader {
/**
* Return the boot versions parsed by this instance.
*/
List<InitializrMetadata.BootVersion> getBootVersions() {
List<DefaultMetadataElement> getBootVersions() {
content.projectReleases.collect {
def version = new InitializrMetadata.BootVersion()
def version = new DefaultMetadataElement()
version.id = it.version
def name = it.versionDisplayName
version.name = (it.snapshot ? name + ' (SNAPSHOT)' : name)

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2014 the original author or authors.
* Copyright 2012-2015 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package io.spring.initializr.support
package io.spring.initializr.util
import groovy.text.GStringTemplateEngine
import groovy.text.Template

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package io.spring.initializr.support
package io.spring.initializr.util
import groovy.transform.InheritConstructors

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package io.spring.initializr.support
package io.spring.initializr.util
import groovy.transform.EqualsAndHashCode
import groovy.transform.ToString

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package io.spring.initializr.support
package io.spring.initializr.util
import groovy.transform.EqualsAndHashCode
import groovy.transform.ToString

View File

@@ -18,12 +18,12 @@ package io.spring.initializr.web
import javax.annotation.PostConstruct
import io.spring.initializr.InitializrMetadataProvider
import io.spring.initializr.metadata.InitializrMetadataProvider
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.web.servlet.support.ServletUriComponentsBuilder
import static io.spring.initializr.support.GroovyTemplate.template
import static io.spring.initializr.util.GroovyTemplate.template
/**
* A base controller that uses a {@link InitializrMetadataProvider}
@@ -40,7 +40,7 @@ abstract class AbstractInitializrController {
@PostConstruct
void initialize() {
forceSsl = metadataProvider.get().env.forceSsl
forceSsl = metadataProvider.get().configuration.env.forceSsl
}
/**
@@ -55,7 +55,7 @@ abstract class AbstractInitializrController {
/**
* Generate a full URL of the service, mostly for use in templates.
* @see io.spring.initializr.InitializrMetadata.Env#forceSsl
* @see io.spring.initializr.InitializrConfiguration.Env#forceSsl
*/
protected String generateAppUrl() {
def builder = ServletUriComponentsBuilder.fromCurrentServletMapping()

View File

@@ -17,10 +17,13 @@
package io.spring.initializr.web
import groovy.util.logging.Slf4j
import io.spring.initializr.CommandLineHelpGenerator
import io.spring.initializr.InitializrMetadataVersion
import io.spring.initializr.ProjectGenerator
import io.spring.initializr.ProjectRequest
import io.spring.initializr.generator.CommandLineHelpGenerator
import io.spring.initializr.mapper.InitializrMetadataJsonMapper
import io.spring.initializr.mapper.InitializrMetadataV21JsonMapper
import io.spring.initializr.mapper.InitializrMetadataV2JsonMapper
import io.spring.initializr.mapper.InitializrMetadataVersion
import io.spring.initializr.generator.ProjectGenerator
import io.spring.initializr.generator.ProjectRequest
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.http.HttpHeaders
@@ -55,7 +58,7 @@ class MainController extends AbstractInitializrController {
@ModelAttribute
ProjectRequest projectRequest() {
def request = new ProjectRequest()
metadataProvider.get().initializeProjectRequest(request)
request.initialize(metadataProvider.get())
request
}
@@ -92,10 +95,17 @@ class MainController extends AbstractInitializrController {
private ResponseEntity<String> serviceCapabilitiesFor(InitializrMetadataVersion version) {
String appUrl = generateAppUrl()
def content = metadataProvider.get().generateJson(version, appUrl)
def content = getJsonMapper(version).write(metadataProvider.get(), appUrl)
return ResponseEntity.ok().contentType(version.mediaType).body(content)
}
private static InitializrMetadataJsonMapper getJsonMapper(InitializrMetadataVersion version) {
switch(version) {
case InitializrMetadataVersion.V2: return new InitializrMetadataV2JsonMapper();
default: return new InitializrMetadataV21JsonMapper();
}
}
@RequestMapping(value = '/', produces = 'text/html')
@ResponseBody
String home() {

View File

@@ -1 +1 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=io.spring.initializr.InitializrAutoConfiguration
org.springframework.boot.autoconfigure.EnableAutoConfiguration=io.spring.initializr.config.InitializrAutoConfiguration

View File

@@ -26,45 +26,45 @@
</div>
</div>
<form id="form" class="form-horizontal" action="/starter.zip" method="get" role="form">
<input id="baseDir" name="baseDir" type="hidden" value="${defaults.artifactId}">
<input id="baseDir" name="baseDir" type="hidden" value="${artifactId.content}">
<div class="row">
<div class="col-sm-6">
<h3>Project metadata</h3>
<div class="form-group">
<label for="groupId" class="col-md-3 control-label">Group</label>
<div class="col-md-8">
<input id="groupId" class="form-control" type="text" value="${defaults.groupId}" name="groupId">
<input id="groupId" class="form-control" type="text" value="${groupId.content}" name="groupId">
</div>
</div>
<div class="form-group">
<label for="artifactId" class="col-md-3 control-label">Artifact</label>
<div class="col-md-8">
<input id="artifactId" class="form-control" type="text" value="${defaults.artifactId}" name="artifactId">
<input id="artifactId" class="form-control" type="text" value="${artifactId.content}" name="artifactId">
</div>
</div>
<div class="form-group">
<label for="name" class="col-md-3 control-label">Name</label>
<div class="col-md-8">
<input id="name" class="form-control" type="text" value="${defaults.name}" name="name">
<input id="name" class="form-control" type="text" value="${name.content}" name="name">
</div>
</div>
<div class="form-group">
<label for="description" class="col-md-3 control-label">Description</label>
<div class="col-md-8">
<input id="description" class="form-control" type="text" value="${defaults.description}" name="description">
<input id="description" class="form-control" type="text" value="${description.content}" name="description">
</div>
</div>
<div class="form-group">
<label for="packageName" class="col-md-3 control-label">Package Name</label>
<div class="col-md-8">
<input id="packageName" class="form-control" type="text" value="${defaults.packageName}" name="packageName">
<input id="packageName" class="form-control" type="text" value="${packageName.content}" name="packageName">
</div>
</div>
<div class="form-group">
<label for="type" class="col-md-3 control-label">Type</label>
<div class="col-md-8">
<select class="form-control" id="type" name="type">
<% types.each { %>
<% types.content.each { %>
<option data-action="${it.action}" value="${it.id}" ${it.default==true ? ' selected' : ''}>${it.name}</option>
<% } %>
</select>
@@ -74,7 +74,7 @@
<label for="packaging" class="col-md-3 control-label">Packaging</label>
<div class="col-md-8">
<select class="form-control" id="packaging" name="packaging">
<% packagings.each { %>
<% packagings.content.each { %>
<option value="${it.id}" ${it.default==true ? ' selected' : ''}>${it.name}</option>
<% } %>
</select>
@@ -84,7 +84,7 @@
<label for="javaVersion" class="col-md-3 control-label">Java Version</label>
<div class="col-md-8">
<select class="form-control" name="javaVersion" id="javaVersion">
<% javaVersions.each { %>
<% javaVersions.content.each { %>
<option value="${it.id}" ${it.default==true ? ' selected' : ''}>${it.name}</option>
<% } %>
</select>
@@ -94,7 +94,7 @@
<label for="language" class="col-md-3 control-label">Language</label>
<div class="col-md-8">
<select class="form-control" name="language" id="language">
<% languages.each { %>
<% languages.content.each { %>
<option value="${it.id}" ${it.default==true ? ' selected' : ''}>${it.name}</option>
<% } %>
</select>
@@ -104,7 +104,7 @@
<label for="bootVersion" class="col-md-3 control-label">Spring Boot Version</label>
<div class="col-md-8">
<select class="form-control" name="bootVersion" id="bootVersion">
<% bootVersions.each { %>
<% bootVersions.content.each { %>
<option value="${it.id}" ${it.default==true ? ' selected' : ''}>${it.name}</option>
<% } %>
</select>
@@ -113,7 +113,7 @@
</div>
<div id="dependencies" class="col-sm-6">
<h3>Project dependencies</h3>
<% dependencies.each { %>
<% dependencies.content.each { %>
<div class="form-group col-xs-6">
<h4>${it.name}</h4>
<% it.content.each { %>

View File

@@ -35,44 +35,44 @@
<h1>Spring Initializr</h1>
<div>
<form id="form" action="/starter.zip" method="get">
<label for="groupId">Group:</label> <input id="groupId" type="text" value="${defaults.groupId}" name="groupId"/>
<label for="artifactId">Artifact:</label> <input id="artifactId" type="text" value="${defaults.artifactId}" name="artifactId"/>
<label for="name">Name:</label> <input id="name" type="text" value="${defaults.name}" name="name"/>
<label for="name">Description:</label> <input id="description" type="text" value="${defaults.description}" name="description"/>
<label for="packageName">Package Name:</label> <input id="packageName" type="text" value="${defaults.packageName}" name="packageName"/>
<label for="groupId">Group:</label> <input id="groupId" type="text" value="${groupId.content}" name="groupId"/>
<label for="artifactId">Artifact:</label> <input id="artifactId" type="text" value="${artifactId.content}" name="artifactId"/>
<label for="name">Name:</label> <input id="name" type="text" value="${name.content}" name="name"/>
<label for="name">Description:</label> <input id="description" type="text" value="${description.content}" name="description"/>
<label for="packageName">Package Name:</label> <input id="packageName" type="text" value="${packageName.content}" name="packageName"/>
<label>Styles:</label>
<% dependencies.each { %>
<% dependencies.content.each { %>
<% it.content.each { %>
<label class="checkbox">
<input type="checkbox" name="style" value="${it.id}"/>
${it.name}
</label><% } } %>
<label>Type:</label>
<% types.each { %>
<% types.content.each { %>
<label class="radio">
<input type="radio" name="type" value="${it.stsId}"${it.default==true ? ' checked="true"' : ''} onclick="javascript:this.form.action='${it.action}'"/>
${it.name}
</label><% } %>
<label>Packaging:</label>
<% packagings.each { %>
<% packagings.content.each { %>
<label class="radio">
<input type="radio" name="packaging" value="${it.id}"${it.default==true ? ' checked="true"' : ''}/>
${it.name}
</label><% } %>
<label>Java Version:</label>
<% javaVersions.each { %>
<% javaVersions.content.each { %>
<label class="radio">
<input type="radio" name="javaVersion" value="${it.id}"${it.default==true ? ' checked="true"' : ''}/>
${it.name}
</label><% } %>
<label>Language:</label>
<% languages.each { %>
<% languages.content.each { %>
<label class="radio">
<input type="radio" name="language" value="${it.id}"${it.default==true ? ' checked="true"' : ''}/>
${it.name}
</label><% } %>
<label>Spring Boot Version:</label>
<% bootVersions.each { %>
<% bootVersions.content.each { %>
<label class="radio">
<input type="radio" name="bootVersion" value="${it.id}"${it.default==true ? ' checked="true"' : ''}/>
${it.name}

View File

@@ -0,0 +1,116 @@
/*
* Copyright 2012-2015 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
import org.junit.Test
import static org.junit.Assert.assertEquals
/**
* @author Stephane Nicoll
*/
class InitializrConfigurationTests {
private final InitializrConfiguration properties = new InitializrConfiguration()
@Test
void generateApplicationNameSimple() {
assertEquals 'DemoApplication', this.properties.generateApplicationName('demo')
}
@Test
void generateApplicationNameSimpleApplication() {
assertEquals 'DemoApplication', this.properties.generateApplicationName('demoApplication')
}
@Test
void generateApplicationNameSimpleCamelCase() {
assertEquals 'MyDemoApplication', this.properties.generateApplicationName('myDemo')
}
@Test
void generateApplicationNameSimpleUnderscore() {
assertEquals 'MyDemoApplication', this.properties.generateApplicationName('my_demo')
}
@Test
void generateApplicationNameSimpleColon() {
assertEquals 'MyDemoApplication', this.properties.generateApplicationName('my:demo')
}
@Test
void generateApplicationNameSimpleSpace() {
assertEquals 'MyDemoApplication', this.properties.generateApplicationName('my demo')
}
@Test
void generateApplicationNamSsimpleDash() {
assertEquals 'MyDemoApplication', this.properties.generateApplicationName('my-demo')
}
@Test
void generateApplicationNameUpperCaseUnderscore() {
assertEquals 'MyDemoApplication', this.properties.generateApplicationName('MY_DEMO')
}
@Test
void generateApplicationNameUpperCaseDash() {
assertEquals 'MyDemoApplication', this.properties.generateApplicationName('MY-DEMO')
}
@Test
void generateApplicationNameMultiSpaces() {
assertEquals 'MyDemoApplication', this.properties.generateApplicationName(' my demo ')
}
@Test
void generateApplicationNameMultiSpacesUpperCase() {
assertEquals 'MyDemoApplication', this.properties.generateApplicationName(' MY DEMO ')
}
@Test
void generateApplicationNameNull() {
assertEquals this.properties.env.fallbackApplicationName, this.properties.generateApplicationName(null)
}
@Test
void generateApplicationNameInvalidStartCharacter() {
assertEquals this.properties.env.fallbackApplicationName, this.properties.generateApplicationName('1MyDemo')
}
@Test
void generateApplicationNameInvalidPartCharacter() {
assertEquals this.properties.env.fallbackApplicationName, this.properties.generateApplicationName('MyDe|mo')
}
@Test
void generateApplicationNameInvalidApplicationName() {
assertEquals this.properties.env.fallbackApplicationName, this.properties.generateApplicationName('SpringBoot')
}
@Test
void generateApplicationNameAnotherInvalidApplicationName() {
assertEquals this.properties.env.fallbackApplicationName, this.properties.generateApplicationName('Spring')
}
@Test
void validateArtifactRepository() {
this.properties.env.artifactRepository = 'http://foo/bar'
assertEquals 'http://foo/bar/', this.properties.env.artifactRepository
}
}

View File

@@ -1,350 +0,0 @@
/*
* Copyright 2012-2015 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
import io.spring.initializr.test.InitializrMetadataBuilder
import org.junit.Rule
import org.junit.Test
import org.junit.rules.ExpectedException
import static org.junit.Assert.*
/**
* @author Stephane Nicoll
*/
class InitializrMetadataTests {
@Rule
public final ExpectedException thrown = ExpectedException.none()
private final InitializrMetadata metadata = new InitializrMetadata()
@Test
void createRootSpringBootStarter() {
InitializrMetadata.Dependency d = new InitializrMetadata.Dependency();
d.asSpringBootStarter("")
assertEquals 'org.springframework.boot', d.groupId
assertEquals 'spring-boot-starter', d.artifactId
}
@Test
void setCoordinatesFromId() {
def dependency = createDependency('org.foo:bar:1.2.3')
metadata.validateDependency(dependency)
assertEquals 'org.foo', dependency.groupId
assertEquals 'bar', dependency.artifactId
assertEquals '1.2.3', dependency.version
assertEquals 'org.foo:bar:1.2.3', dependency.id
}
@Test
void setCoordinatesFromIdNoVersion() {
def dependency = createDependency('org.foo:bar')
metadata.validateDependency(dependency)
assertEquals 'org.foo', dependency.groupId
assertEquals 'bar', dependency.artifactId
assertNull dependency.version
assertEquals 'org.foo:bar', dependency.id
}
@Test
void setIdFromCoordinates() {
def dependency = new InitializrMetadata.Dependency()
dependency.groupId = 'org.foo'
dependency.artifactId = 'bar'
dependency.version = '1.0'
metadata.validateDependency(dependency)
assertEquals 'org.foo:bar', dependency.id
}
@Test
void setIdFromCoordinatesNoVersion() {
def dependency = new InitializrMetadata.Dependency()
dependency.groupId = 'org.foo'
dependency.artifactId = 'bar'
metadata.validateDependency(dependency)
assertEquals 'org.foo:bar', dependency.id
}
@Test
void setIdFromSimpleName() {
def dependency = createDependency('web')
metadata.validateDependency(dependency)
assertEquals 'org.springframework.boot', dependency.groupId
assertEquals 'spring-boot-starter-web', dependency.artifactId
assertNull dependency.version
assertEquals 'web', dependency.id
}
@Test
void invalidDependency() {
thrown.expect(InvalidInitializrMetadataException)
metadata.validateDependency(new InitializrMetadata.Dependency())
}
@Test
void invalidDependencyScope() {
def dependency = createDependency('web')
thrown.expect(InvalidInitializrMetadataException)
dependency.setScope('whatever')
}
@Test
void invalidSpringBootRange() {
def dependency = createDependency('web')
dependency.versionRange = 'A.B.C'
thrown.expect(InvalidInitializrMetadataException)
thrown.expectMessage('A.B.C')
metadata.validateDependency(dependency)
}
@Test
void invalidIdFormatTooManyColons() {
def dependency = createDependency('org.foo:bar:1.0:test:external')
thrown.expect(InvalidInitializrMetadataException)
metadata.validateDependency(dependency)
}
@Test
void generateIdWithNoGroupId() {
def dependency = new InitializrMetadata.Dependency()
dependency.artifactId = 'bar'
thrown.expect(IllegalArgumentException)
dependency.generateId()
}
@Test
void generateIdWithNoArtifactId() {
def dependency = new InitializrMetadata.Dependency()
dependency.groupId = 'foo'
thrown.expect(IllegalArgumentException)
dependency.generateId()
}
@Test
void addDependencyInCustomizer() {
def group = new InitializrMetadata.DependencyGroup()
group.name = 'Extra'
def dependency = createDependency('com.foo:foo:1.0.0')
group.content.add(dependency)
metadata.setCustomizers([new InitializrMetadataCustomizer() {
void customize(InitializrMetadata metadata) {
metadata.dependencies.add(group)
}
}])
metadata.validate()
assertEquals 1, metadata.dependencies.size()
}
@Test
void indexedDependencies() {
def dependency = createDependency('first')
def dependency2 = createDependency('second')
def metadata = InitializrMetadataBuilder.withDefaults()
.addDependencyGroup('foo', dependency, dependency2).validateAndGet()
assertSame dependency, metadata.getDependency('first')
assertSame dependency2, metadata.getDependency('second')
assertNull metadata.getDependency('anotherId')
}
@Test
void addTwoDependenciesWithSameId() {
def dependency = createDependency('conflict')
def dependency2 = createDependency('conflict')
def builder = InitializrMetadataBuilder.withDefaults()
.addDependencyGroup('foo', dependency, dependency2)
thrown.expect(IllegalArgumentException)
thrown.expectMessage('conflict')
builder.validateAndGet()
}
@Test
void addDependencyWithAliases() {
def dependency = createDependency('first')
dependency.aliases.add('alias1')
dependency.aliases.add('alias2')
def metadata = InitializrMetadataBuilder.withDefaults()
.addDependencyGroup('foo', dependency).validateAndGet()
assertSame dependency, metadata.getDependency('first')
assertSame dependency, metadata.getDependency('alias1')
assertSame dependency, metadata.getDependency('alias2')
}
@Test
void aliasClashWithAnotherDependency() {
def dependency = createDependency('first')
dependency.aliases.add('alias1')
dependency.aliases.add('alias2')
def dependency2 = createDependency('alias2')
def builder = InitializrMetadataBuilder.withDefaults()
.addDependencyGroup('foo', dependency)
.addDependencyGroup('bar', dependency2)
thrown.expect(IllegalArgumentException)
thrown.expectMessage('alias2')
builder.validateAndGet()
}
@Test
void createProjectRequest() {
def metadata = InitializrMetadataBuilder.withDefaults().validateAndGet()
def request = doCreateProjectRequest(metadata)
assertEquals metadata.defaults.groupId, request.groupId
}
@Test
void validateAction() {
def metadata = new InitializrMetadataBuilder()
.addType('foo', false, 'my-action.zip', 'none', 'none').validateAndGet()
assertEquals '/my-action.zip', metadata.getType('foo').action
}
@Test
void validateArtifactRepository() {
def metadata = InitializrMetadataBuilder.withDefaults().instance()
metadata.env.artifactRepository = 'http://foo/bar'
metadata.validate()
assertEquals 'http://foo/bar/', metadata.env.artifactRepository
}
@Test
void getDefaultNoDefault() {
List elements = []
elements << createJavaVersion('one', false) << createJavaVersion('two', false)
assertEquals 'one', InitializrMetadata.getDefault(elements)
}
@Test
void getDefaultEmpty() {
List elements = []
assertNull InitializrMetadata.getDefault(elements)
}
@Test
void getDefault() {
List elements = []
elements << createJavaVersion('one', false) << createJavaVersion('two', true)
assertEquals 'two', InitializrMetadata.getDefault(elements)
}
@Test
void generateApplicationNameSimple() {
assertEquals 'DemoApplication', this.metadata.generateApplicationName('demo')
}
@Test
void generateApplicationNameSimpleApplication() {
assertEquals 'DemoApplication', this.metadata.generateApplicationName('demoApplication')
}
@Test
void generateApplicationNameSimpleCamelCase() {
assertEquals 'MyDemoApplication', this.metadata.generateApplicationName('myDemo')
}
@Test
void generateApplicationNameSimpleUnderscore() {
assertEquals 'MyDemoApplication', this.metadata.generateApplicationName('my_demo')
}
@Test
void generateApplicationNameSimpleColon() {
assertEquals 'MyDemoApplication', this.metadata.generateApplicationName('my:demo')
}
@Test
void generateApplicationNameSimpleSpace() {
assertEquals 'MyDemoApplication', this.metadata.generateApplicationName('my demo')
}
@Test
void generateApplicationNamSsimpleDash() {
assertEquals 'MyDemoApplication', this.metadata.generateApplicationName('my-demo')
}
@Test
void generateApplicationNameUpperCaseUnderscore() {
assertEquals 'MyDemoApplication', this.metadata.generateApplicationName('MY_DEMO')
}
@Test
void generateApplicationNameUpperCaseDash() {
assertEquals 'MyDemoApplication', this.metadata.generateApplicationName('MY-DEMO')
}
@Test
void generateApplicationNameMultiSpaces() {
assertEquals 'MyDemoApplication', this.metadata.generateApplicationName(' my demo ')
}
@Test
void generateApplicationNameMultiSpacesUpperCase() {
assertEquals 'MyDemoApplication', this.metadata.generateApplicationName(' MY DEMO ')
}
@Test
void generateApplicationNameInvalidStartCharacter() {
assertEquals this.metadata.env.fallbackApplicationName, this.metadata.generateApplicationName('1MyDemo')
}
@Test
void generateApplicationNameInvalidPartCharacter() {
assertEquals this.metadata.env.fallbackApplicationName, this.metadata.generateApplicationName('MyDe|mo')
}
@Test
void generateApplicationNameInvalidApplicationName() {
assertEquals this.metadata.env.fallbackApplicationName, this.metadata.generateApplicationName('SpringBoot')
}
@Test
void generateApplicationNameAnotherInvalidApplicationName() {
assertEquals this.metadata.env.fallbackApplicationName, this.metadata.generateApplicationName('Spring')
}
private static ProjectRequest doCreateProjectRequest(InitializrMetadata metadata) {
def request = new ProjectRequest()
metadata.initializeProjectRequest(request)
request
}
private static InitializrMetadata.Dependency createDependency(String id) {
def dependency = new InitializrMetadata.Dependency()
dependency.id = id
dependency
}
private static InitializrMetadata.JavaVersion createJavaVersion(String version, boolean selected) {
def javaVersion = new InitializrMetadata.JavaVersion()
javaVersion.id = version
javaVersion.default = selected
javaVersion
}
}

View File

@@ -14,9 +14,11 @@
* limitations under the License.
*/
package io.spring.initializr
package io.spring.initializr.generator
import io.spring.initializr.test.InitializrMetadataBuilder
import io.spring.initializr.metadata.Dependency
import io.spring.initializr.metadata.Type
import io.spring.initializr.test.InitializrMetadataTestBuilder
import org.junit.Test
import static org.hamcrest.CoreMatchers.containsString
@@ -32,9 +34,9 @@ class CommandLineHelpGeneratorTest {
@Test
void generateGenericCapabilities() {
def metadata = InitializrMetadataBuilder.withDefaults().addDependencyGroup("test",
def metadata = InitializrMetadataTestBuilder.withDefaults().addDependencyGroup("test",
createDependency('id-b', 'depB'),
createDependency('id-a', 'depA', 'and some description')).validateAndGet()
createDependency('id-a', 'depA', 'and some description')).build()
String content = generator.generateGenericCapabilities(metadata, "https://fake-service")
assertCommandLineCapabilities(content)
assertThat content, containsString('id-a | and some description |')
@@ -46,9 +48,9 @@ class CommandLineHelpGeneratorTest {
@Test
void generateCapabilitiesWithTypeDescription() {
def metadata = InitializrMetadataBuilder.withDefaults()
.addType(new InitializrMetadata.Type(id: 'foo', name: 'foo-name', description: 'foo-desc'))
.validateAndGet()
def metadata = InitializrMetadataTestBuilder.withDefaults()
.addType(new Type(id: 'foo', name: 'foo-name', description: 'foo-desc'))
.build()
String content = generator.generateGenericCapabilities(metadata, "https://fake-service")
assertCommandLineCapabilities(content)
assertThat content, containsString('| foo')
@@ -57,9 +59,9 @@ class CommandLineHelpGeneratorTest {
@Test
void generateCurlCapabilities() {
def metadata = InitializrMetadataBuilder.withDefaults().addDependencyGroup("test",
def metadata = InitializrMetadataTestBuilder.withDefaults().addDependencyGroup("test",
createDependency('id-b', 'depB'),
createDependency('id-a', 'depA', 'and some description')).validateAndGet()
createDependency('id-a', 'depA', 'and some description')).build()
String content = generator.generateCurlCapabilities(metadata, "https://fake-service")
assertCommandLineCapabilities(content)
assertThat content, containsString('id-a | and some description |')
@@ -71,9 +73,9 @@ class CommandLineHelpGeneratorTest {
@Test
void generateHttpCapabilities() {
def metadata = InitializrMetadataBuilder.withDefaults().addDependencyGroup("test",
def metadata = InitializrMetadataTestBuilder.withDefaults().addDependencyGroup("test",
createDependency('id-b', 'depB'),
createDependency('id-a', 'depA', 'and some description')).validateAndGet()
createDependency('id-a', 'depA', 'and some description')).build()
String content = generator.generateHttpieCapabilities(metadata, "https://fake-service")
assertCommandLineCapabilities(content)
assertThat content, containsString('id-a | and some description |')
@@ -86,9 +88,9 @@ class CommandLineHelpGeneratorTest {
@Test
void generateSpringBootCliCapabilities() {
def metadata = InitializrMetadataBuilder.withDefaults().addDependencyGroup("test",
def metadata = InitializrMetadataTestBuilder.withDefaults().addDependencyGroup("test",
createDependency('id-b', 'depB'),
createDependency('id-a', 'depA', 'and some description')).validateAndGet()
createDependency('id-a', 'depA', 'and some description')).build()
String content = generator.generateSpringBootCliCapabilities(metadata, "https://fake-service")
assertThat content, containsString("| Id")
assertThat content, containsString("| Tags")
@@ -105,11 +107,9 @@ class CommandLineHelpGeneratorTest {
@Test
void generateCapabilitiesWithVersionRange() {
InitializrMetadata.Dependency first = new InitializrMetadata.Dependency(
id: 'first', description: 'first desc', versionRange: '1.2.0.RELEASE')
InitializrMetadata.Dependency second = new InitializrMetadata.Dependency(
id: 'second', description: 'second desc', versionRange: ' [1.2.0.RELEASE,1.3.0.M1) ')
def metadata = InitializrMetadataBuilder.withDefaults().addDependencyGroup("test", first, second).validateAndGet()
def first = new Dependency(id: 'first', description: 'first desc', versionRange: '1.2.0.RELEASE')
def second = new Dependency(id: 'second', description: 'second desc', versionRange: ' [1.2.0.RELEASE,1.3.0.M1) ')
def metadata = InitializrMetadataTestBuilder.withDefaults().addDependencyGroup("test", first, second).build()
String content = generator.generateSpringBootCliCapabilities(metadata, "https://fake-service")
assertThat content, containsString('| first | first desc | >= 1.2.0.RELEASE |')
assertThat content, containsString('| second | second desc | [1.2.0.RELEASE,1.3.0.M1) |')
@@ -128,7 +128,7 @@ class CommandLineHelpGeneratorTest {
}
private static def createDependency(String id, String name, String description) {
new InitializrMetadata.Dependency(id: id, name: name, description: description)
new Dependency(id: id, name: name, description: description)
}
}

View File

@@ -14,9 +14,11 @@
* limitations under the License.
*/
package io.spring.initializr
package io.spring.initializr.generator
import io.spring.initializr.test.InitializrMetadataBuilder
import io.spring.initializr.metadata.Dependency
import io.spring.initializr.metadata.InitializrMetadata
import io.spring.initializr.test.InitializrMetadataTestBuilder
import io.spring.initializr.test.MetricsAssert
import io.spring.initializr.test.TestCounterService
import org.junit.Before
@@ -27,8 +29,8 @@ import org.junit.Test
*/
class ProjectGenerationMetricsListenerTests {
private InitializrMetadata metadata = InitializrMetadataBuilder.withDefaults()
.addDependencyGroup('core', 'web', 'security', 'spring-data').validateAndGet()
private InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults()
.addDependencyGroup('core', 'web', 'security', 'spring-data').build()
private ProjectGenerationMetricsListener listener
private MetricsAssert metricsAssert
@@ -80,13 +82,13 @@ class ProjectGenerationMetricsListenerTests {
@Test
void aliasedDependencyUseStandardId() {
def dependency = new InitializrMetadata.Dependency()
dependency.id ='foo'
def dependency = new Dependency()
dependency.id = 'foo'
dependency.aliases << 'foo-old'
def metadata = InitializrMetadataBuilder.withDefaults()
.addDependencyGroup('core', dependency).validateAndGet()
def metadata = InitializrMetadataTestBuilder.withDefaults()
.addDependencyGroup('core', dependency).build()
def request = new ProjectRequest()
metadata.initializeProjectRequest(request)
request.initialize(metadata)
request.style << 'foo-old'
request.resolve(metadata)
listener.onGeneratedProject(request)
@@ -218,7 +220,7 @@ class ProjectGenerationMetricsListenerTests {
private ProjectRequest initialize() {
def request = new ProjectRequest()
metadata.initializeProjectRequest(request)
request.initialize(metadata)
request
}

View File

@@ -14,10 +14,11 @@
* limitations under the License.
*/
package io.spring.initializr
package io.spring.initializr.generator
import io.spring.initializr.metadata.Dependency
import io.spring.initializr.test.GradleBuildAssert
import io.spring.initializr.test.InitializrMetadataBuilder
import io.spring.initializr.test.InitializrMetadataTestBuilder
import io.spring.initializr.test.PomAssert
import io.spring.initializr.test.ProjectAssert
import org.junit.Before
@@ -44,8 +45,8 @@ class ProjectGeneratorTests {
@Before
void setup() {
def metadata = InitializrMetadataBuilder.withDefaults()
.addDependencyGroup('test', 'web', 'security', 'data-jpa', 'aop', 'batch', 'integration').validateAndGet()
def metadata = InitializrMetadataTestBuilder.withDefaults()
.addDependencyGroup('test', 'web', 'security', 'data-jpa', 'aop', 'batch', 'integration').build()
projectGenerator.metadata = metadata
projectGenerator.tmpdir = folder.newFolder().absolutePath
}
@@ -99,14 +100,11 @@ class ProjectGeneratorTests {
@Test
void mavenPomWithWebFacet() {
def dependency = new InitializrMetadata.Dependency()
dependency.id = 'thymeleaf'
dependency.groupId = 'org.foo'
dependency.artifactId = 'thymeleaf'
def dependency = new Dependency(id: 'thymeleaf', groupId: 'org.foo', artifactId: 'thymeleaf')
dependency.facets << 'web'
def metadata = InitializrMetadataBuilder.withDefaults()
def metadata = InitializrMetadataTestBuilder.withDefaults()
.addDependencyGroup('core', 'web', 'security', 'data-jpa')
.addDependencyGroup('test', dependency).validateAndGet()
.addDependencyGroup('test', dependency).build()
projectGenerator.metadata = metadata
def request = createProjectRequest('thymeleaf')
@@ -116,20 +114,18 @@ class ProjectGeneratorTests {
}
@Test
void mavenWarPomWithWebFacet() {
def dependency = new InitializrMetadata.Dependency()
dependency.id = 'thymeleaf'
dependency.groupId = 'org.foo'
dependency.artifactId = 'thymeleaf'
void mavenWarWithWebFacet() {
def dependency = new Dependency(id: 'thymeleaf', groupId: 'org.foo', artifactId: 'thymeleaf')
dependency.facets << 'web'
def metadata = InitializrMetadataBuilder.withDefaults()
def metadata = InitializrMetadataTestBuilder.withDefaults()
.addDependencyGroup('core', 'web', 'security', 'data-jpa')
.addDependencyGroup('test', dependency).validateAndGet()
.addDependencyGroup('test', dependency).build()
projectGenerator.metadata = metadata
def request = createProjectRequest('thymeleaf')
request.packaging = 'war'
generateMavenPom(request).hasStartClass('demo.DemoApplication')
generateProject(request).isJavaWarProject().isMavenProject().
pomAssert().hasStartClass('demo.DemoApplication')
.hasSpringBootStarterTomcat()
.hasDependency('org.foo', 'thymeleaf') // This is tagged as web facet so it brings the web one
.hasSpringBootStarterTest()
@@ -238,16 +234,16 @@ class ProjectGeneratorTests {
@Test
void mavenPomWithCustomScope() {
def h2 = new InitializrMetadata.Dependency(id: 'h2', groupId: 'org.h2', artifactId: 'h2', scope: 'runtime')
def hamcrest = new InitializrMetadata.Dependency(id: 'hamcrest', groupId: 'org.hamcrest',
def h2 = new Dependency(id: 'h2', groupId: 'org.h2', artifactId: 'h2', scope: 'runtime')
def hamcrest = new Dependency(id: 'hamcrest', groupId: 'org.hamcrest',
artifactId: 'hamcrest', scope: 'test')
def servlet = new InitializrMetadata.Dependency(id: 'servlet-api', groupId: 'javax.servlet',
def servlet = new Dependency(id: 'servlet-api', groupId: 'javax.servlet',
artifactId: 'servlet-api', scope: 'provided')
def metadata = InitializrMetadataBuilder.withDefaults()
def metadata = InitializrMetadataTestBuilder.withDefaults()
.addDependencyGroup('core', 'web', 'security', 'data-jpa')
.addDependencyGroup('database', h2)
.addDependencyGroup('container', servlet)
.addDependencyGroup('test', hamcrest).validateAndGet()
.addDependencyGroup('test', hamcrest).build()
projectGenerator.metadata = metadata
def request = createProjectRequest('hamcrest', 'h2', 'servlet-api', 'data-jpa', 'web')
generateMavenPom(request).hasDependency(h2).hasDependency(hamcrest).hasDependency(servlet)
@@ -257,16 +253,16 @@ class ProjectGeneratorTests {
@Test
void gradleBuildWithCustomScope() {
def h2 = new InitializrMetadata.Dependency(id: 'h2', groupId: 'org.h2', artifactId: 'h2', scope: 'runtime')
def hamcrest = new InitializrMetadata.Dependency(id: 'hamcrest', groupId: 'org.hamcrest',
def h2 = new Dependency(id: 'h2', groupId: 'org.h2', artifactId: 'h2', scope: 'runtime')
def hamcrest = new Dependency(id: 'hamcrest', groupId: 'org.hamcrest',
artifactId: 'hamcrest', scope: 'test')
def servlet = new InitializrMetadata.Dependency(id: 'servlet-api', groupId: 'javax.servlet',
def servlet = new Dependency(id: 'servlet-api', groupId: 'javax.servlet',
artifactId: 'servlet-api', scope: 'provided')
def metadata = InitializrMetadataBuilder.withDefaults()
def metadata = InitializrMetadataTestBuilder.withDefaults()
.addDependencyGroup('core', 'web', 'security', 'data-jpa')
.addDependencyGroup('database', h2)
.addDependencyGroup('container', servlet)
.addDependencyGroup('test', hamcrest).validateAndGet()
.addDependencyGroup('test', hamcrest).build()
projectGenerator.metadata = metadata
def request = createProjectRequest('hamcrest', 'h2', 'servlet-api', 'data-jpa', 'web')
generateGradleBuild(request)
@@ -294,7 +290,7 @@ class ProjectGeneratorTests {
ProjectRequest createProjectRequest(String... styles) {
def request = new ProjectRequest()
projectGenerator.metadata.initializeProjectRequest(request)
request.initialize(projectGenerator.metadata)
request.style.addAll Arrays.asList(styles)
request
}

View File

@@ -14,9 +14,12 @@
* limitations under the License.
*/
package io.spring.initializr
package io.spring.initializr.generator
import io.spring.initializr.test.InitializrMetadataBuilder
import io.spring.initializr.InitializrConfiguration
import io.spring.initializr.metadata.Dependency
import io.spring.initializr.metadata.InitializrMetadata
import io.spring.initializr.test.InitializrMetadataTestBuilder
import org.junit.Rule
import org.junit.Test
import org.junit.rules.ExpectedException
@@ -32,11 +35,37 @@ class ProjectRequestTests {
@Rule
public final ExpectedException thrown = ExpectedException.none()
@Test
void initializeProjectRequest() {
def metadata = new InitializrMetadata(new InitializrConfiguration())
metadata.groupId.content = 'org.acme'
metadata.artifactId.content = 'my-project'
ProjectRequest request = new ProjectRequest()
request.initialize(metadata)
assertEquals 'org.acme', request.groupId
assertEquals 'my-project', request.artifactId
}
@Test
void initializeProjectRequestWithDefaults() {
def metadata = InitializrMetadataTestBuilder.withDefaults().build()
ProjectRequest request = new ProjectRequest()
request.initialize(metadata)
assertEquals metadata.name.content, request.name
assertEquals metadata.types.default.id, request.type
assertEquals metadata.description.content, request.description
assertEquals metadata.groupId.content, request.groupId
assertEquals metadata.artifactId.content, request.artifactId
assertEquals metadata.version.content, request.version
assertEquals metadata.bootVersions.default.id, request.bootVersion
assertEquals metadata.packagings.default.id, request.packaging
}
@Test
void resolve() {
def request = new ProjectRequest()
def metadata = InitializrMetadataBuilder.withDefaults()
.addDependencyGroup('code', 'web', 'security', 'spring-data').validateAndGet()
def metadata = InitializrMetadataTestBuilder.withDefaults()
.addDependencyGroup('code', 'web', 'security', 'spring-data').build()
request.type = 'maven-project'
request.style << 'web' << 'spring-data'
@@ -49,8 +78,8 @@ class ProjectRequestTests {
@Test
void resolveWithDependencies() {
def request = new ProjectRequest()
def metadata = InitializrMetadataBuilder.withDefaults()
.addDependencyGroup('code', 'web', 'security', 'spring-data').validateAndGet()
def metadata = InitializrMetadataTestBuilder.withDefaults()
.addDependencyGroup('code', 'web', 'security', 'spring-data').build()
request.type = 'maven-project'
request.dependencies << 'web' << 'spring-data'
@@ -63,8 +92,8 @@ class ProjectRequestTests {
@Test
void resolveFullMetadata() {
def request = new ProjectRequest()
def metadata = InitializrMetadataBuilder.withDefaults()
.addDependencyGroup('code', createDependency('org.foo', 'acme', '1.2.0')).validateAndGet()
def metadata = InitializrMetadataTestBuilder.withDefaults()
.addDependencyGroup('code', createDependency('org.foo', 'acme', '1.2.0')).build()
request.style << 'org.foo:acme'
request.resolve(metadata)
assertDependency(request.resolvedDependencies[0], 'org.foo', 'acme', '1.2.0')
@@ -73,8 +102,8 @@ class ProjectRequestTests {
@Test
void resolveUnknownSimpleIdAsSpringBootStarter() {
def request = new ProjectRequest()
def metadata = InitializrMetadataBuilder.withDefaults()
.addDependencyGroup('code', 'org.foo:bar').validateAndGet()
def metadata = InitializrMetadataTestBuilder.withDefaults()
.addDependencyGroup('code', 'org.foo:bar').build()
request.style << 'org.foo:bar' << 'foo-bar'
request.resolve(metadata)
@@ -85,8 +114,8 @@ class ProjectRequestTests {
@Test
void resolveUnknownDependency() {
def request = new ProjectRequest()
def metadata = InitializrMetadataBuilder.withDefaults()
.addDependencyGroup('code', 'org.foo:bar').validateAndGet()
def metadata = InitializrMetadataTestBuilder.withDefaults()
.addDependencyGroup('code', 'org.foo:bar').build()
request.style << 'org.foo:acme' // does not exist and
@@ -101,8 +130,8 @@ class ProjectRequestTests {
def request = new ProjectRequest()
def dependency = createDependency('org.foo', 'bar', '1.2.0.RELEASE')
dependency.versionRange = '[1.0.1.RELEASE, 1.2.0.RELEASE)'
def metadata = InitializrMetadataBuilder.withDefaults()
.addDependencyGroup('code', dependency).validateAndGet()
def metadata = InitializrMetadataTestBuilder.withDefaults()
.addDependencyGroup('code', dependency).build()
request.style << 'org.foo:bar'
request.bootVersion = '1.1.2.RELEASE'
@@ -114,8 +143,8 @@ class ProjectRequestTests {
def request = new ProjectRequest()
def dependency = createDependency('org.foo', 'bar', '1.2.0.RELEASE')
dependency.versionRange = '[1.0.1.RELEASE, 1.2.0.RELEASE)'
def metadata = InitializrMetadataBuilder.withDefaults()
.addDependencyGroup('code', dependency).validateAndGet()
def metadata = InitializrMetadataTestBuilder.withDefaults()
.addDependencyGroup('code', dependency).build()
request.style << 'org.foo:bar'
request.bootVersion = '0.9.9.RELEASE'
@@ -129,7 +158,7 @@ class ProjectRequestTests {
@Test
void resolveBuild() {
def request = new ProjectRequest()
def metadata = InitializrMetadataBuilder.withDefaults().validateAndGet()
def metadata = InitializrMetadataTestBuilder.withDefaults().build()
request.type = 'gradle-project'
request.resolve(metadata)
@@ -139,8 +168,8 @@ class ProjectRequestTests {
@Test
void resolveBuildNoTag() {
def request = new ProjectRequest()
def metadata = InitializrMetadataBuilder.withDefaults()
.addType('foo', false, '/foo.zip', null, null).validateAndGet()
def metadata = InitializrMetadataTestBuilder.withDefaults()
.addType('foo', false, '/foo.zip', null, null).build()
request.type = 'foo'
request.resolve(metadata)
@@ -150,7 +179,7 @@ class ProjectRequestTests {
@Test
void resolveUnknownType() {
def request = new ProjectRequest()
def metadata = InitializrMetadataBuilder.withDefaults().validateAndGet()
def metadata = InitializrMetadataTestBuilder.withDefaults().build()
request.type = 'foo-project'
thrown.expect(InvalidProjectRequestException)
@@ -161,17 +190,17 @@ class ProjectRequestTests {
@Test
void resolveApplicationNameWithNoName() {
def request = new ProjectRequest()
def metadata = InitializrMetadataBuilder.withDefaults().validateAndGet()
def metadata = InitializrMetadataTestBuilder.withDefaults().build()
request.resolve(metadata)
assertEquals metadata.env.fallbackApplicationName, request.applicationName
assertEquals metadata.configuration.env.fallbackApplicationName, request.applicationName
}
@Test
void resolveApplicationName() {
def request = new ProjectRequest()
request.name = 'Foo2'
def metadata = InitializrMetadataBuilder.withDefaults().validateAndGet()
def metadata = InitializrMetadataTestBuilder.withDefaults().build()
request.resolve(metadata)
assertEquals 'Foo2Application', request.applicationName
@@ -182,29 +211,25 @@ class ProjectRequestTests {
def request = new ProjectRequest()
request.name = 'Foo2'
request.applicationName ='MyApplicationName'
def metadata = InitializrMetadataBuilder.withDefaults().validateAndGet()
def metadata = InitializrMetadataTestBuilder.withDefaults().build()
request.resolve(metadata)
assertEquals 'MyApplicationName', request.applicationName
}
private static void assertBootStarter(InitializrMetadata.Dependency actual, String name) {
def expected = new InitializrMetadata.Dependency()
private static void assertBootStarter(Dependency actual, String name) {
def expected = new Dependency()
expected.asSpringBootStarter(name)
assertDependency(actual, expected.groupId, expected.artifactId, expected.version)
assertEquals name, actual.id
}
private static InitializrMetadata.Dependency createDependency(String groupId, String artifactId, String version) {
def dependency = new InitializrMetadata.Dependency()
dependency.groupId = groupId
dependency.artifactId = artifactId
dependency.version = version
dependency
private static Dependency createDependency(String groupId, String artifactId, String version) {
new Dependency(groupId: groupId, artifactId: artifactId, version: version)
}
private static void assertDependency(InitializrMetadata.Dependency actual, String groupId,
private static void assertDependency(Dependency actual, String groupId,
String artifactId, String version) {
assertEquals groupId, actual.groupId
assertEquals artifactId, actual.artifactId

View File

@@ -17,8 +17,8 @@
package io.spring.initializr.mapper
import groovy.json.JsonSlurper
import io.spring.initializr.InitializrMetadata
import io.spring.initializr.test.InitializrMetadataBuilder
import io.spring.initializr.metadata.InitializrMetadata
import io.spring.initializr.test.InitializrMetadataTestBuilder
import org.junit.Test
import static org.junit.Assert.assertEquals
@@ -33,8 +33,8 @@ class InitializrMetadataJsonMapperTests {
@Test
void withNoAppUrl() {
InitializrMetadata metadata = new InitializrMetadataBuilder().addType('foo', true, '/foo.zip', 'none', 'test')
.addDependencyGroup('foo', 'one', 'two').validateAndGet()
InitializrMetadata metadata = new InitializrMetadataTestBuilder().addType('foo', true, '/foo.zip', 'none', 'test')
.addDependencyGroup('foo', 'one', 'two').build()
def json = jsonMapper.write(metadata, null)
def result = slurper.parseText(json)
assertEquals '/foo.zip?type=foo{&dependencies,packaging,javaVersion,language,bootVersion,' +
@@ -43,8 +43,8 @@ class InitializrMetadataJsonMapperTests {
@Test
void withAppUrl() {
InitializrMetadata metadata = new InitializrMetadataBuilder().addType('foo', true, '/foo.zip', 'none', 'test')
.addDependencyGroup('foo', 'one', 'two').validateAndGet()
InitializrMetadata metadata = new InitializrMetadataTestBuilder().addType('foo', true, '/foo.zip', 'none', 'test')
.addDependencyGroup('foo', 'one', 'two').build()
def json = jsonMapper.write(metadata, 'http://server:8080/my-app')
def result = slurper.parseText(json)
assertEquals 'http://server:8080/my-app/foo.zip?type=foo{&dependencies,packaging,javaVersion,' +

View File

@@ -0,0 +1,101 @@
/*
* Copyright 2012-2015 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 org.junit.Rule
import org.junit.Test
import org.junit.rules.ExpectedException
import static org.junit.Assert.assertNull
import static org.junit.Assert.assertSame
/**
* @author Stephane Nicoll
*/
class DependenciesCapabilityTest {
@Rule
public final ExpectedException thrown = ExpectedException.none()
@Test
void indexedDependencies() {
def dependency = new Dependency(id: 'first')
def dependency2 = new Dependency(id: 'second')
def capability = createDependenciesCapability('foo', dependency, dependency2)
capability.validate()
assertSame dependency, capability.get('first')
assertSame dependency2, capability.get('second')
assertNull capability.get('anotherId')
}
@Test
void addTwoDependenciesWithSameId() {
def dependency = new Dependency(id: 'conflict')
def dependency2 = new Dependency(id: 'conflict')
def capability = createDependenciesCapability('foo', dependency, dependency2)
thrown.expect(IllegalArgumentException)
thrown.expectMessage('conflict')
capability.validate()
}
@Test
void addDependencyWithAliases() {
def dependency = new Dependency(id: 'first')
dependency.aliases.add('alias1')
dependency.aliases.add('alias2')
def capability = createDependenciesCapability('foo', dependency)
capability.validate()
assertSame dependency, capability.get('first')
assertSame dependency, capability.get('alias1')
assertSame dependency, capability.get('alias2')
}
@Test
void aliasClashWithAnotherDependency() {
def dependency = new Dependency(id: 'first')
dependency.aliases.add('alias1')
dependency.aliases.add('alias2')
def dependency2 = new Dependency(id: 'alias2')
def capability = new DependenciesCapability()
capability.content << createDependencyGroup('foo', dependency)
capability.content << createDependencyGroup('bar', dependency2)
thrown.expect(IllegalArgumentException)
thrown.expectMessage('alias2')
capability.validate()
}
private static DependenciesCapability createDependenciesCapability(String groupName, Dependency... dependencies) {
DependenciesCapability capability = new DependenciesCapability()
DependencyGroup group = createDependencyGroup(groupName, dependencies)
capability.content << group
capability
}
private static DependencyGroup createDependencyGroup(String groupName, Dependency... dependencies) {
DependencyGroup group = new DependencyGroup(name: groupName)
for (Dependency dependency : dependencies) {
group.content << dependency
}
group
}
}

View File

@@ -0,0 +1,139 @@
/*
* Copyright 2012-2015 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 org.junit.Rule
import org.junit.Test
import org.junit.rules.ExpectedException
import static org.junit.Assert.assertEquals
import static org.junit.Assert.assertNull
/**
* @author Stephane Nicoll
*/
class DependencyTests {
@Rule
public final ExpectedException thrown = ExpectedException.none()
@Test
void createRootSpringBootStarter() {
Dependency d = new Dependency();
d.asSpringBootStarter("")
assertEquals 'org.springframework.boot', d.groupId
assertEquals 'spring-boot-starter', d.artifactId
}
@Test
void setCoordinatesFromId() {
def dependency = new Dependency(id: 'org.foo:bar:1.2.3')
dependency.resolve()
assertEquals 'org.foo', dependency.groupId
assertEquals 'bar', dependency.artifactId
assertEquals '1.2.3', dependency.version
assertEquals 'org.foo:bar:1.2.3', dependency.id
}
@Test
void setCoordinatesFromIdNoVersion() {
def dependency = new Dependency(id: 'org.foo:bar')
dependency.resolve()
assertEquals 'org.foo', dependency.groupId
assertEquals 'bar', dependency.artifactId
assertNull dependency.version
assertEquals 'org.foo:bar', dependency.id
}
@Test
void setIdFromCoordinates() {
def dependency = new Dependency()
dependency.groupId = 'org.foo'
dependency.artifactId = 'bar'
dependency.version = '1.0'
dependency.resolve()
assertEquals 'org.foo:bar', dependency.id
}
@Test
void setIdFromCoordinatesNoVersion() {
def dependency = new Dependency()
dependency.groupId = 'org.foo'
dependency.artifactId = 'bar'
dependency.resolve()
assertEquals 'org.foo:bar', dependency.id
}
@Test
void setIdFromSimpleName() {
def dependency = new Dependency(id: 'web')
dependency.resolve()
assertEquals 'org.springframework.boot', dependency.groupId
assertEquals 'spring-boot-starter-web', dependency.artifactId
assertNull dependency.version
assertEquals 'web', dependency.id
}
@Test
void invalidDependency() {
thrown.expect(InvalidInitializrMetadataException)
new Dependency().resolve()
}
@Test
void invalidDependencyScope() {
def dependency = new Dependency(id: 'web')
thrown.expect(InvalidInitializrMetadataException)
dependency.setScope('whatever')
}
@Test
void invalidSpringBootRange() {
def dependency = new Dependency(id: 'web')
dependency.versionRange = 'A.B.C'
thrown.expect(InvalidInitializrMetadataException)
thrown.expectMessage('A.B.C')
dependency.resolve()
}
@Test
void invalidIdFormatTooManyColons() {
def dependency = new Dependency(id: 'org.foo:bar:1.0:test:external')
thrown.expect(InvalidInitializrMetadataException)
dependency.resolve()
}
@Test
void generateIdWithNoGroupId() {
def dependency = new Dependency()
dependency.artifactId = 'bar'
thrown.expect(IllegalArgumentException)
dependency.generateId()
}
@Test
void generateIdWithNoArtifactId() {
def dependency = new Dependency()
dependency.groupId = 'foo'
thrown.expect(IllegalArgumentException)
dependency.generateId()
}
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright 2012-2015 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 org.junit.Test
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean
import org.springframework.boot.bind.PropertiesConfigurationFactory
import org.springframework.core.io.ClassPathResource
import org.springframework.core.io.Resource
import static org.junit.Assert.assertEquals
import static org.junit.Assert.assertNotNull
/**
* @author Stephane Nicoll
*/
class InitializrMetadataBuilderTests {
@Test
void loadDefaultConfig() {
def bean = load(new ClassPathResource("application-test-default.yml"))
def metadata = new InitializrMetadataBuilder().fromConfiguration(bean).build()
assertNotNull metadata
assertEquals("Wrong number of dependencies", 9, metadata.dependencies.all.size())
assertEquals("Wrong number of dependency group", 2, metadata.dependencies.content.size())
assertEquals("Wrong number of types", 4, metadata.types.content.size())
}
@Test
void addDependencyInCustomizer() {
def group = new DependencyGroup(name: 'Extra')
def dependency = new Dependency(id: 'com.foo:foo:1.0.0')
group.content << dependency
def metadata = new InitializrMetadataBuilder().withCustomizer(new InitializrMetadataCustomizer() {
@Override
void customize(InitializrMetadata metadata) {
metadata.dependencies.content << group
}
}).build()
assertEquals 1, metadata.dependencies.content.size()
assertEquals group, metadata.dependencies.content[0]
}
private static InitializrProperties load(Resource resource) {
PropertiesConfigurationFactory<InitializrProperties> factory =
new PropertiesConfigurationFactory<>(InitializrProperties)
factory.setTargetName("initializr")
factory.setProperties(loadProperties(resource))
factory.afterPropertiesSet();
return factory.getObject();
}
private static Properties loadProperties(Resource resource) {
YamlPropertiesFactoryBean yamlFactory = new YamlPropertiesFactoryBean()
yamlFactory.setResources(resource)
yamlFactory.afterPropertiesSet()
return yamlFactory.getObject()
}
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright 2012-2015 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 org.junit.Test
import static org.junit.Assert.assertEquals
import static org.junit.Assert.assertNull
/**
* @author Stephane Nicoll
*/
class SingleSelectCapabilityTests {
@Test
void defaultEmpty() {
SingleSelectCapability capability = new SingleSelectCapability('test')
assertNull capability.default
}
@Test
void defaultNoDefault() {
SingleSelectCapability capability = new SingleSelectCapability('test')
capability.content << new DefaultMetadataElement(id: 'foo', default: false)
capability.content << new DefaultMetadataElement(id: 'bar', default: false)
assertNull capability.default
}
@Test
void defaultType() {
SingleSelectCapability capability = new SingleSelectCapability('test')
DefaultMetadataElement first = new DefaultMetadataElement(id: 'foo', default: false)
DefaultMetadataElement second = new DefaultMetadataElement(id: 'bar', default: true)
capability.content << first << second
assertEquals second, capability.default
}
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright 2012-2015 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 org.junit.Test
import static org.junit.Assert.assertEquals
import static org.junit.Assert.assertNull
/**
* @author Stephane Nicoll
*/
class TypeCapabilityTests {
@Test
void defaultEmpty() {
TypeCapability capability = new TypeCapability()
assertNull capability.default
}
@Test
void defaultNoDefault() {
TypeCapability capability = new TypeCapability()
capability.content << new Type(id: 'foo', default: false) << new Type(id: 'bar', default: false)
assertNull capability.default
}
@Test
void defaultType() {
TypeCapability capability = new TypeCapability()
Type first = new Type(id: 'foo', default: false)
Type second = new Type(id: 'bar', default: true)
capability.content << first << second
assertEquals second, capability.default
}
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2012-2015 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 org.junit.Test
import static org.junit.Assert.assertEquals
/**
* @author Stephane Nicoll
*/
class TypeTests {
@Test
void parseAction() {
def type = new Type(id: 'foo', action: 'my-action.zip')
assertEquals '/my-action.zip', type.action
}
}

View File

@@ -14,9 +14,9 @@
* limitations under the License.
*/
package io.spring.initializr
package io.spring.initializr.support
import io.spring.initializr.test.InitializrMetadataBuilder
import io.spring.initializr.test.InitializrMetadataTestBuilder
import org.junit.Test
import static org.junit.Assert.*
@@ -28,17 +28,17 @@ class DefaultInitializrMetadataProviderTests {
@Test
void bootVersionsAreReplaced() {
def metadata = new InitializrMetadataBuilder()
.addBootVersion('0.0.9.RELEASE', true).addBootVersion('0.0.8.RELEASE', false).validateAndGet()
assertEquals '0.0.9.RELEASE', metadata.defaults.bootVersion
def metadata = new InitializrMetadataTestBuilder()
.addBootVersion('0.0.9.RELEASE', true).addBootVersion('0.0.8.RELEASE', false).build()
assertEquals '0.0.9.RELEASE', metadata.bootVersions.default.id
def provider = new DefaultInitializrMetadataProvider(metadata)
def updatedMetadata = provider.get()
assertNotNull updatedMetadata.bootVersions
assertFalse 'Boot versions must be set', updatedMetadata.bootVersions.isEmpty()
assertFalse 'Boot versions must be set', updatedMetadata.bootVersions.content.isEmpty()
def defaultVersion = null
updatedMetadata.bootVersions.each {
updatedMetadata.bootVersions.content.each {
assertFalse '0.0.9.RELEASE should have been removed', '0.0.9.RELEASE'.equals(it.id)
assertFalse '0.0.8.RELEASE should have been removed', '0.0.8.RELEASE'.equals(it.id)
if (it.default) {
@@ -46,7 +46,8 @@ class DefaultInitializrMetadataProviderTests {
}
}
assertNotNull 'A default boot version must be set', defaultVersion
assertEquals 'Default boot version not updated properly', defaultVersion, updatedMetadata.defaults.bootVersion
assertEquals 'Default boot version not updated properly', defaultVersion,
updatedMetadata.bootVersions.default.id
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2014 the original author or authors.
* Copyright 2012-2015 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.
@@ -14,8 +14,10 @@
* limitations under the License.
*/
package io.spring.initializr
package io.spring.initializr.support
import io.spring.initializr.InitializrConfiguration
import io.spring.initializr.metadata.InitializrMetadata
import org.junit.Test
import static org.junit.Assert.assertNotNull
@@ -26,11 +28,11 @@ import static org.junit.Assert.fail
*/
class SpringBootMetadataReaderTests {
private final InitializrMetadata metadata = new InitializrMetadata()
private final InitializrMetadata metadata = new InitializrMetadata(new InitializrConfiguration())
@Test
void readAvailableVersions() {
def versions = new SpringBootMetadataReader(metadata.env.springBootMetadataUrl).bootVersions
def versions = new SpringBootMetadataReader(metadata.configuration.env.springBootMetadataUrl).bootVersions
assertNotNull "spring boot versions should not be null", versions
boolean defaultFound
versions.each {

View File

@@ -16,7 +16,7 @@
package io.spring.initializr.test
import io.spring.initializr.ProjectRequest
import io.spring.initializr.generator.ProjectRequest
import static org.junit.Assert.assertTrue

View File

@@ -1,150 +0,0 @@
/*
* Copyright 2012-2015 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.test
import io.spring.initializr.InitializrMetadata
/**
* Easily create a {@link InitializrMetadata} instance for testing purposes.
*
* @author Stephane Nicoll
* @since 1.0
*/
class InitializrMetadataBuilder {
private final InitializrMetadata metadata = new InitializrMetadata()
static InitializrMetadataBuilder withDefaults() {
new InitializrMetadataBuilder().addDefaults()
}
InitializrMetadata validateAndGet() {
metadata.validate()
instance()
}
InitializrMetadata instance() {
metadata
}
InitializrMetadataBuilder addDependencyGroup(String name, String... ids) {
def group = new InitializrMetadata.DependencyGroup()
group.name = name
for (String id : ids) {
def dependency = new InitializrMetadata.Dependency()
dependency.id = id
group.content.add(dependency)
}
metadata.dependencies.add(group)
this
}
InitializrMetadataBuilder addDependencyGroup(String name, InitializrMetadata.Dependency... dependencies) {
def group = new InitializrMetadata.DependencyGroup()
group.name = name
group.content.addAll(dependencies)
metadata.dependencies.add(group)
this
}
InitializrMetadataBuilder addDefaults() {
addDefaultTypes().addDefaultPackagings().addDefaultJavaVersions()
.addDefaultLanguages().addDefaultBootVersions()
}
InitializrMetadataBuilder addDefaultTypes() {
addType('maven-build', false, '/pom.xml', 'maven', 'build')
.addType('maven-project', true, '/starter.zip', 'maven', 'project')
.addType('gradle-build', false, '/build.gradle', 'gradle', 'build')
.addType('gradle-project', false, '/starter.zip', 'gradle', 'project')
}
InitializrMetadataBuilder addType(String id, boolean defaultValue, String action, String build, String format) {
def type = new InitializrMetadata.Type()
type.id = id
type.name = id
type.default = defaultValue
type.action = action
if (build) {
type.tags['build'] = build
}
if (format) {
type.tags['format'] = format
}
addType(type)
}
InitializrMetadataBuilder addType(InitializrMetadata.Type type) {
metadata.types.add(type)
this
}
InitializrMetadataBuilder addDefaultPackagings() {
addPackaging('jar', true).addPackaging('war', false)
}
InitializrMetadataBuilder addPackaging(String id, boolean defaultValue) {
def packaging = new InitializrMetadata.Packaging()
packaging.id = id
packaging.name = id
packaging.default = defaultValue
metadata.packagings.add(packaging)
this
}
InitializrMetadataBuilder addDefaultJavaVersions() {
addJavaVersion('1.6', false).addJavaVersion('1.7', true).addJavaVersion('1.8', false)
}
InitializrMetadataBuilder addJavaVersion(String version, boolean defaultValue) {
def javaVersion = new InitializrMetadata.JavaVersion()
javaVersion.id = version
javaVersion.name = version
javaVersion.default = defaultValue
metadata.javaVersions.add(javaVersion)
this
}
InitializrMetadataBuilder addDefaultLanguages() {
addLanguage('java', true).addPackaging('groovy', false)
}
InitializrMetadataBuilder addLanguage(String id, boolean defaultValue) {
def language = new InitializrMetadata.Language()
language.id = id
language.name = id
language.default = defaultValue
metadata.languages.add(language)
this
}
InitializrMetadataBuilder addDefaultBootVersions() {
addBootVersion('1.0.2.RELEASE', false).addBootVersion('1.1.5.RELEASE', true)
.addBootVersion('1.2.0.BUILD-SNAPSHOT', false)
}
InitializrMetadataBuilder addBootVersion(String id, boolean defaultValue) {
def bootVersion = new InitializrMetadata.BootVersion()
bootVersion.id = id
bootVersion.name = id
bootVersion.default = defaultValue
metadata.bootVersions.add(bootVersion)
this
}
}

View File

@@ -0,0 +1,143 @@
/*
* Copyright 2012-2015 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.test
import io.spring.initializr.metadata.DefaultMetadataElement
import io.spring.initializr.metadata.Dependency
import io.spring.initializr.metadata.DependencyGroup
import io.spring.initializr.metadata.InitializrMetadata
import io.spring.initializr.metadata.InitializrMetadataBuilder
import io.spring.initializr.metadata.Type
/**
* Easily create a {@link InitializrMetadata} instance for testing purposes.
*
* @author Stephane Nicoll
* @since 1.0
*/
class InitializrMetadataTestBuilder {
private final InitializrMetadataBuilder builder = new InitializrMetadataBuilder()
static InitializrMetadataTestBuilder withDefaults() {
new InitializrMetadataTestBuilder().addDefaults()
}
InitializrMetadata build() {
builder.build()
}
InitializrMetadataTestBuilder addDependencyGroup(String name, String... ids) {
builder.withCustomizer {
def group = new DependencyGroup(name: name)
for (String id : ids) {
def dependency = new Dependency(id: id)
group.content << dependency
}
it.dependencies.content << group
}
this
}
InitializrMetadataTestBuilder addDependencyGroup(String name, Dependency... dependencies) {
builder.withCustomizer {
def group = new DependencyGroup(name: name)
group.content.addAll(dependencies)
it.dependencies.content << group
}
this
}
InitializrMetadataTestBuilder addDefaults() {
addDefaultTypes().addDefaultPackagings().addDefaultJavaVersions()
.addDefaultLanguages().addDefaultBootVersions()
}
InitializrMetadataTestBuilder addDefaultTypes() {
addType('maven-build', false, '/pom.xml', 'maven', 'build')
.addType('maven-project', true, '/starter.zip', 'maven', 'project')
.addType('gradle-build', false, '/build.gradle', 'gradle', 'build')
.addType('gradle-project', false, '/starter.zip', 'gradle', 'project')
}
InitializrMetadataTestBuilder addType(String id, boolean defaultValue, String action, String build, String format) {
def type = new Type(id: id, name: id, default: defaultValue, action: action)
if (build) {
type.tags['build'] = build
}
if (format) {
type.tags['format'] = format
}
addType(type)
}
InitializrMetadataTestBuilder addType(Type type) {
builder.withCustomizer { it.types.content << type }
this
}
InitializrMetadataTestBuilder addDefaultPackagings() {
addPackaging('jar', true).addPackaging('war', false)
}
InitializrMetadataTestBuilder addPackaging(String id, boolean defaultValue) {
builder.withCustomizer {
def packaging = new DefaultMetadataElement(id: id, name: id, default: defaultValue)
it.packagings.content << packaging
}
this
}
InitializrMetadataTestBuilder addDefaultJavaVersions() {
addJavaVersion('1.6', false).addJavaVersion('1.7', true).addJavaVersion('1.8', false)
}
InitializrMetadataTestBuilder addJavaVersion(String version, boolean defaultValue) {
builder.withCustomizer {
def javaVersion = new DefaultMetadataElement(id: version, name: version, default: defaultValue)
it.javaVersions.content << javaVersion
}
this
}
InitializrMetadataTestBuilder addDefaultLanguages() {
addLanguage('java', true).addPackaging('groovy', false)
}
InitializrMetadataTestBuilder addLanguage(String id, boolean defaultValue) {
builder.withCustomizer {
def language = new DefaultMetadataElement(id: id, name: id, default: defaultValue)
it.languages.content << language
}
this
}
InitializrMetadataTestBuilder addDefaultBootVersions() {
addBootVersion('1.0.2.RELEASE', false).addBootVersion('1.1.5.RELEASE', true)
.addBootVersion('1.2.0.BUILD-SNAPSHOT', false)
}
InitializrMetadataTestBuilder addBootVersion(String id, boolean defaultValue) {
builder.withCustomizer {
def bootVersion = new DefaultMetadataElement(id: id, name: id, default: defaultValue)
it.bootVersions.content << bootVersion
}
this
}
}

View File

@@ -16,8 +16,8 @@
package io.spring.initializr.test
import io.spring.initializr.InitializrMetadata
import io.spring.initializr.ProjectRequest
import io.spring.initializr.generator.ProjectRequest
import io.spring.initializr.metadata.Dependency
import org.custommonkey.xmlunit.SimpleNamespaceContext
import org.custommonkey.xmlunit.XMLUnit
import org.custommonkey.xmlunit.XpathEngine
@@ -38,7 +38,7 @@ class PomAssert {
final XpathEngine eng
final Document doc
final Map<String, InitializrMetadata.Dependency> dependencies = [:]
final Map<String, Dependency> dependencies = [:]
PomAssert(String content) {
eng = XMLUnit.newXpathEngine()
@@ -111,11 +111,11 @@ class PomAssert {
}
PomAssert hasSpringBootStarterTomcat() {
hasDependency(new InitializrMetadata.Dependency(id: 'tomcat', scope: 'provided').asSpringBootStarter('tomcat'))
hasDependency(new Dependency(id: 'tomcat', scope: 'provided').asSpringBootStarter('tomcat'))
}
PomAssert hasSpringBootStarterTest() {
hasDependency(new InitializrMetadata.Dependency(id: 'test', scope: 'test').asSpringBootStarter('test'))
hasDependency(new Dependency(id: 'test', scope: 'test').asSpringBootStarter('test'))
}
PomAssert hasSpringBootStarterDependency(String dependency) {
@@ -131,10 +131,10 @@ class PomAssert {
}
PomAssert hasDependency(String groupId, String artifactId, String version) {
hasDependency(new InitializrMetadata.Dependency(groupId: groupId, artifactId: artifactId, version: version))
hasDependency(new Dependency(groupId: groupId, artifactId: artifactId, version: version))
}
PomAssert hasDependency(InitializrMetadata.Dependency expected) {
PomAssert hasDependency(Dependency expected) {
def id = generateId(expected.groupId, expected.artifactId)
def dependency = dependencies[id]
assertNotNull "No dependency found with '$id' --> ${dependencies.keySet()}", dependency
@@ -191,7 +191,7 @@ class PomAssert {
for (int i = 0; i < nodes.length; i++) {
def item = nodes.item(i)
if (item instanceof Element) {
def dependency = new InitializrMetadata.Dependency()
def dependency = new Dependency()
def element = (Element) item
def groupId = element.getElementsByTagName('groupId')
if (groupId.length > 0) {
@@ -217,7 +217,7 @@ class PomAssert {
}
private static String generateId(String groupId, String artifactId) {
def dependency = new InitializrMetadata.Dependency()
def dependency = new Dependency()
dependency.groupId = groupId
dependency.artifactId = artifactId
dependency.generateId()

View File

@@ -16,8 +16,6 @@
package io.spring.initializr.test
import io.spring.initializr.InitializrMetadata
import static org.junit.Assert.assertEquals
import static org.junit.Assert.assertTrue
@@ -151,7 +149,7 @@ class ProjectAssert {
}
private static generateDefaultApplicationName() {
InitializrMetadata.Defaults.DEFAULT_NAME.capitalize() + 'Application'
'DemoApplication'
}
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package io.spring.initializr.support
package io.spring.initializr.util
import org.hamcrest.BaseMatcher
import org.hamcrest.Description

View File

@@ -14,14 +14,14 @@
* limitations under the License.
*/
package io.spring.initializr.support
package io.spring.initializr.util
import org.junit.Rule
import org.junit.Test
import org.junit.rules.ExpectedException
import static io.spring.initializr.support.Version.parse
import static io.spring.initializr.support.Version.safeParse
import static io.spring.initializr.util.Version.parse
import static io.spring.initializr.util.Version.safeParse
import static org.hamcrest.MatcherAssert.assertThat
import static org.hamcrest.Matchers.*
import static org.junit.Assert.assertNull

View File

@@ -16,9 +16,10 @@
package io.spring.initializr.web
import io.spring.initializr.DefaultInitializrMetadataProvider
import io.spring.initializr.InitializrMetadata
import io.spring.initializr.InitializrMetadataProvider
import io.spring.initializr.metadata.DefaultMetadataElement
import io.spring.initializr.metadata.InitializrMetadata
import io.spring.initializr.support.DefaultInitializrMetadataProvider
import io.spring.initializr.metadata.InitializrMetadataProvider
import io.spring.initializr.test.ProjectAssert
import org.junit.Rule
import org.junit.rules.TemporaryFolder
@@ -170,7 +171,7 @@ abstract class AbstractInitializrControllerIntegrationTests {
InitializrMetadataProvider initializrMetadataProvider(InitializrMetadata metadata) {
new DefaultInitializrMetadataProvider(metadata) {
@Override
protected List<InitializrMetadata.BootVersion> fetchBootVersions() {
protected List<DefaultMetadataElement> fetchBootVersions() {
null // Disable metadata fetching from spring.io
}
}

View File

@@ -19,8 +19,8 @@ package io.spring.initializr.web
import java.nio.charset.Charset
import groovy.json.JsonSlurper
import io.spring.initializr.InitializrMetadata
import io.spring.initializr.InitializrMetadataVersion
import io.spring.initializr.mapper.InitializrMetadataVersion
import io.spring.initializr.metadata.Dependency
import org.json.JSONObject
import org.junit.Ignore
import org.junit.Test
@@ -70,7 +70,7 @@ class MainControllerIntegrationTests extends AbstractInitializrControllerIntegra
@Test
void dependencyInRange() {
def biz = new InitializrMetadata.Dependency(id: 'biz', groupId: 'org.acme',
def biz = new Dependency(id: 'biz', groupId: 'org.acme',
artifactId: 'biz', version: '1.3.5', scope: 'runtime')
downloadTgz('/starter.tgz?style=org.acme:biz&bootVersion=1.2.1.RELEASE').isJavaProject().isMavenProject()
.hasStaticAndTemplatesResources(false).pomAssert()
@@ -372,7 +372,7 @@ class MainControllerIntegrationTests extends AbstractInitializrControllerIntegra
@Test
void downloadWithUnknownSpringBootStarter() { // Simple id are accepted as spring-boot-starter
downloadZip('/starter.zip?style=foo').pomAssert().hasSpringBootStarterDependency('foo')
downloadZip('/starter.zip?style=foo').pomAssert().hasSpringBootStarterDependency('foo')
}
// Existing tests for backward compatibility