summaryrefslogtreecommitdiffstats
path: root/utils/src/main/java/org/onap
diff options
context:
space:
mode:
authorJim Hahn <jrh3@att.com>2019-09-09 16:51:32 -0400
committerJim Hahn <jrh3@att.com>2019-09-11 15:32:01 -0400
commit173c4dbea9a1175a6f18031a221bb701deeecaa7 (patch)
treecff8d6fc46b6096b551b075e489b406c50b61531 /utils/src/main/java/org/onap
parent216b2beaf25eba50e948374d07e92b6c0a02b7c9 (diff)
Create StandardYamlCoder
Created StandardYamlCoder which is like a StandardCoder, except that the original converts to/from JSON, while the new class converts to/from YAML. Also added YamlMessageBodyHandler and incorporated it into the http server so that it supports a media type of */yaml. Change-Id: Ibd83a9f6d355a330f63e435f2bb41affcf1947c2 Issue-ID: POLICY-2065 Signed-off-by: Jim Hahn <jrh3@att.com>
Diffstat (limited to 'utils/src/main/java/org/onap')
-rw-r--r--utils/src/main/java/org/onap/policy/common/utils/coder/StandardCoder.java21
-rw-r--r--utils/src/main/java/org/onap/policy/common/utils/coder/StandardYamlCoder.java264
-rw-r--r--utils/src/main/java/org/onap/policy/common/utils/coder/YamlException.java63
3 files changed, 348 insertions, 0 deletions
diff --git a/utils/src/main/java/org/onap/policy/common/utils/coder/StandardCoder.java b/utils/src/main/java/org/onap/policy/common/utils/coder/StandardCoder.java
index 80eddb86..d3d69812 100644
--- a/utils/src/main/java/org/onap/policy/common/utils/coder/StandardCoder.java
+++ b/utils/src/main/java/org/onap/policy/common/utils/coder/StandardCoder.java
@@ -211,6 +211,16 @@ public class StandardCoder implements Coder {
}
/**
+ * Encodes an object into a json tree, without catching exceptions.
+ *
+ * @param object object to be encoded
+ * @return a json element representing the object
+ */
+ protected JsonElement toJsonTree(Object object) {
+ return GSON.toJsonTree(object);
+ }
+
+ /**
* Encodes an object into json, without catching exceptions.
*
* @param object object to be encoded
@@ -232,6 +242,17 @@ public class StandardCoder implements Coder {
}
/**
+ * Decodes a json element into an object, without catching exceptions.
+ *
+ * @param json json element to be decoded
+ * @param clazz class of object to be decoded
+ * @return the object represented by the given json element
+ */
+ protected <T> T fromJson(JsonElement json, Class<T> clazz) {
+ return convertFromDouble(clazz, GSON.fromJson(json, clazz));
+ }
+
+ /**
* Decodes a json string into an object, without catching exceptions.
*
* @param json json string to be decoded
diff --git a/utils/src/main/java/org/onap/policy/common/utils/coder/StandardYamlCoder.java b/utils/src/main/java/org/onap/policy/common/utils/coder/StandardYamlCoder.java
new file mode 100644
index 00000000..357b106e
--- /dev/null
+++ b/utils/src/main/java/org/onap/policy/common/utils/coder/StandardYamlCoder.java
@@ -0,0 +1,264 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.common.utils.coder;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonNull;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonPrimitive;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map.Entry;
+import org.yaml.snakeyaml.DumperOptions;
+import org.yaml.snakeyaml.Yaml;
+import org.yaml.snakeyaml.emitter.Emitter;
+import org.yaml.snakeyaml.error.YAMLException;
+import org.yaml.snakeyaml.nodes.MappingNode;
+import org.yaml.snakeyaml.nodes.Node;
+import org.yaml.snakeyaml.nodes.NodeTuple;
+import org.yaml.snakeyaml.nodes.ScalarNode;
+import org.yaml.snakeyaml.nodes.SequenceNode;
+import org.yaml.snakeyaml.nodes.Tag;
+import org.yaml.snakeyaml.resolver.Resolver;
+import org.yaml.snakeyaml.serializer.Serializer;
+
+/**
+ * YAML encoder and decoder using the "standard" mechanism, which is currently gson. All
+ * of the methods perform conversion to/from YAML (instead of JSON).
+ */
+public class StandardYamlCoder extends StandardCoder {
+
+ /**
+ * Constructs the object.
+ */
+ public StandardYamlCoder() {
+ super();
+ }
+
+ @Override
+ protected String toJson(Object object) {
+ StringWriter output = new StringWriter();
+ toJson(output, object);
+ return output.toString();
+ }
+
+ @Override
+ protected void toJson(Writer target, Object object) {
+ DumperOptions dumper = new DumperOptions();
+ Serializer serializer = new Serializer(new Emitter(target, dumper), new Resolver(), dumper, null);
+
+ try {
+ serializer.open();
+ serializer.serialize(makeYaml(toJsonTree(object)));
+ serializer.close();
+
+ } catch (IOException e) {
+ throw new YAMLException(e);
+ }
+ }
+
+ @Override
+ protected <T> T fromJson(String yaml, Class<T> clazz) {
+ Node node = new Yaml().compose(new StringReader(yaml));
+ return fromJson(makeGson(node), clazz);
+ }
+
+ @Override
+ protected <T> T fromJson(Reader source, Class<T> clazz) {
+ Node node = new Yaml().compose(source);
+ return fromJson(makeGson(node), clazz);
+ }
+
+ /**
+ * Converts an arbitrary gson element into a corresponding Yaml node.
+ *
+ * @param jel gson element to be converted
+ * @return a yaml node corresponding to the element
+ */
+ private Node makeYaml(JsonElement jel) {
+ if (jel.isJsonArray()) {
+ return makeYamlSequence((JsonArray) jel);
+
+ } else if (jel.isJsonObject()) {
+ return makeYamlMap((JsonObject) jel);
+
+ } else if (jel.isJsonPrimitive()) {
+ return makeYamlPrim((JsonPrimitive) jel);
+
+ } else {
+ return new ScalarNode(Tag.NULL, "", null, null, DumperOptions.ScalarStyle.PLAIN);
+ }
+ }
+
+ /**
+ * Converts an arbitrary gson array into a corresponding Yaml sequence.
+ *
+ * @param jel gson element to be converted
+ * @return a yaml node corresponding to the element
+ */
+ private Node makeYamlSequence(JsonArray jel) {
+ List<Node> nodes = new ArrayList<>(jel.size());
+ jel.forEach(item -> nodes.add(makeYaml(item)));
+
+ return new SequenceNode(Tag.SEQ, true, nodes, null, null, DumperOptions.FlowStyle.AUTO);
+ }
+
+ /**
+ * Converts an arbitrary gson object into a corresponding Yaml map.
+ *
+ * @param jel gson element to be converted
+ * @return a yaml node corresponding to the element
+ */
+ private Node makeYamlMap(JsonObject jel) {
+ List<NodeTuple> nodes = new ArrayList<>(jel.size());
+
+ for (Entry<String, JsonElement> entry : jel.entrySet()) {
+ Node key = new ScalarNode(Tag.STR, entry.getKey(), null, null, DumperOptions.ScalarStyle.PLAIN);
+ Node value = makeYaml(entry.getValue());
+
+ nodes.add(new NodeTuple(key, value));
+ }
+
+ return new MappingNode(Tag.MAP, true, nodes, null, null, DumperOptions.FlowStyle.AUTO);
+ }
+
+ /**
+ * Converts an arbitrary gson primitive into a corresponding Yaml scalar.
+ *
+ * @param jel gson element to be converted
+ * @return a yaml node corresponding to the element
+ */
+ private Node makeYamlPrim(JsonPrimitive jel) {
+ Tag tag;
+ if (jel.isNumber()) {
+ Class<? extends Number> clazz = jel.getAsNumber().getClass();
+
+ if (clazz == Double.class || clazz == Float.class) {
+ tag = Tag.FLOAT;
+
+ } else {
+ tag = Tag.INT;
+ }
+
+ } else if (jel.isBoolean()) {
+ tag = Tag.BOOL;
+
+ } else {
+ // treat anything else as a string
+ tag = Tag.STR;
+ }
+
+ return new ScalarNode(tag, jel.getAsString(), null, null, DumperOptions.ScalarStyle.PLAIN);
+ }
+
+ /**
+ * Converts an arbitrary Yaml node into a corresponding gson element.
+ *
+ * @param node node to be converted
+ * @return a gson element corresponding to the node
+ */
+ private JsonElement makeGson(Node node) {
+ if (node instanceof MappingNode) {
+ return makeGsonObject((MappingNode) node);
+
+ } else if (node instanceof SequenceNode) {
+ return makeGsonArray((SequenceNode) node);
+
+ } else {
+ return makeGsonPrim((ScalarNode) node);
+ }
+
+ // yaml doesn't appear to use anchor nodes when decoding so ignore them for now
+ }
+
+ /**
+ * Converts a Yaml sequence into a corresponding gson array.
+ *
+ * @param node node to be converted
+ * @return a gson element corresponding to the node
+ */
+ private JsonElement makeGsonArray(SequenceNode node) {
+ List<Node> nodes = node.getValue();
+
+ JsonArray array = new JsonArray(nodes.size());
+ nodes.forEach(subnode -> array.add(makeGson(subnode)));
+
+ return array;
+ }
+
+ /**
+ * Converts a Yaml map into a corresponding gson object.
+ *
+ * @param node node to be converted
+ * @return a gson element corresponding to the node
+ */
+ private JsonElement makeGsonObject(MappingNode node) {
+ JsonObject obj = new JsonObject();
+
+ for (NodeTuple tuple : node.getValue()) {
+ Node key = tuple.getKeyNode();
+ String skey = ((ScalarNode) key).getValue();
+
+ obj.add(skey, makeGson(tuple.getValueNode()));
+ }
+
+ return obj;
+ }
+
+ /**
+ * Converts a Yaml scalar into a corresponding gson primitive.
+ *
+ * @param node node to be converted
+ * @return a gson element corresponding to the node
+ */
+ private JsonElement makeGsonPrim(ScalarNode node) {
+ try {
+ Tag tag = node.getTag();
+
+ if (tag == Tag.INT) {
+ return new JsonPrimitive(Long.valueOf(node.getValue()));
+
+ } else if (tag == Tag.FLOAT) {
+ return new JsonPrimitive(Double.valueOf(node.getValue()));
+
+ } else if (tag == Tag.BOOL) {
+ return new JsonPrimitive(Boolean.valueOf(node.getValue()));
+
+ } else if (tag == Tag.NULL) {
+ return JsonNull.INSTANCE;
+
+ } else {
+ // treat anything else as a string
+ return new JsonPrimitive(node.getValue());
+ }
+
+ } catch (NumberFormatException ex) {
+ // just treat it as a string
+ return new JsonPrimitive(node.getValue());
+ }
+ }
+}
diff --git a/utils/src/main/java/org/onap/policy/common/utils/coder/YamlException.java b/utils/src/main/java/org/onap/policy/common/utils/coder/YamlException.java
new file mode 100644
index 00000000..d6591b3b
--- /dev/null
+++ b/utils/src/main/java/org/onap/policy/common/utils/coder/YamlException.java
@@ -0,0 +1,63 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.common.utils.coder;
+
+import org.yaml.snakeyaml.error.Mark;
+
+/**
+ * Runtime Exception generated by StandardYamlCoder.
+ */
+public class YamlException extends RuntimeException {
+ private static final long serialVersionUID = 1L;
+
+ private final Mark problemMark;
+
+
+ /**
+ * Constructs the object.
+ *
+ * @param reason reason for the exception
+ * @param problemMark where the exception occurred within the input
+ */
+ public YamlException(String reason, Mark problemMark) {
+ super(reason);
+
+ this.problemMark = problemMark;
+ }
+
+ /**
+ * Constructs the object.
+ *
+ * @param reason reason for the exception
+ * @param problemMark where the exception occurred within the input
+ * @param cause cause of the exception
+ */
+ public YamlException(String reason, Mark problemMark, Throwable cause) {
+ super(reason, cause);
+
+ this.problemMark = problemMark;
+ }
+
+ @Override
+ public String getMessage() {
+ return super.getMessage() + problemMark;
+ }
+}