Added JacksonHandler which provides jackson behavior in gson.
Also added classes to facilitate testing of gson serializations.
Added compareGson(xxx, Class).
Removed trailing spaces from some files.
Updated license dates.
Replaced incorrect constant with ${xxx} in json test file.
Fixed typo in test method name.
Change-Id: If05b654d76a4ffc88646f03334be82b32506f28f
Issue-ID: POLICY-1428
Signed-off-by: Jim Hahn <jrh3@att.com>
--- /dev/null
+/*
+ * ============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.gson;
+
+import com.google.gson.GsonBuilder;
+
+/**
+ * Provider used to serialize and deserialize policy objects via gson using jackson
+ * default behaviors and annotations.
+ */
+public class JacksonHandler extends GsonMessageBodyHandler {
+
+ /**
+ * Constructs the object.
+ */
+ public JacksonHandler() {
+ this(new GsonBuilder());
+ }
+
+ /**
+ * Constructs the object.
+ * @param builder builder to use to create the gson object
+ */
+ public JacksonHandler(GsonBuilder builder) {
+ super(builder
+ .registerTypeAdapterFactory(new JacksonFieldAdapterFactory())
+ .registerTypeAdapterFactory(new JacksonMethodAdapterFactory())
+ .setExclusionStrategies(new JacksonExclusionStrategy())
+ .create());
+ }
+
+}
--- /dev/null
+/*
+ * ============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.gson;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.StringReader;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.TreeMap;
+import javax.ws.rs.core.MediaType;
+import org.junit.Test;
+import org.onap.policy.common.gson.JacksonHandler;
+import org.onap.policy.common.gson.annotation.GsonJsonAnyGetter;
+import org.onap.policy.common.gson.annotation.GsonJsonAnySetter;
+
+public class JacksonHandlerTest {
+
+ @Test
+ public void test() throws Exception {
+ JacksonHandler hdlr = new JacksonHandler();
+
+ assertTrue(hdlr.isReadable(null, null, null, MediaType.APPLICATION_JSON_TYPE));
+ assertFalse(hdlr.isReadable(null, null, null, MediaType.TEXT_PLAIN_TYPE));
+
+ JsonObject expected = new JsonObject();
+ expected.addProperty("myId", 100);
+ expected.addProperty("value", "a value");
+ expected.addProperty("abc", "def");
+ expected.addProperty("hello", "world");
+
+ Data data = new Data();
+ data.id = 10;
+ data.value = "a value";
+ data.props = new HashMap<>();
+ data.props.put("abc", "def");
+ data.props.put("hello", "world");
+
+ /*
+ * Ensure everything serializes as expected.
+ */
+ ByteArrayOutputStream outstr = new ByteArrayOutputStream();
+ hdlr.writeTo(data, Data.class, Data.class, null, null, null, outstr);
+
+ StringReader rdr = new StringReader(outstr.toString("UTF-8"));
+ JsonObject json = new Gson().fromJson(rdr, JsonObject.class);
+
+ assertEquals(expected, json);
+
+ /*
+ * Ensure everything deserializes as expected.
+ */
+ Data data2 = (Data) hdlr.readFrom(Object.class, Data.class, null, null, null,
+ new ByteArrayInputStream(outstr.toByteArray()));
+
+ // id is not serialized, so we must copy it manually before comparing
+ data2.id = data.id;
+
+ assertEquals(data.toString(), data2.toString());
+ }
+
+ /**
+ * This class includes all policy-specific gson annotations.
+ */
+ public static class Data {
+ protected int id;
+
+ protected String value;
+
+ protected Map<String, String> props;
+
+ public int getMyId() {
+ return 100;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ @GsonJsonAnyGetter
+ public Map<String, String> getProps() {
+ return props;
+ }
+
+ /**
+ * Sets a property.
+ * @param name property name
+ * @param value new value
+ */
+ @GsonJsonAnySetter
+ public void setProperty(String name, String value) {
+ if (props == null) {
+ props = new TreeMap<>();
+ }
+
+ props.put(name, value);
+ }
+
+ @Override
+ public String toString() {
+ return "Data [id=" + id + ", value=" + value + ", props=" + props + "]";
+ }
+ }
+}
<artifactId>logback-classic</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.onap.policy.common</groupId>
+ <artifactId>utils-test</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
- <version>3.11.1</version>
<scope>test</scope>
</dependency>
import org.onap.policy.common.endpoints.event.comm.bus.NoopTopicSource;
import org.onap.policy.common.endpoints.event.comm.bus.UebTopicSink;
import org.onap.policy.common.endpoints.event.comm.bus.UebTopicSource;
+import org.onap.policy.common.gson.annotation.GsonJsonIgnore;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
}
@JsonIgnore
+ @GsonJsonIgnore
@Override
public List<UebTopicSource> getUebTopicSources() {
return UebTopicSource.factory.inventory();
}
@JsonIgnore
+ @GsonJsonIgnore
@Override
public List<DmaapTopicSource> getDmaapTopicSources() {
return DmaapTopicSource.factory.inventory();
}
+ @JsonIgnore
+ @GsonJsonIgnore
@Override
public List<NoopTopicSource> getNoopTopicSources() {
return NoopTopicSource.factory.inventory();
}
@JsonIgnore
+ @GsonJsonIgnore
@Override
public List<UebTopicSink> getUebTopicSinks() {
return UebTopicSink.factory.inventory();
}
@JsonIgnore
+ @GsonJsonIgnore
@Override
public List<DmaapTopicSink> getDmaapTopicSinks() {
return DmaapTopicSink.factory.inventory();
}
@JsonIgnore
+ @GsonJsonIgnore
@Override
public List<NoopTopicSink> getNoopTopicSinks() {
return NoopTopicSink.factory.inventory();
* @return list of managed endpoints
*/
@JsonIgnore
+ @GsonJsonIgnore
protected List<Startable> getEndpoints() {
final List<Startable> endpoints = new ArrayList<>();
* ============LICENSE_START=======================================================
* policy-endpoints
* ================================================================================
- * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved.
* Modifications Copyright (C) 2018 Samsung Electronics Co., Ltd.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
import org.onap.dmaap.mr.test.clients.ProtocolTypeConstants;
import org.onap.policy.common.endpoints.event.comm.bus.DmaapTopicSinkFactory;
import org.onap.policy.common.endpoints.properties.PolicyEndPointProperties;
+import org.onap.policy.common.gson.annotation.GsonJsonIgnore;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
* The actual Cambria publisher.
*/
@JsonIgnore
+ @GsonJsonIgnore
protected volatile CambriaBatchingPublisher publisher;
/**
import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
import org.onap.policy.common.endpoints.event.comm.bus.internal.BusTopicParams;
import org.onap.policy.common.endpoints.http.client.HttpClient;
+import org.onap.policy.common.gson.annotation.GsonJsonIgnore;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
}
@JsonIgnore
+ @GsonJsonIgnore
@Override
public String getPassword() {
return password;
* ============LICENSE_START=======================================================
* ONAP
* ================================================================================
- * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2017-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.
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.onap.aaf.cadi.filter.CadiFilter;
import org.onap.policy.common.endpoints.http.server.HttpServletServer;
+import org.onap.policy.common.gson.annotation.GsonJsonIgnore;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
* @return the password
*/
@JsonIgnore
+ @GsonJsonIgnore
public String getPassword() {
return password;
}
import org.onap.policy.common.endpoints.event.comm.bus.DmaapTopicPropertyBuilder;
import org.onap.policy.common.endpoints.event.comm.bus.NoopTopicPropertyBuilder;
import org.onap.policy.common.endpoints.properties.PolicyEndPointProperties;
+import org.onap.policy.common.utils.gson.GsonTestUtils;
public class TopicEndpointProxyTest {
|| exists(topics, DMAAP_SINK_TOPIC);
}
+ @Test
+ public void testSerialize() {
+ TopicEndpoint manager = new TopicEndpointProxy();
+
+ manager.addTopicSources(configuration);
+ manager.addTopicSinks(configuration);
+
+ new GsonTestUtils().compareGson(manager, TopicEndpointProxyTest.class);
+ }
+
@Test
public void addTopicSources() {
TopicEndpoint manager = new TopicEndpointProxy();
* ============LICENSE_START=======================================================
* policy-endpoints
* ================================================================================
- * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2018-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.
import org.junit.Before;
import org.junit.Test;
import org.onap.policy.common.endpoints.event.comm.bus.TopicTestBase;
+import org.onap.policy.common.utils.gson.GsonTestUtils;
public class BusTopicBaseTest extends TopicTestBase {
assertNotNull(base.toString());
}
+ @Test
+ public void testSerialize() {
+ new GsonTestUtils().compareGson(base, BusTopicBaseTest.class);
+ }
+
@Test
public void testGetApiKey() {
assertEquals(MY_API_KEY, base.getApiKey());
* ============LICENSE_START=======================================================
* policy-endpoints
* ================================================================================
- * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2018-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.
import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
import org.onap.policy.common.endpoints.event.comm.TopicListener;
import org.onap.policy.common.endpoints.event.comm.bus.TopicTestBase;
+import org.onap.policy.common.utils.gson.GsonTestUtils;
public class InlineBusTopicSinkTest extends TopicTestBase {
sink.shutdown();
}
+ @Test
+ public void testSerialize() {
+ new GsonTestUtils().compareGson(sink, InlineBusTopicSinkTest.class);
+ }
+
@Test
public void testInlineBusTopicSinkImpl() {
// verify that different wrappers can be built
* ============LICENSE_START=======================================================
* policy-endpoints
* ================================================================================
- * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2018-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.
import org.junit.Test;
import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
import org.onap.policy.common.endpoints.event.comm.bus.TopicTestBase;
+import org.onap.policy.common.utils.gson.GsonTestUtils;
public class InlineDmaapTopicSinkTest extends TopicTestBase {
private InlineDmaapTopicSink sink;
sink.shutdown();
}
+ @Test
+ public void testSerialize() {
+ new GsonTestUtils().compareGson(sink, InlineDmaapTopicSinkTest.class);
+ }
+
@Test
public void testToString() {
assertTrue(sink.toString().startsWith("InlineDmaapTopicSink ["));
* ============LICENSE_START=======================================================
* policy-endpoints
* ================================================================================
- * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2018-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.
import org.junit.Test;
import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
import org.onap.policy.common.endpoints.event.comm.bus.TopicTestBase;
+import org.onap.policy.common.utils.gson.GsonTestUtils;
public class InlineUebTopicSinkTest extends TopicTestBase {
private InlineUebTopicSink sink;
sink.shutdown();
}
+ @Test
+ public void testSerialize() {
+ new GsonTestUtils().compareGson(sink, InlineUebTopicSinkTest.class);
+ }
+
@Test
public void testToString() {
assertTrue(sink.toString().startsWith("InlineUebTopicSink ["));
* ============LICENSE_START=======================================================
* policy-endpoints
* ================================================================================
- * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2018-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.
import org.onap.policy.common.endpoints.event.comm.TopicListener;
import org.onap.policy.common.endpoints.event.comm.bus.TopicTestBase;
import org.onap.policy.common.endpoints.event.comm.bus.internal.BusConsumer.FilterableBusConsumer;
+import org.onap.policy.common.utils.gson.GsonTestUtils;
public class SingleThreadedBusTopicSourceTest extends TopicTestBase {
private Thread thread;
source.shutdown();
}
+ @Test
+ public void testSerialize() {
+ new GsonTestUtils().compareGson(source, SingleThreadedBusTopicSourceTest.class);
+ }
+
@Test
public void testRegister() {
source.register(listener);
// do nothing
}
};
-
+
assertNotNull(source2.makePollerThread());
}
* ============LICENSE_START=======================================================
* policy-endpoints
* ================================================================================
- * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2018-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.
import org.junit.Test;
import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
import org.onap.policy.common.endpoints.event.comm.bus.TopicTestBase;
+import org.onap.policy.common.utils.gson.GsonTestUtils;
public class SingleThreadedDmaapTopicSourceTest extends TopicTestBase {
private SingleThreadedDmaapTopicSource source;
source.shutdown();
}
+ @Test
+ public void testSerialize() {
+ new GsonTestUtils().compareGson(source, SingleThreadedDmaapTopicSourceTest.class);
+ }
+
@Test
public void testToString() {
assertTrue(source.toString().startsWith("SingleThreadedDmaapTopicSource ["));
* ============LICENSE_START=======================================================
* policy-endpoints
* ================================================================================
- * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2018-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.
import org.junit.Test;
import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
import org.onap.policy.common.endpoints.event.comm.bus.TopicTestBase;
+import org.onap.policy.common.utils.gson.GsonTestUtils;
public class SingleThreadedUebTopicSourceTest extends TopicTestBase {
private SingleThreadedUebTopicSource source;
source.shutdown();
}
+ @Test
+ public void testSerialize() {
+ new GsonTestUtils().compareGson(source, SingleThreadedUebTopicSourceTest.class);
+ }
+
@Test
public void testToString() {
assertTrue(source.toString().startsWith("SingleThreadedUebTopicSource ["));
* ============LICENSE_START=======================================================
* ONAP Policy Engine - Common Modules
* ================================================================================
- * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2018-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.
import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
import org.onap.policy.common.endpoints.event.comm.TopicListener;
import org.onap.policy.common.endpoints.event.comm.bus.TopicTestBase;
+import org.onap.policy.common.utils.gson.GsonTestUtils;
public class TopicBaseTest extends TopicTestBase {
@Before
public void setUp() {
super.setUp();
-
+
base = new TopicBaseImpl(servers, MY_TOPIC);
}
new TopicBaseImpl(servers, "");
}
+ @Test
+ public void testSerialize() {
+ new GsonTestUtils().compareGson(base, TopicBaseTest.class);
+ }
+
@Test
public void testRegister() {
TopicListener listener = mock(TopicListener.class);
/**
* Constructor.
- *
+ *
* @param servers list of servers
* @param topic topic name
*/
/**
* Adds an event to the list of recent events.
- *
+ *
* @param event event to be added
*/
public void addEvent(String event) {
import org.junit.Before;
import org.junit.Test;
import org.onap.policy.common.endpoints.http.server.HttpServletServer;
+import org.onap.policy.common.utils.gson.GsonTestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
assertFalse(MyJacksonProvider.hasWrittenSome());
}
+ @Test
+ public void testSerialize() {
+ HttpServletServer server = HttpServletServer.factory.build("echo", "localhost", port, "/", false, true);
+ server.addServletPackage("/*", this.getClass().getPackage().getName());
+ server.addFilterClass("/*", TestFilter.class.getCanonicalName());
+
+ // ensure we can serialize the server
+ new GsonTestUtils().compareGson(server, HttpServerTest.class);
+ }
+
@Test
public void testSingleServer() throws Exception {
logger.info("-- testSingleServer() --");
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.gson.annotations.SerializedName;
+import org.onap.policy.common.gson.annotation.GsonJsonProperty;
/**
* "ECHO" request and response supporting serialization and de-serialization via
*/
public class RestEchoReqResp {
@JsonProperty("reqId")
+ @GsonJsonProperty("reqId")
@SerializedName("reqId")
private int requestId;
@JsonProperty("textValue")
+ @GsonJsonProperty("textValue")
@SerializedName("textValue")
private String text;
--- /dev/null
+{
+ "locked" : false,
+ "alive" : false,
+ "topicSources" : [ {
+ "servers" : [ "my-server" ],
+ "topic" : "ueb-source",
+ "recentEvents" : [ ],
+ "alive" : false,
+ "locked" : false,
+ "apiKey" : null,
+ "apiSecret" : null,
+ "useHttps" : true,
+ "allowSelfSignedCerts" : true,
+ "consumerGroup" : "${obj.topicSources[0].consumerGroup}",
+ "consumerInstance" : "${obj.topicSources[0].consumerInstance}",
+ "fetchTimeout" : 15000,
+ "fetchLimit" : 100,
+ "topicCommInfrastructure" : "UEB"
+ }, {
+ "servers" : [ "my-server" ],
+ "topic" : "dmaap-source",
+ "recentEvents" : [ ],
+ "alive" : false,
+ "locked" : false,
+ "apiKey" : "my-api-key",
+ "apiSecret" : "my-api-secret",
+ "useHttps" : true,
+ "allowSelfSignedCerts" : true,
+ "consumerGroup" : "my-cons-group",
+ "consumerInstance" : "my-cons-inst",
+ "fetchTimeout" : 101,
+ "fetchLimit" : 100,
+ "topicCommInfrastructure" : "DMAAP"
+ }, {
+ "servers" : [ "my-server" ],
+ "topic" : "noop-source",
+ "recentEvents" : [ ],
+ "alive" : false,
+ "locked" : false,
+ "topicCommInfrastructure" : "NOOP"
+ } ],
+ "topicSinks" : [ {
+ "servers" : [ "my-server" ],
+ "topic" : "ueb-sink",
+ "recentEvents" : [ ],
+ "alive" : false,
+ "locked" : false,
+ "apiKey" : null,
+ "apiSecret" : null,
+ "useHttps" : true,
+ "allowSelfSignedCerts" : true,
+ "topicCommInfrastructure" : "UEB",
+ "partitionKey" : "${obj.topicSinks[0].partitionKey}"
+ }, {
+ "servers" : [ "my-server" ],
+ "topic" : "dmaap-sink",
+ "recentEvents" : [ ],
+ "alive" : false,
+ "locked" : false,
+ "apiKey" : "my-api-key",
+ "apiSecret" : "my-api-secret",
+ "useHttps" : true,
+ "allowSelfSignedCerts" : true,
+ "topicCommInfrastructure" : "DMAAP",
+ "partitionKey" : "my-partition"
+ }, {
+ "servers" : [ "my-server" ],
+ "topic" : "noop-sink",
+ "recentEvents" : [ ],
+ "alive" : false,
+ "locked" : false,
+ "topicCommInfrastructure" : "NOOP"
+ } ]
+}
--- /dev/null
+{
+ "servers" : [ "svra", "svrb" ],
+ "topic" : "my-topic",
+ "recentEvents" : [ ],
+ "alive" : false,
+ "locked" : false,
+ "apiKey" : "my-api-key",
+ "apiSecret" : "my-api-secret",
+ "useHttps" : true,
+ "allowSelfSignedCerts" : true,
+ "topicCommInfrastructure" : "NOOP"
+}
--- /dev/null
+{
+ "servers" : [ "svra", "svrb" ],
+ "topic" : "my-topic",
+ "recentEvents" : [ ],
+ "alive" : false,
+ "locked" : false,
+ "apiKey" : "my-api-key",
+ "apiSecret" : "my-api-secret",
+ "useHttps" : true,
+ "allowSelfSignedCerts" : true,
+ "topicCommInfrastructure" : "NOOP",
+ "partitionKey" : "my-partition"
+}
--- /dev/null
+{
+ "servers" : [ "svra", "svrb" ],
+ "topic" : "my-topic",
+ "recentEvents" : [ ],
+ "alive" : false,
+ "locked" : false,
+ "apiKey" : "my-api-key",
+ "apiSecret" : "my-api-secret",
+ "useHttps" : true,
+ "allowSelfSignedCerts" : true,
+ "topicCommInfrastructure" : "DMAAP",
+ "partitionKey" : "my-partition"
+}
--- /dev/null
+{
+ "servers" : [ "svra", "svrb" ],
+ "topic" : "my-topic",
+ "recentEvents" : [ ],
+ "alive" : false,
+ "locked" : false,
+ "apiKey" : "my-api-key",
+ "apiSecret" : "my-api-secret",
+ "useHttps" : true,
+ "allowSelfSignedCerts" : true,
+ "topicCommInfrastructure" : "UEB",
+ "partitionKey" : "my-partition"
+}
--- /dev/null
+{
+ "servers" : [ "svra", "svrb" ],
+ "topic" : "my-topic",
+ "recentEvents" : [ ],
+ "alive" : false,
+ "locked" : false,
+ "apiKey" : "my-api-key",
+ "apiSecret" : "my-api-secret",
+ "useHttps" : true,
+ "allowSelfSignedCerts" : true,
+ "consumerGroup" : "my-cons-group",
+ "consumerInstance" : "my-cons-inst",
+ "fetchTimeout" : 101,
+ "fetchLimit" : 100,
+ "topicCommInfrastructure" : "NOOP"
+}
--- /dev/null
+{
+ "servers" : [ "svra", "svrb" ],
+ "topic" : "my-topic",
+ "recentEvents" : [ ],
+ "alive" : false,
+ "locked" : false,
+ "apiKey" : "my-api-key",
+ "apiSecret" : "my-api-secret",
+ "useHttps" : true,
+ "allowSelfSignedCerts" : true,
+ "consumerGroup" : "my-cons-group",
+ "consumerInstance" : "my-cons-inst",
+ "fetchTimeout" : 101,
+ "fetchLimit" : 100,
+ "topicCommInfrastructure" : "DMAAP"
+}
--- /dev/null
+{
+ "servers" : [ "svra", "svrb" ],
+ "topic" : "my-topic",
+ "recentEvents" : [ ],
+ "alive" : false,
+ "locked" : false,
+ "apiKey" : "my-api-key",
+ "apiSecret" : "my-api-secret",
+ "useHttps" : true,
+ "allowSelfSignedCerts" : true,
+ "consumerGroup" : "my-cons-group",
+ "consumerInstance" : "my-cons-inst",
+ "fetchTimeout" : 101,
+ "fetchLimit" : 100,
+ "topicCommInfrastructure" : "UEB"
+}
--- /dev/null
+{
+ "servers" : [ "svra", "svrb" ],
+ "topic" : "my-topic",
+ "recentEvents" : [ ],
+ "alive" : false,
+ "locked" : false,
+ "topicCommInfrastructure" : "NOOP"
+}
--- /dev/null
+{
+ "aaf": false,
+ "alive": false,
+ "host": "localhost",
+ "name": "echo",
+ "port": ${obj.port}
+}
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
- <version>3.11.1</version>
<scope>test</scope>
</dependency>
<dependency>
<artifactId>utils</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.onap.policy.common</groupId>
+ <artifactId>gson</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito</artifactId>
--- /dev/null
+/*-
+ * ============LICENSE_START=======================================================
+ * policy-management
+ * ================================================================================
+ * Copyright (C) 2017-2018 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.gson;
+
+import com.google.gson.TypeAdapter;
+import com.google.gson.stream.JsonReader;
+import java.io.IOException;
+
+/**
+ * Gson serializer, providing stub implementation of "read".
+ *
+ * @param <T> type of object that this serializes
+ */
+public abstract class GsonSerializer<T> extends TypeAdapter<T> {
+ @Override
+ public T read(JsonReader in) throws IOException {
+ throw new UnsupportedOperationException("read from pseudo TypeAdapter");
+ }
+}
--- /dev/null
+/*-
+ * ============LICENSE_START=======================================================
+ * policy-management
+ * ================================================================================
+ * Copyright (C) 2017-2018 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.gson;
+
+import static org.junit.Assert.assertEquals;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParseException;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import javax.script.Bindings;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import javax.script.ScriptException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Utilities used to test encoding and decoding of Policy objects.
+ */
+public class GsonTestUtils {
+
+ private static final Logger logger = LoggerFactory.getLogger(GsonTestUtils.class);
+
+ /**
+ * Matches script items, of the form ${xxx}, within text.
+ */
+ private static final Pattern SCRIPT_PAT = Pattern.compile("\\$\\{([^}]+)\\}");
+
+ /**
+ * Engine used to interpolate strings before they're compared.
+ */
+ private static volatile ScriptEngine engine = null;
+
+ /**
+ * Used to encode and decode an object via gson.
+ */
+ private Gson gson;
+
+ /**
+ * Constructs the object.
+ */
+ public GsonTestUtils() {
+ GsonTestUtils other = new GsonTestUtilsBuilder().build();
+
+ gson = other.gson;
+ }
+
+ /**
+ * Constructs the object.
+ *
+ * @param gson used to encode via gson
+ */
+ protected GsonTestUtils(Gson gson) {
+ this.gson = gson;
+ }
+
+ public Gson getGson() {
+ return gson;
+ }
+
+ /**
+ * Serializes and then deserializes an object using gson.
+ *
+ * @param object the object to be serialized
+ * @param clazz the class of object to deserialize
+ * @return the deserialized object
+ */
+ public <T> T gsonRoundTrip(T object, Class<T> clazz) {
+ String sgson = gsonEncode(object);
+ return gson.fromJson(sgson, clazz);
+ }
+
+ /**
+ * Encodes an object using gson and then compares it to the expected value, after
+ * sorting the elements. The class name is used to find the json file, whose contents
+ * is interpolated (i.e., script elements, of the form ${obj.xxx}, are expanded).
+ *
+ * @param object the object to be encoded
+ * @param expected the expected value
+ * @throws Exception if the file cannot be read
+ */
+ public void compareGson(Object object, Class<?> expected) {
+ compareGson(object, new File(expected.getSimpleName() + ".json"));
+ }
+
+ /**
+ * Encodes an object using gson and then compares it to the expected value, after
+ * sorting the elements. The content of the file is interpolated (i.e., script
+ * elements, of the form ${obj.xxx}, are expanded).
+ *
+ * @param object the object to be encoded
+ * @param expected the expected value
+ * @throws Exception if the file cannot be read
+ */
+ public void compareGson(Object object, File expected) {
+ // file is not required to have a full path - find it via getResource()
+ URL url = object.getClass().getResource(expected.getName());
+ if (url == null) {
+ throw new JsonParseException(new FileNotFoundException(expected.getName()));
+ }
+
+ String expectedText;
+ try {
+ expectedText = readFile(new File(url.getFile()));
+
+ } catch (IOException e) {
+ throw new JsonParseException("error reading: " + expected, e);
+ }
+
+ compareGson(object, expectedText);
+ }
+
+ /**
+ * Encodes an object using gson and then compares it to the expected value, after
+ * sorting the elements. The expected value is interpolated (i.e., script elements, of
+ * the form ${obj.xxx}, are expanded).
+ *
+ * @param object the object to be encoded
+ * @param expected the expected value
+ */
+ public void compareGson(Object object, String expected) {
+ String result = applyScripts(expected, object);
+ compareGson(object, gson.fromJson(result, JsonElement.class));
+ }
+
+ /**
+ * Encodes an object using gson and then compares it to the expected value, after
+ * sorting the elements.
+ *
+ * @param object the object to be encoded
+ * @param expected the expected value
+ */
+ public void compareGson(Object object, JsonElement expected) {
+ String sgson = gsonEncode(object);
+
+ JsonElement gsonjo = reorder(gson.fromJson(sgson, JsonElement.class));
+ JsonElement expjo = reorder(expected);
+
+ assertEquals(expjo.toString(), gsonjo.toString());
+ }
+
+ /**
+ * Reads the content of a file.
+ * @param file file to read
+ * @return the content of the file
+ * @throws IOException if an error occurs
+ */
+ protected String readFile(File file) throws IOException {
+ return new String(Files.readAllBytes(file.toPath()), StandardCharsets.UTF_8);
+ }
+
+
+ /**
+ * Interpolates script elements, of the form ${obj.xxx}, within some text. The script
+ * is evaluated via javascript, where "obj" references the object used by each script
+ * element.
+ *
+ * @param object object to be used by the script
+ * @param text text to be evaluated
+ * @return the text, after interpolating the script elements
+ */
+ public String applyScripts(String text, Object object) {
+ Matcher mat = SCRIPT_PAT.matcher(text);
+ if (!mat.find()) {
+ // contains no script elements - just return it as is
+ return text;
+ }
+
+ // create the engine and bind the object to the variable, "obj"
+ if (engine == null) {
+ // race condition here, but it's ok to overwrite with a new engine
+ engine = new ScriptEngineManager().getEngineByName("javascript");
+ }
+
+ Bindings bindings = engine.createBindings();
+ bindings.put("obj", object);
+
+ // work our way through the text, interpolating script elements as we go
+ StringBuilder bldr = new StringBuilder();
+ int ilast = 0;
+ mat.reset();
+ while (mat.find(ilast)) {
+ // append segment that appears between last match and this
+ int inext = mat.start();
+ bldr.append(text.substring(ilast, inext));
+
+ // next match begins after the current match
+ ilast = mat.end();
+
+ // interpolate the script
+ String script = mat.group(1);
+ try {
+ Object result = engine.eval(script, bindings);
+ bldr.append(result == null ? "null" : result.toString());
+
+ } catch (ScriptException e) {
+ throw new RuntimeException("cannot expand element: " + mat.group(), e);
+ }
+ }
+
+ // append final segment
+ bldr.append(text.substring(ilast));
+
+ return bldr.toString();
+ }
+
+ /**
+ * Encodes an object using gson.
+ *
+ * @param object the object to be encoded
+ * @return the encoded object
+ */
+ public String gsonEncode(Object object) {
+ String sgson = gson.toJson(object);
+ logger.debug("gson=" + sgson);
+ return sgson;
+ }
+
+ /**
+ * Recursively re-orders a json object, arranging the keys alphabetically and removing
+ * null items.
+ *
+ * @param jsonObj object from which nulls are to be removed
+ * @return a new object, without the null items
+ */
+ public JsonObject reorder(JsonObject jsonObj) {
+ JsonObject newjo = new JsonObject();
+
+ // sort the keys before copying to the new object
+ List<Entry<String, JsonElement>> sortedSet = new ArrayList<>(jsonObj.entrySet());
+ Collections.sort(sortedSet, (left, right) -> left.getKey().compareTo(right.getKey()));
+
+ for (Entry<String, JsonElement> ent : sortedSet) {
+ JsonElement val = ent.getValue();
+ if (val.isJsonNull()) {
+ continue;
+ }
+
+ newjo.add(ent.getKey(), reorder(val));
+ }
+
+ return newjo;
+ }
+
+ /**
+ * Recursively re-orders a json array, arranging the keys alphabetically and removing
+ * null items.
+ *
+ * @param jsonArray array from which nulls are to be removed
+ * @return a new array, with null items removed from all elements
+ */
+ public JsonArray reorder(JsonArray jsonArray) {
+ JsonArray newarr = new JsonArray();
+ for (JsonElement ent : jsonArray) {
+ newarr.add(reorder(ent));
+ }
+
+ return newarr;
+ }
+
+ /**
+ * Recursively re-orders a json element, arranging the keys alphabetically and
+ * removing null items.
+ *
+ * @param jsonEl element from which nulls are to be removed
+ * @return a new element, with null items removed
+ */
+ public JsonElement reorder(JsonElement jsonEl) {
+ if (jsonEl == null) {
+ return null;
+
+ } else if (jsonEl.isJsonObject()) {
+ return reorder(jsonEl.getAsJsonObject());
+
+ } else if (jsonEl.isJsonArray()) {
+ return reorder(jsonEl.getAsJsonArray());
+
+ } else {
+ return jsonEl;
+ }
+ }
+}
--- /dev/null
+/*-
+ * ============LICENSE_START=======================================================
+ * policy-management
+ * ================================================================================
+ * Copyright (C) 2017-2018 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.gson;
+
+import com.google.gson.GsonBuilder;
+import com.google.gson.TypeAdapterFactory;
+import org.onap.policy.common.gson.JacksonHandler;
+
+/**
+ * Used to builder a utility class.
+ */
+public class GsonTestUtilsBuilder {
+ private final GsonBuilder gsonBldr;
+
+ /**
+ * Constructs the object.
+ */
+ public GsonTestUtilsBuilder() {
+ gsonBldr = new GsonBuilder();
+
+ // register jackson behaviors with the builder
+ new JacksonHandler(gsonBldr);
+ }
+
+ /**
+ * Builds the utility.
+ *
+ * @return a new utility
+ */
+ public GsonTestUtils build() {
+ return new GsonTestUtils(gsonBldr.create());
+ }
+
+ /**
+ * Adds gson support for serializing a mock of a class.
+ *
+ * @param clazz mocked class to be supported
+ * @param sgson gson serializer
+ */
+ protected <T> void addMock(Class<T> clazz, TypeAdapterFactory sgson) {
+ gsonBldr.registerTypeAdapterFactory(sgson);
+ }
+}
--- /dev/null
+/*
+ * ============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.gson;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonWriter;
+import java.io.IOException;
+import java.io.StringReader;
+import org.junit.Test;
+
+public class GsonSerializerTest {
+
+ @Test
+ public void testReadJsonReader() {
+ JsonReader rdr = new JsonReader(new StringReader("10"));
+
+ GsonSerializer<Object> ser = new GsonSerializer<Object>() {
+ @Override
+ public void write(JsonWriter out, Object value) throws IOException {
+ // do nothing
+ }
+ };
+
+ assertThatThrownBy(() -> ser.read(rdr)).isInstanceOf(UnsupportedOperationException.class)
+ .hasMessage("read from pseudo TypeAdapter");
+ }
+}
--- /dev/null
+/*
+ * ============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.gson;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import com.google.gson.Gson;
+import com.google.gson.TypeAdapter;
+import com.google.gson.TypeAdapterFactory;
+import com.google.gson.reflect.TypeToken;
+import com.google.gson.stream.JsonWriter;
+import java.io.IOException;
+import org.junit.Before;
+import org.junit.Test;
+
+public class GsonTestUtilsBuilderTest {
+
+ private GsonTestUtilsBuilder bldr;
+ private GsonTestUtils utils;
+
+ @Before
+ public void setUp() {
+ bldr = new MyBuilder();
+ utils = bldr.build();
+ }
+
+ @Test
+ public void testBuilderAddMock() {
+ PreMock pre = mock(PreMock.class);
+ when(pre.getId()).thenReturn(2000);
+
+ assertEquals("{\"name\":2000}", utils.gsonEncode(pre));
+ }
+
+ /**
+ * Builder that provides an adapter for mock(PreMock.class).
+ */
+ private static class MyBuilder extends GsonTestUtilsBuilder {
+ public MyBuilder() {
+ TypeAdapterFactory sgson = new TypeAdapterFactory() {
+ @Override
+ public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
+ Class<? super T> clazz = type.getRawType();
+
+ if (PreMock.class.isAssignableFrom(clazz)) {
+ return new GsonSerializer<T>() {
+ @Override
+ public void write(JsonWriter out, T value) throws IOException {
+ PreMock obj = (PreMock) value;
+ out.beginObject().name("name").value(obj.getId()).endObject();
+ }
+ };
+ }
+
+ return null;
+ }
+ };
+
+ addMock(PreMock.class, sgson);
+ }
+ }
+
+ /**
+ * Class that will be mocked.
+ */
+ public static class PreMock {
+ protected int id = 1000;
+
+ public int getId() {
+ return id;
+ }
+ }
+}
--- /dev/null
+/*
+ * ============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.gson;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonNull;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParseException;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import javax.script.ScriptException;
+import org.junit.Before;
+import org.junit.Test;
+
+public class GsonTestUtilsTest {
+ private static final String HELLO = "hello";
+
+ private GsonTestUtils utils;
+
+ @Before
+ public void setUp() {
+ utils = new GsonTestUtils();
+ }
+
+ @Test
+ public void testGetGson() {
+ assertNotNull(utils.getGson());
+ }
+
+ @Test
+ public void testGsonRoundTrip() {
+ Data data = new Data();
+ data.setId(500);
+
+ // try with null text
+ data.setText(null);
+ assertEquals(data.toString(), utils.gsonRoundTrip(data, Data.class).toString());
+
+ // try with non-null text
+ data.setText(HELLO);
+ assertEquals(data.toString(), utils.gsonRoundTrip(data, Data.class).toString());
+ }
+
+ @Test
+ public void testCompareGsonObjectClass_testCompareGsonObjectFile() {
+ Data data = new Data();
+ data.setId(500);
+ data.setText(HELLO);
+
+ utils.compareGson(data, GsonTestUtilsTest.class);
+
+ // file not found
+ assertThatThrownBy(() -> utils.compareGson(data,
+ new File(GsonTestUtilsTest.class.getSimpleName() + "-NotFound.json")))
+ .isInstanceOf(JsonParseException.class)
+ .hasCauseInstanceOf(FileNotFoundException.class);
+
+ // force I/O error while reading file
+ GsonTestUtils utils2 = new GsonTestUtils() {
+ @Override
+ protected String readFile(File file) throws IOException {
+ throw new IOException("expected exception");
+ }
+ };
+ assertThatThrownBy(() -> utils2.compareGson(data, GsonTestUtilsTest.class))
+ .isInstanceOf(JsonParseException.class).hasCauseInstanceOf(IOException.class)
+ .hasMessage("error reading: GsonTestUtilsTest.json");
+ }
+
+ @Test
+ public void testCompareGsonObjectString() {
+ Data data = new Data();
+ data.setId(600);
+ data.setText(HELLO);
+
+ utils.compareGson(data, "{'id': ${obj.id}, 'text': '${obj.text}'}".replace('\'', '"'));
+ }
+
+ @Test
+ public void testCompareGsonObjectJsonElement() {
+ Data data = new Data();
+ data.setId(650);
+ data.setText(HELLO);
+
+ JsonObject json = new JsonObject();
+ json.addProperty("id", data.getId());
+ json.addProperty("text", data.getText());
+
+ utils.compareGson(data, json);
+
+ // mismatch
+ data.setText("world");
+ assertThatThrownBy(() -> utils.compareGson(data, json)).isInstanceOf(AssertionError.class);
+ }
+
+ @Test
+ public void testApplyScripts() {
+ Data data = new Data();
+ data.setId(700);
+ data.setText(HELLO);
+
+ String result = utils.applyScripts("no interpolation", data);
+ assertEquals("no interpolation", result);
+
+ result = utils.applyScripts("${obj.id} at start, ${obj.text} in middle, and end ${obj.id}", data);
+ assertEquals("700 at start, hello in middle, and end 700", result);
+
+ // try null value
+ data.setText(null);
+ result = utils.applyScripts("use ${obj.text} this", data);
+ assertEquals("use null this", result);
+
+ assertThatThrownBy(() -> utils.applyScripts("use ${obj.text} this", null)).isInstanceOf(RuntimeException.class)
+ .hasCauseInstanceOf(ScriptException.class).hasMessage("cannot expand element: ${obj.text}");
+ }
+
+ @Test
+ public void testReorderJsonObject() {
+ // insert properties in a non-alphabetical order
+ JsonObject inner = new JsonObject();
+ inner.addProperty("objBint", 100);
+ inner.add("objBNull", JsonNull.INSTANCE);
+ inner.addProperty("objB", true);
+
+ JsonArray arr = new JsonArray();
+ arr.add(110);
+ arr.add(inner);
+ arr.add(false);
+
+ JsonObject outer = new JsonObject();
+ outer.add("objANull", JsonNull.INSTANCE);
+ outer.addProperty("objA", true);
+ outer.addProperty("objAStr", "obj-a-string");
+ outer.add("nested-array", arr);
+
+ outer = utils.reorder(outer);
+ assertEquals("{'nested-array':[110,{'objB':true,'objBint':100},false],'objA':true,'objAStr':'obj-a-string'}"
+ .replace('\'', '"'), outer.toString());
+ }
+
+ @Test
+ public void testReorderJsonArray() {
+ // insert properties in a non-alphabetical order
+ JsonObject inner = new JsonObject();
+ inner.add("objCNull", JsonNull.INSTANCE);
+ inner.addProperty("objCStr", "obj-c-string");
+ inner.addProperty("objC", true);
+
+ JsonArray arr = new JsonArray();
+ arr.add(200);
+ arr.add(inner);
+ arr.add(false);
+
+ arr = utils.reorder(arr);
+ assertEquals("[200,{'objC':true,'objCStr':'obj-c-string'},false]".replace('\'', '"'), arr.toString());
+ }
+
+ @Test
+ public void testReorderJsonElement() {
+ // null element
+ JsonElement jsonEl = null;
+ assertNull(utils.reorder(jsonEl));
+
+ // object element
+ JsonObject obj = new JsonObject();
+ obj.add("objDNull", JsonNull.INSTANCE);
+ obj.addProperty("objDStr", "obj-d-string");
+ obj.addProperty("objD", true);
+ jsonEl = obj;
+ jsonEl = utils.reorder(jsonEl);
+ assertEquals("{'objD':true,'objDStr':'obj-d-string'}".replace('\'', '"'), jsonEl.toString());
+
+ // boolean
+ jsonEl = obj.get("objD");
+ jsonEl = utils.reorder(jsonEl);
+ assertEquals("true", jsonEl.toString());
+
+ // JsonNull
+ jsonEl = JsonNull.INSTANCE;
+ jsonEl = utils.reorder(jsonEl);
+ assertEquals("null", jsonEl.toString());
+
+ // array element
+ JsonObject inner = new JsonObject();
+ inner.add("objENull", JsonNull.INSTANCE);
+ inner.addProperty("objEStr", "obj-e-string");
+ inner.addProperty("objE", true);
+
+ JsonArray arr = new JsonArray();
+ arr.add(300);
+ arr.add(inner);
+ arr.add(false);
+ jsonEl = arr;
+ jsonEl = utils.reorder(jsonEl);
+ assertEquals("[300,{'objE':true,'objEStr':'obj-e-string'},false]".replace('\'', '"'), jsonEl.toString());
+ }
+
+ public static class Data {
+ private int id;
+ private String text;
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getText() {
+ return text;
+ }
+
+ public void setText(String text) {
+ this.text = text;
+ }
+
+ @Override
+ public String toString() {
+ return "Data [id=" + id + ", text=" + text + "]";
+ }
+ }
+}
--- /dev/null
+{
+ "id": ${obj.id},
+ "text": "${obj.text}"
+}