You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by gn...@apache.org on 2020/01/27 15:47:27 UTC
[camel] 06/10: [CAMEL-14437] Move a few helper methods from
JSonSchemaHelper to AnnotationProcessorHelper
This is an automated email from the ASF dual-hosted git repository.
gnodet pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git
commit 6f7f520eb53e7c4ce71fb3f0b0207316b15adb4e
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Sat Jan 25 01:41:07 2020 +0100
[CAMEL-14437] Move a few helper methods from JSonSchemaHelper to AnnotationProcessorHelper
# Conflicts:
# tooling/apt/src/test/java/org/apache/camel/tools/apt/EndpointOptionComparatorTest.java
---
tooling/apt/pom.xml | 17 +-
.../camel/tools/apt/AnnotationProcessorHelper.java | 166 +++++++++
.../apt/CoreEipAnnotationProcessorHelper.java | 7 +-
.../tools/apt/EndpointAnnotationProcessor.java | 11 +-
.../tools/apt/SpringAnnotationProcessorHelper.java | 7 +-
.../tools/apt/AnnotationProcessorHelperTest.java} | 19 +-
.../tools/apt/EndpointOptionComparatorTest.java | 11 +-
.../camel/tooling/util/JSonSchemaHelper.java | 399 ---------------------
8 files changed, 207 insertions(+), 430 deletions(-)
diff --git a/tooling/apt/pom.xml b/tooling/apt/pom.xml
index 7a1d1cc..c89dbf8 100644
--- a/tooling/apt/pom.xml
+++ b/tooling/apt/pom.xml
@@ -86,8 +86,21 @@
<!-- testing -->
<dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter-api</artifactId>
+ <version>${junit-jupiter-version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter-engine</artifactId>
+ <version>${junit-jupiter-version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter-params</artifactId>
+ <version>${junit-jupiter-version}</version>
<scope>test</scope>
</dependency>
diff --git a/tooling/apt/src/main/java/org/apache/camel/tools/apt/AnnotationProcessorHelper.java b/tooling/apt/src/main/java/org/apache/camel/tools/apt/AnnotationProcessorHelper.java
index a938f08..4cfecfe 100644
--- a/tooling/apt/src/main/java/org/apache/camel/tools/apt/AnnotationProcessorHelper.java
+++ b/tooling/apt/src/main/java/org/apache/camel/tools/apt/AnnotationProcessorHelper.java
@@ -17,14 +17,18 @@
package org.apache.camel.tools.apt;
import java.io.BufferedWriter;
+import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
+import java.net.URI;
+import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.Collections;
+import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
@@ -45,6 +49,8 @@ import javax.tools.Diagnostic;
import javax.tools.FileObject;
import javax.tools.StandardLocation;
+import org.apache.camel.tooling.util.Strings;
+
import static org.apache.camel.tooling.util.Strings.canonicalClassName;
import static org.apache.camel.tooling.util.Strings.isNullOrEmpty;
@@ -53,6 +59,8 @@ import static org.apache.camel.tooling.util.Strings.isNullOrEmpty;
*/
public final class AnnotationProcessorHelper {
+ private static final String VALID_CHARS = ".,-='/\\!&%():;#${}";
+
private AnnotationProcessorHelper() {
}
@@ -360,4 +368,162 @@ public final class AnnotationProcessorHelper {
// ignore
}
}
+
+ /**
+ * Gets the JSon schema type.
+ *
+ * @param type the java type
+ * @return the json schema type, is never null, but returns <tt>object</tt> as the generic type
+ */
+ public static String getType(String type, boolean enumType) {
+ if (enumType) {
+ return "enum";
+ } else if (type == null) {
+ // return generic type for unknown type
+ return "object";
+ } else if (type.equals(URI.class.getName()) || type.equals(URL.class.getName())) {
+ return "string";
+ } else if (type.equals(File.class.getName())) {
+ return "string";
+ } else if (type.equals(Date.class.getName())) {
+ return "string";
+ } else if (type.startsWith("java.lang.Class")) {
+ return "string";
+ } else if (type.startsWith("java.util.List") || type.startsWith("java.util.Collection")) {
+ return "array";
+ }
+
+ String primitive = getPrimitiveType(type);
+ if (primitive != null) {
+ return primitive;
+ }
+
+ return "object";
+ }
+
+ /**
+ * Gets the JSon schema primitive type.
+ *
+ * @param name the java type
+ * @return the json schema primitive type, or <tt>null</tt> if not a primitive
+ */
+ public static String getPrimitiveType(String name) {
+ // special for byte[] or Object[] as its common to use
+ if ("java.lang.byte[]".equals(name) || "byte[]".equals(name)) {
+ return "string";
+ } else if ("java.lang.Byte[]".equals(name) || "Byte[]".equals(name)) {
+ return "array";
+ } else if ("java.lang.Object[]".equals(name) || "Object[]".equals(name)) {
+ return "array";
+ } else if ("java.lang.String[]".equals(name) || "String[]".equals(name)) {
+ return "array";
+ } else if ("java.lang.Character".equals(name) || "Character".equals(name) || "char".equals(name)) {
+ return "string";
+ } else if ("java.lang.String".equals(name) || "String".equals(name)) {
+ return "string";
+ } else if ("java.lang.Boolean".equals(name) || "Boolean".equals(name) || "boolean".equals(name)) {
+ return "boolean";
+ } else if ("java.lang.Integer".equals(name) || "Integer".equals(name) || "int".equals(name)) {
+ return "integer";
+ } else if ("java.lang.Long".equals(name) || "Long".equals(name) || "long".equals(name)) {
+ return "integer";
+ } else if ("java.lang.Short".equals(name) || "Short".equals(name) || "short".equals(name)) {
+ return "integer";
+ } else if ("java.lang.Byte".equals(name) || "Byte".equals(name) || "byte".equals(name)) {
+ return "integer";
+ } else if ("java.lang.Float".equals(name) || "Float".equals(name) || "float".equals(name)) {
+ return "number";
+ } else if ("java.lang.Double".equals(name) || "Double".equals(name) || "double".equals(name)) {
+ return "number";
+ }
+
+ return null;
+ }
+
+ /**
+ * Sanitizes the javadoc to removed invalid characters so it can be used as json description
+ *
+ * @param javadoc the javadoc
+ * @return the text that is valid as json
+ */
+ public static String sanitizeDescription(String javadoc, boolean summary) {
+ if (isNullOrEmpty(javadoc)) {
+ return null;
+ }
+
+ // lets just use what java accepts as identifiers
+ StringBuilder sb = new StringBuilder();
+
+ // split into lines
+ String[] lines = javadoc.split("\n");
+
+ boolean first = true;
+ for (String line : lines) {
+ line = line.trim();
+
+ if (line.startsWith("**")) {
+ continue;
+ }
+ // remove leading javadoc *
+ if (line.startsWith("*")) {
+ line = line.substring(1);
+ line = line.trim();
+ }
+
+ // terminate if we reach @param, @return or @deprecated as we only want the javadoc summary
+ if (line.startsWith("@param") || line.startsWith("@return") || line.startsWith("@deprecated")) {
+ break;
+ }
+
+ // skip lines that are javadoc references
+ if (line.startsWith("@")) {
+ continue;
+ }
+
+ // remove all XML tags
+ line = line.replaceAll("<.*?>", "");
+
+ // remove all inlined javadoc links, eg such as {@link org.apache.camel.spi.Registry}
+ // use #? to remove leading # in case its a local reference
+ line = line.replaceAll("\\{\\@\\w+\\s#?([\\w.#(\\d,)]+)\\}", "$1");
+
+ // we are starting from a new line, so add a whitespace
+ if (!first) {
+ sb.append(' ');
+ }
+
+ // create a new line
+ StringBuilder cb = new StringBuilder();
+ for (char c : line.toCharArray()) {
+ if (Character.isJavaIdentifierPart(c) || VALID_CHARS.indexOf(c) != -1) {
+ cb.append(c);
+ } else if (Character.isWhitespace(c)) {
+ // always use space as whitespace, also for line feeds etc
+ cb.append(' ');
+ }
+ }
+
+ // append data
+ String s = cb.toString().trim();
+ sb.append(s);
+
+ boolean empty = isNullOrEmpty(s);
+ boolean endWithDot = s.endsWith(".");
+ boolean haveText = sb.length() > 0;
+
+ if (haveText && summary && (empty || endWithDot)) {
+ // if we only want a summary, then skip at first empty line we encounter, or if the sentence ends with a dot
+ break;
+ }
+
+ first = false;
+ }
+
+ String s = sb.toString();
+ // remove double whitespaces, and trim
+ s = s.replaceAll("\\s+", " ");
+ // unescape http links
+ s = s.replaceAll("\\\\(http:|https:)", "$1");
+ return s.trim();
+ }
}
diff --git a/tooling/apt/src/main/java/org/apache/camel/tools/apt/CoreEipAnnotationProcessorHelper.java b/tooling/apt/src/main/java/org/apache/camel/tools/apt/CoreEipAnnotationProcessorHelper.java
index 1e8d8f9..08c52ab 100644
--- a/tooling/apt/src/main/java/org/apache/camel/tools/apt/CoreEipAnnotationProcessorHelper.java
+++ b/tooling/apt/src/main/java/org/apache/camel/tools/apt/CoreEipAnnotationProcessorHelper.java
@@ -46,7 +46,6 @@ import javax.xml.bind.annotation.XmlValue;
import org.apache.camel.spi.AsPredicate;
import org.apache.camel.spi.Metadata;
-import org.apache.camel.tooling.util.JSonSchemaHelper;
import org.apache.camel.tooling.util.PackageHelper;
import org.apache.camel.tooling.util.Strings;
import org.apache.camel.tooling.model.EipModel;
@@ -233,7 +232,7 @@ public class CoreEipAnnotationProcessorHelper {
if (doc != null) {
// need to sanitize the description first (we only want a
// summary)
- doc = JSonSchemaHelper.sanitizeDescription(doc, true);
+ doc = AnnotationProcessorHelper.sanitizeDescription(doc, true);
// the javadoc may actually be empty, so only change the doc
// if we got something
if (!Strings.isNullOrEmpty(doc)) {
@@ -1045,10 +1044,10 @@ public class CoreEipAnnotationProcessorHelper {
option.setRequired(required);
option.setDefaultValue("java.lang.Boolean".equals(type) && !Strings.isNullOrEmpty(defaultValue )
? Boolean.parseBoolean(defaultValue) : defaultValue);
- option.setDescription(JSonSchemaHelper.sanitizeDescription(description, false));
+ option.setDescription(AnnotationProcessorHelper.sanitizeDescription(description, false));
option.setDeprecated(deprecated);
option.setDeprecationNote(Strings.isNullOrEmpty(deprecationNote) ? null : deprecationNote);
- option.setType(JSonSchemaHelper.getType(type, enumType));
+ option.setType(AnnotationProcessorHelper.getType(type, enumType));
option.setJavaType(type);
option.setEnums(enums != null && !enums.isEmpty() ? new ArrayList<>(enums) : null);
option.setOneOfs(oneOfs != null && !oneOfs.isEmpty() ? new ArrayList<>(oneOfs) : null);
diff --git a/tooling/apt/src/main/java/org/apache/camel/tools/apt/EndpointAnnotationProcessor.java b/tooling/apt/src/main/java/org/apache/camel/tools/apt/EndpointAnnotationProcessor.java
index 137aee0..71c5810 100644
--- a/tooling/apt/src/main/java/org/apache/camel/tools/apt/EndpointAnnotationProcessor.java
+++ b/tooling/apt/src/main/java/org/apache/camel/tools/apt/EndpointAnnotationProcessor.java
@@ -59,7 +59,6 @@ import org.apache.camel.tooling.model.BaseOptionModel;
import org.apache.camel.tooling.model.ComponentModel;
import org.apache.camel.tooling.model.ComponentModel.ComponentOptionModel;
import org.apache.camel.tooling.model.ComponentModel.EndpointOptionModel;
-import org.apache.camel.tooling.util.JSonSchemaHelper;
import org.apache.camel.tooling.util.PackageHelper;
import org.apache.camel.tooling.util.Strings;
import org.apache.camel.tools.apt.helper.EndpointHelper;
@@ -218,7 +217,7 @@ public class EndpointAnnotationProcessor extends AbstractCamelAnnotationProcesso
.findFirst().orElse(null);
}
// as its json we need to sanitize the docs
- doc = JSonSchemaHelper.sanitizeDescription(doc, false);
+ doc = AnnotationProcessorHelper.sanitizeDescription(doc, false);
option.setDescription(doc);
if (isNullOrEmpty(doc)) {
@@ -380,7 +379,7 @@ public class EndpointAnnotationProcessor extends AbstractCamelAnnotationProcesso
String doc = elementUtils.getDocComment(typeElement);
if (doc != null) {
// need to sanitize the description first (we only want a summary)
- doc = JSonSchemaHelper.sanitizeDescription(doc, true);
+ doc = AnnotationProcessorHelper.sanitizeDescription(doc, true);
// the javadoc may actually be empty, so only change the doc if we got something
if (!Strings.isNullOrEmpty(doc)) {
model.setDescription(doc);
@@ -522,7 +521,7 @@ public class EndpointAnnotationProcessor extends AbstractCamelAnnotationProcesso
option.setKind("property");
option.setName(name);
option.setDisplayName(displayName);
- option.setType(JSonSchemaHelper.getType(fieldTypeName, false));
+ option.setType(AnnotationProcessorHelper.getType(fieldTypeName, false));
option.setJavaType(fieldTypeName);
option.setRequired(required);
option.setDefaultValue(defaultValue);
@@ -649,7 +648,7 @@ public class EndpointAnnotationProcessor extends AbstractCamelAnnotationProcesso
option.setKind("path");
option.setName(name);
option.setDisplayName(displayName);
- option.setType(JSonSchemaHelper.getType(fieldTypeName, false));
+ option.setType(AnnotationProcessorHelper.getType(fieldTypeName, false));
option.setJavaType(fieldTypeName);
option.setRequired(required);
option.setDefaultValue(defaultValue);
@@ -763,7 +762,7 @@ public class EndpointAnnotationProcessor extends AbstractCamelAnnotationProcesso
option.setKind("parameter");
option.setName(name);
option.setDisplayName(displayName);
- option.setType(JSonSchemaHelper.getType(fieldTypeName, false));
+ option.setType(AnnotationProcessorHelper.getType(fieldTypeName, false));
option.setJavaType(fieldTypeName);
option.setRequired(required);
option.setDefaultValue(defaultValue);
diff --git a/tooling/apt/src/main/java/org/apache/camel/tools/apt/SpringAnnotationProcessorHelper.java b/tooling/apt/src/main/java/org/apache/camel/tools/apt/SpringAnnotationProcessorHelper.java
index 55ce384..88d2012 100644
--- a/tooling/apt/src/main/java/org/apache/camel/tools/apt/SpringAnnotationProcessorHelper.java
+++ b/tooling/apt/src/main/java/org/apache/camel/tools/apt/SpringAnnotationProcessorHelper.java
@@ -41,7 +41,6 @@ import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import org.apache.camel.spi.Metadata;
-import org.apache.camel.tooling.util.JSonSchemaHelper;
import org.apache.camel.tooling.util.PackageHelper;
import org.apache.camel.tooling.util.Strings;
import org.apache.camel.tooling.model.EipModel;
@@ -128,7 +127,7 @@ public class SpringAnnotationProcessorHelper {
if (doc != null) {
// need to sanitize the description first (we only want a
// summary)
- doc = JSonSchemaHelper.sanitizeDescription(doc, true);
+ doc = AnnotationProcessorHelper.sanitizeDescription(doc, true);
// the javadoc may actually be empty, so only change the doc
// if we got something
if (!Strings.isNullOrEmpty(doc)) {
@@ -470,10 +469,10 @@ public class SpringAnnotationProcessorHelper {
option.setKind(kind);
option.setRequired(required);
option.setDefaultValue(defaultValue);
- option.setDescription(JSonSchemaHelper.sanitizeDescription(description, false));
+ option.setDescription(AnnotationProcessorHelper.sanitizeDescription(description, false));
option.setDeprecated(deprecated);
option.setDeprecationNote(deprecationNote);
- option.setType(JSonSchemaHelper.getType(type, enumType));
+ option.setType(AnnotationProcessorHelper.getType(type, enumType));
option.setJavaType(type);
option.setEnums(enums != null && !enums.isEmpty() ? new ArrayList<>(enums) : null);
option.setOneOfs(oneOfs != null && !oneOfs.isEmpty() ? new ArrayList<>(oneOfs) : null);
diff --git a/tooling/camel-tooling-util/src/test/java/org/apache/camel/tooling/util/JSonSchemaHelperTest.java b/tooling/apt/src/test/java/org/apache/camel/tools/apt/AnnotationProcessorHelperTest.java
similarity index 88%
rename from tooling/camel-tooling-util/src/test/java/org/apache/camel/tooling/util/JSonSchemaHelperTest.java
rename to tooling/apt/src/test/java/org/apache/camel/tools/apt/AnnotationProcessorHelperTest.java
index 8a0421c..64b5889 100644
--- a/tooling/camel-tooling-util/src/test/java/org/apache/camel/tooling/util/JSonSchemaHelperTest.java
+++ b/tooling/apt/src/test/java/org/apache/camel/tools/apt/AnnotationProcessorHelperTest.java
@@ -14,13 +14,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.camel.tooling.util;
+package org.apache.camel.tools.apt;
+import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-public class JSonSchemaHelperTest {
+public class AnnotationProcessorHelperTest {
private static final String JAVADOC = ""
+ " * When in streaming mode, then the splitter splits the original message on-demand, and each splitted\n"
@@ -72,13 +71,13 @@ public class JSonSchemaHelperTest {
@Test
public void testSanitizeJavaDoc() throws Exception {
String s = "* more memory. The total size is provided in the {@link org.apache.camel.Exchange#SPLIT_SIZE} header.";
- String s2 = JSonSchemaHelper.sanitizeDescription(s, false);
- assertEquals("more memory. The total size is provided in the org.apache.camel.Exchange#SPLIT_SIZE header.", s2);
+ String s2 = AnnotationProcessorHelper.sanitizeDescription(s, false);
+ Assertions.assertEquals("more memory. The total size is provided in the org.apache.camel.Exchange#SPLIT_SIZE header.", s2);
- String out = JSonSchemaHelper.sanitizeDescription(JAVADOC, false);
- assertEquals(EXPECTED_OUT, out);
+ String out = AnnotationProcessorHelper.sanitizeDescription(JAVADOC, false);
+ Assertions.assertEquals(EXPECTED_OUT, out);
- String out2 = JSonSchemaHelper.sanitizeDescription(JAVADOC2, false);
- assertEquals(EXPECTED_OUT2, out2);
+ String out2 = AnnotationProcessorHelper.sanitizeDescription(JAVADOC2, false);
+ Assertions.assertEquals(EXPECTED_OUT2, out2);
}
}
diff --git a/tooling/apt/src/test/java/org/apache/camel/tools/apt/EndpointOptionComparatorTest.java b/tooling/apt/src/test/java/org/apache/camel/tools/apt/EndpointOptionComparatorTest.java
index ebb28fe..a8cf305 100644
--- a/tooling/apt/src/test/java/org/apache/camel/tools/apt/EndpointOptionComparatorTest.java
+++ b/tooling/apt/src/test/java/org/apache/camel/tools/apt/EndpointOptionComparatorTest.java
@@ -23,7 +23,8 @@ import org.apache.camel.tooling.model.BaseOptionModel;
import org.apache.camel.tools.apt.helper.EndpointHelper;
import org.junit.Test;
-import static org.junit.Assert.assertEquals;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
public class EndpointOptionComparatorTest {
@@ -56,10 +57,10 @@ public class EndpointOptionComparatorTest {
// then by label into the groups
list.sort(EndpointHelper.createGroupAndLabelComparator());
- assertEquals("first", list.get(0).getName()); // common
- assertEquals("second", list.get(1).getName()); // common
- assertEquals("synchronous", list.get(2).getName()); // advanced
- assertEquals("country", list.get(3).getName()); // filter
+ Assertions.assertEquals("first", list.get(0).getName()); // common
+ Assertions.assertEquals("second", list.get(1).getName()); // common
+ Assertions.assertEquals("synchronous", list.get(2).getName()); // advanced
+ Assertions.assertEquals("country", list.get(3).getName()); // filter
}
public static class EndpointOptionModel extends BaseOptionModel {
diff --git a/tooling/camel-tooling-util/src/main/java/org/apache/camel/tooling/util/JSonSchemaHelper.java b/tooling/camel-tooling-util/src/main/java/org/apache/camel/tooling/util/JSonSchemaHelper.java
index 426a8a0..9d04cc9 100644
--- a/tooling/camel-tooling-util/src/main/java/org/apache/camel/tooling/util/JSonSchemaHelper.java
+++ b/tooling/camel-tooling-util/src/main/java/org/apache/camel/tooling/util/JSonSchemaHelper.java
@@ -24,7 +24,6 @@ import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
-import java.util.Set;
import java.util.stream.Collectors;
import org.apache.camel.util.json.JsonObject;
@@ -35,302 +34,9 @@ import org.apache.camel.util.json.Jsoner;
*/
public final class JSonSchemaHelper {
- private static final String VALID_CHARS = ".,-='/\\!&%():;#${}";
-
private JSonSchemaHelper() {
}
- public static String toJson(String name, String displayName, String kind, Boolean required, String type, String defaultValue, String description,
- Boolean deprecated, String deprecationNote, Boolean secret, String group, String label, boolean enumType, Set<String> enums,
- boolean oneOfType, Set<String> oneOffTypes, boolean asPredicate, String optionalPrefix, String prefix, boolean multiValue,
- String configurationClass, String configurationField) {
- String typeName = JSonSchemaHelper.getType(type, enumType);
-
- StringBuilder sb = new StringBuilder();
- sb.append(Strings.doubleQuote(name));
- sb.append(": { \"kind\": ");
- sb.append(Strings.doubleQuote(kind));
-
- // compute a display name if we don't have anything
- if (Strings.isNullOrEmpty(displayName)) {
- displayName = Strings.asTitle(name);
- }
- // we want display name early so its easier to spot
- sb.append(", \"displayName\": ");
- sb.append(Strings.doubleQuote(displayName));
-
- // we want group early so its easier to spot
- if (!Strings.isNullOrEmpty(group)) {
- sb.append(", \"group\": ");
- sb.append(Strings.doubleQuote(group));
- }
-
- // we want label early so its easier to spot
- if (!Strings.isNullOrEmpty(label)) {
- sb.append(", \"label\": ");
- sb.append(Strings.doubleQuote(label));
- }
-
- if (required != null) {
- // boolean type
- sb.append(", \"required\": ");
- sb.append(required.toString());
- }
-
- sb.append(", \"type\": ");
- if ("enum".equals(typeName)) {
- String actualType = JSonSchemaHelper.getType(type, false);
- sb.append(Strings.doubleQuote(actualType));
- sb.append(", \"javaType\": \"").append(type).append("\"");
- sb.append(", \"enum\": [ ");
- sb.append(enums.stream().map(Strings::doubleQuote).collect(Collectors.joining(", ")));
- sb.append(" ]");
- } else if (oneOfType) {
- sb.append(Strings.doubleQuote(typeName));
- sb.append(", \"javaType\": \"").append(type).append("\"");
- sb.append(", \"oneOf\": [ ");
- sb.append(oneOffTypes.stream().map(Strings::doubleQuote).collect(Collectors.joining(", ")));
- sb.append(" ]");
- } else if ("array".equals(typeName)) {
- sb.append(Strings.doubleQuote("array"));
- sb.append(", \"javaType\": \"").append(type).append("\"");
- } else {
- sb.append(Strings.doubleQuote(typeName));
- sb.append(", \"javaType\": \"").append(type).append("\"");
- }
-
- if (!Strings.isNullOrEmpty(optionalPrefix)) {
- sb.append(", \"optionalPrefix\": ");
- String text = safeDefaultValue(optionalPrefix);
- sb.append(Strings.doubleQuote(text));
- }
-
- if (!Strings.isNullOrEmpty(prefix)) {
- sb.append(", \"prefix\": ");
- String text = safeDefaultValue(prefix);
- sb.append(Strings.doubleQuote(text));
- }
- if (multiValue) {
- // boolean value
- sb.append(", \"multiValue\": true");
- }
-
- if (deprecated != null) {
- sb.append(", \"deprecated\": ");
- // boolean value
- sb.append(deprecated.toString());
- }
- if (!Strings.isNullOrEmpty(deprecationNote)) {
- sb.append(", \"deprecationNote\": ");
- sb.append(Strings.doubleQuote(deprecationNote));
- }
-
- if (secret != null) {
- sb.append(", \"secret\": ");
- // boolean value
- sb.append(secret.toString());
- }
-
- if (!Strings.isNullOrEmpty(defaultValue)) {
- sb.append(", \"defaultValue\": ");
- String text = safeDefaultValue(defaultValue);
- // the type can either be boolean, integer, number or text based
- if ("boolean".equals(typeName) || "integer".equals(typeName) || "number".equals(typeName)) {
- sb.append(text);
- } else {
- // text should be quoted
- sb.append(Strings.doubleQuote(text));
- }
- }
-
- // for expressions we want to know if it must be used as predicate or not
- boolean predicate = "expression".equals(kind) || asPredicate;
- if (predicate) {
- sb.append(", \"asPredicate\": ");
- if (asPredicate) {
- sb.append("true");
- } else {
- sb.append("false");
- }
- }
-
- if (!Strings.isNullOrEmpty(configurationClass)) {
- sb.append(", \"configurationClass\": ");
- sb.append(Strings.doubleQuote(configurationClass));
- }
- if (!Strings.isNullOrEmpty(configurationField)) {
- sb.append(", \"configurationField\": ");
- sb.append(Strings.doubleQuote(configurationField));
- }
-
- if (!Strings.isNullOrEmpty(description)) {
- sb.append(", \"description\": ");
- String text = sanitizeDescription(description, false);
- sb.append(Strings.doubleQuote(text));
- }
-
- sb.append(" }");
- return sb.toString();
- }
-
- /**
- * Gets the JSon schema type.
- *
- * @param type the java type
- * @return the json schema type, is never null, but returns <tt>object</tt> as the generic type
- */
- public static String getType(String type, boolean enumType) {
- if (enumType) {
- return "enum";
- } else if (type == null) {
- // return generic type for unknown type
- return "object";
- } else if (type.equals(URI.class.getName()) || type.equals(URL.class.getName())) {
- return "string";
- } else if (type.equals(File.class.getName())) {
- return "string";
- } else if (type.equals(Date.class.getName())) {
- return "string";
- } else if (type.startsWith("java.lang.Class")) {
- return "string";
- } else if (type.startsWith("java.util.List") || type.startsWith("java.util.Collection")) {
- return "array";
- }
-
- String primitive = getPrimitiveType(type);
- if (primitive != null) {
- return primitive;
- }
-
- return "object";
- }
-
- /**
- * Gets the JSon schema primitive type.
- *
- * @param name the java type
- * @return the json schema primitive type, or <tt>null</tt> if not a primitive
- */
- public static String getPrimitiveType(String name) {
- // special for byte[] or Object[] as its common to use
- if ("java.lang.byte[]".equals(name) || "byte[]".equals(name)) {
- return "string";
- } else if ("java.lang.Byte[]".equals(name) || "Byte[]".equals(name)) {
- return "array";
- } else if ("java.lang.Object[]".equals(name) || "Object[]".equals(name)) {
- return "array";
- } else if ("java.lang.String[]".equals(name) || "String[]".equals(name)) {
- return "array";
- } else if ("java.lang.Character".equals(name) || "Character".equals(name) || "char".equals(name)) {
- return "string";
- } else if ("java.lang.String".equals(name) || "String".equals(name)) {
- return "string";
- } else if ("java.lang.Boolean".equals(name) || "Boolean".equals(name) || "boolean".equals(name)) {
- return "boolean";
- } else if ("java.lang.Integer".equals(name) || "Integer".equals(name) || "int".equals(name)) {
- return "integer";
- } else if ("java.lang.Long".equals(name) || "Long".equals(name) || "long".equals(name)) {
- return "integer";
- } else if ("java.lang.Short".equals(name) || "Short".equals(name) || "short".equals(name)) {
- return "integer";
- } else if ("java.lang.Byte".equals(name) || "Byte".equals(name) || "byte".equals(name)) {
- return "integer";
- } else if ("java.lang.Float".equals(name) || "Float".equals(name) || "float".equals(name)) {
- return "number";
- } else if ("java.lang.Double".equals(name) || "Double".equals(name) || "double".equals(name)) {
- return "number";
- }
-
- return null;
- }
-
- /**
- * Sanitizes the javadoc to removed invalid characters so it can be used as json description
- *
- * @param javadoc the javadoc
- * @return the text that is valid as json
- */
- public static String sanitizeDescription(String javadoc, boolean summary) {
- if (Strings.isNullOrEmpty(javadoc)) {
- return null;
- }
-
- // lets just use what java accepts as identifiers
- StringBuilder sb = new StringBuilder();
-
- // split into lines
- String[] lines = javadoc.split("\n");
-
- boolean first = true;
- for (String line : lines) {
- line = line.trim();
-
- if (line.startsWith("**")) {
- continue;
- }
- // remove leading javadoc *
- if (line.startsWith("*")) {
- line = line.substring(1);
- line = line.trim();
- }
-
- // terminate if we reach @param, @return or @deprecated as we only want the javadoc summary
- if (line.startsWith("@param") || line.startsWith("@return") || line.startsWith("@deprecated")) {
- break;
- }
-
- // skip lines that are javadoc references
- if (line.startsWith("@")) {
- continue;
- }
-
- // remove all XML tags
- line = line.replaceAll("<.*?>", "");
-
- // remove all inlined javadoc links, eg such as {@link org.apache.camel.spi.Registry}
- // use #? to remove leading # in case its a local reference
- line = line.replaceAll("\\{\\@\\w+\\s#?([\\w.#(\\d,)]+)\\}", "$1");
-
- // we are starting from a new line, so add a whitespace
- if (!first) {
- sb.append(' ');
- }
-
- // create a new line
- StringBuilder cb = new StringBuilder();
- for (char c : line.toCharArray()) {
- if (Character.isJavaIdentifierPart(c) || VALID_CHARS.indexOf(c) != -1) {
- cb.append(c);
- } else if (Character.isWhitespace(c)) {
- // always use space as whitespace, also for line feeds etc
- cb.append(' ');
- }
- }
-
- // append data
- String s = cb.toString().trim();
- sb.append(s);
-
- boolean empty = Strings.isNullOrEmpty(s);
- boolean endWithDot = s.endsWith(".");
- boolean haveText = sb.length() > 0;
-
- if (haveText && summary && (empty || endWithDot)) {
- // if we only want a summary, then skip at first empty line we encounter, or if the sentence ends with a dot
- break;
- }
-
- first = false;
- }
-
- String s = sb.toString();
- // remove double whitespaces, and trim
- s = s.replaceAll("\\s+", " ");
- // unescape http links
- s = s.replaceAll("\\\\(http:|https:)", "$1");
- return s.trim();
- }
-
/**
* Parses the json schema to split it into a list or rows, where each row contains key value pairs with the metadata
*
@@ -392,19 +98,6 @@ public final class JSonSchemaHelper {
.replace("\\t", "\\\\t");
}
- /**
- * 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 Map<String, String> transformMap(Map<?, ?> jsonMap) {
Map<String, String> answer = new LinkedHashMap<>();
@@ -426,96 +119,4 @@ public final class JSonSchemaHelper {
return answer;
}
- /**
- * Gets the value with the key in a safe way, eg returning an empty string if there was no value for the key.
- */
- public static String getSafeValue(String key, List<Map<String, String>> rows) {
- for (Map<String, String> row : rows) {
- String value = row.get(key);
- if (value != null) {
- return value;
- }
- }
- return "";
- }
-
- /**
- * Gets the value with the key in a safe way, eg returning an empty string if there was no value for the key.
- */
- public static String getSafeValue(String key, Map<String, String> rows) {
- String value = rows.get(key);
- if (value != null) {
- return value;
- }
- return "";
- }
-
- public static String getPropertyDefaultValue(List<Map<String, String>> rows, String name) {
- for (Map<String, String> row : rows) {
- String defaultValue = null;
- boolean found = false;
- if (row.containsKey("name")) {
- found = name.equals(row.get("name"));
- }
- if (row.containsKey("defaultValue")) {
- defaultValue = row.get("defaultValue");
- }
- if (found) {
- return defaultValue;
- }
- }
- return null;
- }
-
- public static String getPropertyDescriptionValue(List<Map<String, String>> rows, String name) {
- for (Map<String, String> row : rows) {
- String description = null;
- boolean found = false;
- if (row.containsKey("name")) {
- found = name.equals(row.get("name"));
- }
- if (row.containsKey("description")) {
- description = row.get("description");
- }
- if (found) {
- return description;
- }
- }
- return null;
- }
-
- public static String getPropertyJavaType(List<Map<String, String>> rows, String name) {
- for (Map<String, String> row : rows) {
- String javaType = null;
- boolean found = false;
- if (row.containsKey("name")) {
- found = name.equals(row.get("name"));
- }
- if (row.containsKey("javaType")) {
- javaType = row.get("javaType");
- }
- if (found) {
- return javaType;
- }
- }
- return null;
- }
-
- public static String getPropertyType(List<Map<String, String>> rows, String name) {
- for (Map<String, String> row : rows) {
- String type = null;
- boolean found = false;
- if (row.containsKey("name")) {
- found = name.equals(row.get("name"));
- }
- if (row.containsKey("type")) {
- type = row.get("type");
- }
- if (found) {
- return type;
- }
- }
- return null;
- }
-
}