/* Copyright 2008, 2009, 2010 by the Oxford University Computing Laboratory
This file is part of HermiT.
HermiT is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
HermiT 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with HermiT. If not, see <http://www.gnu.org/licenses/>.
*/
package org.semanticweb.HermiT.datatypes.binarydata;
import java.util.Collection;
public class BinaryDataLengthInterval {
protected final BinaryDataType m_binaryDataType;
protected final int m_minLength;
protected final int m_maxLength;
public BinaryDataLengthInterval(BinaryDataType binaryDataType,int minLength,int maxLength) {
assert !isIntervalEmpty(binaryDataType,minLength,maxLength);
m_binaryDataType=binaryDataType;
m_minLength=minLength;
m_maxLength=maxLength;
}
/**
* Computes the intersection of this interval with the supplied one. If the two intervals do not intersect, the result is null.
*/
public BinaryDataLengthInterval intersectWith(BinaryDataLengthInterval that) {
if (m_binaryDataType!=that.m_binaryDataType)
return null;
int newMinLength=Math.max(m_minLength,that.m_minLength);
int newMaxLength=Math.min(m_maxLength,that.m_maxLength);
if (isIntervalEmpty(m_binaryDataType,newMinLength,newMaxLength))
return null;
else if (isEqual(m_binaryDataType,newMinLength,newMaxLength))
return this;
else if (that.isEqual(m_binaryDataType,newMinLength,newMaxLength))
return that;
else
return new BinaryDataLengthInterval(m_binaryDataType,newMinLength,newMaxLength);
}
protected boolean isEqual(BinaryDataType binaryDataType,int minLength,int maxLength) {
return m_binaryDataType==binaryDataType && m_minLength==minLength && m_maxLength==maxLength;
}
public int subtractSizeFrom(int argument) {
if (argument<=0 || m_maxLength==Integer.MAX_VALUE)
return 0;
// If m_minLength or m_maxLength is more than 7, then the number of
// values exceeds the range of long.
if (m_minLength>=7 || m_maxLength>=7)
return 0;
// We now compute the actual number of values.
long size=getNumberOfValuesOfLength(m_maxLength)-getNumberOfValuesOfLength(m_minLength-1);
return (int)Math.max(argument-size,0L);
}
protected long getNumberOfValuesOfLength(int length) {
if (length<0)
return 0L;
else {
long valuesOfLength=1L;
long total=1L;
for (int i=1;i<=length;i++) {
valuesOfLength*=256L;
total+=valuesOfLength;
}
return total;
}
}
public boolean contains(BinaryData value) {
return m_binaryDataType==value.getBinaryDataType() && m_minLength<=value.getNumberOfBytes() && value.getNumberOfBytes()<=m_maxLength;
}
public void enumerateValues(Collection<Object> values) {
if (m_maxLength==Integer.MAX_VALUE)
throw new IllegalStateException("Internal error: the data range is infinite!");
if (m_minLength==0)
values.add(new BinaryData(m_binaryDataType,new byte[0]));
byte[] temp=new byte[m_maxLength];
processPosition(temp,values,0);
}
protected void processPosition(byte[] temp,Collection<Object> values,int position) {
if (position<m_maxLength) {
for (int b=0;b<=255;b++) {
temp[position]=(byte)b;
if (m_minLength<=position+1) {
byte[] copy=new byte[position+1];
System.arraycopy(temp,0,copy,0,copy.length);
values.add(new BinaryData(m_binaryDataType,copy));
}
processPosition(temp,values,position+1);
}
}
}
public String toString() {
StringBuffer buffer=new StringBuffer();
buffer.append(m_binaryDataType.toString());
buffer.append('[');
buffer.append(m_minLength);
buffer.append("..");
if (m_maxLength==Integer.MAX_VALUE)
buffer.append("+INF");
else
buffer.append(m_maxLength);
buffer.append(']');
return buffer.toString();
}
protected static boolean isIntervalEmpty(BinaryDataType binaryDataType,int minLength,int maxLength) {
return minLength>maxLength;
}
}