add caching to graph inventory client

add caching to graph inventory client
updated properties files to read cache properties

Issue-ID: SO-3398
Signed-off-by: Benjamin, Max (mb388a) <mb388a@att.com>
Change-Id: Ib3e67ae014b6668c9b004aae1e8b5d49b9ce6b06
diff --git a/common/src/main/java/org/onap/so/client/AddCacheHeaders.java b/common/src/main/java/org/onap/so/client/AddCacheHeaders.java
new file mode 100644
index 0000000..1a41be1
--- /dev/null
+++ b/common/src/main/java/org/onap/so/client/AddCacheHeaders.java
@@ -0,0 +1,28 @@
+package org.onap.so.client;
+
+import java.io.IOException;
+import java.util.Collections;
+import javax.annotation.Priority;
+import javax.ws.rs.client.ClientRequestContext;
+import javax.ws.rs.client.ClientResponseContext;
+import javax.ws.rs.client.ClientResponseFilter;
+import javax.ws.rs.ext.Provider;
+
+@Provider
+@Priority(1)
+public class AddCacheHeaders implements ClientResponseFilter {
+
+    private final CacheProperties props;
+
+    public AddCacheHeaders(CacheProperties props) {
+        this.props = props;
+    }
+
+    public void filter(ClientRequestContext request, ClientResponseContext response) throws IOException {
+        if (request.getMethod().equalsIgnoreCase("GET")) {
+            response.getHeaders().putIfAbsent("Cache-Control",
+                    Collections.singletonList("public, max-age=" + (props.getMaxAge() / 1000)));
+        }
+
+    }
+}
diff --git a/common/src/main/java/org/onap/so/client/CacheFactory.java b/common/src/main/java/org/onap/so/client/CacheFactory.java
new file mode 100644
index 0000000..6bc4858
--- /dev/null
+++ b/common/src/main/java/org/onap/so/client/CacheFactory.java
@@ -0,0 +1,25 @@
+package org.onap.so.client;
+
+
+import java.util.concurrent.TimeUnit;
+import javax.cache.configuration.Factory;
+import javax.cache.expiry.Duration;
+import javax.cache.expiry.ExpiryPolicy;
+import javax.cache.expiry.TouchedExpiryPolicy;
+
+public class CacheFactory implements Factory<ExpiryPolicy> {
+
+    private static final long serialVersionUID = 8948728679233836929L;
+
+    private final CacheProperties props;
+
+    public CacheFactory(CacheProperties props) {
+        this.props = props;
+    }
+
+    @Override
+    public ExpiryPolicy create() {
+        return TouchedExpiryPolicy.factoryOf(new Duration(TimeUnit.MILLISECONDS, props.getMaxAge())).create();
+    }
+
+}
diff --git a/common/src/main/java/org/onap/so/client/CacheProperties.java b/common/src/main/java/org/onap/so/client/CacheProperties.java
new file mode 100644
index 0000000..4fb2a87
--- /dev/null
+++ b/common/src/main/java/org/onap/so/client/CacheProperties.java
@@ -0,0 +1,13 @@
+package org.onap.so.client;
+
+public interface CacheProperties {
+
+
+    default Long getMaxAge() {
+        return 60000L;
+    }
+
+    default String getCacheName() {
+        return "default-http-cache";
+    }
+}
diff --git a/common/src/main/java/org/onap/so/client/RestClient.java b/common/src/main/java/org/onap/so/client/RestClient.java
index 9fce328..be0a0f3 100644
--- a/common/src/main/java/org/onap/so/client/RestClient.java
+++ b/common/src/main/java/org/onap/so/client/RestClient.java
@@ -188,8 +188,20 @@
         return APPLICATION_MERGE_PATCH_JSON;
     }
 
+    protected ClientBuilder getClientBuilder() {
+        ClientBuilder builder = ClientBuilder.newBuilder();
+        if (props.isCachingEnabled()) {
+            enableCaching(builder);
+        }
+        return builder.readTimeout(props.getReadTimeout(), TimeUnit.MILLISECONDS);
+    }
+
+    protected ClientBuilder enableCaching(ClientBuilder builder) {
+        return builder;
+    }
+
     protected Client getClient() {
-        return ClientBuilder.newBuilder().readTimeout(props.getReadTimeout(), TimeUnit.MILLISECONDS).build();
+        return getClientBuilder().build();
     }
 
     protected abstract ONAPComponentsList getTargetEntity();
diff --git a/common/src/main/java/org/onap/so/client/RestClientSSL.java b/common/src/main/java/org/onap/so/client/RestClientSSL.java
index 8956e20..c6252e4 100644
--- a/common/src/main/java/org/onap/so/client/RestClientSSL.java
+++ b/common/src/main/java/org/onap/so/client/RestClientSSL.java
@@ -24,7 +24,6 @@
 import java.security.KeyStore;
 import java.security.NoSuchAlgorithmException;
 import java.util.Optional;
-import java.util.concurrent.TimeUnit;
 import javax.net.ssl.SSLContext;
 import javax.ws.rs.client.Client;
 import javax.ws.rs.client.ClientBuilder;
@@ -57,8 +56,7 @@
                 }
             }
             // Use default SSL context
-            client = ClientBuilder.newBuilder().sslContext(SSLContext.getDefault())
-                    .readTimeout(props.getReadTimeout(), TimeUnit.MILLISECONDS).build();
+            client = getClientBuilder().sslContext(SSLContext.getDefault()).build();
             logger.info("RestClientSSL using default SSL context!");
         } catch (NoSuchAlgorithmException e) {
             throw new RuntimeException(e);
diff --git a/common/src/main/java/org/onap/so/client/RestProperties.java b/common/src/main/java/org/onap/so/client/RestProperties.java
index 36da424..a7a0ef6 100644
--- a/common/src/main/java/org/onap/so/client/RestProperties.java
+++ b/common/src/main/java/org/onap/so/client/RestProperties.java
@@ -49,4 +49,12 @@
     public default Long getReadTimeout() {
         return Long.valueOf(60000);
     }
+
+    public default boolean isCachingEnabled() {
+        return false;
+    }
+
+    public default CacheProperties getCacheProperties() {
+        return new CacheProperties() {};
+    }
 }
diff --git a/common/src/test/java/org/onap/so/client/RestClientTest.java b/common/src/test/java/org/onap/so/client/RestClientTest.java
index c6e282c..d40576b 100644
--- a/common/src/test/java/org/onap/so/client/RestClientTest.java
+++ b/common/src/test/java/org/onap/so/client/RestClientTest.java
@@ -49,6 +49,7 @@
 import org.onap.logging.filter.base.ONAPComponents;
 import org.onap.logging.filter.base.ONAPComponentsList;
 import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
+import com.github.tomakehurst.wiremock.extension.responsetemplating.ResponseTemplateTransformer;
 import com.github.tomakehurst.wiremock.junit.WireMockRule;
 
 @RunWith(MockitoJUnitRunner.class)
@@ -61,7 +62,8 @@
     public ExpectedException thrown = ExpectedException.none();
 
     @Rule
-    public WireMockRule wireMockRule = new WireMockRule(WireMockConfiguration.options().dynamicPort());
+    public WireMockRule wireMockRule = new WireMockRule(
+            WireMockConfiguration.options().dynamicPort().extensions(new ResponseTemplateTransformer(false)));
 
     @Test
     public void retries() throws Exception {
diff --git a/common/src/test/resources/logback-test.xml b/common/src/test/resources/logback-test.xml
index b52e6be..3c5f259 100644
--- a/common/src/test/resources/logback-test.xml
+++ b/common/src/test/resources/logback-test.xml
@@ -19,61 +19,60 @@
   -->
 
 <configuration>
-	<property name="p_tim" value="%d{&quot;yyyy-MM-dd'T'HH:mm:ss.SSSXXX&quot;, UTC}"/>
-    <property name="p_lvl" value="%level"/>
-    <property name="p_log" value="%logger"/>
-    <property name="p_mdc" value="%replace(%replace(%mdc){'\t','\\\\t'}){'\n', '\\\\n'}"/>
-    <property name="p_msg" value="%replace(%replace(%msg){'\t', '\\\\t'}){'\n','\\\\n'}"/>
-    <property name="p_exc" value="%replace(%replace(%rootException){'\t', '\\\\t'}){'\n','\\\\n'}"/>
-    <property name="p_mak" value="%replace(%replace(%marker){'\t', '\\\\t'}){'\n','\\\\n'}"/>
-    <property name="p_thr" value="%thread"/>
-    <property name="pattern" value="%nopexception${p_tim}\t${p_thr}\t${p_lvl}\t${p_log}\t${p_mdc}\t${p_msg}\t${p_exc}\t${p_mak}\t%n"/>
+  <property name="p_tim" value="%d{&quot;yyyy-MM-dd'T'HH:mm:ss.SSSXXX&quot;, UTC}" />
+  <property name="p_lvl" value="%level" />
+  <property name="p_log" value="%logger" />
+  <property name="p_mdc" value="%replace(%replace(%mdc){'\t','\\\\t'}){'\n', '\\\\n'}" />
+  <property name="p_msg" value="%replace(%replace(%msg){'\t', '\\\\t'}){'\n','\\\\n'}" />
+  <property name="p_exc" value="%replace(%replace(%rootException){'\t', '\\\\t'}){'\n','\\\\n'}" />
+  <property name="p_mak" value="%replace(%replace(%marker){'\t', '\\\\t'}){'\n','\\\\n'}" />
+  <property name="p_thr" value="%thread" />
+  <property name="pattern"
+    value="%nopexception${p_tim}\t${p_thr}\t${p_lvl}\t${p_log}\t${p_mdc}\t${p_msg}\t${p_exc}\t${p_mak}\t%n" />
 
 
-	<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
-		<encoder>
-			<pattern>${pattern}</pattern>
-		</encoder>
-	</appender>
+  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+    <encoder>
+      <pattern>${pattern}</pattern>
+    </encoder>
+  </appender>
 
-	<appender name="test"
-		class="org.onap.so.utils.TestAppender" />
+  <appender name="test" class="org.onap.so.utils.TestAppender" />
 
-	<logger name="com.att.ecomp.audit" level="info" additivity="false">
-		<appender-ref ref="STDOUT" />
-	</logger>
+  <logger name="com.att.ecomp.audit" level="info" additivity="false">
+    <appender-ref ref="STDOUT" />
+  </logger>
 
-	<logger name="com.att.eelf.metrics" level="info" additivity="false">
-		<appender-ref ref="STDOUT" />
-	</logger>
+  <logger name="com.att.eelf.metrics" level="info" additivity="false">
+    <appender-ref ref="STDOUT" />
+  </logger>
 
-	<logger name="com.att.eelf.error" level="WARN" additivity="false">
-		<appender-ref ref="STDOUT" />
-	</logger>
+  <logger name="com.att.eelf.error" level="WARN" additivity="false">
+    <appender-ref ref="STDOUT" />
+  </logger>
 
-	<logger name="org.onap" level="${so.log.level:-DEBUG}" additivity="false">
-		<appender-ref ref="STDOUT" />
-		<appender-ref ref="test" />
-	</logger>
-	
-	<logger name="org.flywaydb" level="DEBUG" additivity="false">
-        <appender-ref ref="STDOUT" />
-    </logger>
-	
+  <logger name="org.onap" level="${so.log.level:-DEBUG}" additivity="false">
+    <appender-ref ref="STDOUT" />
+    <appender-ref ref="test" />
+  </logger>
 
-	<logger name="ch.vorburger" level="WARN" additivity="false">
-		<appender-ref ref="STDOUT" />
-	</logger>
-	
-	<logger name="org.reflections" level="ERROR" additivity="false">
-		<appender-ref ref="STDOUT" />
-	</logger>
-	
+  <logger name="org.flywaydb" level="DEBUG" additivity="false">
+    <appender-ref ref="STDOUT" />
+  </logger>
 
-	<root level="WARN">
-		<appender-ref ref="STDOUT" />
-		<appender-ref ref="test" />
-	</root>
+
+  <logger name="ch.vorburger" level="WARN" additivity="false">
+    <appender-ref ref="STDOUT" />
+  </logger>
+
+  <logger name="org.reflections" level="ERROR" additivity="false">
+    <appender-ref ref="STDOUT" />
+  </logger>
+
+  <root level="WARN">
+    <appender-ref ref="STDOUT" />
+    <appender-ref ref="test" />
+  </root>
 
 
 </configuration>
\ No newline at end of file