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

com.bol.ipresource.etree.NestedIntervalMap Maven / Gradle / Ivy

Go to download

High performance, low memory IP library (originally developed for RIPE NCC Whois server)

There is a newer version: 1.4.7
Show newest version
package com.bol.ipresource.etree;

import com.bol.ipresource.ip.Interval;
import com.bol.ipresource.util.CollectionHelper;
import com.bol.ipresource.util.Validate;
import com.google.common.collect.Lists;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

/**
 * A map with intervals as keys. Intervals are only allowed to intersect if they
 * are fully contained in the other interval (in other words, siblings are not
 * allowed to intersect, but nesting is ok).
 * 

* Note that this implementation is not synchronized. If * multiple threads access a map concurrently, and at least one of the threads * modifies the map structurally, it must be synchronized externally. (A * structural modification is any operation that adds or deletes one or more * mappings; merely changing the value associated with an existing key is not a * structural modification.) This is typically accomplished by synchronizing on * some object that naturally encapsulates the map. * * @param the type of the interval (must implement {@link Interval}). * @param the type of the values to store. */ public final class NestedIntervalMap, V> implements IntervalMap { private final ChildNodeMap children; /** * Construct an empty {@link NestedIntervalMap}. */ public NestedIntervalMap() { this.children = new ChildNodeTreeMap<>(); } /** * Construct a new {@link NestedIntervalMap} with (key, values) of * source copied. * * @param source the source to copy. */ public NestedIntervalMap(NestedIntervalMap source) { this.children = new ChildNodeTreeMap<>(source.children); } @Override public void put(K key, V value) { Validate.notNull(key); Validate.notNull(value); children.addChild(new InternalNode<>(key, value)); } @Override public void remove(K key) { Validate.notNull(key); children.removeChild(key); } @Override public void remove(K key, V value) { Validate.notNull(key); Validate.notNull(value); if (value.equals(CollectionHelper.uniqueResult(findExact(key)))) { remove(key); } } @Override public List findFirstLessSpecific(K key) { Validate.notNull(key); InternalNode node = internalFindFirstLessSpecific(key); return mapToValues(node); } @Override public List findAllLessSpecific(K key) { Validate.notNull(key); return mapToValues(internalFindAllLessSpecific(key)); } @Override public List findExactAndAllLessSpecific(K key) { Validate.notNull(key); return mapToValues(internalFindExactAndAllLessSpecific(key)); } @Override public List findExact(K key) { Validate.notNull(key); InternalNode node = internalFindExact(key); return mapToValues(node); } @Override public List findExactOrFirstLessSpecific(K key) { Validate.notNull(key); return mapToValues(internalFindExactOrFirstLessSpecific(key)); } @Override public List findFirstMoreSpecific(K key) { Validate.notNull(key); return mapToValues(internalFindFirstMoreSpecific(key)); } @Override public List findAllMoreSpecific(K key) { Validate.notNull(key); return mapToValues(internalFindAllMoreSpecific(key)); } @Override public List findExactAndAllMoreSpecific(K key) { Validate.notNull(key); return mapToValues(internalFindExactAndAllMoreSpecific(key)); } /** * Clears all values from the map. */ @Override public void clear() { children.clear(); } @Override public boolean equals(Object obj) { return this == obj || obj != null && getClass() == obj.getClass() && this.children.equals(((NestedIntervalMap) obj).children); } @Override public int hashCode() { return children.hashCode(); } @Override public String toString() { return children.toString(); } private List mapToValues(InternalNode node) { if (node == null) { return Collections.emptyList(); } return Collections.singletonList(node.getValue()); } private List mapToValues(Collection> nodes) { List result = Lists.newArrayListWithExpectedSize(nodes.size()); for (InternalNode node : nodes) { result.add(node.getValue()); } return result; } private InternalNode internalFindExactOrFirstLessSpecific(K range) { List> list = internalFindExactAndAllLessSpecific(range); return list.isEmpty() ? null : list.get(list.size() - 1); } private InternalNode internalFindFirstLessSpecific(K range) { List> list = internalFindAllLessSpecific(range); if (list.isEmpty()) { return null; } else { return list.get(list.size() - 1); } } private List> internalFindAllLessSpecific(K range) { List> result = internalFindExactAndAllLessSpecific(range); if (result.isEmpty()) { return result; } InternalNode last = result.get(result.size() - 1); if (last.getInterval().equals(range)) { return result.subList(0, result.size() - 1); } else { return result; } } private List> internalFindExactAndAllLessSpecific(K range) { List> result = new ArrayList<>(); children.findExactAndAllLessSpecific(result, range); return result; } private InternalNode internalFindExact(K range) { List> exactAndAllLessSpecific = internalFindExactAndAllLessSpecific(range); if (exactAndAllLessSpecific.isEmpty()) { return null; } InternalNode last = exactAndAllLessSpecific.get(exactAndAllLessSpecific.size() - 1); if (last.getInterval().equals(range)) { return last; } return null; } private List> internalFindFirstMoreSpecific(K range) { List> result = new ArrayList<>(); InternalNode container = internalFindExactOrFirstLessSpecific(range); if (container == null) { children.findFirstMoreSpecific(result, range); } else { container.getChildren().findFirstMoreSpecific(result, range); } return result; } private List> internalFindAllMoreSpecific(K range) { List> result = internalFindExactAndAllMoreSpecific(range); if (!result.isEmpty() && result.get(0).getInterval().equals(range)) { return result.subList(1, result.size()); } else { return result; } } private List> internalFindExactAndAllMoreSpecific(K range) { List> result = new ArrayList<>(); InternalNode containing = internalFindExactOrFirstLessSpecific(range); if (containing == null) { children.findExactAndAllMoreSpecific(result, range); } else { if (containing.getInterval().equals(range)) { result.add(containing); } containing.getChildren().findExactAndAllMoreSpecific(result, range); } return result; } public abstract static class Key> { private final K key; public Key(K key) { Validate.notNull(key); this.key = key; } public K getKey() { return key; } @Override public int hashCode() { return key.hashCode(); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } Key that = (Key) obj; return this.key.equals(that.key); } @Override public String toString() { return "IpResource(" + key + ")"; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy