/** * Handles an element being removed from the container. */ private void handleElementRemoved(E deletedElement) { // To start with though, we do a quick check to see if deletedElement has // the same tag name as value elements. if (!entryTagName.equals(getDocument().getTagName(deletedElement))) { // Exit, because deletedElement definitely isn't part of this container. return; } if (obsoleteElements.remove(deletedElement)) { // Element was obsolete, so ignore the removal event return; } T value = valueOf(deletedElement); E existingElement = valueElements.get(value); if (existingElement != deletedElement) { // deleted element was not part of the backing store for this map, so // ignore it } else { valueElements.remove(value); fireOnValueRemoved(value); } }
/** * Handles a new element being added to the container. If it represents a new * value, that value is recorded. If it represents a value already in this * container, either the old element or the new element is marked obsolete. * The element marked obsolete is the one that appears later in the document. */ private void handleElementAdded(E newElement) { ObservableMutableDocument<? super E, E, ?> document = getDocument(); assert container.equals(document.getParentElement(newElement)); if (!entryTagName.equals(document.getTagName(newElement))) { return; } T value = valueOf(newElement); E oldEntry = valueElements.get(value); if (oldEntry == null) { // Entry is for a new value - add it to the element map and fire an event // to collection listeners valueElements.put(value, newElement); fireOnValueAdded(value); } else if (document.getLocation(oldEntry) < document.getLocation(newElement)) { // newEntry is not needed, so mark it obsolete obsoleteElements.add(newElement); } else { // oldEntry is no needed, so mark it obsoleted and use the new one instead obsoleteElements.add(oldEntry); valueElements.put(value, newElement); } }