All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.leaprnd.deltadom.matching.NodeChecksums Maven / Gradle / Ivy

Go to download

A high performance Java library for finding the differences between two HTML documents

The newest version!
package com.leaprnd.deltadom.matching;

import org.w3c.dom.Node;

import java.util.ConcurrentModificationException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;

import static java.util.Collections.singleton;

class NodeChecksums {

	private final HashMap checksumsByNode = new HashMap<>();
	private final HashMap nodesByUniqueChecksum = new HashMap<>();
	private final HashMap> nodesByDuplicateChecksum = new HashMap<>();

	public void put(Node node, NodeChecksum checksum) {
		checksumsByNode.put(node, checksum);
		final var oldNodes = nodesByDuplicateChecksum.get(checksum);
		if (oldNodes != null) {
			oldNodes.add(node);
			return;
		}
		final var collision = nodesByUniqueChecksum.putIfAbsent(checksum, node);
		if (collision == null) {
			return;
		}
		verify(nodesByUniqueChecksum.remove(checksum, collision));
		final var newNodes = new HashSet();
		newNodes.add(node);
		newNodes.add(collision);
		verify(nodesByDuplicateChecksum.putIfAbsent(checksum, newNodes) == null);
	}

	public Node removeNodeIfUnique(NodeChecksum checksum) {
		final var node = nodesByUniqueChecksum.remove(checksum);
		if (node == null) {
			return null;
		}
		verify(checksumsByNode.remove(node, checksum));
		return node;
	}

	public Set removeNodesBy(NodeChecksum checksum) {
		final var unique = removeNodeIfUnique(checksum);
		if (unique == null) {
			return removeNodesIfDuplicate(checksum);
		}
		return singleton(unique);
	}

	public Set removeNodesIfDuplicate(NodeChecksum checksum) {
		final var nodes = nodesByDuplicateChecksum.remove(checksum);
		if (nodes == null) {
			return null;
		}
		for (final var node : nodes) {
			verify(checksumsByNode.remove(node, checksum));
		}
		return nodes;
	}

	public int getTotalSize() {
		return checksumsByNode.size();
	}

	public int getUniqueSize() {
		return nodesByUniqueChecksum.size();
	}

	public NodeChecksum getChecksumOf(Node node) {
		return checksumsByNode.get(node);
	}

	public Set getNodes() {
		return checksumsByNode.keySet();
	}

	public boolean remove(Node root) {
		final var checksum = checksumsByNode.remove(root);
		if (checksum == null) {
			return false;
		}
		if (nodesByUniqueChecksum.remove(checksum, root)) {
			return true;
		}
		final var oldNodes = nodesByDuplicateChecksum.get(checksum);
		switch (oldNodes.size()) {
			case 0, 1 -> throw new ConcurrentModificationException();
			case 2 -> {
				verify(nodesByDuplicateChecksum.remove(checksum, oldNodes));
				for (final var oldNode : oldNodes) {
					if (oldNode == root) {
						continue;
					}
					verify(nodesByUniqueChecksum.putIfAbsent(checksum, oldNode) == null);
				}
			}
			default -> verify(oldNodes.remove(root));
		}
		return true;
	}

	public Set getUniqueChecksums() {
		return nodesByUniqueChecksum.keySet();
	}

	public Set getDuplicateChecksums() {
		return nodesByDuplicateChecksum.keySet();
	}

	private static void verify(boolean test) {
		if (test) {
			return;
		}
		throw new ConcurrentModificationException();
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy