diff --git a/src/main/java/net/openhft/chronicle/map/FilePerKeyMap.java b/src/main/java/net/openhft/chronicle/map/FilePerKeyMap.java index 7c22f0bc9..21039e287 100644 --- a/src/main/java/net/openhft/chronicle/map/FilePerKeyMap.java +++ b/src/main/java/net/openhft/chronicle/map/FilePerKeyMap.java @@ -6,9 +6,7 @@ import org.jetbrains.annotations.NotNull; import java.io.File; import java.io.IOException; import java.nio.file.*; -import java.util.Collection; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.function.Consumer; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -48,7 +46,7 @@ public class FilePerKeyMap implements ChronicleMap { @Override public boolean containsValue(Object value) { - return false; + return getFiles(dirPath).anyMatch(p->getFileContents(p).equals(value)); } @Override @@ -70,52 +68,18 @@ public class FilePerKeyMap implements ChronicleMap { return (V) existingValue; } - private Stream getFiles(Path path){ - try { - return Files.walk(path).filter(p -> !Files.isDirectory(p)); - } catch (IOException e) { - throw new AssertionError(e); - } - } - - private String getFileContents(Path path){ - String existingValue = null; - if(Files.exists(path)) { - try { - existingValue = Files.readAllLines(path).stream().collect(Collectors.joining()); - } catch (IOException e) { - throw new AssertionError(e); - } - } - return existingValue; - } - - private void writeToFile(Path path, String value){ - try { - Files.write(path, value.getBytes(), StandardOpenOption.CREATE, - StandardOpenOption.TRUNCATE_EXISTING, - StandardOpenOption.WRITE); - } catch (IOException e) { - throw new AssertionError(e); - } - } - - private void deleteFile(Path path){ - try { - Files.delete(path); - } catch (IOException e) { - throw new AssertionError(e); - } - } - @Override public V remove(Object key) { - return null; + String existing = (String)get(key); + if(existing != null){ + deleteFile(Paths.get(dir, (String)key)); + } + return (V)existing; } @Override public void putAll(Map m) { - + m.entrySet().stream().forEach(e->put(e.getKey(), e.getValue())); } @Override @@ -126,19 +90,23 @@ public class FilePerKeyMap implements ChronicleMap { @NotNull @Override public Set keySet() { - return null; + return getFiles(dirPath).map(p -> (K) p.getFileName().toString()) + .collect(Collectors.toSet()); } @NotNull @Override public Collection values() { - return null; + return getFiles(dirPath).map(p -> (V) getFileContents(p)) + .collect(Collectors.toSet()); } @NotNull @Override public Set> entrySet() { - return null; + return getFiles(dirPath).map(p -> + (Entry) new FPMEntry(p.getFileName().toString(), getFileContents(p))) + .collect(Collectors.toSet()); } @Override @@ -247,6 +215,47 @@ public class FilePerKeyMap implements ChronicleMap { return null; } + + private Stream getFiles(Path path){ + try { + return Files.walk(path).filter(p -> !Files.isDirectory(p)); + } catch (IOException e) { + throw new AssertionError(e); + } + } + + private String getFileContents(Path path){ + String existingValue = null; + if(Files.exists(path)) { + try { + existingValue = Files.readAllLines(path).stream().collect(Collectors.joining()); + } catch (IOException e) { + throw new AssertionError(e); + } + } + return existingValue; + } + + private void writeToFile(Path path, String value){ + try { + Files.write(path, value.getBytes(), StandardOpenOption.CREATE, + StandardOpenOption.TRUNCATE_EXISTING, + StandardOpenOption.WRITE); + } catch (IOException e) { + throw new AssertionError(e); + } + } + + private void deleteFile(Path path){ + try { + Files.delete(path); + } catch (IOException e) { + throw new AssertionError(e); + } + } + + + private void checkTypeIsString(Object... objs) { for(Object o : objs){ if(!(o instanceof String)) @@ -254,4 +263,49 @@ public class FilePerKeyMap implements ChronicleMap { "of type String. Unsupported type: '" + o + "'"); } } + + private static class FPMEntry implements Entry + { + private K key; + private V value; + + public FPMEntry(K key, V value){ + this.key = key; + this.value = value; + } + + @Override + public K getKey() { + return key; + } + + @Override + public V getValue() { + return value; + } + + @Override + public Object setValue(Object value) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + FPMEntry entry = (FPMEntry) o; + + if (key != null ? !key.equals(entry.key) : entry.key != null) return false; + return !(value != null ? !value.equals(entry.value) : entry.value != null); + + } + + @Override + public int hashCode() { + int result = key != null ? key.hashCode() : 0; + result = 31 * result + (value != null ? value.hashCode() : 0); + return result; + } + } } diff --git a/src/test/java/net/openhft/chronicle/map/FilePerMapKeyTest.java b/src/test/java/net/openhft/chronicle/map/FilePerMapKeyTest.java index 21e32d748..7f0500255 100644 --- a/src/test/java/net/openhft/chronicle/map/FilePerMapKeyTest.java +++ b/src/test/java/net/openhft/chronicle/map/FilePerMapKeyTest.java @@ -2,6 +2,11 @@ package net.openhft.chronicle.map; import org.junit.Test; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + import static org.junit.Assert.*; /** @@ -41,10 +46,12 @@ public class FilePerMapKeyTest { assertTrue(map.containsKey("one")); assertFalse(map.containsKey("two")); + assertTrue(map.containsValue("test2")); + assertFalse(map.containsValue("test5")); //Check the size is one int size = map.size(); - assertEquals(1,size); + assertEquals(1, size); assertFalse(map.isEmpty()); map.clear(); @@ -53,5 +60,56 @@ public class FilePerMapKeyTest { assertEquals(0, size); assertTrue(map.isEmpty()); + + map.put("one", "test1"); + map.put("two", "test2"); + map.put("three", "test3"); + + assertEquals(3, map.size()); + + val = map.remove("two"); + assertEquals("test2", val); + + assertEquals(2, map.size()); + + val = map.remove("four");//doesn't exist + assertEquals(null, val); + + map.clear(); + + Map copyFrom = new HashMap<>(); + copyFrom.put("five", "test5"); + copyFrom.put("six", "test6"); + copyFrom.put("seven", "test7"); + map.putAll(copyFrom); + assertEquals(3, map.size()); + + Set set = map.keySet(); + assertEquals(3, set.size()); + assertTrue(set.contains("five")); + assertTrue(set.contains("six")); + assertTrue(set.contains("seven")); + + set = (Set)map.values(); + assertEquals(3, set.size()); + assertTrue(set.contains("test5")); + assertTrue(set.contains("test6")); + assertTrue(set.contains("test7")); + + Set entryset = (Set)map.entrySet(); + assertEquals(3, entryset.size()); + for(Iterator it = entryset.iterator(); it.hasNext();){ + Map.Entry entry = it.next(); + if(entry.getKey().equals("five")){ + assertEquals(entry.getValue(),"test5"); + }else if(entry.getKey().equals("six")){ + assertEquals(entry.getValue(),"test6"); + }else if(entry.getKey().equals("seven")){ + assertEquals(entry.getValue(),"test7"); + }else{ + //should never get here!! + assertTrue(false); + } + } } }