/** * <copyright> * * This program and the accompanying materials are made available under the * terms of the BSD 3-clause license which accompanies this distribution. * * </copyright> */ package siple; import java.util.*; /** * Instances of this class represent comparable addresses in <i>Dewey</i> * notation.<br> * <br> * If an address <tt>A</tt> and an address <tt>B</tt> are compared * (<tt>A.compareTo(B)</tt>) it is decided, whether <tt>A</tt> is * <i>smaller</i>, <i>equal</i> or <i>greater</i> than <tt>B</tt> or not. * <i>Dewey</i> addresses can be viewed as tree labels, whereas an address * specifies an unique tree node. Each <i>Dewey</i> address consists of * arbitrary many parts, whereas each part is a natural number. The root * node's address has one part with value 1. Any other node's address is the * address of its parent node extended with an additional part, whose value is * the node's child number. E.g. assume a parent node <tt>P</tt> with address * <tt>1.54.8</tt>. Its third child has address <tt>1.54.8.3</tt>.<br> * <br> * If an address <tt>A</tt> represents a node in the subtree of <tt>B</tt>, we * define <tt>A</tt> to be <i>greater</i> than <tt>B</tt>. If <tt>B</tt> is in * the subtree of <tt>A</tt>, we define that <tt>A</tt> is <i>smaller</i> than * B. If neither, <tt>A</tt> is in the subtree of <tt>B</tt> or <tt>B</tt> is * in the subtree of <tt>A</tt>, <tt>A</tt> and <tt>B</tt> must have one * nearest ancestor node <tt>ANC</tt>. Let <tt>ANC_CHILD_A</tt> and * <tt>ANC_CHILD_B</tt> be child nodes of <tt>ANC</tt>. In this case <tt>A</tt> * is <i>smaller</i> than <tt>B</tt>, iff<br> * - the path from <tt>A</tt> to <tt>ANC</tt> contains the node * <tt>ANC_CHILD_A</tt> and<br> * - the path from <tt>B</tt> to <tt>ANC</tt> contains the node * <tt>ANC_CHILD_B</tt> and<br> * - <tt>ANC_CHILD_A</tt> is <i>smaller</i> than <tt>ANC_CHILD_B</tt> * (thus <tt>ANC_CHILD_A.compareTo(ANC_CHILD_B) == 1</tt>).<br> * If <tt>A</tt> is <i>smaller</i> than <tt>B</tt>, <tt>B</tt> must be * <i>greater</i> than <tt>A</tt>. * @author C. Bürger */ public class DeweyAddress implements Comparable<DeweyAddress>, Cloneable { private List<Integer> address; /** * Constructs a new NodeAddress, not yet initialized with any <i>Dewey</i> * address. */ public DeweyAddress() { address = new ArrayList<Integer>(); } /** * Adds another part to the address. E.g. assume address <tt>1.5</tt> is * represented by <tt>DeweyAddress</tt> <tt>na</tt>. * <tt>na.addAddressPart(23).addAddressPart(2)</tt> results into the * address <tt>1.5.23.2</tt>. * @param part The part to add. * @return This address. */ public DeweyAddress addAddressPart(int part) { address.add(part); return this; } /** * Decides if this node is an ancestor of the other node. * @param otherAddress The other node to compare to. * @return True, if the other node is a successor of this node. */ public boolean isAncestor(DeweyAddress otherAddress) { if (address.size() >= otherAddress.address.size()) return false; Iterator<Integer> iter2 = otherAddress.address.iterator(); for (Integer part1:address) { int part2 = iter2.next(); if (part1 != part2) return false; } return true; } /** * Decides if this node is a successor of the other node. If this node is * a successor, its address must be greater than the other node. * @param otherAddress The other node to compare to. * @return True, if the other node is an ancestor of this node. */ public boolean isSuccessor(DeweyAddress otherAddress) { return otherAddress.isAncestor(this); } /** * Compares this address with another one to decide, whether this address * is <i>smaller</i> than the other one, both addresses are equal or this * address is <i>greater</i> than the other one. * @param otherAddress The address to which compare this one. * @return 1 if this address is <i>smaller</i> than the other one, 0 if * both addresses are <i>equal</i> or -1 if this address is <i>greater</i> * than the other one. */ public int compareTo(DeweyAddress otherAddress) { Iterator<Integer> iter2 = otherAddress.address.iterator(); for (Integer part1:address) { if (!iter2.hasNext()) return -1; int part2 = iter2.next(); if (part1 < part2) return 1; if (part1 > part2) return -1; } if (iter2.hasNext()) return 1; return 0; } public boolean equals(Object o) { if (!(o instanceof DeweyAddress)) return false; return ((DeweyAddress)o).compareTo(this) == 0; } public DeweyAddress clone() { DeweyAddress result = new DeweyAddress(); result.address = new ArrayList<Integer>(address); return result; } /** * Returns a human readable <i>Dewey</i> address. E.g. <tt>1.3.2.65</tt> * @return A readable <i>Dewey</i> address. */ public String toString() { StringBuilder result = new StringBuilder(3*address.size()); for (Integer part:address) { result.append(part); result.append('.'); } result.deleteCharAt(result.length() - 1); return result.toString(); } }