package io.github.lucaseasedup.logit.storage; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.commons.lang.StringUtils; public final class StorageEntry implements Iterable<StorageDatum> { @Override public String toString() { StringBuilder sb = new StringBuilder(); for (StorageDatum datum : this) { if (sb.length() > 0) { sb.append(", "); } sb.append("\""); sb.append(datum.getKey()); sb.append("\": \""); sb.append(datum.getValue()); sb.append("\""); } return "Entry {" + sb + "}"; } public String get(String key) { if (StringUtils.isBlank(key)) throw new IllegalArgumentException(); return backend.get(key); } public void put(String key, String value) { if (StringUtils.isBlank(key)) throw new IllegalArgumentException(); String oldValue; if (value == null) { oldValue = backend.put(key, ""); } else { oldValue = backend.put(key, value); } if (oldValue == null || !oldValue.equals(value)) { dirtyKeys.add(key); } } public Set<String> getKeys() { return backend.keySet(); } public boolean containsKey(String key) { return get(key) != null; } public StorageEntry copy() { StorageEntry copy = new StorageEntry(); copy.backend = new LinkedHashMap<>(backend); return copy; } public StorageEntry copyDirty() { StorageEntry copy = new StorageEntry(); for (Map.Entry<String, String> e : backend.entrySet()) { if (isKeyDirty(e.getKey())) { copy.backend.put(e.getKey(), e.getValue()); } } return copy; } public boolean isKeyDirty(String key) { if (key == null) throw new IllegalArgumentException(); return dirtyKeys.contains(key); } public void clearKeyDirty(String key) { if (key == null) throw new IllegalArgumentException(); dirtyKeys.remove(key); } @Override public Iterator<StorageDatum> iterator() { return new DatumIterator(); } public static List<StorageEntry> copyList(List<StorageEntry> entries) { if (entries == null) throw new IllegalArgumentException(); return copyList(entries, new SelectorConstant(true)); } public static List<StorageEntry> copyList( List<StorageEntry> entries, Selector selector ) { if (entries == null || selector == null) throw new IllegalArgumentException(); List<StorageEntry> copies = new LinkedList<>(); for (StorageEntry entry : entries) { if (SqlUtils.resolveSelector(selector, entry)) { copies.add(entry.copy()); } } return copies; } public static List<StorageEntry> copyList( List<StorageEntry> entries, List<String> keys, Selector selector ) { if (entries == null || selector == null) throw new IllegalArgumentException(); List<StorageEntry> copies = new LinkedList<>(); for (StorageEntry entry : entries) { if (SqlUtils.resolveSelector(selector, entry)) { StorageEntry.Builder copyBuilder = new StorageEntry.Builder(); for (StorageDatum datum : entry) { if (keys == null || keys.contains(datum.getKey())) { copyBuilder.put(datum.getKey(), datum.getValue()); } } copies.add(copyBuilder.build()); } } return copies; } public final class DatumIterator implements Iterator<StorageDatum> { public DatumIterator() { it = backend.entrySet().iterator(); } @Override public boolean hasNext() { return it.hasNext(); } @Override public StorageDatum next() { Map.Entry<String, String> el = it.next(); return new StorageDatum(el.getKey(), el.getValue()); } @Override public void remove() { it.remove(); } private final Iterator<Map.Entry<String, String>> it; } public static final class Builder { public Builder put(String key, String value) { entry.put(key, value); return this; } public Builder putAll(StorageEntry sourceEntry) { for (StorageDatum datum : sourceEntry) { put(datum.getKey(), datum.getValue()); } return this; } public StorageEntry build() { StorageEntry builtEntry = entry; entry = new StorageEntry(); builtEntry.dirtyKeys.clear(); return builtEntry; } private StorageEntry entry = new StorageEntry(); } private Map<String, String> backend = new LinkedHashMap<>(); private final Set<String> dirtyKeys = new HashSet<>(); }