mirror of
https://gitee.com/dcren/initializr.git
synced 2025-09-19 01:58:16 +08:00
Better describe service capability
Make sure that the title and description of each capability is configurable and expose that information in the meta-data. This typically allows to customize the header of each capability in the UI and the description in help usage such as the optimized text output for command line clients. See gh-89
This commit is contained in:
@@ -93,7 +93,7 @@ class CommandLineHelpGenerator {
|
||||
defaults['baseDir'] = 'no base dir'
|
||||
defaults['dependencies'] = 'none'
|
||||
|
||||
Map parametersDescription = buildParametersDescription()
|
||||
Map parametersDescription = buildParametersDescription(metadata)
|
||||
String[][] parameterTable = new String[defaults.size() + 1][];
|
||||
parameterTable[0] = ["Parameter", "Description", "Default value"]
|
||||
defaults.sort().keySet().eachWithIndex { id, i ->
|
||||
@@ -117,7 +117,7 @@ class CommandLineHelpGenerator {
|
||||
|
||||
|
||||
Map defaults = metadata.defaults()
|
||||
Map parametersDescription = buildParametersDescription()
|
||||
Map parametersDescription = buildParametersDescription(metadata)
|
||||
String[][] parameterTable = new String[defaults.size() + 1][];
|
||||
parameterTable[0] = ["Id", "Description", "Default value"]
|
||||
defaults.keySet().eachWithIndex { id, i ->
|
||||
@@ -165,24 +165,16 @@ class CommandLineHelpGenerator {
|
||||
TableGenerator.generate(typeTable)
|
||||
}
|
||||
|
||||
protected Map buildParametersDescription() {
|
||||
protected Map buildParametersDescription(InitializrMetadata metadata) {
|
||||
Map result = [:]
|
||||
result['groupId'] = 'project coordinates'
|
||||
result['artifactId'] = 'project coordinates (infer archive name)'
|
||||
result['version'] = 'project version'
|
||||
result['name'] = 'project name (infer application name)'
|
||||
result['description'] = 'project description'
|
||||
result['packageName'] = 'root package'
|
||||
metadata.properties.each { key, value ->
|
||||
if (value.hasProperty('description') && value.hasProperty('id')) {
|
||||
result[value.id] = value['description']
|
||||
}
|
||||
}
|
||||
result['applicationName'] = 'application name'
|
||||
result['dependencies'] = 'dependency identifiers (comma separated)'
|
||||
result['type'] = 'project type'
|
||||
result['packaging'] = 'project packaging'
|
||||
result['language'] = 'programming language'
|
||||
result['javaVersion'] = 'language level'
|
||||
result['bootVersion'] = 'spring boot version'
|
||||
result['baseDir'] = 'base directory to create in the archive'
|
||||
result
|
||||
|
||||
}
|
||||
|
||||
private static String buildVersionRangeRepresentation(String range) {
|
||||
|
@@ -30,7 +30,8 @@ class DependenciesCapability extends ServiceCapability<List<DependencyGroup>> {
|
||||
private final Map<String, Dependency> indexedDependencies = [:]
|
||||
|
||||
DependenciesCapability() {
|
||||
super('dependencies', ServiceCapabilityType.HIERARCHICAL_MULTI_SELECT)
|
||||
super('dependencies', ServiceCapabilityType.HIERARCHICAL_MULTI_SELECT,
|
||||
'Project dependencies', 'dependency identifiers (comma-separated)')
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -30,23 +30,27 @@ class InitializrMetadata {
|
||||
|
||||
final TypeCapability types = new TypeCapability()
|
||||
|
||||
final SingleSelectCapability bootVersions = new SingleSelectCapability('bootVersion')
|
||||
final SingleSelectCapability bootVersions =
|
||||
new SingleSelectCapability('bootVersion', 'Spring Boot Version', 'spring boot version')
|
||||
|
||||
final SingleSelectCapability packagings = new SingleSelectCapability('packaging')
|
||||
final SingleSelectCapability packagings =
|
||||
new SingleSelectCapability('packaging', 'Packaging', 'project packaging')
|
||||
|
||||
final SingleSelectCapability javaVersions = new SingleSelectCapability('javaVersion')
|
||||
final SingleSelectCapability javaVersions =
|
||||
new SingleSelectCapability('javaVersion', 'Java Version', 'language level')
|
||||
|
||||
final SingleSelectCapability languages = new SingleSelectCapability('language')
|
||||
final SingleSelectCapability languages =
|
||||
new SingleSelectCapability('language', 'Language', 'programming language')
|
||||
|
||||
final TextCapability name = new TextCapability('name')
|
||||
final TextCapability name = new TextCapability('name', 'Name', 'project name (infer application name)')
|
||||
|
||||
final TextCapability description = new TextCapability('description')
|
||||
final TextCapability description = new TextCapability('description', 'Description', 'project description' )
|
||||
|
||||
final TextCapability groupId = new TextCapability('groupId')
|
||||
final TextCapability groupId = new TextCapability('groupId', 'Group', 'project coordinates')
|
||||
|
||||
final TextCapability artifactId = new ArtifactIdCapability(name)
|
||||
|
||||
final TextCapability version = new TextCapability('version')
|
||||
final TextCapability version = new TextCapability('version', 'Version', 'project version')
|
||||
|
||||
final TextCapability packageName = new PackageCapability(name)
|
||||
|
||||
@@ -130,7 +134,7 @@ class InitializrMetadata {
|
||||
private final TextCapability nameCapability
|
||||
|
||||
ArtifactIdCapability(TextCapability nameCapability) {
|
||||
super('artifactId')
|
||||
super('artifactId', 'Artifact', 'project coordinates (infer archive name)')
|
||||
this.nameCapability = nameCapability
|
||||
}
|
||||
|
||||
@@ -145,7 +149,7 @@ class InitializrMetadata {
|
||||
private final TextCapability nameCapability
|
||||
|
||||
PackageCapability(TextCapability nameCapability) {
|
||||
super('packageName')
|
||||
super('packageName', 'Package Name', 'root package')
|
||||
this.nameCapability = nameCapability
|
||||
}
|
||||
|
||||
|
@@ -152,12 +152,12 @@ class InitializrMetadataBuilder {
|
||||
metadata.packagings.merge(properties.packagings)
|
||||
metadata.javaVersions.merge(properties.javaVersions)
|
||||
metadata.languages.merge(properties.languages)
|
||||
metadata.groupId.merge(properties.defaults.groupId)
|
||||
metadata.artifactId.merge(properties.defaults.artifactId)
|
||||
metadata.version.merge(properties.defaults.version)
|
||||
metadata.name.merge(properties.defaults.name)
|
||||
metadata.description.merge(properties.defaults.description)
|
||||
metadata.packageName.merge(properties.defaults.packageName)
|
||||
properties.groupId.apply(metadata.groupId)
|
||||
properties.artifactId.apply(metadata.artifactId)
|
||||
properties.version.apply(metadata.version)
|
||||
properties.name.apply(metadata.name)
|
||||
properties.description.apply(metadata.description)
|
||||
properties.packageName.apply(metadata.packageName)
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -16,7 +16,7 @@
|
||||
|
||||
package io.spring.initializr.metadata
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties
|
||||
|
||||
@@ -27,32 +27,61 @@ import org.springframework.boot.context.properties.ConfigurationProperties
|
||||
* @since 1.0
|
||||
*/
|
||||
@ConfigurationProperties(prefix = 'initializr', ignoreUnknownFields = false)
|
||||
@JsonIgnoreProperties(["dependencies", "types", "packagings", "javaVersions", "languages", "bootVersions", "defaults"])
|
||||
class InitializrProperties extends InitializrConfiguration {
|
||||
|
||||
@JsonIgnore
|
||||
final List<DependencyGroup> dependencies = []
|
||||
|
||||
@JsonIgnore
|
||||
final List<Type> types = []
|
||||
|
||||
@JsonIgnore
|
||||
final List<DefaultMetadataElement> packagings = []
|
||||
|
||||
@JsonIgnore
|
||||
final List<DefaultMetadataElement> javaVersions = []
|
||||
|
||||
@JsonIgnore
|
||||
final List<DefaultMetadataElement> languages = []
|
||||
|
||||
@JsonIgnore
|
||||
final List<DefaultMetadataElement> bootVersions = []
|
||||
|
||||
final Defaults defaults = new Defaults()
|
||||
@JsonIgnore
|
||||
final SimpleElement groupId = new SimpleElement(value: 'org.test')
|
||||
|
||||
static class Defaults {
|
||||
@JsonIgnore
|
||||
final SimpleElement artifactId = new SimpleElement()
|
||||
|
||||
String groupId = 'org.test'
|
||||
String artifactId
|
||||
String version = '0.0.1-SNAPSHOT'
|
||||
String name = 'demo'
|
||||
String description = 'Demo project for Spring Boot'
|
||||
String packageName
|
||||
@JsonIgnore
|
||||
final SimpleElement version = new SimpleElement(value: '0.0.1-SNAPSHOT')
|
||||
|
||||
@JsonIgnore
|
||||
final SimpleElement name = new SimpleElement(value: 'demo')
|
||||
|
||||
@JsonIgnore
|
||||
final SimpleElement description = new SimpleElement(value: 'Demo project for Spring Boot')
|
||||
|
||||
@JsonIgnore
|
||||
final SimpleElement packageName = new SimpleElement()
|
||||
|
||||
|
||||
static class SimpleElement {
|
||||
String title
|
||||
String description
|
||||
String value
|
||||
|
||||
void apply(TextCapability capability) {
|
||||
if (title) {
|
||||
capability.title = title
|
||||
}
|
||||
if (description) {
|
||||
capability.description = description
|
||||
}
|
||||
if (value) {
|
||||
capability.content = value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -36,6 +36,14 @@ abstract class ServiceCapability<T> {
|
||||
|
||||
final ServiceCapabilityType type
|
||||
|
||||
/**
|
||||
* A title of the capability, used as a header text or label.
|
||||
*/
|
||||
String title
|
||||
|
||||
/**
|
||||
* A description of the capability, used in help usage or UI tooltips.
|
||||
*/
|
||||
String description
|
||||
|
||||
protected ServiceCapability(String id, ServiceCapabilityType type) {
|
||||
@@ -43,6 +51,13 @@ abstract class ServiceCapability<T> {
|
||||
this.type = type
|
||||
}
|
||||
|
||||
protected ServiceCapability(String id, ServiceCapabilityType type, String title, String description) {
|
||||
this.id = id
|
||||
this.type = type
|
||||
this.title = title
|
||||
this.description = description
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the "content" of this capability. The structure of the content
|
||||
* vastly depends on the {@link ServiceCapability type} of the capability.
|
||||
@@ -64,6 +79,9 @@ abstract class ServiceCapability<T> {
|
||||
Assert.notNull(other, "Other must not be null")
|
||||
Assert.state(this.id.equals(other.id))
|
||||
Assert.state(this.type.equals(other.type))
|
||||
if (other.title) {
|
||||
this.title = other.title
|
||||
}
|
||||
if (other.description) {
|
||||
this.description = other.description
|
||||
}
|
||||
|
@@ -31,7 +31,11 @@ class SingleSelectCapability extends ServiceCapability<List<DefaultMetadataEleme
|
||||
|
||||
@JsonCreator
|
||||
SingleSelectCapability(@JsonProperty("id") String id) {
|
||||
super(id, ServiceCapabilityType.SINGLE_SELECT)
|
||||
this(id, null, null)
|
||||
}
|
||||
|
||||
SingleSelectCapability(String id, String title, String description) {
|
||||
super(id, ServiceCapabilityType.SINGLE_SELECT, title, description)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -31,12 +31,11 @@ class TextCapability extends ServiceCapability<String> {
|
||||
|
||||
@JsonCreator
|
||||
TextCapability(@JsonProperty("id") String id) {
|
||||
super(id, ServiceCapabilityType.TEXT);
|
||||
this(id, null, null)
|
||||
}
|
||||
|
||||
TextCapability(String id, String content) {
|
||||
this(id)
|
||||
this.content = content
|
||||
TextCapability(String id, String title, String description) {
|
||||
super(id, ServiceCapabilityType.TEXT, title, description)
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -27,7 +27,7 @@ class TypeCapability extends ServiceCapability<List<Type>> {
|
||||
final List<Type> content = []
|
||||
|
||||
TypeCapability() {
|
||||
super('type', ServiceCapabilityType.ACTION)
|
||||
super('type', ServiceCapabilityType.ACTION, 'Type', 'project type')
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -31,37 +31,37 @@
|
||||
<div class="col-sm-6">
|
||||
<h3>Project metadata</h3>
|
||||
<div class="form-group">
|
||||
<label for="groupId" class="col-md-3 control-label">Group</label>
|
||||
<label for="groupId" class="col-md-3 control-label">${groupId.title}</label>
|
||||
<div class="col-md-8">
|
||||
<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>
|
||||
<label for="artifactId" class="col-md-3 control-label">${artifactId.title}</label>
|
||||
<div class="col-md-8">
|
||||
<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>
|
||||
<label for="name" class="col-md-3 control-label">${name.title}</label>
|
||||
<div class="col-md-8">
|
||||
<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>
|
||||
<label for="description" class="col-md-3 control-label">${description.title}</label>
|
||||
<div class="col-md-8">
|
||||
<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>
|
||||
<label for="packageName" class="col-md-3 control-label">${packageName.title}</label>
|
||||
<div class="col-md-8">
|
||||
<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>
|
||||
<label for="type" class="col-md-3 control-label">${types.title}</label>
|
||||
<div class="col-md-8">
|
||||
<select class="form-control" id="type" name="type">
|
||||
<% types.content.each { %>
|
||||
@@ -71,7 +71,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="packaging" class="col-md-3 control-label">Packaging</label>
|
||||
<label for="packaging" class="col-md-3 control-label">${packagings.title}</label>
|
||||
<div class="col-md-8">
|
||||
<select class="form-control" id="packaging" name="packaging">
|
||||
<% packagings.content.each { %>
|
||||
@@ -81,7 +81,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="javaVersion" class="col-md-3 control-label">Java Version</label>
|
||||
<label for="javaVersion" class="col-md-3 control-label">${javaVersions.title}</label>
|
||||
<div class="col-md-8">
|
||||
<select class="form-control" name="javaVersion" id="javaVersion">
|
||||
<% javaVersions.content.each { %>
|
||||
@@ -91,7 +91,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="language" class="col-md-3 control-label">Language</label>
|
||||
<label for="language" class="col-md-3 control-label">${languages.title}</label>
|
||||
<div class="col-md-8">
|
||||
<select class="form-control" name="language" id="language">
|
||||
<% languages.content.each { %>
|
||||
@@ -101,7 +101,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="bootVersion" class="col-md-3 control-label">Spring Boot Version</label>
|
||||
<label for="bootVersion" class="col-md-3 control-label">${bootVersions.title}</label>
|
||||
<div class="col-md-8">
|
||||
<select class="form-control" name="bootVersion" id="bootVersion">
|
||||
<% bootVersions.content.each { %>
|
||||
@@ -112,7 +112,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div id="dependencies" class="col-sm-6">
|
||||
<h3>Project dependencies</h3>
|
||||
<h3>${dependencies.title}</h3>
|
||||
<% dependencies.content.each { %>
|
||||
<div class="form-group col-xs-6">
|
||||
<h4>${it.name}</h4>
|
||||
|
@@ -26,24 +26,35 @@ import static org.junit.Assert.assertEquals
|
||||
class TextCapabilityTests {
|
||||
|
||||
@Test
|
||||
void mergeContent() {
|
||||
TextCapability capability = new TextCapability('foo', '1234')
|
||||
capability.merge(new TextCapability('foo', '4567'))
|
||||
void mergeValue() {
|
||||
TextCapability capability = new TextCapability('foo')
|
||||
capability.content = '1234'
|
||||
def another = new TextCapability('foo')
|
||||
another.content = '4567'
|
||||
capability.merge(another)
|
||||
assertEquals 'foo', capability.id
|
||||
assertEquals ServiceCapabilityType.TEXT, capability.type
|
||||
assertEquals '4567', capability.content
|
||||
}
|
||||
|
||||
@Test
|
||||
void mergeDescription() {
|
||||
TextCapability capability = new TextCapability('foo', '1234')
|
||||
def other = new TextCapability('foo', '')
|
||||
other.description = 'my description'
|
||||
capability.merge(other)
|
||||
void mergeTitle() {
|
||||
TextCapability capability = new TextCapability('foo', 'Foo', 'my desc')
|
||||
capability.merge(new TextCapability('foo', 'AnotherFoo', ''))
|
||||
assertEquals 'foo', capability.id
|
||||
assertEquals ServiceCapabilityType.TEXT, capability.type
|
||||
assertEquals '1234', capability.content
|
||||
assertEquals 'my description', capability.description
|
||||
assertEquals 'AnotherFoo', capability.title
|
||||
assertEquals 'my desc', capability.description
|
||||
}
|
||||
|
||||
@Test
|
||||
void mergeDescription() {
|
||||
TextCapability capability = new TextCapability('foo', 'Foo', 'my desc')
|
||||
capability.merge(new TextCapability('foo', '', 'another desc'))
|
||||
assertEquals 'foo', capability.id
|
||||
assertEquals ServiceCapabilityType.TEXT, capability.type
|
||||
assertEquals 'Foo', capability.title
|
||||
assertEquals 'another desc', capability.description
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,8 +1,13 @@
|
||||
initializr:
|
||||
defaults:
|
||||
groupId: org.foo
|
||||
artifactId: foo-bar
|
||||
version: 1.2.4-SNAPSHOT
|
||||
name: FooBar
|
||||
description: FooBar Project
|
||||
packageName: org.foo.demo
|
||||
groupId:
|
||||
value: org.foo
|
||||
artifactId:
|
||||
value: foo-bar
|
||||
version:
|
||||
value: 1.2.4-SNAPSHOT
|
||||
name:
|
||||
value: FooBar
|
||||
description:
|
||||
value: FooBar Project
|
||||
packageName:
|
||||
value: org.foo.demo
|
@@ -1,7 +1,9 @@
|
||||
{
|
||||
"artifactId": {
|
||||
"content": "demo",
|
||||
"description": "project coordinates (infer archive name)",
|
||||
"id": "artifactId",
|
||||
"title": "Artifact",
|
||||
"type": "TEXT"
|
||||
},
|
||||
"bootVersions": {
|
||||
@@ -22,7 +24,9 @@
|
||||
"name": "1.0.2"
|
||||
}
|
||||
],
|
||||
"description": "spring boot version",
|
||||
"id": "bootVersion",
|
||||
"title": "Spring Boot Version",
|
||||
"type": "SINGLE_SELECT"
|
||||
},
|
||||
"configuration": {
|
||||
@@ -130,17 +134,23 @@
|
||||
"name": "Other"
|
||||
}
|
||||
],
|
||||
"description": "dependency identifiers (comma-separated)",
|
||||
"id": "dependencies",
|
||||
"title": "Project dependencies",
|
||||
"type": "HIERARCHICAL_MULTI_SELECT"
|
||||
},
|
||||
"description": {
|
||||
"content": "Demo project for Spring Boot",
|
||||
"description": "project description",
|
||||
"id": "description",
|
||||
"title": "Description",
|
||||
"type": "TEXT"
|
||||
},
|
||||
"groupId": {
|
||||
"content": "org.test",
|
||||
"description": "project coordinates",
|
||||
"id": "groupId",
|
||||
"title": "Group",
|
||||
"type": "TEXT"
|
||||
},
|
||||
"javaVersions": {
|
||||
@@ -161,7 +171,9 @@
|
||||
"name": "1.8"
|
||||
}
|
||||
],
|
||||
"description": "language level",
|
||||
"id": "javaVersion",
|
||||
"title": "Java Version",
|
||||
"type": "SINGLE_SELECT"
|
||||
},
|
||||
"languages": {
|
||||
@@ -177,17 +189,23 @@
|
||||
"name": "Java"
|
||||
}
|
||||
],
|
||||
"description": "programming language",
|
||||
"id": "language",
|
||||
"title": "Language",
|
||||
"type": "SINGLE_SELECT"
|
||||
},
|
||||
"name": {
|
||||
"content": "demo",
|
||||
"description": "project name (infer application name)",
|
||||
"id": "name",
|
||||
"title": "Name",
|
||||
"type": "TEXT"
|
||||
},
|
||||
"packageName": {
|
||||
"content": "demo",
|
||||
"description": "root package",
|
||||
"id": "packageName",
|
||||
"title": "Package Name",
|
||||
"type": "TEXT"
|
||||
},
|
||||
"packagings": {
|
||||
@@ -203,7 +221,9 @@
|
||||
"name": "War"
|
||||
}
|
||||
],
|
||||
"description": "project packaging",
|
||||
"id": "packaging",
|
||||
"title": "Packaging",
|
||||
"type": "SINGLE_SELECT"
|
||||
},
|
||||
"types": {
|
||||
@@ -257,12 +277,16 @@
|
||||
}
|
||||
}
|
||||
],
|
||||
"description": "project type",
|
||||
"id": "type",
|
||||
"title": "Type",
|
||||
"type": "ACTION"
|
||||
},
|
||||
"version": {
|
||||
"content": "0.0.1-SNAPSHOT",
|
||||
"description": "project version",
|
||||
"id": "version",
|
||||
"title": "Version",
|
||||
"type": "TEXT"
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user