summaryrefslogtreecommitdiffstats
path: root/dcaedt_catalog/commons/src
diff options
context:
space:
mode:
authorStone, Avi (as206k) <as206k@att.com>2018-04-12 15:46:31 +0300
committerStone, Avi (as206k) <as206k@att.com>2018-04-12 15:49:38 +0300
commit5032434b101f25fa44d2e1f8dc8393e30af1ed4f (patch)
tree2dc7d37a8048e025c7412af080640da4c9a22b65 /dcaedt_catalog/commons/src
parent2205633792f95f46a02bbf8f87f0c2637265d924 (diff)
DCAE-D be initial commit
DCAE-D be initial commit Issue-ID: SDC-1218 Change-Id: Id18ba96c499e785aa9ac395fbaf32d57f08c281b Signed-off-by: Stone, Avi (as206k) <as206k@att.com>
Diffstat (limited to 'dcaedt_catalog/commons/src')
-rw-r--r--dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Action.java11
-rw-r--r--dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Actions.java201
-rw-r--r--dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Future.java35
-rw-r--r--dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/FutureHandler.java13
-rw-r--r--dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Futures.java257
-rw-r--r--dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Http.java107
-rw-r--r--dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/JSONHttpMessageConverter.java100
-rw-r--r--dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/ListBuilder.java59
-rw-r--r--dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/MapBuilder.java80
-rw-r--r--dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Neo.java54
-rw-r--r--dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Proxies.java37
-rw-r--r--dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Proxy.java144
-rw-r--r--dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Proxy.pojo145
-rw-r--r--dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/ProxyBuilder.java92
-rw-r--r--dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Recycler.java329
15 files changed, 1664 insertions, 0 deletions
diff --git a/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Action.java b/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Action.java
new file mode 100644
index 0000000..fb36950
--- /dev/null
+++ b/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Action.java
@@ -0,0 +1,11 @@
+package org.onap.sdc.dcae.catalog.commons;
+
+import org.onap.sdc.dcae.catalog.commons.Future;
+
+/**
+ */
+public interface Action<T> {
+
+ public Future<T> execute();
+
+}
diff --git a/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Actions.java b/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Actions.java
new file mode 100644
index 0000000..132b0c0
--- /dev/null
+++ b/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Actions.java
@@ -0,0 +1,201 @@
+package org.onap.sdc.dcae.catalog.commons;
+
+import java.util.List;
+import java.util.LinkedList;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.concurrent.CountDownLatch;
+
+import org.onap.sdc.common.onaplog.OnapLoggerDebug;
+import org.onap.sdc.common.onaplog.OnapLoggerError;
+import org.onap.sdc.common.onaplog.Enums.LogLevel;
+import org.onap.sdc.dcae.catalog.commons.Action;
+import org.onap.sdc.dcae.catalog.commons.Future;
+import org.onap.sdc.dcae.catalog.commons.FutureHandler;
+import org.onap.sdc.dcae.catalog.commons.Futures;
+
+/**
+ */
+public interface Actions {
+
+ /** */
+ public static interface CompoundAction<T> extends Action<List<T>> {
+
+ public CompoundAction<T> addAction(Action<T> theAction);
+
+ public List<Action<T>> actions();
+
+ public Future<List<T>> execute();
+ }
+
+
+ public static class BasicCompoundAction<T> implements CompoundAction<T> {
+
+ private LinkedList<Action<T>> actions = new LinkedList<Action<T>>();
+
+
+
+ public CompoundAction<T> addAction(Action<T> theAction) {
+ this.actions.add(theAction);
+ return this;
+ }
+
+ public List<Action<T>> actions() {
+ return this.actions;
+ }
+
+ public Future<List<T>> execute() {
+ CompoundFuture<T> cf = new CompoundFuture<T>(this.actions.size());
+ for (Action a: this.actions)
+ cf.addFuture(a.execute());
+ return cf;
+ }
+ }
+
+
+ public static class CompoundFuture<T> extends Futures.BasicFuture<List<T>> {
+
+ private static OnapLoggerError errLogger = OnapLoggerError.getInstance();
+ private static OnapLoggerDebug debugLogger = OnapLoggerDebug.getInstance();
+
+ private LinkedList<Future<T>> futures = new LinkedList<Future<T>>();
+ private FutureHandler<T> hnd;
+
+ CompoundFuture(int theActionCount) {
+
+ hnd = new Futures.BasicHandler<T>(new CountDownLatch(theActionCount)) {
+
+ private List<T> results = new ArrayList<T>(Collections.nCopies(theActionCount, null));
+
+ protected void process(Future<T> theResult) {
+ synchronized(CompoundFuture.this) {
+ if (theResult.failed()) {
+ CompoundFuture.this.cause(theResult.cause());
+ //and stop processing of other results
+ this.results = null;
+ //??
+ }
+ else {
+ if (this.results != null)
+ this.results.set(futures.indexOf(theResult), theResult.result());
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Got result for action {}. Count at {}", futures.indexOf(theResult), this.latch.getCount());
+ }
+ if (this.latch.getCount() == 1) {//this was the last result
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Got all results: {}", this.results);
+ CompoundFuture.this.result(this.results);
+ }
+ }
+ }
+ };
+ }
+
+ CompoundFuture<T> addFuture(Future<T> theFuture) {
+ synchronized(this) {
+ futures.add(theFuture);
+ theFuture.setHandler(this.hnd);
+ }
+ return this;
+ }
+
+ }
+
+/*
+ public static class CompoundFutureHandler<T> implements FutureHandler<T> {
+
+ protected List<T> result = null;
+ protected List<Throwable> error = null;
+ protected CountDownLatch latch = null;
+
+ CompoundFutureHandler(int theResultCount) {
+ this(new CountDownLatch(theResultCount));
+ }
+
+ public void handle(Future<T> theResult) {
+ if (this.latch != null) {
+ this.latch.countDown();
+ }
+ }
+
+ public T result()
+ throws InterruptedException, RuntimeException {
+ return result(true);
+ }
+
+ public BasicHandler<T> waitForCompletion() throws InterruptedException {
+ this.latch.await();
+ return this;
+ }
+
+ }
+*/
+
+ public static class Sequence<T> implements Action<List<T>> {
+
+ private static OnapLoggerError errLogger = OnapLoggerError.getInstance();
+ private static OnapLoggerDebug debugLogger = OnapLoggerDebug.getInstance();
+
+ private List<Action<T>> actions = new LinkedList<Action<T>>();
+ private int current = 0;
+ private SequenceFuture<T> future = new SequenceFuture<T>();
+
+ public Sequence<T> add(Action<T> theAction) {
+ if (this.current > 0)
+ throw new IllegalStateException("In execution");
+ this.actions.add(theAction);
+ return this;
+ }
+
+ /* we allow 'early' access to the future so that a client can pass its reference while
+ * it still builds the sequence, for example.
+ */
+ public Future<List<T>> future() {
+ return this.future;
+ }
+
+ //need to add protection when for the 'no action' case
+ public Future<List<T>> execute() {
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Starting serialized execution of {}", actions);
+ if (hasNext())
+ next().execute().setHandler(future.hnd);
+ return this.future;
+ }
+
+ protected boolean hasNext() {
+ return this.current < actions.size();
+ }
+
+ protected Action next() {
+ return actions.get(this.current++);
+ }
+
+ private class SequenceFuture<T> extends Futures.BasicFuture<List<T>> {
+
+ private List<T> results = new LinkedList<T>();
+ private FutureHandler<T> hnd = new Futures.BasicHandler<T>() {
+
+ protected void process(Future<T> theResult) {
+
+ if (theResult.failed()) {
+ SequenceFuture.this.cause(theResult.cause());
+ //and stop processing of other results
+ }
+ else {
+ SequenceFuture.this.results.add(theResult.result());
+ if (Sequence.this.hasNext()) {
+ Sequence.this.next().execute().setHandler(this);
+ }
+ else {
+ SequenceFuture.this.result(SequenceFuture.this.results);
+ }
+ }
+ }
+ };
+
+
+ }
+
+
+
+ }
+
+}
diff --git a/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Future.java b/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Future.java
new file mode 100644
index 0000000..c50f467
--- /dev/null
+++ b/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Future.java
@@ -0,0 +1,35 @@
+package org.onap.sdc.dcae.catalog.commons;
+
+import org.onap.sdc.dcae.catalog.commons.Future;
+import org.onap.sdc.dcae.catalog.commons.FutureHandler;
+
+/**
+ * Modeled after the vertx future
+ */
+public interface Future<T> {
+
+ public T result();
+
+ public Future<T> result(T theResult);
+
+//rename 'cause' to 'failure'
+
+ public Throwable cause();
+
+ public Future<T> cause(Throwable theError);
+
+ public boolean succeeded();
+
+ public boolean failed();
+
+ public boolean complete();
+
+ public T waitForResult() throws Exception;
+
+ //public T waitForResult(long theTimeout) throws Exception;
+
+ public Future<T> waitForCompletion() throws InterruptedException;
+
+ public Future<T> setHandler(FutureHandler<T> theHandler);
+
+}
diff --git a/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/FutureHandler.java b/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/FutureHandler.java
new file mode 100644
index 0000000..b689412
--- /dev/null
+++ b/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/FutureHandler.java
@@ -0,0 +1,13 @@
+package org.onap.sdc.dcae.catalog.commons;
+
+import org.onap.sdc.dcae.catalog.commons.Future;
+
+/**
+ * Modeled after the vertx future
+ */
+@FunctionalInterface
+public interface FutureHandler<T> {
+
+ public void handle(Future<T> theResult);
+
+}
diff --git a/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Futures.java b/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Futures.java
new file mode 100644
index 0000000..ffaf42b
--- /dev/null
+++ b/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Futures.java
@@ -0,0 +1,257 @@
+package org.onap.sdc.dcae.catalog.commons;
+
+import java.util.List;
+import java.util.LinkedList;
+import java.util.Collections;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.function.Function;
+
+import org.onap.sdc.common.onaplog.OnapLoggerDebug;
+import org.onap.sdc.common.onaplog.OnapLoggerError;
+import org.onap.sdc.dcae.catalog.commons.Future;
+import org.onap.sdc.dcae.catalog.commons.FutureHandler;
+import org.onap.sdc.common.onaplog.Enums.LogLevel;
+
+
+/**
+ */
+public class Futures<T> {
+
+ private Futures() {
+ }
+
+
+ public static <T> Future<T> failedFuture(Throwable theError) {
+ return new BasicFuture<T>()
+ .cause(theError);
+ }
+
+ public static <T> Future<T> succeededFuture(T theResult) {
+ return new BasicFuture<T>()
+ .result(theResult);
+ }
+
+ public static <T> Future<T> future() {
+ return new BasicFuture<T>();
+ }
+
+ public static <U,V> Future<V> advance(Future<U> theStep,
+ final Function<U,V> theResultFunction) {
+ return advance(theStep, theResultFunction, Function.identity());
+ }
+
+ public static <U,V> Future<V> advance(Future<U> theStep,
+ final Function<U,V> theResultFunction,
+ final Function<Throwable, Throwable> theErrorFunction) {
+ final Future<V> adv = new BasicFuture<V>();
+ theStep.setHandler(new FutureHandler<U>() {
+ public void handle(Future<U> theResult) {
+ if (theResult.failed())
+ adv.cause(theErrorFunction.apply(theResult.cause()));
+ else
+ adv.result(theResultFunction.apply(theResult.result()));
+ }
+ });
+ return adv;
+ }
+
+ /** */
+ public static class BasicFuture<T> implements Future<T> {
+
+ protected boolean succeeded,
+ failed;
+
+ protected FutureHandler<T> handler;
+ protected Throwable cause;
+ protected T result;
+
+
+ protected BasicFuture() {
+ }
+
+ public T result() {
+ return this.result;
+ }
+
+ public Future<T> result(T theResult) {
+ this.result = theResult;
+ this.succeeded = true;
+ this.cause = null;
+ this.failed = false;
+ callHandler();
+ return this;
+ }
+
+ public Throwable cause() {
+ return this.cause;
+ }
+
+ public Future<T> cause(Throwable theCause) {
+ this.cause = theCause;
+ this.failed = true;
+ this.result = null;
+ this.succeeded = false;
+ callHandler();
+ return this;
+ }
+
+ public boolean succeeded() {
+ return this.succeeded;
+ }
+
+ public boolean failed() {
+ return this.failed;
+ }
+
+ public boolean complete() {
+ return this.failed || this.succeeded;
+ }
+
+ public Future<T> setHandler(FutureHandler<T> theHandler) {
+ this.handler = theHandler;
+ callHandler();
+ return this;
+ }
+
+ public T waitForResult() throws Exception {
+ BasicHandler<T> hnd = buildHandler();
+ setHandler(hnd);
+ hnd.waitForCompletion();
+ if (failed())
+ throw (Exception)cause();
+ else
+ return result();
+ }
+
+ public Future<T> waitForCompletion() throws InterruptedException {
+ BasicHandler<T> hnd = buildHandler();
+ setHandler(hnd);
+ hnd.waitForCompletion();
+ return this;
+ }
+
+ protected void callHandler() {
+ if (this.handler != null && complete()) {
+ this.handler.handle(this);
+ }
+ }
+
+ protected BasicHandler<T> buildHandler() {
+ return new BasicHandler<T>();
+ }
+ }
+
+
+ /** */
+ public static class BasicHandler<T>
+ implements FutureHandler<T> {
+
+ protected T result = null;
+ protected Throwable error = null;
+ protected CountDownLatch latch = null;
+
+ BasicHandler() {
+ this(new CountDownLatch(1));
+ }
+
+ BasicHandler(CountDownLatch theLatch) {
+ this.latch = theLatch;
+ }
+
+ public void handle(Future<T> theResult) {
+ process(theResult);
+ if (this.latch != null) {
+ this.latch.countDown();
+ }
+ }
+
+ protected void process(Future<T> theResult) {
+ if (theResult.failed()) {
+ this.error = theResult.cause();
+ }
+ else {
+ this.result = theResult.result();
+ }
+ }
+
+ public T result(boolean doWait)
+ throws InterruptedException, RuntimeException {
+ if (doWait) {
+ waitForCompletion();
+ }
+ if (null == this.error)
+ return this.result;
+
+ throw new RuntimeException(this.error);
+ }
+
+ public T result()
+ throws InterruptedException, RuntimeException {
+ return result(true);
+ }
+
+ public BasicHandler<T> waitForCompletion() throws InterruptedException {
+ this.latch.await();
+ return this;
+ }
+ }
+
+ /** */
+ public static class Accumulator<T> extends BasicFuture<List<T>>
+ implements Future<List<T>> {
+
+ protected List<Future<T>> futures = new LinkedList<Future<T>>();
+ //protected List<T> results = new LinkedList<T>();
+ protected BasicHandler<T> handler = null;
+
+ private static OnapLoggerError errLogger = OnapLoggerError.getInstance();
+ private static OnapLoggerDebug debugLogger = OnapLoggerDebug.getInstance();
+
+ public Accumulator() {
+ this.result = new LinkedList<T>();
+ }
+
+ public Accumulator<T> add(Future<T> theFuture) {
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Intersection add");
+ this.futures.add(theFuture);
+ this.result.add(null);
+ return this;
+ }
+
+ public Accumulator<T> addAll(Accumulator<T> theFutures) {
+
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Intersection addAll");
+
+ return this;
+ }
+
+ public Future<List<T>> accumulate() {
+ this.futures = Collections.unmodifiableList(this.futures);
+ this.handler = new BasicHandler<T>(new CountDownLatch(this.futures.size())) {
+ protected void process(Future<T> theResult) {
+ if (theResult.failed()) {
+ Accumulator.this.cause = theResult.cause();
+ }
+ else {
+ Accumulator.this.result.set(
+ Accumulator.this.futures.indexOf(theResult), theResult.result());
+ }
+ if (this.latch.getCount() == 1) {
+ if (Accumulator.this.cause != null)
+ Accumulator.this.cause(Accumulator.this.cause);
+ else
+ Accumulator.this.result(Accumulator.this.result);
+ }
+ }
+ };
+ futures.stream()
+ .forEach(f -> f.setHandler(this.handler));
+
+ return this;
+ }
+
+ }
+
+
+}
diff --git a/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Http.java b/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Http.java
new file mode 100644
index 0000000..0f28495
--- /dev/null
+++ b/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Http.java
@@ -0,0 +1,107 @@
+package org.onap.sdc.dcae.catalog.commons;
+
+import java.util.List;
+
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.http.client.SimpleClientHttpRequestFactory;
+import org.springframework.http.converter.HttpMessageConverter;
+import org.springframework.util.concurrent.ListenableFutureCallback;
+import org.springframework.web.client.AsyncRestTemplate;
+import org.springframework.web.client.HttpClientErrorException;
+import org.springframework.web.client.RestClientException;
+import org.springframework.web.client.RestTemplate;
+
+public class Http {
+
+ protected Http() {
+ }
+
+
+ public static <T> Future<T> exchange(String theUri, HttpMethod theMethod, HttpEntity theRequest, Class<T> theResponseType) {
+
+ AsyncRestTemplate restTemplate = new AsyncRestTemplate();
+
+ List<HttpMessageConverter<?>> converters = restTemplate.getMessageConverters();
+ converters.add(0, new JSONHttpMessageConverter());
+ restTemplate.setMessageConverters(converters);
+
+ HttpFuture<T> result = new HttpFuture<T>();
+ try {
+ restTemplate
+ .exchange(theUri, theMethod, theRequest, theResponseType)
+ .addCallback(result.callback);
+ }
+ catch (RestClientException rcx) {
+ return Futures.failedFuture(rcx);
+ }
+ catch (Exception x) {
+ return Futures.failedFuture(x);
+ }
+
+ return result;
+ }
+
+ /**
+ *
+ * @param theUri
+ * @param theMethod
+ * @param theRequest
+ * @param theResponseType
+ * @param readTimeOut pass -1 if you dont need to customize the read time out interval
+ * @return
+ */
+ public static <T> ResponseEntity<T> exchangeSync(String theUri, HttpMethod theMethod, HttpEntity theRequest, Class<T> theResponseType, int readTimeOut) {
+
+ RestTemplate restTemplate = new RestTemplate();
+
+ if(readTimeOut!=-1){
+ SimpleClientHttpRequestFactory rf = (SimpleClientHttpRequestFactory) restTemplate.getRequestFactory();
+ rf.setReadTimeout(1 * readTimeOut);
+ }
+
+ List<HttpMessageConverter<?>> converters = restTemplate.getMessageConverters();
+ converters.add(0, new JSONHttpMessageConverter());
+ restTemplate.setMessageConverters(converters);
+ ResponseEntity<T> result = null;
+
+ try {
+ result = restTemplate.exchange(theUri, theMethod, theRequest, theResponseType);
+ }
+ catch (RestClientException rcx) {
+ return new ResponseEntity<T>((T) rcx.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+ catch (Exception x) {
+ return new ResponseEntity<T>((T) x.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+
+ return result;
+ }
+
+
+
+ public static class HttpFuture<T> extends Futures.BasicFuture<T> {
+
+ HttpFuture() {
+ }
+
+ ListenableFutureCallback<ResponseEntity<T>> callback = new ListenableFutureCallback<ResponseEntity<T>>() {
+
+ public void onSuccess(ResponseEntity<T> theResult) {
+ HttpFuture.this.result(theResult.getBody());
+ }
+
+ public void onFailure(Throwable theError) {
+ if (theError instanceof HttpClientErrorException) {
+ HttpFuture.this.cause(new Exception((HttpClientErrorException)theError));
+ }
+ else {
+ HttpFuture.this.cause(theError);
+ }
+ }
+ };
+
+ }
+}
diff --git a/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/JSONHttpMessageConverter.java b/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/JSONHttpMessageConverter.java
new file mode 100644
index 0000000..e711279
--- /dev/null
+++ b/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/JSONHttpMessageConverter.java
@@ -0,0 +1,100 @@
+package org.onap.sdc.dcae.catalog.commons;
+
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.Writer;
+import java.lang.reflect.Type;
+import java.nio.charset.Charset;
+
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpInputMessage;
+import org.springframework.http.HttpOutputMessage;
+import org.springframework.http.MediaType;
+import org.springframework.http.converter.AbstractHttpMessageConverter;
+import org.springframework.http.converter.HttpMessageNotReadableException;
+import org.springframework.http.converter.HttpMessageNotWritableException;
+
+import org.json.JSONObject;
+import org.json.JSONArray;
+import org.json.JSONTokener;
+import org.json.JSONException;
+
+/**
+ */
+public class JSONHttpMessageConverter extends AbstractHttpMessageConverter<Object> {
+
+ public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
+
+ /** */
+ public JSONHttpMessageConverter() {
+ super(new MediaType("application", "json", DEFAULT_CHARSET));
+ }
+ /*
+ @Override
+ public boolean canRead(Class<?> theClazz, MediaType theMediaType) {
+ return canRead(theMediaType);
+ }
+
+ @Override
+ public boolean canWrite(Class<?> theClazz, MediaType theMediaType) {
+ return canWrite(theMediaType);
+ }
+ */
+ @Override
+ protected boolean supports(Class<?> theClazz) {
+ return theClazz.equals(JSONObject.class) ||
+ theClazz.equals(JSONArray.class);
+ }
+
+ @Override
+ protected Object readInternal(Class<?> theClazz, HttpInputMessage theInputMessage)
+ throws IOException, HttpMessageNotReadableException {
+
+ Reader json = new InputStreamReader(theInputMessage.getBody(), getCharset(theInputMessage.getHeaders()));
+
+ try {
+ if (theClazz.equals(JSONObject.class))
+ return new JSONObject(new JSONTokener(json));
+ if (theClazz.equals(JSONArray.class))
+ return new JSONArray(new JSONTokener(json));
+
+ throw new HttpMessageNotReadableException("Could not process input, cannot handle " + theClazz);
+ }
+ catch (JSONException jsonx) {
+ throw new HttpMessageNotReadableException("Could not read JSON: " + jsonx.getMessage(), jsonx);
+ }
+ }
+
+ @Override
+ protected void writeInternal(Object theObject, HttpOutputMessage theOutputMessage)
+ throws IOException, HttpMessageNotWritableException {
+
+ Writer writer = new OutputStreamWriter(theOutputMessage.getBody(), getCharset(theOutputMessage.getHeaders()));
+
+ try {
+ if (theObject instanceof JSONObject) {
+ ((JSONObject)theObject).write(writer);
+ }
+ else if (theObject instanceof JSONArray) {
+ ((JSONArray)theObject).write(writer);
+ }
+
+ writer.close();
+ }
+ catch(JSONException jsonx) {
+ throw new HttpMessageNotWritableException("Could not write JSON: " + jsonx.getMessage(), jsonx);
+ }
+ }
+
+ private Charset getCharset(HttpHeaders theHeaders) {
+ if (theHeaders != null &&
+ theHeaders.getContentType() != null &&
+ theHeaders.getContentType().getCharSet() != null) {
+ return theHeaders.getContentType().getCharSet();
+ }
+ return DEFAULT_CHARSET;
+ }
+
+}
diff --git a/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/ListBuilder.java b/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/ListBuilder.java
new file mode 100644
index 0000000..2538893
--- /dev/null
+++ b/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/ListBuilder.java
@@ -0,0 +1,59 @@
+package org.onap.sdc.dcae.catalog.commons;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.onap.sdc.dcae.catalog.commons.ListBuilder;
+
+import java.util.LinkedList;
+
+public class ListBuilder<T> {
+
+ private List<T> list;
+
+ public ListBuilder() {
+ this.list = new LinkedList<T>();
+ }
+
+ public boolean isEmpty() {
+ return this.list.isEmpty();
+ }
+
+ public ListBuilder add(T theValue) {
+ this.list.add(theValue);
+ return this;
+ }
+
+ public ListBuilder addAll(final Iterable<? extends T> theValues) {
+ for (final T val : theValues) {
+ this.list.add(val);
+ }
+ return this;
+ }
+
+ public ListBuilder addAll(final List<? extends T> theList) {
+ this.list.addAll(theList);
+ return this;
+ }
+
+ public ListBuilder addAll(final T[] theArray) {
+ for (T t: theArray) this.list.add(t);
+ return this;
+ }
+
+ public List build() {
+ return this.list;
+ }
+
+ public List buildOpt() {
+ return this.list.isEmpty() ? null : this.list;
+ }
+
+ public static <V> List<V> asList(V[] theArray) {
+ return Arrays.asList(theArray);
+ }
+
+ public static <V> List<V> asListOpt(V[] theArray) {
+ return (theArray != null && theArray.length > 0) ? Arrays.asList(theArray) : null;
+ }
+}
diff --git a/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/MapBuilder.java b/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/MapBuilder.java
new file mode 100644
index 0000000..3aa2a56
--- /dev/null
+++ b/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/MapBuilder.java
@@ -0,0 +1,80 @@
+package org.onap.sdc.dcae.catalog.commons;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.util.function.Function;
+
+import org.onap.sdc.dcae.catalog.commons.MapBuilder;
+
+import java.util.function.BiFunction;
+
+public class MapBuilder<K,V> {
+
+ private Map<K,V> map;
+
+ public MapBuilder() {
+ this.map = new HashMap<K,V>();
+ }
+
+ public boolean isEmpty() {
+ return this.map.isEmpty();
+ }
+
+ public MapBuilder<K,V> put(K theKey, V theValue) {
+ this.map.put(theKey, theValue);
+ return this;
+ }
+
+ public MapBuilder<K,V> putOpt(K theKey, V theValue) {
+ if (theValue != null) {
+ this.map.put(theKey, theValue);
+ }
+ return this;
+ }
+
+ public MapBuilder<K,V> put(final Map.Entry<? extends K, ? extends V> theEntry) {
+ this.map.put(theEntry.getKey(), theEntry.getValue());
+ return this;
+ }
+
+ public MapBuilder<K,V> putOpt(final Map.Entry<? extends K, ? extends V> theEntry) {
+ if (theEntry != null) {
+ this.map.put(theEntry.getKey(), theEntry.getValue());
+ }
+ return this;
+ }
+
+ public MapBuilder<K,V> putAll(final Iterable<? extends Map.Entry<? extends K, ? extends V>> theEntries) {
+ for (final Map.Entry<? extends K, ? extends V> e : theEntries) {
+ this.map.put(e.getKey(), e.getValue());
+ }
+ return this;
+ }
+
+ /* If theEntries contains multiple entries with the same key then the key gets a suffix in order to make it unique
+ .. */
+// public MapBuilder forceAll(final Iterable<? extends Map.Entry<? extends K, ? extends V>> theEntries,
+ public MapBuilder<K,V> forceAll(final Iterable<? extends Map.Entry<K, V>> theEntries,
+ Function<Map.Entry<K, V> , K> rekeyFunction) {
+ for (final Map.Entry<? extends K, ? extends V> e : theEntries) {
+ K key = e.getKey();
+ if (this.map.containsKey(key))
+ key = rekeyFunction.apply((Map.Entry<K,V>)e);
+ this.map.put(key, e.getValue());
+ }
+ return this;
+ }
+
+ public MapBuilder<K,V> putAll(final Map<? extends K, ? extends V> theMap) {
+ this.map.putAll(theMap);
+ return this;
+ }
+
+ public Map<K,V> build() {
+ return this.map;
+ }
+
+ public Map<K,V> buildOpt() {
+ return this.map.isEmpty() ? null : this.map;
+ }
+}
diff --git a/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Neo.java b/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Neo.java
new file mode 100644
index 0000000..f818163
--- /dev/null
+++ b/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Neo.java
@@ -0,0 +1,54 @@
+package org.onap.sdc.dcae.catalog.commons;
+
+import java.util.Iterator;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterators;
+
+import org.json.JSONObject;
+
+
+public class Neo {
+
+ /*
+ */
+ public static String literalMap(JSONObject theProps,
+ String theNameAlias,
+ String theValueAlias,
+ String theAssignmentOp,
+ String theRelationOp,
+ Predicate theFieldFilter) {
+ if(theProps.length() == 0)
+ return "";
+ StringBuilder sb = new StringBuilder("");
+ for (Iterator i = Iterators.filter(theProps.keys(),
+ theFieldFilter);
+ i.hasNext();) {
+ String propName = (String)i.next();
+
+ if (theNameAlias != null) {
+ sb.append(theNameAlias)
+ .append('.');
+ }
+ sb.append('`')
+ .append(propName)
+ .append('`')
+ .append(theAssignmentOp)
+ .append(" {")
+ .append(theValueAlias)
+ .append("}.")
+ .append('`')
+ .append(propName)
+ .append('`')
+ .append(theRelationOp);
+ }
+ return sb.substring(0, sb.length() - theRelationOp.length());
+ }
+
+ public static String literalMap(JSONObject theProps,
+ String theAlias) {
+ return literalMap(theProps, null, theAlias, ":", ",", f -> true);
+ }
+
+}
+
diff --git a/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Proxies.java b/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Proxies.java
new file mode 100644
index 0000000..8983599
--- /dev/null
+++ b/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Proxies.java
@@ -0,0 +1,37 @@
+package org.onap.sdc.dcae.catalog.commons;
+
+import java.util.Map;
+import java.lang.reflect.ParameterizedType;
+
+import org.json.JSONObject;
+
+import org.onap.sdc.dcae.catalog.commons.ProxyBuilder;
+
+
+public class Proxies {
+
+ private Proxies() {
+ }
+
+
+ private static ProxyBuilder builder = new ProxyBuilder();
+
+ public static <T> T build(Map theData, Class<T> theType) {
+ return builder.build(new JSONObject(theData), theType);
+ }
+
+ public static <T> T build(Map theData, Map theContextData, Class<T> theType) {
+ return builder.build(new JSONObject(theData), theContextData, theType);
+ }
+
+ public static <T> T build(JSONObject theData, Class<T> theType) {
+ return builder.build(theData, theType);
+ }
+
+ public static <T> Class<T> typeArgument(Class theType) {
+ return (Class<T>)
+ ((ParameterizedType)theType.getGenericSuperclass()).
+ getActualTypeArguments()[0];
+ }
+
+}
diff --git a/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Proxy.java b/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Proxy.java
new file mode 100644
index 0000000..d368886
--- /dev/null
+++ b/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Proxy.java
@@ -0,0 +1,144 @@
+package org.onap.sdc.dcae.catalog.commons;
+
+import java.util.List;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Collections;
+
+import java.util.stream.Collectors;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import java.lang.reflect.Type;
+import java.lang.reflect.Method;
+import java.lang.reflect.Array;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+
+import java.lang.invoke.MethodHandles;
+
+import com.google.common.reflect.Invokable;
+import org.onap.sdc.dcae.catalog.commons.Proxy;
+import org.onap.sdc.dcae.catalog.commons.ProxyBuilder;
+import com.google.common.reflect.AbstractInvocationHandler;
+
+import org.apache.commons.beanutils.ConvertUtils;
+
+import org.json.JSONObject;
+import org.json.JSONArray;
+
+public class Proxy extends AbstractInvocationHandler {
+
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target(ElementType.METHOD)
+
+ public static @interface DataMap {
+
+ public String map() default "";
+
+ public boolean proxy() default false;
+
+ public Class elementType() default Void.class;
+ }
+
+
+ public static final Constructor<MethodHandles.Lookup> lookupHandleConstructor;
+
+ static {
+ try {
+ lookupHandleConstructor =
+ MethodHandles.Lookup.class.getDeclaredConstructor(Class.class,
+ int.class);
+
+ if (!lookupHandleConstructor.isAccessible()) {
+ lookupHandleConstructor.setAccessible(true);
+ }
+ }
+ catch (Exception x) {
+ throw new RuntimeException(x);
+ }
+ }
+
+
+ private JSONObject data;
+ private ProxyBuilder builder;
+
+ protected Proxy(JSONObject theData, ProxyBuilder theBuilder) {
+ this.data = theData;
+ this.builder = theBuilder;
+ }
+
+ public JSONObject data() {
+ return this.data;
+ }
+
+ public ProxyBuilder getBuilder() {
+ return this.builder;
+ }
+
+ protected Object handleInvocation(
+ Object theProxy,Method theMethod,Object[] theArgs)
+ throws Throwable {
+ if (theMethod.isDefault()) {
+ final Class<?> declaringClass = theMethod.getDeclaringClass();
+
+ return lookupHandleConstructor
+ .newInstance(declaringClass, MethodHandles.Lookup.PRIVATE)
+ .unreflectSpecial(theMethod, declaringClass)
+ .bindTo(theProxy)
+ .invokeWithArguments(theArgs);
+ }
+
+ String key = theMethod.getName();
+
+ Proxy.DataMap dataMap = (Proxy.DataMap)theMethod.getAnnotation(Proxy.DataMap.class);
+ if (dataMap != null) {
+ String dataKey = dataMap.map();
+ if (dataKey != null && !"".equals(dataKey))
+ key = dataKey;
+ }
+
+ //this is ugly, can this be done through an extension mechanism such as plugging in functions?
+ if ( builder.hasExtension(key) )
+ return this.builder.extension(key).apply(this, theArgs);
+
+ //we give priority to the context (because of the 'catalog' property issue in catalog service) but
+ //how natural is this?
+ Object val = this.builder.context(key);
+ if (val == null)
+ val = this.data.opt(key);
+
+ if (val == null)
+ return null;
+
+//as we create proxies here we should store them back in the 'data' so that we do not do it again
+//can we always 'recognize' them?
+ if (val instanceof String &&
+ String.class != theMethod.getReturnType()) {
+ //??This will yield a POJO ..
+ return ConvertUtils.convert((String)val, theMethod.getReturnType());
+ }
+ else if (val instanceof JSONObject) {
+ if (dataMap != null && dataMap.proxy()) {
+ return builder.build((JSONObject)val, theMethod.getReturnType());
+ }
+ }
+ else if (val instanceof JSONArray&& dataMap != null &&
+ dataMap.proxy() &&
+ List.class.isAssignableFrom(theMethod.getReturnType())) {
+
+ List res = (List) theMethod.getReturnType().newInstance();
+ for (int i = 0; i < ((JSONArray) val).length(); i++) {
+ res.add(builder.build(((JSONArray) val).getJSONObject(i), dataMap.elementType()));
+ }
+ return res;
+
+ }
+ return val;
+ }
+}
diff --git a/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Proxy.pojo b/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Proxy.pojo
new file mode 100644
index 0000000..b3b5cb9
--- /dev/null
+++ b/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Proxy.pojo
@@ -0,0 +1,145 @@
+package org.onap.sdc.dcae.catalog.commons;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Collections;
+
+import java.util.stream.Collectors;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import java.lang.reflect.Type;
+import java.lang.reflect.Method;
+import java.lang.reflect.Array;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+
+import java.lang.invoke.MethodHandles;
+
+import com.google.common.reflect.Invokable;
+import com.google.common.reflect.AbstractInvocationHandler;
+
+import org.apache.commons.beanutils.ConvertUtils;
+
+
+/**
+ */
+public class Proxy
+ extends AbstractInvocationHandler {
+
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target(ElementType.METHOD)
+
+ public static @interface DataMap {
+
+ public String map() default "";
+
+ public boolean proxy() default false;
+
+ public Class elementType() default Void.class;
+ }
+
+
+ public static Constructor<MethodHandles.Lookup> lookupHandleConstructor;
+
+ static {
+ try {
+ lookupHandleConstructor =
+ MethodHandles.Lookup.class.getDeclaredConstructor(Class.class,
+ int.class);
+
+ if (!lookupHandleConstructor.isAccessible()) {
+ lookupHandleConstructor.setAccessible(true);
+ }
+ }
+ catch (Exception x) {
+ throw new RuntimeException(x);
+ }
+ }
+
+
+ private Map data;
+ private ProxyBuilder builder;
+
+ protected Proxy(Map theData, ProxyBuilder theBuilder) {
+ this.data = theData;
+ this.builder = theBuilder;
+ }
+
+ public Map data() {
+ return this.data;
+ }
+
+ public ProxyBuilder getBuilder() {
+ return this.builder;
+ }
+
+ protected Object handleInvocation(
+ Object theProxy,Method theMethod,Object[] theArgs)
+ throws Throwable {
+ if (theMethod.isDefault()) {
+ final Class<?> declaringClass = theMethod.getDeclaringClass();
+ /*
+ return MethodHandles.lookup()
+ .in(declaringClass)
+ .unreflectSpecial(theMethod, declaringClass)
+ .bindTo(theProxy)
+ .invokeWithArguments(theArgs);
+ */
+ return lookupHandleConstructor
+ .newInstance(declaringClass, MethodHandles.Lookup.PRIVATE)
+ .unreflectSpecial(theMethod, declaringClass)
+ .bindTo(theProxy)
+ .invokeWithArguments(theArgs);
+ }
+
+ String key = theMethod.getName();
+
+ Proxy.DataMap dataMap = (Proxy.DataMap)theMethod.getAnnotation(Proxy.DataMap.class);
+ if (dataMap != null) {
+ String dataKey = dataMap.map();
+ if (dataKey != null && !"".equals(dataKey))
+ key = dataKey;
+ }
+
+ //this is ugly, can this be done through an extension mechanism such as plugging in functions?
+ if ( builder.hasExtension(key) )
+ return this.builder.extension(key).apply(this, theArgs);
+
+ Object val = this.data.getOrDefault(key, this.builder.context(key));
+
+System.out.println("!! " + key + " : " + val);
+
+//as we create proxies here we should store them back in the 'data' so that we do not do it again
+//can we always 'recognize' them?
+ if (val instanceof String &&
+ String.class != theMethod.getReturnType()) {
+ return ConvertUtils.convert((String)val, theMethod.getReturnType());
+ }
+ else if (val instanceof Map) {
+ if (dataMap != null && dataMap.proxy()) {
+ return builder.build((Map)val, theMethod.getReturnType());
+ }
+ }
+ else if (val instanceof List) {
+ if (dataMap != null && dataMap.proxy()) {
+ return ((List)val)
+ .stream()
+ .map(e -> this.builder.build((Map)e, dataMap.elementType()))
+ .collect(Collectors.toList());
+ }
+ }
+/*
+ else if (val.getClass().isArray()) {
+ if (dataMap != null && dataMap.proxy()) {
+ }
+ }
+*/
+ return val;
+ }
+}
diff --git a/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/ProxyBuilder.java b/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/ProxyBuilder.java
new file mode 100644
index 0000000..e3a422a
--- /dev/null
+++ b/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/ProxyBuilder.java
@@ -0,0 +1,92 @@
+package org.onap.sdc.dcae.catalog.commons;
+
+import java.util.Map;
+
+import java.util.function.Function;
+import java.util.function.BiFunction;
+
+import org.apache.commons.beanutils.ConvertUtils;
+import org.apache.commons.beanutils.Converter;
+
+import org.json.JSONObject;
+
+import org.onap.sdc.dcae.catalog.commons.Proxy;
+import org.onap.sdc.dcae.catalog.commons.ProxyBuilder;
+
+
+public class ProxyBuilder {
+
+ private Map<String, ?> context;
+ private Map<String, BiFunction<Proxy, Object[], Object>> extensions;
+
+ public ProxyBuilder() {
+ }
+/*
+ public <T> T build(Map theData, Class<T> theType) {
+ return build(theData, this.context, theType);
+ }
+
+ public <T> T build(Map theData, Map theContextData, Class<T> theType) {
+ return (T)java.lang.reflect.Proxy.newProxyInstance(
+ ProxyBuilder.class.getClassLoader(),
+ new Class[] { theType },
+ new Proxy(theData, this));
+ }
+*/
+ public <T> T build(Map theData, Class<T> theType) {
+ return build(new JSONObject(theData), theType);
+ }
+
+ public <T> T build(Map theData, Map theContextData, Class<T> theType) {
+ return build(new JSONObject(theData), theContextData, theType);
+ }
+
+ public <T> T build(JSONObject theData, Class<T> theType) {
+ return build(theData, this.context, theType);
+ }
+
+ public <T> T build(JSONObject theData, Map theContextData, Class<T> theType) {
+ return (T)java.lang.reflect.Proxy.newProxyInstance(
+ ProxyBuilder.class.getClassLoader(),
+ new Class[] { theType },
+ new Proxy(theData, this));
+ }
+
+
+
+
+ public ProxyBuilder withConverter(final Function<Object, ?> theConverter, Class theType) {
+ ConvertUtils.register(new Converter() {
+ public Object convert(Class theToType, Object theValue) {
+ return theConverter.apply(theValue);
+ }
+ },
+ theType);
+ return this;
+ }
+
+ /*
+ plug in an extension to the proxy default behaviour.
+ */
+ public ProxyBuilder withExtensions(Map<String, BiFunction<Proxy, Object[], Object>> theExtensions) {
+ this.extensions = theExtensions;
+ return this;
+ }
+
+ public ProxyBuilder withContext(Map<String, ?> theContext) {
+ this.context = theContext;
+ return this;
+ }
+
+ protected Object context(String theName) {
+ return this.context == null ? null : this.context.get(theName);
+ }
+
+ protected BiFunction<Proxy, Object[], Object> extension(String theName) {
+ return this.extensions == null ? null : this.extensions.get(theName);
+ }
+
+ protected boolean hasExtension(String theName) {
+ return this.extensions == null ? false : this.extensions.containsKey(theName);
+ }
+}
diff --git a/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Recycler.java b/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Recycler.java
new file mode 100644
index 0000000..3493cb1
--- /dev/null
+++ b/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Recycler.java
@@ -0,0 +1,329 @@
+package org.onap.sdc.dcae.catalog.commons;
+
+import java.io.Reader;
+import java.io.IOException;
+
+import java.util.List;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.AbstractMap;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.Collections;
+import java.util.Spliterators;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+
+import org.apache.commons.jxpath.Pointer;
+import org.apache.commons.jxpath.JXPathContext;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.core.type.TypeReference;
+
+import org.onap.sdc.common.onaplog.OnapLoggerDebug;
+import org.onap.sdc.common.onaplog.Enums.LogLevel;
+import org.yaml.snakeyaml.Yaml;
+
+
+/**
+ * Practically a copy of the Validator's service Recycler, minus the Spring framework aspects + picking up the
+ * description of every node
+ */
+public class Recycler {
+
+ private static final String PROPERTIES = "properties";
+ private static final String VALUE = "value";
+ private static final String ASSIGNMENT = "assignment";
+ private static final String CAPABILITY = "capability";
+ private static final String RELATIONSHIP = "relationship";
+ private static final String NAME = "name";
+ private static OnapLoggerDebug debugLogger = OnapLoggerDebug.getInstance();
+ private List<Map> imports;
+ private List<String> metas;
+
+ public Recycler() {
+ withImports();
+ withMetas(null);
+ }
+
+ public Recycler withImports(String... theImports) {
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Setting imports to {}", theImports);
+ ListBuilder importsBuilder = new ListBuilder();
+ for (int i = 0; i < theImports.length; i++) {
+ importsBuilder.add(new MapBuilder()
+ .put("i" + i, theImports[i])
+ .build());
+ }
+ this.imports = importsBuilder.build();
+ return this;
+ }
+
+ private List imports() {
+ ListBuilder importsBuilder = new ListBuilder();
+ for (Map e: this.imports) {
+ importsBuilder.add(new MapBuilder()
+ .putAll(e)
+ .build());
+ }
+ return importsBuilder.build();
+ }
+
+ public Recycler withMetas(String... theMetas) {
+ this.metas = (theMetas == null) ? Collections.emptyList() : Arrays.asList(theMetas);
+ return this;
+ }
+
+ public Object recycle(final Reader theSource) throws Exception {
+ return this.recycle(new ObjectMapper().readValue(theSource, (Class)HashMap.class));
+ }
+
+ public Object recycle(final Object theDump) {
+
+ final JXPathContext jxroot = JXPathContext.newContext(theDump);
+ jxroot.setLenient(true);
+
+ final Map<String, Object> nodeTemplates =
+ (Map<String, Object>)new MapBuilder()
+ .putAll(
+ StreamSupport
+ .stream(
+ Spliterators.spliteratorUnknownSize((Iterator<Pointer>)jxroot.iteratePointers("/nodes"), 16), false)
+ .map(p -> {
+ JXPathContext jxnode = jxroot.getRelativeContext(p);
+ return new AbstractMap.SimpleEntry<String,Object>(
+ (String)jxnode.getValue(NAME) + "_" + (String)jxnode.getValue("nid"),
+ new MapBuilder()
+ .put("type", jxnode.getValue("type/name"))
+ .put("description", jxnode.getValue("description"))
+ .putOpt("metadata", nodeMetadata(jxnode))
+ .putOpt(PROPERTIES, nodeProperties(jxnode))
+ .putOpt("requirements", nodeRequirements(jxnode))
+ .putOpt("capabilities", nodeCapabilities(jxnode))
+ .build());
+ })::iterator)
+ .buildOpt();
+
+ return new MapBuilder()
+ .put("tosca_definitions_version", "tosca_simple_yaml_1_0_0")
+ .put("imports", imports())
+ .put("topology_template", new MapBuilder()
+ .putOpt("node_templates", nodeTemplates)
+ .build())
+ .build();
+ }
+
+ /* */
+ private Object nodeProperties(JXPathContext theNodeContext) {
+ return
+ new MapBuilder()
+ .putAll(
+ StreamSupport.stream(
+ Spliterators.spliteratorUnknownSize((Iterator<Map>)theNodeContext.iterate(PROPERTIES), 16), false)
+ .map(m -> new AbstractMap.SimpleEntry(m.get(NAME), this.nodeProperty(m)))
+ .filter(e -> e.getValue() != null)
+ ::iterator)
+ .buildOpt();
+ }
+
+ /* */
+ private Object nodeProperty(final Map theSpec) {
+ Object value = theSpec.get(VALUE);
+ if (value == null) {
+ value = theSpec.get("default");
+ if (value == null) {
+ /*final*/ Map assign = (Map)theSpec.get(ASSIGNMENT);
+ if (assign != null) {
+ value = assign.get(VALUE);
+ }
+ }
+ }
+ String type = (String)theSpec.get("type");
+ if (value != null && type != null) {
+ value = getValueByType(value, type);
+ }
+ return value;
+ }
+
+ private Object getValueByType(Object value, String type) {
+ Object returnValue = null;
+ try {
+ if ("map".equals(type) && !(value instanceof Map)) {
+ returnValue = new ObjectMapper().readValue(value.toString(), new TypeReference<Map>(){});
+ }
+ else if ("list".equals(type) && !(value instanceof List)) {
+ returnValue = new ObjectMapper().readValue(value.toString(), new TypeReference<List>(){});
+ }
+ else if ("integer".equals(type) && (value instanceof String)) {
+ returnValue = Integer.valueOf((String)value);
+ }
+ else if ("float".equals(type) && (value instanceof String)) {
+ returnValue = Double.valueOf((String)value); //double because that's how the yaml parser would encode it
+ }
+ }
+ catch (NumberFormatException nfx) {
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Failed to process String representation {} of numeric data: {}", value, nfx);
+ }
+ catch (IOException iox) {
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Failed to process {} representation of a collection: {}", value.getClass().getName(), iox);
+ }
+ return returnValue;
+ }
+
+ /* */
+ private List nodeRequirements(JXPathContext theNodeContext) {
+ return
+ new ListBuilder()
+ .addAll(
+ StreamSupport.stream(
+ Spliterators.spliteratorUnknownSize((Iterator<Map>)theNodeContext.iterate("requirements"), 16), false)
+ .flatMap(m -> this.nodeRequirement(m, theNodeContext).stream())
+ //nicer that the ListBuilder buy cannot handle the empty lists, i.e. it will generate empty requirement lists
+ // .collect(Collectors.toList())
+ .toArray())
+ .buildOpt();
+ }
+
+ /*
+ * @param theSpec the requirement entry that appears within the node specification
+ * @param theNodeContext .. Should I pass the root context instead of assuming that the nodes context has it as parent?
+ * @return a List as one requirement (definition) could end up being instantiated multiple times
+ */
+ private List nodeRequirement(final Map theSpec, JXPathContext theNodeContext/*Iterator theTargets*/) {
+
+ final ListBuilder value = new ListBuilder();
+
+ final Map target = (Map)theSpec.get("target");
+ final Map capability = (Map)theSpec.get(CAPABILITY);
+ final Map relationship = (Map)theSpec.get(RELATIONSHIP);
+
+ //this are actual assignments
+ for (Iterator i = theNodeContext.getParentContext().iterate("/relations[@n2='" + theNodeContext.getValue("nid") + "']/meta[@p2='" + theSpec.get(NAME) +"']"); i.hasNext(); ) {
+
+ String targetNodeName = (String)((Map)i.next()).get("n1");
+
+ //make sure target exists
+ Map targetNode = (Map)theNodeContext.getParentContext().getValue("/nodes[@nid='" + targetNodeName + "']");
+ if (null == targetNode) {
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Relation points to non-existing node {}", targetNodeName);
+ continue; //this risks of producing a partial template ..
+ }
+
+ value.add(new MapBuilder().put(theSpec.get(NAME), new MapBuilder()
+ .putOpt("node", targetNode.get(NAME) + "_" + targetNode.get("nid"))
+ .putOpt(CAPABILITY, capability == null ? null : capability.get(NAME))
+ .putOpt(RELATIONSHIP, relationship == null ? null : relationship.get("type"))
+ .build()).build());
+ }
+ addTemporary(theSpec, theNodeContext, value, capability, relationship);
+
+ if (value.isEmpty()) {
+ value.add(new MapBuilder().put(theSpec.get(NAME), new MapBuilder()
+ .putOpt("node", target == null ? null : target.get(NAME) + "_" + target.get("nid"))
+ .putOpt(CAPABILITY, capability == null ? null : capability.get(NAME))
+ .putOpt(RELATIONSHIP, relationship == null ? null : relationship.get("type"))
+ .build()).build());
+ }
+
+ return value.build();
+ }
+
+ private void addTemporary(Map theSpec, JXPathContext theNodeContext, ListBuilder value, Map capability, Map relationship) {
+ //temporary
+ for (Iterator i = theNodeContext.getParentContext().iterate("/relations[@n1='" + theNodeContext.getValue("nid") + "']/meta[@p1='" + theSpec.get(NAME) +"']"); i.hasNext(); ) {
+
+ String targetNodeName = (String)((Map)i.next()).get("n2");
+
+ Map targetNode = (Map)theNodeContext.getParentContext().getValue("/nodes[@nid='" + targetNodeName + "']");
+ //make sure target exists
+ if (null == targetNode) {
+ debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Relation points to non-existing node {}", targetNode);
+ continue; //this risks of producing a partial template ..
+ }
+
+ value.add(new MapBuilder().put(theSpec.get(NAME), new MapBuilder()
+ .putOpt("node", targetNode.get(NAME) + "_" + targetNode.get("nid"))
+ .putOpt(CAPABILITY, capability == null ? null : capability.get(NAME))
+ .putOpt(RELATIONSHIP, relationship == null ? null : relationship.get("type"))
+ .build()).build());
+ }
+ //end temporary
+ }
+
+ /* */
+ private Map nodeCapabilities(JXPathContext theNodeContext) {
+ return
+ new MapBuilder()
+ .putAll(
+ StreamSupport.stream(
+ Spliterators.spliteratorUnknownSize((Iterator<Map>)theNodeContext.iterate("capabilities"), 16), false)
+ .map(m -> this.nodeCapability(m))
+ .filter(c -> c != null)
+ ::iterator)
+ .buildOpt();
+ }
+
+ /**
+ * this handles a capability assignment which only includes properties and attributes so unless there
+ * are any properties/attributes assignments we might not generate anything
+ */
+ private Map.Entry nodeCapability(final Map theSpec) {
+ List<Map> properties = (List<Map>) theSpec.get(PROPERTIES);
+ if (properties == null || properties.isEmpty()) {
+ return null;
+ }
+
+ return new AbstractMap.SimpleEntry(theSpec.get(NAME),
+ new MapBuilder()
+ .put(PROPERTIES,
+ new MapBuilder().putAll(properties.stream()
+ .filter(p -> p.containsKey(ASSIGNMENT) ||
+ p.containsKey(VALUE))
+ .map(p -> new AbstractMap.SimpleEntry(
+ p.get(NAME),
+ p.containsKey(ASSIGNMENT) ?
+ ((Map) p.get(ASSIGNMENT)).get(VALUE)
+ : p.get(VALUE))
+ )
+ ::iterator)
+ .build())
+ .build());
+ }
+
+
+ /* */
+ private Object nodeMetadata(JXPathContext theNodeContext) {
+ return
+ new MapBuilder()
+ .putAll(
+ this.metas
+ .stream()
+ .flatMap(m -> {
+ Object v = theNodeContext.getValue(m);
+ if (v == null) {
+ return Stream.empty();
+ }
+ if (v instanceof Map) {
+ return ((Map) v).entrySet()
+ .stream()
+ .map(e -> new AbstractMap.SimpleEntry<String, Object>
+ (((Map.Entry) e).getKey().toString(),
+ ((Map.Entry) e).getValue().toString()));
+ }
+ return Stream.of(new AbstractMap.SimpleEntry<String,Object>(m, v.toString()));
+ })
+ ::iterator)
+ .buildOpt();
+ }
+
+
+ public static String toString(Object theVal) {
+ return new Yaml().dump(theVal);
+ }
+
+
+ public static void main(String[] theArgs) throws Exception {
+ debugLogger.log(LogLevel.DEBUG, Recycler.class.getName(),
+ Recycler.toString(
+ new Recycler().recycle(new java.io.FileReader(theArgs[0]))));
+ }
+}