private void cleanup() { if (!obsoleteEntries.isEmpty()) { ObservableMutableDocument<? super E, E, ?> document = getDocument(); Collection<E> toDelete = new ArrayList<E>(obsoleteEntries); for (E e : toDelete) { document.deleteNode(e); } // Deletion callbacks should cleanup obsoleteEntries collection one by one. assert obsoleteEntries.isEmpty(); } }
/** * Creates an entry element for the specified map entry. * * @param value */ private void createEntry(C value) { Map<String, String> attrs = new HashMap<String, String>(); attrs.put(valueAttrName, serializer.toString(value)); E entry = getDocument().createChildElement(container, entryTagName, attrs); }
/** * Gets the value of an entry. * * @param entry * @return the value of an entry. */ private C valueOf(E entry) { return serializer.fromString(getDocument().getAttribute(entry, valueAttrName)); }
/** * Clears the cache reference to an entry, if the cache refers to it, in * response to an entry element being removed. */ @Override public void onElementRemoved(E entry) { if (!entryTagName.equals(getDocument().getTagName(entry))) { return; } // It is possible, in transient states, that there are multiple entries in the document for the // same key. Therefore, we can not blindly remove the entry from the cache based on key alone. if (value == entry) { C oldValue = get(); value = null; triggerOnEntryChanged(oldValue, null); } else { obsoleteEntries.remove(entry); } }
/** * Loads from the document state, aggressively removing obsolete values. */ private void load() { ObservableMutableDocument<? super E, E, ?> document = getDocument(); E value = DocHelper.getFirstChildElement(document, container); E nextValue; while (value != null) { nextValue = DocHelper.getNextSiblingElement(document, value); onElementAdded(value); value = nextValue; } }
/** * Updates the entry cache, if necessary, in response to an entry element * being added. * * This method also aggressively deletes any entries that are not greater * than the cached entry. */ @Override public void onElementAdded(E entry) { ObservableMutableDocument<? super E, E, ?> document = getDocument(); assert container.equals(document.getParentElement(entry)); if (!entryTagName.equals(document.getTagName(entry))) { return; } C newValue = valueOf(entry); C oldValue = get(); // If the new value should end up in the cache, delete the old one (if applicable) and update // the entry cache. // Otherwise, the new value is aggressively deleted. if (oldValue == null || oldValue.compareTo(newValue) < 0) { invalidateCacheEntry(); // This should clean up the old entry in onEntryRemoved. value = entry; triggerOnEntryChanged(oldValue, newValue); } else { invalidateEntry(entry); } }