inet.ipaddr.format.AddressDivisionSeries Maven / Gradle / Ivy
/*
* Copyright 2016-2018 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;
import java.math.BigInteger;
import inet.ipaddr.AddressNetwork;
import inet.ipaddr.PrefixLenException;
import inet.ipaddr.format.string.AddressStringDivisionSeries;
/**
* Represents a series of groups of address divisions or segments. Each group may have a different bit size.
*
* This interface is the super interface of all interfaces and classes representing a series of divisions or segments.
*
* @author sfoley
*
*/
public interface AddressDivisionSeries extends AddressItem, AddressStringDivisionSeries {
/**
* Use this method to compare the counts of two address series.
*
* Rather than calculating counts with getCount(), there can be more efficient ways of comparing whether one series represents more individual address series than another.
*
* @return a positive integer if this AddressDivisionSeries has a larger count than the provided, 0 if they are the same, a negative integer if the other has a larger count.
*/
default int isMore(AddressDivisionSeries other) {
if(!isMultiple()) {
return other.isMultiple() ? -1 : 0;
}
if(!other.isMultiple()) {
return 1;
}
return getCount().compareTo(other.getCount());
}
/**
* @return the given division in this series. The first is at index 0.
*/
@Override
AddressGenericDivision getDivision(int index);
/**
* Get standard-format strings for each of the divisions in the series.
*
* @return
*/
String[] getDivisionStrings();
/**
* The bit-length of the portion of the address that is not specific to an individual address but common amongst a group of addresses.
*
* Typically this is the largest number of bits in the upper-most portion of the section for which the remaining bits assume all possible values.
*
* For IP addresses, this must be explicitly defined when the address is created. For example, 1.2.0.0/16 has a prefix length of 16, while 1.2.*.* has no prefix length,
* even though they both represent the same set of addresses and are considered equal. Prefixes can be considered variable for any given IP addresses and can
* depend on the routing table.
*
* The methods {@link AddressDivisionSeries#getMinPrefixLengthForBlock()} and {@link AddressDivisionSeries#getPrefixLengthForSingleBlock()} can help you to obtain or define a prefix length if one does not exist already.
* 1.2.0.0/16 and 1.2.*.* both the same equivalent and minimum prefix length of 16.
*
* For MAC addresses, the prefix is initially defined by the range, so 1:2:3:*:*:* has a prefix length of 24 by definition. Addresses derived from the original may retain the original prefix length regardless of their range.
*
*/
Integer getPrefixLength();
/**
* Whether there exists a prefix length associated with this series.
*/
boolean isPrefixed();
/**
* Returns whether this address segment series represents a block of addresses associated with its prefix length.
*
* This returns false if it has no prefix length or if it is a range of addresses that does not include
* the entire subnet block for the prefix length.
*
* If {@link AddressNetwork#getPrefixConfiguration} is set to consider all prefixes as subnets, this returns true for any series with a prefix length.
*
* An important distinction of {@link #containsPrefixBlock(int)} with this method is that this method returns
* false if the series does not have a prefix length assigned to it,
* even if there exists one or more prefix lengths for which {@link #containsPrefixBlock(int)} returns true.
* @return
*/
boolean isPrefixBlock();
/**
* Returns whether the range of values matches a single subnet block for the prefix length
*
* An important distinction of this method with {@link #containsSinglePrefixBlock(int)} is that this method returns
* false if the series does not have a prefix length assigned to it,
* even if there exists a prefix length for which {@link #containsSinglePrefixBlock(int)}
* returns true.
*
*
* @return
*/
boolean isSinglePrefixBlock();
/**
* If this has a prefix length, the count of the range of values in the prefix.
*
* If this has no prefix length, returns the same value as {@link #getCount()}
*
* @return
*/
default BigInteger getPrefixCount() {
Integer prefixLength = getPrefixLength();
if(prefixLength == null || prefixLength >= getBitCount()) {
return getCount();
}
return getPrefixCount(prefixLength);
}
@Override
default BigInteger getPrefixCount(int prefixLength) {
if(prefixLength < 0 || prefixLength > getBitCount()) {
throw new PrefixLenException(this, prefixLength);
}
BigInteger result = BigInteger.ONE;
if(isMultiple()) {
int divisionCount = getDivisionCount();
int divPrefixLength = prefixLength;
for(int i = 0; i < divisionCount; i++) {
AddressGenericDivision division = getDivision(i);
int divBitCount = division.getBitCount();
if(division.isMultiple()) {
BigInteger divCount = (divPrefixLength < divBitCount) ? division.getPrefixCount(divPrefixLength) : division.getCount();
result = result.multiply(divCount);
}
if(divPrefixLength <= divBitCount) {
break;
}
divPrefixLength -= divBitCount;
}
}
return result;
}
@Override
default BigInteger getCount() {
BigInteger result = BigInteger.ONE;
int count = getDivisionCount();
if(count > 0) {
for(int i = 0; i < count; i++) {
AddressGenericDivision div = getDivision(i);
if(div.isMultiple()) {
BigInteger divCount = div.getCount();
result = result.multiply(divCount);
}
}
}
return result;
}
/**
* Returns the count of values in the initial (higher) count of divisions.
*
* @return
*/
default BigInteger getBlockCount(int divCount) {
if(divCount < 0) {
throw new IllegalArgumentException();
}
BigInteger result = BigInteger.ONE;
int divisionCount = getDivisionCount();
if(divCount < divisionCount) {
divisionCount = divCount;
}
for(int i = 0; i < divisionCount; i++) {
AddressGenericDivision division = getDivision(i);
if(division.isMultiple()) {
result = result.multiply(division.getCount());
}
}
return result;
}
@Override
default int getBitCount() {
int count = getDivisionCount();
int bitCount = 0;
for(int i = 0; i < count; i++) {
bitCount += getDivision(i).getBitCount();
}
return bitCount;
}
/**
* Returns whether the series represents a range of values that are sequential.
*
* Generally, this means that any division covering a range of values must be followed by divisions that are full range, covering all values.
*
* @return
*/
default boolean isSequential() {
int count = getDivisionCount();
if(count > 1) {
for(int i = 0; i < count; i++) {
if(getDivision(i).isMultiple()) {
for(++i; i < count; i++) {
if(!getDivision(i).isFullRange()) {
return false;
}
}
return true;
}
}
}
return true;
}
/**
* Gets the minimal segment index for which all following segments are full-range blocks.
*
* The segment at this index is not a full-range block unless all segments are full-range.
* The segment at this index and all following segments form a sequential range.
* For the full series to be sequential, the preceding segments must be single-valued.
*
* @return
*/
default int getSequentialBlockIndex() {
int segCount = getDivisionCount();
if(segCount == 0) {
return 0;
}
for(segCount--; segCount > 0 && getDivision(segCount).isFullRange(); segCount--);
return segCount;
}
}