Introduce StorageService#read(StorageConsumer)

With the old method there was no easy way to access the last modified
timestamp, so a new method is introduced following the consumer
pattern introduced with readAll(). The old read method might be
deprecated in the future.

Change-Id: Id542cd8856a2a2c194cc703c0ff352f6eeaeff10
Signed-off-by: Michael Ochmann <michael.ochmann@sap.com>
diff --git a/org.eclipse.skalli.api/src/main/java/org/eclipse/skalli/services/persistence/StorageService.java b/org.eclipse.skalli.api/src/main/java/org/eclipse/skalli/services/persistence/StorageService.java
index dacc30f..7ad09b7 100644
--- a/org.eclipse.skalli.api/src/main/java/org/eclipse/skalli/services/persistence/StorageService.java
+++ b/org.eclipse.skalli.api/src/main/java/org/eclipse/skalli/services/persistence/StorageService.java
@@ -46,6 +46,15 @@
      */
     public InputStream read(String category, String key) throws IOException;
 
+    /** Reads the content specified by its category and key from the storage.
+     *
+     * @param category  category or type of the content.
+     * @param key  the unique key of the content within its category.
+     * @param consumer consumer for the content.
+     * @throws IOException  if an i/o error occured while reading content from the store.
+     */
+    public void read(String category, String key, StorageConsumer consumer) throws IOException;
+
     /**
      * Provides all stored content for the given category to the specified consumer.
      *
diff --git a/org.eclipse.skalli.core/src/main/java/org/eclipse/skalli/core/storage/FileStorageComponent.java b/org.eclipse.skalli.core/src/main/java/org/eclipse/skalli/core/storage/FileStorageComponent.java
index d4a99da..4700d90 100644
--- a/org.eclipse.skalli.core/src/main/java/org/eclipse/skalli/core/storage/FileStorageComponent.java
+++ b/org.eclipse.skalli.core/src/main/java/org/eclipse/skalli/core/storage/FileStorageComponent.java
@@ -115,12 +115,17 @@
     }
 
     @Override
+    public void read(String category, String key, StorageConsumer consumer) throws IOException {
+        File file = getFile(category, key);
+        if (file.exists() && file.isFile()) {
+            consumer.consume(category, key, file.lastModified(), toStream(file));
+        }
+    }
+
+    @Override
     public void readAll(String category, StorageConsumer consumer) throws IOException {
         for (String key: keys(category)) {
-            File file = getFile(category, key);
-            if (file.exists() && file.isFile()) {
-                consumer.consume(category, key, file.lastModified(), toStream(file));
-            }
+            read(category, key, consumer);
         }
     }
 
diff --git a/org.eclipse.skalli.jpa/src/main/java/org/eclipse/skalli/core/storage/jpa/JPAStorageComponent.java b/org.eclipse.skalli.jpa/src/main/java/org/eclipse/skalli/core/storage/jpa/JPAStorageComponent.java
index b5bbd04..c94039d 100644
--- a/org.eclipse.skalli.jpa/src/main/java/org/eclipse/skalli/core/storage/jpa/JPAStorageComponent.java
+++ b/org.eclipse.skalli.jpa/src/main/java/org/eclipse/skalli/core/storage/jpa/JPAStorageComponent.java
@@ -95,6 +95,20 @@
     }
 
     @Override
+    public void read(String category, String id, StorageConsumer consumer) throws IOException {
+        EntityManager em = getEntityManager();
+        try {
+            StorageItem item = findStorageItem(category, id, em);
+            if (item != null) {
+                consumer.consume(item.getCategory(), item.getId(), item.getDateModified().getTime(),
+                        asStream(item.getContent()));
+            }
+        } finally {
+            em.close();
+        }
+    }
+
+    @Override
     public void readAll(String category, StorageConsumer consumer) throws IOException {
         EntityManager em = getEntityManager();
         try {
diff --git a/org.eclipse.skalli.testutil/src/main/java/org/eclipse/skalli/testutil/HashMapStorageService.java b/org.eclipse.skalli.testutil/src/main/java/org/eclipse/skalli/testutil/HashMapStorageService.java
index 42b09f5..c4ec17c 100644
--- a/org.eclipse.skalli.testutil/src/main/java/org/eclipse/skalli/testutil/HashMapStorageService.java
+++ b/org.eclipse.skalli.testutil/src/main/java/org/eclipse/skalli/testutil/HashMapStorageService.java
@@ -56,6 +56,14 @@
     }
 
     @Override
+    public void read(String category, String id, StorageConsumer consumer) throws IOException {
+        ByteArrayStorageItem item = store.get(keyOf(category, id));
+        if (item != null) {
+            consumer.consume(category, item.getId(), item.lastModified(), item.getContent());
+        }
+    }
+
+    @Override
     public void readAll(String category, StorageConsumer consumer) throws IOException {
        for (ByteArrayStorageItem next: store.values()) {
            consumer.consume(category, next.getId(), next.lastModified(), next.getContent());