/* 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.rdfplainliteral; import java.util.Collection; public class RDFPlainLiteralLengthInterval { public static final int CHARACTER_COUNT=1112033; public static enum LanguageTagMode { PRESENT,ABSENT }; protected final LanguageTagMode m_languageTagMode; protected final int m_minLength; protected final int m_maxLength; public RDFPlainLiteralLengthInterval(LanguageTagMode languageTagMode,int minLength,int maxLength) { assert !isIntervalEmpty(languageTagMode,minLength,maxLength); m_languageTagMode=languageTagMode; 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 RDFPlainLiteralLengthInterval intersectWith(RDFPlainLiteralLengthInterval that) { if (m_languageTagMode!=that.m_languageTagMode) return null; int newMinLength=Math.max(m_minLength,that.m_minLength); int newMaxLength=Math.min(m_maxLength,that.m_maxLength); if (isIntervalEmpty(m_languageTagMode,newMinLength,newMaxLength)) return null; else if (isEqual(m_languageTagMode,newMinLength,newMaxLength)) return this; else if (that.isEqual(m_languageTagMode,newMinLength,newMaxLength)) return that; else return new RDFPlainLiteralLengthInterval(m_languageTagMode,newMinLength,newMaxLength); } protected boolean isEqual(LanguageTagMode languageTagMode,int minLength,int maxLength) { return m_languageTagMode==languageTagMode && m_minLength==minLength && m_maxLength==maxLength; } public int subtractSizeFrom(int argument) { if (argument<=0 || m_maxLength==Integer.MAX_VALUE || m_languageTagMode==LanguageTagMode.PRESENT) return 0; // If m_minLength or m_maxLength is more than 4, then the number of // values exceeds the range of long. if (m_minLength>=4 || m_maxLength>=4) 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*=(long)CHARACTER_COUNT; total+=valuesOfLength; } return total; } } public boolean contains(String value) { return m_languageTagMode==LanguageTagMode.ABSENT && m_minLength<=value.length() && value.length()<=m_maxLength && RDFPlainLiteralPatternValueSpaceSubset.s_xsdString.run(value); } public boolean contains(RDFPlainLiteralDataValue value) { String string=value.getString(); String languageTag=value.getLanguageTag(); return m_languageTagMode==LanguageTagMode.PRESENT && m_minLength<=string.length() && string.length()<=m_maxLength && RDFPlainLiteralPatternValueSpaceSubset.s_xsdString.run(string) && RDFPlainLiteralPatternValueSpaceSubset.s_languageTag.run(languageTag); } public void enumerateValues(Collection<Object> values) { if (m_maxLength==Integer.MAX_VALUE || m_languageTagMode==LanguageTagMode.PRESENT) throw new IllegalStateException("Internal error: the data range is infinite!"); if (m_minLength==0) values.add(""); char[] temp=new char[m_maxLength]; processPosition(temp,values,0); } protected void processPosition(char[] temp,Collection<Object> values,int position) { if (position<m_maxLength) { for (int c=0;c<=0xFFFF;c++) if (isRDFPlainLiteralCharacter((char)c)) { temp[position]=(char)c; if (m_minLength<=position+1) values.add(new String(temp,0,position+1)); processPosition(temp,values,position+1); } } } public String toString() { StringBuffer buffer=new StringBuffer(); buffer.append('['); buffer.append(m_minLength); buffer.append(".."); if (m_maxLength==Integer.MAX_VALUE) buffer.append("+INF"); else buffer.append(m_maxLength); buffer.append(']'); if (m_languageTagMode==LanguageTagMode.ABSENT) buffer.append("@<none>"); else buffer.append("@<lt>"); return buffer.toString(); } protected static boolean isIntervalEmpty(LanguageTagMode languageTagMode,int minLength,int maxLength) { return minLength>maxLength; } protected static boolean isRDFPlainLiteralCharacter(char c) { return c==0x9 || c==0xA || c==0xD || (0x20<=c && c<=0xD7FF) || (0xE000<=c && c<=0xFFFD); } }