Skip to content

Commit c6adf19

Browse files
committed
Initial version
0 parents  commit c6adf19

15 files changed

+883
-0
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.idea
2+
target
3+
*.iml

LICENSE

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
Copyright 2018 Attila Majoros
2+
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
7+
http://www.apache.org/licenses/LICENSE-2.0
8+
9+
Unless required by applicable law or agreed to in writing, software
10+
distributed under the License is distributed on an "AS IS" BASIS,
11+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
See the License for the specific language governing permissions and
13+
limitations under the License.

README.md

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
[![License](https://img.shields.io/:license-Apache2-blue.svg)](http://www.apache.org/licenses/LICENSE-2.0)
2+
3+
# Thorntail (*formely wildfly-swarm*) configuration schema generator
4+
5+
This utility can be used to generate a **JSON Schema** which can be used to validate
6+
**[Thorntail](https://thorntail.io)** (*[wildfly-swarm](http://wildfly-swarm.io)*) `YAML` configuration files (eg.: `project-defaults.yml`).
7+
8+
The currently generated schema files can be downloaded from [the releases page](https://github.com/codelens-io/thorntail-json-schema-generator/releases)
9+
10+
* thorntail-schema-2.0.0.json
11+
* thorntail-schema-2.0.0-compact.json
12+
* thorntail-schema-2.0.0.properties
13+
14+
To generate schema files build the project, and run the jar:
15+
16+
```
17+
$ mvn clean package
18+
$ cd target;
19+
$ java -jar thorntail-json-schema-generator-1.0.0-SNAPSHOT.jar 2.0.0 ~/Developer/thorntail
20+
21+
Thorntail schema generator
22+
============================================================
23+
version: 2.0.0
24+
output directory: /Users/user/Developer/thorntail/
25+
building schema model...
26+
writing schema files...
27+
... done
28+
```
29+
30+
The jar file requires at least one parameter, which is the **version**, the second parameter is the
31+
**output directory**. If omitted, the current directory will be used.
32+
33+
The result `thorntail-schema-<version>-compact.json` can be used in **[IntelliJ IDEA](https://www.jetbrains.com/idea)** to
34+
validate the configuration file, ot the validation can be done with other command line tools,
35+
like: [pajv](https://www.npmjs.com/package/pajv)
36+
37+
```
38+
pajv -s path/to/thorntail-schema-2.0.0.json -d path/to/project-defaults.yml
39+
```
40+
41+
The utility also builds a `properties` file with the available parameters (*with type and documentation*).

pom.xml

+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
6+
<groupId>io.codelens.tool</groupId>
7+
<artifactId>thorntail-json-schema-generator</artifactId>
8+
<version>1.0.0</version>
9+
<packaging>jar</packaging>
10+
11+
<name>Thorntail configuration schema generator</name>
12+
<description>Utility that can be used to generate a JSON Schema which can be used to validate Thorntail YAML configuration files</description>
13+
14+
<scm>
15+
<url>https://github.com/codelens-io/thorntail-json-schema-generator</url>
16+
<connection>[email protected]:codelens-io/thorntail-json-schema-generator.git</connection>
17+
<tag>HEAD</tag>
18+
</scm>
19+
20+
<properties>
21+
<wildfly.swarm.version>2018.5.0</wildfly.swarm.version>
22+
23+
<maven.compiler.source>1.8</maven.compiler.source>
24+
<maven.compiler.target>1.8</maven.compiler.target>
25+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
26+
</properties>
27+
28+
<build>
29+
<plugins>
30+
<plugin>
31+
<groupId>org.apache.maven.plugins</groupId>
32+
<artifactId>maven-dependency-plugin</artifactId>
33+
<version>3.0.2</version>
34+
<executions>
35+
<execution>
36+
<id>copy-deps</id>
37+
<phase>package</phase>
38+
<goals>
39+
<goal>copy-dependencies</goal>
40+
</goals>
41+
<configuration>
42+
<outputDirectory>${project.build.directory}/lib</outputDirectory>
43+
</configuration>
44+
</execution>
45+
</executions>
46+
</plugin>
47+
<plugin>
48+
<groupId>org.apache.maven.plugins</groupId>
49+
<artifactId>maven-jar-plugin</artifactId>
50+
<version>3.0.2</version>
51+
<configuration>
52+
<archive>
53+
<manifest>
54+
<mainClass>io.codelens.tools.thorntail.SchemaGenerator</mainClass>
55+
<addClasspath>true</addClasspath>
56+
<classpathPrefix>lib/</classpathPrefix>
57+
</manifest>
58+
</archive>
59+
</configuration>
60+
</plugin>
61+
<plugin>
62+
<groupId>org.apache.maven.plugins</groupId>
63+
<artifactId>maven-source-plugin</artifactId>
64+
<version>3.0.1</version>
65+
<executions>
66+
<execution>
67+
<id>attach-sources</id>
68+
<goals>
69+
<goal>jar</goal>
70+
</goals>
71+
</execution>
72+
</executions>
73+
</plugin>
74+
</plugins>
75+
</build>
76+
77+
<dependencyManagement>
78+
<dependencies>
79+
<dependency>
80+
<groupId>org.wildfly.swarm</groupId>
81+
<artifactId>bom-all</artifactId>
82+
<version>${wildfly.swarm.version}</version>
83+
<scope>import</scope>
84+
<type>pom</type>
85+
</dependency>
86+
</dependencies>
87+
</dependencyManagement>
88+
89+
<dependencies>
90+
<dependency>
91+
<groupId>org.reflections</groupId>
92+
<artifactId>reflections</artifactId>
93+
<version>0.9.11</version>
94+
</dependency>
95+
96+
<dependency>
97+
<groupId>org.wildfly.swarm</groupId>
98+
<artifactId>full</artifactId>
99+
</dependency>
100+
</dependencies>
101+
102+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package io.codelens.tools.thorntail;
2+
3+
public interface ModelBuilder {
4+
5+
void build(SchemaModel model);
6+
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
package io.codelens.tools.thorntail;
2+
3+
import javax.json.Json;
4+
import javax.json.JsonObjectBuilder;
5+
import javax.json.JsonValue;
6+
import java.util.ArrayList;
7+
import java.util.List;
8+
import java.util.Map;
9+
import java.util.Optional;
10+
11+
public class Node {
12+
13+
public static final String KEY = "KEY";
14+
15+
static final String SCHEMA = "$schema";
16+
static final String ID = "id";
17+
static final String TITLE = "title";
18+
static final String TYPE = "type";
19+
static final String DOT = ".";
20+
static final String DESCR = "description";
21+
static final String PROPERTIES = "properties";
22+
static final String ADDITIONAL_PROPERTIES = "additionalProperties";
23+
24+
private List<String> keySuggestions = new ArrayList<>();
25+
private List<Node> children = new ArrayList<>();
26+
private Node parent;
27+
private String name;
28+
private String description;
29+
private NodeType javaType;
30+
31+
public boolean isLeaf() {
32+
return children.isEmpty();
33+
}
34+
35+
public boolean isKey() {
36+
return KEY.equals(name);
37+
}
38+
39+
public List<Node> getChildren() {
40+
return children;
41+
}
42+
43+
public Node getParent() {
44+
return parent;
45+
}
46+
47+
public String getName() {
48+
return name;
49+
}
50+
51+
public NodeType getJavaType() {
52+
return javaType;
53+
}
54+
55+
protected void setJavaType(NodeType type) {
56+
this.javaType = type;
57+
}
58+
59+
public String getDescription() {
60+
return description;
61+
}
62+
63+
protected void setDescription(String description) {
64+
this.description = description;
65+
}
66+
67+
public String getPath() {
68+
return parent != null ? parent.getPath() + DOT + name : name;
69+
}
70+
71+
public void addKeySuggestion(String suggestion) {
72+
keySuggestions.add(suggestion);
73+
}
74+
75+
protected void appendChild(Node node) {
76+
node.parent = this;
77+
children.add(node);
78+
}
79+
80+
protected boolean isChildKey() {
81+
return !children.isEmpty() && children.size() == 1 && children.get(0).isKey();
82+
}
83+
84+
protected List<Node> getKeyChildren() {
85+
return children.get(0).children;
86+
}
87+
88+
protected Optional<Node> getChildByName(String name) {
89+
return children.stream().filter(node -> node.getName().equals(name)).findFirst();
90+
}
91+
92+
protected JsonObjectBuilder toJsonObjectBuilder(boolean writeDescription) {
93+
JsonObjectBuilder nodeDescriptorObjectBuilder = Json.createObjectBuilder();
94+
nodeDescriptorObjectBuilder.add(TYPE, javaType.getJsonString());
95+
if (writeDescription && description != null && !description.trim().isEmpty()) {
96+
nodeDescriptorObjectBuilder.add(DESCR, description);
97+
}
98+
99+
if (!isLeaf()) {
100+
if (isChildKey()) {
101+
processChildKeys(nodeDescriptorObjectBuilder, writeDescription);
102+
} else {
103+
processSingles(nodeDescriptorObjectBuilder, writeDescription);
104+
}
105+
}
106+
return Json.createObjectBuilder().add(name, nodeDescriptorObjectBuilder);
107+
}
108+
109+
private void processSingles(JsonObjectBuilder nodeDescriptorObjectBuilder, boolean writeDescription) {
110+
JsonObjectBuilder properties = Json.createObjectBuilder();
111+
for (Node child : children) {
112+
addAll(properties, child.toJsonObjectBuilder(writeDescription).build());
113+
}
114+
nodeDescriptorObjectBuilder.add(PROPERTIES, properties);
115+
nodeDescriptorObjectBuilder.add(ADDITIONAL_PROPERTIES, Boolean.FALSE);
116+
}
117+
118+
private void processChildKeys(JsonObjectBuilder nodeDescriptorObjectBuilder, boolean writeDescription) {
119+
JsonObjectBuilder properties = Json.createObjectBuilder();
120+
for (Node child : getKeyChildren()) {
121+
addAll(properties, child.toJsonObjectBuilder(writeDescription).build());
122+
}
123+
List<String> childKeySuggestions = children.get(0).keySuggestions;
124+
if (!childKeySuggestions.isEmpty()) {
125+
JsonObjectBuilder suggestedProperties = Json.createObjectBuilder();
126+
for (String suggestion : childKeySuggestions) {
127+
Node suggestionNode = Node.createSuggestionNode(suggestion);
128+
suggestionNode.children = getKeyChildren();
129+
addAll(suggestedProperties, suggestionNode.toJsonObjectBuilder(writeDescription).build());
130+
}
131+
nodeDescriptorObjectBuilder.add(PROPERTIES, suggestedProperties);
132+
}
133+
JsonObjectBuilder additionalProperties = Json.createObjectBuilder().
134+
add(TYPE, NodeType.OBJECT.getJsonString()).
135+
add(PROPERTIES, properties).
136+
add(ADDITIONAL_PROPERTIES, Boolean.FALSE);
137+
nodeDescriptorObjectBuilder.add(ADDITIONAL_PROPERTIES, additionalProperties);
138+
}
139+
140+
private static void addAll(JsonObjectBuilder objectBuilder, Map<String, JsonValue> items) {
141+
items.forEach(objectBuilder::add);
142+
}
143+
144+
protected static Node createNode(String name, String description, NodeType type) {
145+
Node node = new Node();
146+
node.name = name;
147+
node.description = description;
148+
node.javaType = type;
149+
return node;
150+
}
151+
152+
private static Node createSuggestionNode(String name) {
153+
Node node = new Node();
154+
node.name = name;
155+
node.javaType = NodeType.OBJECT;
156+
return node;
157+
}
158+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package io.codelens.tools.thorntail;
2+
3+
public enum NodeType {
4+
NUMBER("number"),
5+
BOOLEAN("boolean"),
6+
STRING("string"),
7+
OBJECT("object"),
8+
9+
/**
10+
* leaf with enabled additional properties
11+
*/
12+
LIST("object");
13+
14+
private String jsonString;
15+
16+
NodeType(String jsonString) {
17+
this.jsonString = jsonString;
18+
}
19+
20+
public String getJsonString() {
21+
return jsonString;
22+
}
23+
}

0 commit comments

Comments
 (0)