Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
io.hawt.jsonschema.maven.plugin.CamelModelGeneratorMojo Maven / Gradle / Ivy
package io.hawt.jsonschema.maven.plugin;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.TreeMap;
import io.hawt.jsonschema.maven.plugin.util.CollectionStringBuffer;
import io.hawt.jsonschema.maven.plugin.util.JSonSchemaHelper;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import static io.hawt.jsonschema.maven.plugin.util.FileHelper.loadText;
import static io.hawt.jsonschema.maven.plugin.util.JSonSchemaHelper.doubleQuote;
import static io.hawt.jsonschema.maven.plugin.util.JSonSchemaHelper.getValue;
import static io.hawt.jsonschema.maven.plugin.util.JSonSchemaHelper.parseJsonSchema;
/**
* To generate camelModel.js from the Apache Camel release
*/
@Mojo(name = "generate-camel-model", defaultPhase = LifecyclePhase.GENERATE_SOURCES)
public class CamelModelGeneratorMojo extends AbstractMojo {
@Parameter(property = "project", required = true)
protected MavenProject project;
@Parameter(defaultValue = "${project.build.directory}")
protected File buildDir;
@Parameter(defaultValue = "${schema-outdir}/camelModel.js")
protected File schemaFile;
/**
* Known icons for the models
*/
private final Properties icons = new Properties();
/**
* Execute goal.
*/
public void execute() throws MojoExecutionException, MojoFailureException {
getLog().info("Assembling Camel model schema");
Artifact camelCatalog = findCamelCatalogArtifact(project);
if (camelCatalog == null) {
getLog().warn("Cannot find Apache Camel on the classpath");
return;
}
getLog().info("Using Apache Camel " + camelCatalog.getVersion());
initIcons();
// we want expression to be first
Map eips = new TreeMap();
Map rests = new TreeMap();
Map dataformats = new TreeMap();
Map languages = new TreeMap();
// find the model json files and split into groups
try {
File core = camelCatalog.getFile();
if (core != null) {
URL url = new URL("file", null, core.getAbsolutePath());
URLClassLoader loader = new URLClassLoader(new URL[]{url});
InputStream is = loader.getResourceAsStream("org/apache/camel/catalog/models.properties");
String lines = loadText(is);
for (String name : lines.split("\n")) {
is = loader.getResourceAsStream("org/apache/camel/catalog/models/" + name + ".json");
String text = loadText(is);
if (text != null) {
// use the model files to split into the groups we use in camelModel.js
List> model = parseJsonSchema("model", text, false);
if (hasLabel(model, "rest")) {
rests.put(name, text);
} else if (hasLabel(model, "dataformat")) {
dataformats.put(name, text);
} else if (hasLabel(model, "language")) {
languages.put(name, text);
} else {
eips.put(name, text);
}
}
}
}
} catch (Exception e) {
throw new MojoFailureException("Error loading models from camel-catalog due " + e.getMessage(), e);
}
if (eips.isEmpty()) {
getLog().info("Cannot update " + schemaFile + " as no Camel models found in the Apache Camel version");
return;
}
try {
FileOutputStream fos = new FileOutputStream(schemaFile, false);
String version = "var _apacheCamelModelVersion = '" + camelCatalog.getVersion() + "';\n\n";
fos.write(version.getBytes());
fos.write("var _apacheCamelModel =".getBytes());
fos.write("{\n".getBytes());
fos.write(" \"definitions\": {\n".getBytes());
// generate expression first as its special and needed for eips
generateExpression(languages.keySet(), fos);
// then followed by the regular eips
Iterator it = eips.keySet().iterator();
generateSchema("eips", "model", eips, fos, it);
fos.write(" },\n".getBytes());
fos.write(" \"rests\": {\n".getBytes());
it = rests.keySet().iterator();
generateSchema("rests", "model", rests, fos, it);
fos.write(" },\n".getBytes());
fos.write(" \"dataformats\": {\n".getBytes());
it = dataformats.keySet().iterator();
generateSchema("dataformats", "model", dataformats, fos, it);
fos.write(" },\n".getBytes());
fos.write(" \"languages\": {\n".getBytes());
it = languages.keySet().iterator();
generateSchema("languages", "model", languages, fos, it);
fos.write(" }\n".getBytes());
fos.write("}\n".getBytes());
fos.close();
} catch (Exception e) {
throw new MojoFailureException("Error writing to file " + schemaFile);
}
getLog().info("Assembled Camel models into combined schema: " + schemaFile);
}
private void initIcons() throws MojoExecutionException {
try {
icons.load(CamelModelGeneratorMojo.class.getClassLoader().getResourceAsStream("icons.properties"));
} catch (IOException e) {
throw new MojoExecutionException("Cannot load list of icons", e);
}
}
private void generateExpression(Set languages, FileOutputStream fos) throws IOException {
StringBuilder sb = new StringBuilder();
// enums as a string
CollectionStringBuffer enums = new CollectionStringBuffer(", ");
for (String name : languages) {
// skip abstract expression as a enum choice
if (!"expression".equals(name)) {
enums.append(doubleQuote(name));
}
}
String enumValues = enums.toString();
CollectionStringBuffer cst = new CollectionStringBuffer(",\n");
sb.append(" ").append(doubleQuote("expression")).append(": {\n");
cst.append(" \"type\": \"object\"");
cst.append(" \"title\": " + doubleQuote("expression"));
cst.append(" \"group\": " + doubleQuote("language"));
cst.append(" \"icon\": " + doubleQuote("generic24.png"));
cst.append(" \"description\": " + doubleQuote("Expression in the choose language"));
sb.append(cst.toString()).append(",\n");
cst = new CollectionStringBuffer(",\n");
sb.append(" \"properties\": {\n");
sb.append(" ").append(doubleQuote("expression")).append(": {\n");
cst.append(" \"kind\": " + doubleQuote("element"));
cst.append(" \"type\": " + doubleQuote("string"));
cst.append(" \"title\": " + doubleQuote("Expression"));
cst.append(" \"description\": " + doubleQuote("The expression"));
cst.append(" \"required\": true\n");
sb.append(cst.toString());
sb.append(" },\n"); // a property
cst = new CollectionStringBuffer(",\n");
sb.append(" ").append(doubleQuote("language")).append(": {\n");
cst.append(" \"kind\": " + doubleQuote("element"));
cst.append(" \"type\": " + doubleQuote("string"));
cst.append(" \"title\": " + doubleQuote("Expression"));
cst.append(" \"description\": " + doubleQuote("The chosen language"));
cst.append(" \"required\": true");
cst.append(" \"enum\": [ " + enumValues + " ]");
sb.append(cst.toString()).append("\n");
sb.append(" }\n"); // a property
sb.append(" }\n"); // properties
sb.append(" },\n"); // expression
fos.write(sb.toString().getBytes());
}
private void generateSchema(String schema, String parent, Map models, FileOutputStream fos, Iterator it) throws IOException {
while (it.hasNext()) {
String name = it.next();
String json = models.get(name);
StringBuilder sb = new StringBuilder();
List> model = parseJsonSchema(parent, json, false);
List> properties = parseJsonSchema("properties", json, true);
String group = getValue("label", model);
String title = getValue("title", model);
String input = getValue("input", model);
String output = getValue("output", model);
String nextSiblingAddedAsChild = "false";
if ("true".equals(input) && "false".equals(output)) {
nextSiblingAddedAsChild = "true";
}
String description = getValue("description", model);
String icon = findIcon(name);
// skip non categroized
if (group == null) {
continue;
}
CollectionStringBuffer cst = new CollectionStringBuffer(",\n");
sb.append(" ").append(doubleQuote(name)).append(": {\n");
cst.append(" \"type\": \"object\"");
cst.append(" \"title\": " + doubleQuote(title));
cst.append(" \"group\": " + doubleQuote(group));
cst.append(" \"icon\": " + doubleQuote(icon));
cst.append(" \"description\": " + doubleQuote(safeDescription(description)));
// eips and rests allow to be defined as a graph with inputs and outputs
if ("eips".equals(schema) || "rests".equals(schema)) {
cst.append(" \"acceptInput\": " + doubleQuote(input));
cst.append(" \"acceptOutput\": " + doubleQuote(output));
cst.append(" \"nextSiblingAddedAsChild\": " + doubleQuote(nextSiblingAddedAsChild));
}
sb.append(cst.toString()).append(",\n");
sb.append(" \"properties\": {\n");
Iterator> it2 = properties.iterator();
while (it2.hasNext()) {
Map option = it2.next();
cst = new CollectionStringBuffer(",\n");
String optionName = option.get("name");
title = asTitle(optionName);
String kind = option.get("kind");
String type = option.get("type");
String required = option.get("required");
String deprecated = option.get("deprecated");
description = option.get("description");
String defaultValue = option.get("defaultValue");
String enumValues = option.get("enum");
// special for aggregate as it has duplicate option names
if ("completionSize".equals(optionName) && "expression".equals(kind)) {
optionName = "completionSizeExpression";
} else if ("completionTimeout".equals(optionName) && "expression".equals(kind)) {
optionName = "completionTimeoutExpression";
}
// skip inputs/outputs
if ("inputs".equals(optionName) || "outputs".equals(optionName)) {
continue;
}
sb.append(" ").append(doubleQuote(optionName)).append(": {\n");
cst.append(" \"kind\": " + doubleQuote(kind));
cst.append(" \"type\": " + doubleQuote(type));
if (defaultValue != null) {
cst.append(" \"defaultValue\": " + doubleQuote(safeDefaultValue(defaultValue)));
}
if (enumValues != null) {
cst.append(" \"enum\": [ " + safeEnumJson(enumValues) + " ]");
}
cst.append(" \"description\": " + doubleQuote(safeDescription(description)));
cst.append(" \"title\": " + doubleQuote(title));
if ("true".equals(required)) {
cst.append(" \"required\": true");
} else {
cst.append(" \"required\": false");
}
if ("true".equals(deprecated)) {
cst.append(" \"deprecated\": true");
} else {
cst.append(" \"deprecated\": false");
}
sb.append(cst.toString());
sb.append("\n");
if (it2.hasNext()) {
sb.append(" },\n"); // a property
} else {
sb.append(" }\n"); // a property
}
}
sb.append(" }\n"); // properties
if (it.hasNext()) {
sb.append(" },\n"); // name
} else {
sb.append(" }\n"); // name
}
fos.write(sb.toString().getBytes());
}
}
private String findIcon(String name) {
String answer = icons.getProperty(name);
if (answer == null) {
// use generic icon as fallback
answer = "generic24.png";
}
return answer;
}
private String asTitle(String name) {
// capitalize the name as tooltip
return JSonSchemaHelper.asTitle(name);
}
private String safeEnumJson(String values) {
CollectionStringBuffer cst = new CollectionStringBuffer();
cst.setSeparator(", ");
for (String v : values.split(",")) {
cst.append(doubleQuote(v));
}
return cst.toString();
}
/**
* The default value may need to be escaped to be safe for json
*/
private static String safeDefaultValue(String value) {
if ("\"".equals(value)) {
return "\\\"";
} else if ("\\".equals(value)) {
return "\\\\";
} else {
return value;
}
}
private static String safeDescription(String description) {
if (description == null) {
return "";
}
// need to escape " as \"
description = description.replaceAll("\"", "\\\\\"");
return description;
}
private static Artifact findCamelCatalogArtifact(MavenProject project) {
Iterator it = project.getDependencyArtifacts().iterator();
while (it.hasNext()) {
Artifact artifact = (Artifact) it.next();
if (artifact.getGroupId().equals("org.apache.camel") && artifact.getArtifactId().equals("camel-catalog")) {
return artifact;
}
}
return null;
}
private static boolean hasLabel(List> model, String label) {
for (Map row : model) {
String entry = row.get("label");
if (entry != null) {
return entry.contains(label);
}
}
return false;
}
}