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 <[email protected]> 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; - } - }
