/******************************************************************************* * This file is part of OpenNMS(R). * * Copyright (C) 2007-2011 The OpenNMS Group, Inc. * OpenNMS(R) is Copyright (C) 1999-2011 The OpenNMS Group, Inc. * * OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc. * * OpenNMS(R) is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation, either version 3 of the License, * or (at your option) any later version. * * OpenNMS(R) is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenNMS(R). If not, see: * http://www.gnu.org/licenses/ * * For more information contact: * OpenNMS(R) Licensing <license@opennms.org> * http://www.opennms.org/ * http://www.opennms.com/ *******************************************************************************/ package org.opennms.netmgt.model.discovery; import java.math.BigInteger; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; /** * IPAddressRange * * @author brozow * @version $Id: $ */ public class IPAddressRange implements Comparable<IPAddressRange>, Iterable<IPAddress> { private final IPAddress m_begin; private final IPAddress m_end; public IPAddressRange(String singleton) { this(singleton, singleton); } public IPAddressRange(IPAddress singleton) { this(singleton, singleton); } /** * <p>Constructor for IPAddressRange.</p> * * @param begin a {@link java.lang.String} object. * @param end a {@link java.lang.String} object. */ public IPAddressRange(String begin, String end) { this(new IPAddress(begin), new IPAddress(end)); } /** * <p>Constructor for IPAddressRange.</p> * * @param begin a {@link org.opennms.netmgt.model.discovery.IPAddress} object. * @param end a {@link org.opennms.netmgt.model.discovery.IPAddress} object. */ public IPAddressRange(IPAddress begin, IPAddress end) { if (begin.isGreaterThan(end)) { throw new IllegalArgumentException(String.format("beginning of range (%s) must come before end of range (%s)", begin, end)); } m_begin = begin; m_end = end; } /** * <p>getBegin</p> * * @return a {@link org.opennms.netmgt.model.discovery.IPAddress} object. */ public IPAddress getBegin() { return m_begin; } /** * <p>getEnd</p> * * @return a {@link org.opennms.netmgt.model.discovery.IPAddress} object. */ public IPAddress getEnd() { return m_end; } /** * <p>size</p> * * @return a long. */ public BigInteger size() { BigInteger size = m_end.toBigInteger(); size = size.subtract(m_begin.toBigInteger()); // Add 1 because the range is inclusive of beginning and end size = size.add(new BigInteger("1")); return size; } /** * <p>contains</p> * * @param addr a {@link org.opennms.netmgt.model.discovery.IPAddress} object. * @return a boolean. */ public boolean contains(IPAddress addr) { if (addr == null) { throw new IllegalArgumentException("addr should not be null"); } return addr.isGreaterThanOrEqualTo(m_begin) && addr.isLessThanOrEqualTo(m_end); } /** * <p>contains</p> * * @param addr a {@link org.opennms.netmgt.model.discovery.IPAddress} object. * @return a boolean. */ public boolean contains(String addr) { return contains(new IPAddress(addr)); } /** * <p>contains</p> * * @param range a {@link org.opennms.netmgt.model.discovery.IPAddressRange} object. * @return a boolean. */ public boolean contains(IPAddressRange range) { return this.contains(range.getBegin()) && this.contains(range.getEnd()); } /** * <p>overlaps</p> * * @param range a {@link org.opennms.netmgt.model.discovery.IPAddressRange} object. * @return a boolean. */ public boolean overlaps(IPAddressRange range) { return this.contains(range.getBegin()) || this.contains(range.getEnd()) || range.contains(this.getBegin()) || range.contains(this.getEnd()); } /** * <p>comesBefore</p> * * @param addr a {@link org.opennms.netmgt.model.discovery.IPAddress} object. * @return a boolean. */ public boolean comesBefore(IPAddress addr) { return m_end.isLessThan(addr); } /** * <p>comesBefore</p> * * @param range a {@link org.opennms.netmgt.model.discovery.IPAddressRange} object. * @return a boolean. */ public boolean comesBefore(IPAddressRange range) { return comesBefore(range.getBegin()); } /** * <p>comesAfter</p> * * @param addr a {@link org.opennms.netmgt.model.discovery.IPAddress} object. * @return a boolean. */ public boolean comesAfter(IPAddress addr) { return m_begin.isGreaterThan(addr); } /** * <p>comesAfter</p> * * @param range a {@link org.opennms.netmgt.model.discovery.IPAddressRange} object. * @return a boolean. */ public boolean comesAfter(IPAddressRange range) { return comesAfter(range.getEnd()); } /** * <p>adjoins</p> * * @param range a {@link org.opennms.netmgt.model.discovery.IPAddressRange} object. * @return a boolean. */ public boolean adjoins(IPAddressRange range) { return this.comesImmediatelyBefore(range) || this.comesImmediatelyAfter(range); } private boolean comesImmediatelyAfter(IPAddressRange range) { return this.comesAfter(range) && getBegin().isSuccessorOf(range.getEnd()); } private boolean comesImmediatelyBefore(IPAddressRange range) { return this.comesBefore(range) && getEnd().isPredecessorOf(range.getBegin()); } /** * <p>iterator</p> * * @return a {@link java.util.Iterator} object. */ public Iterator<IPAddress> iterator() { return new IPAddressRangeIterator(this); } private static class IPAddressRangeIterator implements Iterator<IPAddress> { private final IPAddressRange m_range; private IPAddress m_next; public IPAddressRangeIterator(IPAddressRange range) { m_range = range; m_next = range.getBegin(); } public boolean hasNext() { return (m_next != null); } public IPAddress next() { if (m_next == null) { throw new NoSuchElementException("Already returned the last element"); } final IPAddress next = m_next; m_next = next.incr(); if (!m_range.contains(m_next)) { m_next = null; } return next; } public void remove() { throw new UnsupportedOperationException("IPAddressRangeIterator.remove() is not yet implemented"); } } public int compareTo(IPAddressRange r) { if (this.comesBefore(r)) { // this is less than return -1; } else if (this.comesAfter(r)) { // this is greater than return 1; } else { // otherwise it overlaps return 0; } } /** {@inheritDoc} */ @Override public boolean equals(Object obj) { if (obj instanceof IPAddressRange) { IPAddressRange other = (IPAddressRange) obj; return this.m_begin.equals(other.m_begin) && this.m_end.equals(other.m_end); } return false; } /** {@inheritDoc} */ @Override public int hashCode() { return 31 * m_begin.hashCode() + m_end.hashCode(); } /** {@inheritDoc} */ @Override public String toString() { StringBuilder buf = new StringBuilder(); buf.append('[').append(m_begin).append(',').append(m_end).append(']'); return buf.toString(); } public boolean isSingleton() { return getBegin().equals(getEnd()); } public boolean combinable(IPAddressRange range) { return overlaps(range) || adjoins(range); } public IPAddressRange combine(IPAddressRange range) { if (!combinable(range)) { throw new IllegalArgumentException(String.format("Range %s is not combinable with range %s", this, range)); } return new IPAddressRange(IPAddress.min(range.getBegin(), getBegin()),IPAddress.max(getEnd(), range.getEnd())); } public IPAddressRange[] remove(IPAddressRange range) { if (range.contains(this)) { return new IPAddressRange[0]; } else if (!overlaps(range)) { return new IPAddressRange[] { this }; } else { List<IPAddressRange> ranges = new ArrayList<IPAddressRange>(2); if (getBegin().isLessThan(range.getBegin())) { ranges.add(new IPAddressRange(getBegin(), range.getBegin().decr())); } if (range.getEnd().isLessThan(getEnd())) { ranges.add(new IPAddressRange(range.getEnd().incr(), getEnd())); } return ranges.toArray(new IPAddressRange[ranges.size()]); } } }