Implement the missing HashMapStorageService#archive()

This is a preparation for a subsequent patch that will introduce
a read/write API for archived content.

Change-Id: Iefcc601f8f7c7560a5e193c6d583c24e03f6a85d
Signed-off-by: Michael Ochmann <michael.ochmann@sap.com>
diff --git a/org.eclipse.skalli.commands.test/src/main/java/org/eclipse/skalli/commands/StorageCommandTest.java b/org.eclipse.skalli.commands.test/src/main/java/org/eclipse/skalli/commands/StorageCommandTest.java
index 943ff9a..0c5b349 100644
--- a/org.eclipse.skalli.commands.test/src/main/java/org/eclipse/skalli/commands/StorageCommandTest.java
+++ b/org.eclipse.skalli.commands.test/src/main/java/org/eclipse/skalli/commands/StorageCommandTest.java
@@ -11,6 +11,7 @@
 package org.eclipse.skalli.commands;
 
 import static org.easymock.EasyMock.createMock;
+import static org.eclipse.skalli.testutil.StorageKey.keyOf;
 import static org.junit.Assert.assertTrue;
 
 import java.io.ByteArrayInputStream;
@@ -19,7 +20,6 @@
 
 import org.eclipse.osgi.framework.console.CommandInterpreter;
 import org.eclipse.skalli.testutil.HashMapStorageService;
-import org.eclipse.skalli.testutil.HashMapStorageService.Key;
 import org.eclipse.skalli.testutil.TestUUIDs;
 import org.junit.Test;
 
@@ -43,10 +43,10 @@
 
         assertTrue(Arrays.equals(
                 TEST_CONTENT_1,
-                destination.asMap().get(new Key(CATEGORY_PROJECT, KEY_1))));
+                destination.asMap().get(keyOf(CATEGORY_PROJECT, KEY_1))));
         assertTrue(Arrays.equals(
                 TEST_CONTENT_2,
-                destination.asMap().get(new Key(CATEGORY_PROJECT, KEY_2))));
+                destination.asMap().get(keyOf(CATEGORY_PROJECT, KEY_2))));
     }
 
     private static byte[] getBytesUTF8(String s) {
diff --git a/org.eclipse.skalli.core.test/src/main/java/org/eclipse/skalli/core/persistence/XStreamPersistenceComponentTest.java b/org.eclipse.skalli.core.test/src/main/java/org/eclipse/skalli/core/persistence/XStreamPersistenceComponentTest.java
index 0ed741d..1bd6198 100644
--- a/org.eclipse.skalli.core.test/src/main/java/org/eclipse/skalli/core/persistence/XStreamPersistenceComponentTest.java
+++ b/org.eclipse.skalli.core.test/src/main/java/org/eclipse/skalli/core/persistence/XStreamPersistenceComponentTest.java
@@ -10,6 +10,8 @@
  *******************************************************************************/
 package org.eclipse.skalli.core.persistence;
 
+import static org.eclipse.skalli.testutil.StorageKey.keyOf;
+
 import java.util.ArrayList;
 import java.util.LinkedList;
 import java.util.List;
@@ -115,7 +117,7 @@
             Assert.assertNotNull(entity);
 
             byte[] blob = hashMapStorageService.asMap().get(
-                    new HashMapStorageService.Key(entity.getClass().getSimpleName(), entity.getUuid().toString()));
+                    keyOf(entity.getClass().getSimpleName(), entity.getUuid().toString()));
             Document doc = XMLUtils.documentFromString(new String(blob, "UTF-8"));
 
             // check that the extensible entity has been persisted with its default alias
diff --git a/org.eclipse.skalli.core.test/src/main/java/org/eclipse/skalli/core/persistence/XStreamPersistenceTest.java b/org.eclipse.skalli.core.test/src/main/java/org/eclipse/skalli/core/persistence/XStreamPersistenceTest.java
index eb964b2..aab5630 100644
--- a/org.eclipse.skalli.core.test/src/main/java/org/eclipse/skalli/core/persistence/XStreamPersistenceTest.java
+++ b/org.eclipse.skalli.core.test/src/main/java/org/eclipse/skalli/core/persistence/XStreamPersistenceTest.java
@@ -10,6 +10,7 @@
  *******************************************************************************/
 package org.eclipse.skalli.core.persistence;
 
+import static org.eclipse.skalli.testutil.StorageKey.keyOf;
 import static org.hamcrest.Matchers.startsWith;
 import static org.junit.Assert.*;
 
@@ -34,7 +35,7 @@
 import org.eclipse.skalli.model.EntityBase;
 import org.eclipse.skalli.services.extension.DataMigration;
 import org.eclipse.skalli.testutil.HashMapStorageService;
-import org.eclipse.skalli.testutil.HashMapStorageService.Key;
+import org.eclipse.skalli.testutil.StorageKey;
 import org.eclipse.skalli.testutil.TestExtensibleEntityBase;
 import org.eclipse.skalli.testutil.TestExtensibleEntityEntityService;
 import org.eclipse.skalli.testutil.TestExtension;
@@ -90,13 +91,13 @@
             super(new HashMapStorageService());
         }
 
-        private static Key getHashMapKeyForEntry(TestExtensibleEntityBase entity) {
-            return new HashMapStorageService.Key(TestExtensibleEntityBase.class.getSimpleName(),
+        private static StorageKey getStorageKey(TestExtensibleEntityBase entity) {
+            return keyOf(TestExtensibleEntityBase.class.getSimpleName(),
                     entity.getUuid().toString());
         }
 
         private byte[] getContentFromHashMap(TestExtensibleEntityBase entityKey) {
-            return ((HashMapStorageService) storageService).asMap().get(getHashMapKeyForEntry(entityKey));
+            return ((HashMapStorageService) storageService).asMap().get(getStorageKey(entityKey));
         }
 
         private Document getDocumentFromHashMap(TestExtensibleEntityBase entityKey) throws Exception {
diff --git a/org.eclipse.skalli.testutil/src/main/java/org/eclipse/skalli/testutil/ByteArrayStorageItem.java b/org.eclipse.skalli.testutil/src/main/java/org/eclipse/skalli/testutil/ByteArrayStorageItem.java
new file mode 100644
index 0000000..7f56825
--- /dev/null
+++ b/org.eclipse.skalli.testutil/src/main/java/org/eclipse/skalli/testutil/ByteArrayStorageItem.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2010-2016 SAP AG and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     SAP AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.skalli.testutil;
+
+import static org.eclipse.skalli.testutil.StorageKey.keyOf;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
+public class ByteArrayStorageItem {
+    private StorageKey key;
+    private byte[] buf;
+    private long lastModified;
+
+    public ByteArrayStorageItem(String category, String id, long lastModified, byte[] buf) {
+        this(keyOf(category, id), lastModified, buf);
+    }
+
+    public ByteArrayStorageItem(StorageKey key, long lastModified,  byte[] buf) {
+        this.key = key;
+        this.buf = buf;
+        this.lastModified = lastModified;
+    }
+
+    public ByteArrayStorageItem(StorageKey key, byte[] buf) {
+        this(key, System.currentTimeMillis(), buf);
+    }
+
+    public String getCategory() {
+        return key.getCategory();
+    }
+
+    public String getId() {
+        return key.getKey();
+    }
+
+    public long lastModified() {
+        return lastModified;
+    }
+
+    public InputStream getContent() {
+        return buf != null ? new ByteArrayInputStream(buf) : null;
+    }
+
+    public byte[] toByteArray() {
+        return buf;
+    }
+}
\ No newline at end of file
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 9c939d2..6e09b3d 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
@@ -10,13 +10,15 @@
  *******************************************************************************/
 package org.eclipse.skalli.testutil;
 
-import java.io.ByteArrayInputStream;
+import static org.eclipse.skalli.testutil.StorageKey.keyOf;
+
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Set;
 
 import org.apache.commons.io.IOUtils;
@@ -29,104 +31,49 @@
 @SuppressWarnings("nls")
 public class HashMapStorageService implements StorageService {
 
-    public static class Key {
-        @Override
-        public int hashCode() {
-            final int prime = 31;
-            int result = 1;
-            result = prime * result + ((category == null) ? 0 : category.hashCode());
-            result = prime * result + ((key == null) ? 0 : key.hashCode());
-            return result;
+    private Map<StorageKey, ByteArrayStorageItem> store = new HashMap<StorageKey, ByteArrayStorageItem>();
+    private Map<StorageKey, List<ByteArrayStorageItem>> archive = new HashMap<StorageKey, List<ByteArrayStorageItem>>();
+
+    public Map<StorageKey, byte[]> asMap() {
+        Map<StorageKey, byte[]> result = new HashMap<StorageKey, byte[]>();
+        for (Entry<StorageKey, ByteArrayStorageItem> next: store.entrySet()) {
+            result.put(next.getKey(), next.getValue().toByteArray());
         }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (this == obj) {
-                return true;
-            }
-            if (obj == null) {
-                return false;
-            }
-            if (getClass() != obj.getClass()) {
-                return false;
-            }
-            Key other = (Key) obj;
-            if (category == null) {
-                if (other.category != null) {
-                    return false;
-                }
-            } else if (!category.equalsIgnoreCase((other.category))) {
-                return false;
-            }
-            if (key == null) {
-                if (other.key != null) {
-                    return false;
-                }
-            } else if (!key.equals(other.key)) {
-                return false;
-            }
-            return true;
-        }
-
-        private String category;
-        private String key;
-
-        public String getCategory() {
-            return category;
-        }
-
-        public String getKey() {
-            return key;
-        }
-
-        public Key(String category, String key) {
-            this.category = category;
-            this.key = key;
-        }
-
-        /* (non-Javadoc)
-         * @see java.lang.Object#toString()
-         */
-        @Override
-        public String toString() {
-            return category + "/" + key; //$NON-NLS-1$
-        }
-
-    }
-
-    private Map<Key, byte[]> store = new HashMap<Key, byte[]>();
-
-    public Map<Key, byte[]> asMap() {
-        return store;
+        return result;
     }
 
     @Override
-    public void write(String category, String key, InputStream blob) throws IOException {
-        store.put(new Key(category, key), IOUtils.toByteArray(blob));
+    public void write(String category, String id, InputStream blob) throws IOException {
+        StorageKey key = keyOf(category, id);
+        store.put(key, new ByteArrayStorageItem(key, IOUtils.toByteArray(blob)));
     }
 
     @Override
-    public InputStream read(String category, String key) throws IOException {
-        byte[] content = store.get(new Key(category, key));
-        if (content == null) {
-            return null;
-        }
-        else {
-            return new ByteArrayInputStream(content);
-        }
+    public InputStream read(String category, String id) throws IOException {
+        ByteArrayStorageItem item = store.get(keyOf(category, id));
+        return item != null ? item.getContent() : null;
     }
 
     @Override
-    public void archive(String category, String key) throws IOException {
-        //yet there is no way to read out the history again, so do nothing now
+    public void archive(String category, String id) throws IOException {
+        StorageKey key = keyOf(category, id);
+        ByteArrayStorageItem item = store.get(key);
+        if (item != null) {
+            List<ByteArrayStorageItem> items = archive.get(key);
+            if (items == null) {
+                items = new ArrayList<ByteArrayStorageItem>();
+                archive.put(key, items);
+            }
+            items.add(new ByteArrayStorageItem(key, IOUtils.toByteArray(item.getContent())));
+        }
         return;
     }
 
     @Override
     public List<String> keys(String category) throws IOException {
         List<String> result = new ArrayList<String>();
-        Set<Key> allKeys = store.keySet();
-        for (Key key : allKeys) {
+        Set<StorageKey> allKeys = store.keySet();
+        for (StorageKey key : allKeys) {
             if (key.getCategory().equalsIgnoreCase(category)) {
                 result.add(key.getKey());
             }
@@ -138,6 +85,4 @@
     public String toString() {
         return "HashMapStorageService [blobStore=" + store + "]";
     }
-
-
 }
\ No newline at end of file
diff --git a/org.eclipse.skalli.testutil/src/main/java/org/eclipse/skalli/testutil/StorageKey.java b/org.eclipse.skalli.testutil/src/main/java/org/eclipse/skalli/testutil/StorageKey.java
new file mode 100644
index 0000000..19c3b2c
--- /dev/null
+++ b/org.eclipse.skalli.testutil/src/main/java/org/eclipse/skalli/testutil/StorageKey.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2010-2016 SAP AG and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     SAP AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.skalli.testutil;
+
+public class StorageKey {
+    private String category;
+    private String key;
+
+    private StorageKey(String category, String key) {
+        this.category = category;
+        this.key = key;
+    }
+
+    public static StorageKey keyOf(String category, String key) {
+        return new StorageKey(category, key);
+    }
+
+    public String getCategory() {
+        return category;
+    }
+
+    public String getKey() {
+        return key;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((category == null) ? 0 : category.hashCode());
+        result = prime * result + ((key == null) ? 0 : key.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        StorageKey other = (StorageKey) obj;
+        if (category == null) {
+            if (other.category != null) {
+                return false;
+            }
+        } else if (!category.equalsIgnoreCase((other.category))) {
+            return false;
+        }
+        if (key == null) {
+            if (other.key != null) {
+                return false;
+            }
+        } else if (!key.equals(other.key)) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return category + "/" + key; //$NON-NLS-1$
+    }
+}