
inet.ipaddr.format.util.AbstractTree Maven / Gradle / Ivy
/*
* Copyright 2020 Sean C Foley
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* or at
* https://github.com/seancfoley/IPAddress/blob/master/LICENSE
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inet.ipaddr.format.util;
import java.util.Iterator;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import inet.ipaddr.Address;
import inet.ipaddr.AddressSegmentSeries;
import inet.ipaddr.HostIdentifierException;
import inet.ipaddr.IPAddressSegmentSeries;
import inet.ipaddr.format.util.AddressTrieOps.AddressTrieAddOps;
import inet.ipaddr.format.util.BinaryTreeNode.KeyIterator;
abstract class AbstractTree implements AddressTrieAddOps {
private static final long serialVersionUID = 1L;
static ResourceBundle bundle;
static {
//reuse the same properties file
String propertyFileName = "IPAddressResources";
String name = HostIdentifierException.class.getPackage().getName() + '.' + propertyFileName;
try {
bundle = ResourceBundle.getBundle(name);
} catch (MissingResourceException e) {
System.err.println("bundle " + name + " is missing");
}
}
static String getMessage(String key) {
if(bundle != null) {
try {
return bundle.getString(key);
} catch (MissingResourceException e1) {}
}
return key;
}
BinaryTreeNode root;
protected AbstractTree(BinaryTreeNode root) {
this.root = root;
}
/**
* Returns the root of this trie
* @return
*/
public BinaryTreeNode getRoot() {
return root;
}
/**
* Returns the number of elements in the tree.
* Only nodes for which {@link BinaryTreeNode#isAdded()} returns true are counted.
* When zero is returned, {@link #isEmpty()} returns true.
*
* @return
*/
public int size() {
return getRoot().size();
}
/**
* Returns the number of nodes in the tree, which is always more than the number of elements.
*
* @return
*/
public int nodeSize() {
return getRoot().nodeSize();
}
/**
* Ensures the address is either an individual address or a prefix block subnet.
*
* @param
* @param addr
* @param thro
* @return
*/
@SuppressWarnings("unchecked")
static E checkBlockOrAddress(E addr, boolean thro) {
if(!addr.isMultiple()) {
if(!addr.isPrefixed()) {
return addr;
}
return (E) addr.withoutPrefixLength();
} else if(addr.isSinglePrefixBlock()) {
return addr;
} else {
AddressSegmentSeries series;
if(addr instanceof IPAddressSegmentSeries) {
series = ((IPAddressSegmentSeries) addr).assignPrefixForSingleBlock();
} else {
Integer newPrefix = addr.getPrefixLengthForSingleBlock();
series = newPrefix == null ? null : addr.setPrefixLength(newPrefix, false);
}
if(series != null) {
return (E) series;
}
}
if(thro) {
throw new IllegalArgumentException(getMessage("ipaddress.error.address.not.block"));
}
return null;
}
/**
* Removes all added nodes from the tree, after which {@link #isEmpty()} will return true
*/
public void clear() {
getRoot().clear();
}
@Override
public Iterator iterator() {
return new KeyIterator(nodeIterator(true));
}
@Override
public Iterator descendingIterator() {
return new KeyIterator(nodeIterator(false));
}
@Override
public int hashCode() {
int hashCode = 0;
Iterator extends BinaryTreeNode> these = nodeIterator(true);
while(these.hasNext()) {
BinaryTreeNode> node = these.next();
hashCode += node.hashCode();
}
return hashCode;
}
@SuppressWarnings("unchecked")
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if(o instanceof AbstractTree) {
AbstractTree other = (AbstractTree) o;
if(other.size() != size()) {
return false;
}
Iterator extends BinaryTreeNode> these = nodeIterator(true),
others = other.nodeIterator(true);
while(these.hasNext()) {
BinaryTreeNode> node = these.next(), otherNode = others.next();
if(!node.equals(otherNode)) {
return false;
}
}
return true;
}
return false;
}
/**
* Returns true if there are not any added nodes within this tree
*/
public boolean isEmpty() {
return size() == 0;
}
/**
* Returns a visual representation of the tree with one node per line.
*/
@Override
public String toString() {
return toString(true);
}
/**
* Returns a visual representation of the tree with one node per line, with or without the non-added keys.
*/
public String toString(boolean withNonAddedKeys) {
return getRoot().toTreeString(withNonAddedKeys, true);
}
/**
* Copies the trie, but not the keys or values.
*/
@SuppressWarnings("unchecked")
@Override
public AbstractTree clone() {
try {
return (AbstractTree) super.clone();
} catch (CloneNotSupportedException e) {
return null;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy