Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Extension parsing method to AnnotationScannerExtension #250

Merged
merged 1 commit into from
Jan 31, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 29 additions & 7 deletions implementation/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,6 @@
<scope>test</scope>
<type>pom</type>
</dependency>

</dependencies>

<build>
Expand All @@ -131,13 +130,36 @@
<SMALLRYE_MP_CONFIG_PROP>1234</SMALLRYE_MP_CONFIG_PROP>
</environmentVariables>
<redirectTestOutputToFile>true</redirectTestOutputToFile>
<!--
TODO: Confirm if these are necessary
<enableAssertions>true</enableAssertions>
<argLine>-Xmx512m</argLine>
<forkMode>once</forkMode>
-->
</configuration>
<executions>
<execution>
<id>default-test</id>
<configuration>
<excludes>
<exclude>**/CustomExtensionParsingTests.java</exclude>
</excludes>
</configuration>
</execution>
<execution>
<id>jackson-exclusion-tests</id>
<goals>
<goal>test</goal>
</goals>
<configuration>
<includes>
<include>**/CustomExtensionParsingTests.java</include>
</includes>
<systemProperties>
<classpath.jackson.excluded>true</classpath.jackson.excluded>
</systemProperties>
<classpathDependencyExcludes>
<classpathDependencyExclude>com.fasterxml.jackson.core:jackson-core</classpathDependencyExclude>
<classpathDependencyExclude>com.fasterxml.jackson.core:jackson-databind</classpathDependencyExclude>
<classpathDependencyExclude>com.fasterxml.jackson.dataformat:jackson-dataformat-yaml</classpathDependencyExclude>
</classpathDependencyExcludes>
</configuration>
</execution>
</executions>
MikeEdgar marked this conversation as resolved.
Show resolved Hide resolved
</plugin>
</plugins>
</build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,16 @@
package io.smallrye.openapi.runtime.io;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
Expand All @@ -30,6 +38,7 @@
*/
public final class JsonUtil {

private static final ObjectMapper MAPPER = new ObjectMapper();
private static final JsonNodeFactory factory = JsonNodeFactory.instance;

public static ObjectNode objectNode() {
Expand Down Expand Up @@ -193,4 +202,111 @@ public static void bigDecimalProperty(ObjectNode node, String propertyName, BigD
private static boolean isIntegerValue(BigDecimal bd) {
return bd.signum() == 0 || bd.scale() <= 0 || bd.stripTrailingZeros().scale() <= 0;
}

/**
* Reads the node as a Java object. This is typically expected to be a literal of
* some sort, as in the case of default values and examples. The node may be anything
* from a string to a javascript object.
*
* @param node
*/
public static Object readObject(JsonNode node) {
if (node == null) {
return null;
}
if (node.isBigDecimal()) {
return new BigDecimal(node.asText());
}
if (node.isBigInteger()) {
return new BigInteger(node.asText());
}
if (node.isBoolean()) {
return node.asBoolean();
}
if (node.isDouble()) {
return node.asDouble();
}
if (node.isFloat()) {
return node.asDouble();
}
if (node.isInt()) {
return node.asInt();
}
if (node.isLong()) {
return node.asLong();
}
if (node.isTextual()) {
return node.asText();
}
if (node.isArray()) {
ArrayNode arrayNode = (ArrayNode) node;
List<Object> items = new ArrayList<>();
for (JsonNode itemNode : arrayNode) {
items.add(readObject(itemNode));
}
return items;
}
if (node.isObject()) {
Map<String, Object> items = new LinkedHashMap<>();
for (Iterator<Entry<String, JsonNode>> fields = node.fields(); fields.hasNext();) {
Entry<String, JsonNode> field = fields.next();
String fieldName = field.getKey();
Object fieldValue = readObject(field.getValue());
items.put(fieldName, fieldValue);
}
return items;
}
return null;
}

/**
* Parses an extension value. The value may be:
*
* - JSON object - starts with {
* - JSON array - starts with [
* - number
* - boolean
* - string
*
* @param value
*/
public static Object parseValue(String value) {
if (value == null) {
return null;
}

value = value.trim();

if ("true".equals(value) || "false".equals(value)) {
return Boolean.valueOf(value);
}

switch (value.charAt(0)) {
case '{': /* JSON Object */
case '[': /* JSON Array */
case '-': /* JSON Negative Number */
case '0': /* JSON Numbers */
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
try {
com.fasterxml.jackson.databind.JsonNode node = MAPPER.readTree(value);
return readObject(node);
} catch (Exception e) {
// TODO log the error
break;
}
default:
break;
}

// JSON String
return value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@

package io.smallrye.openapi.runtime.io;

import static io.smallrye.openapi.runtime.io.JsonUtil.readObject;

import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URISyntaxException;
import java.net.URL;
import java.text.ParseException;
Expand All @@ -28,7 +28,6 @@
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.eclipse.microprofile.openapi.models.Components;
import org.eclipse.microprofile.openapi.models.Extensible;
Expand Down Expand Up @@ -1357,62 +1356,6 @@ private Map<String, String> readStringMap(JsonNode node) {
return rval;
}

/**
* Reads the node as a Java object. This is typically expected to be a literal of
* some sort, as in the case of default values and examples. The node may be anything
* from a string to a javascript object.
*
* @param node
*/
private Object readObject(JsonNode node) {
if (node == null) {
return null;
}
if (node.isBigDecimal()) {
return new BigDecimal(node.asText());
}
if (node.isBigInteger()) {
return new BigInteger(node.asText());
}
if (node.isBoolean()) {
return node.asBoolean();
}
if (node.isDouble()) {
return node.asDouble();
}
if (node.isFloat()) {
return node.asDouble();
}
if (node.isInt()) {
return node.asInt();
}
if (node.isLong()) {
return node.asLong();
}
if (node.isTextual()) {
return node.asText();
}
if (node.isArray()) {
ArrayNode arrayNode = (ArrayNode) node;
List<Object> items = new ArrayList<>();
for (JsonNode itemNode : arrayNode) {
items.add(readObject(itemNode));
}
return items;
}
if (node.isObject()) {
Map<String, Object> items = new LinkedHashMap<>();
for (Iterator<Entry<String, JsonNode>> fields = node.fields(); fields.hasNext();) {
Entry<String, JsonNode> field = fields.next();
String fieldName = field.getKey();
Object fieldValue = readObject(field.getValue());
items.put(fieldName, fieldValue);
}
return items;
}
return null;
}

/**
* Reads model extensions.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,19 @@ default boolean isJaxRsAnnotationExtension(AnnotationInstance instance) {
return false;
}

/**
* Parses an OpenAPI Extension value. The value may be:
*
* - JSON object - starts with '{'
* - JSON array - starts with '['
* - number
* - boolean
* - string
*
* @param key the name of the extension property
* @param value the string value of the extension
*/
default Object parseExtension(String key, String value) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tjquinno, please let me know if this method definition will cover what you need to parse extensions.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @MikeEdgar . I think the answer is "yes." I had to shift gears to some other things briefly so I'm not in a position right now to try this (probably first thing next week). But I think it looks as if it'll work.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MikeEdgar Just FYI, I'm using a local build of the latest SmallRye master (with this PR) and I see my AnnotationScannerExtension parseExtension method being invoked as expected. Thanks again.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tjquinno - very good, glad to hear that. I expect there will be a release in the next few days.

return io.smallrye.openapi.runtime.io.JsonUtil.parseValue(value);
}
}
Loading