/**
Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016. All rights reserved.
Contact:
SYSTAP, LLC DBA Blazegraph
2501 Calvert ST NW #106
Washington, DC 20008
licenses@blazegraph.com
This program 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; version 2 of the License.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package com.bigdata.rdf.internal.impl.extensions;
import java.math.BigInteger;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import org.apache.log4j.Logger;
import org.openrdf.model.Literal;
import org.openrdf.model.URI;
import org.openrdf.model.Value;
import org.openrdf.model.datatypes.XMLDatatypeUtil;
import com.bigdata.rdf.internal.IDatatypeURIResolver;
import com.bigdata.rdf.internal.IExtension;
import com.bigdata.rdf.internal.IV;
import com.bigdata.rdf.internal.XSD;
import com.bigdata.rdf.internal.impl.literal.AbstractLiteralIV;
import com.bigdata.rdf.internal.impl.literal.LiteralExtensionIV;
import com.bigdata.rdf.internal.impl.literal.XSDIntegerIV;
import com.bigdata.rdf.model.BigdataURI;
import com.bigdata.rdf.model.BigdataValue;
import com.bigdata.rdf.model.BigdataValueFactory;
/**
* This implementation of {@link IExtension} implements inlining for literals
* that represent the derived numeric types:
* <ul>
* <li>xsd:nonPositiveInteger</li>
* <li>xsd:negativeInteger</li>
* <li>xsd:nonNegativeInteger</li>
* <li>xsd:positiveInteger</li>
* </ul>
*/
public class DerivedNumericsExtension<V extends BigdataValue> implements IExtension<V> {
private static final transient Logger log = Logger.getLogger(DerivedNumericsExtension.class);
private final Map<IV,BigdataURI> datatypes;
public DerivedNumericsExtension(final IDatatypeURIResolver resolver) {
this.datatypes = new LinkedHashMap<IV,BigdataURI>();
resolve(resolver, XSD.POSITIVE_INTEGER);
resolve(resolver, XSD.NEGATIVE_INTEGER);
resolve(resolver, XSD.NON_POSITIVE_INTEGER);
resolve(resolver, XSD.NON_NEGATIVE_INTEGER);
}
private void resolve(final IDatatypeURIResolver resolver, final URI uri) {
if (log.isDebugEnabled()) {
log.debug("resolving: " + uri);
}
final BigdataURI val = resolver.resolve(uri);
datatypes.put(val.getIV(), val);
}
public Set<BigdataURI> getDatatypes() {
return new LinkedHashSet<BigdataURI>(datatypes.values());
}
/**
* Attempts to convert the supplied value into an internal representation
* using BigInteger.
*/
public LiteralExtensionIV createIV(final Value value) {
if (value instanceof Literal == false)
throw new IllegalArgumentException();
final Literal lit = (Literal) value;
final URI dt = lit.getDatatype();
if (dt == null)
throw new IllegalArgumentException();
final String dts = dt.stringValue();
BigdataURI resolvedDT = null;
for (BigdataURI val : datatypes.values()) {
// Note: URI.stringValue() is efficient....
if (val.stringValue().equals(dts)) {
resolvedDT = val;
}
}
if (resolvedDT == null)
throw new IllegalArgumentException();
final String s = lit.getLabel();
final boolean valid;
if (dts.equals(XSD.POSITIVE_INTEGER.stringValue())) {
valid = XMLDatatypeUtil.isValidPositiveInteger(s);
} else if (dts.equals(XSD.NEGATIVE_INTEGER.stringValue())) {
valid = XMLDatatypeUtil.isValidNegativeInteger(s);
} else if (dts.equals(XSD.NON_POSITIVE_INTEGER.stringValue())) {
valid = XMLDatatypeUtil.isValidNonPositiveInteger(s);
} else if (dts.equals(XSD.NON_NEGATIVE_INTEGER.stringValue())) {
valid = XMLDatatypeUtil.isValidNonNegativeInteger(s);
} else {
valid = false;
}
if (!valid) {
throw new RuntimeException("could not correctly parse label: " + s + " for datatype: " + dts);
}
final BigInteger bi = XMLDatatypeUtil.parseInteger(s);
final AbstractLiteralIV delegate = new XSDIntegerIV(bi);
return new LiteralExtensionIV(delegate, resolvedDT.getIV());
}
/**
* Use the BigInteger value of the {@link XSDIntegerIV} delegate to create a
* datatype literal value with the appropriate datatype.
*/
public V asValue(final LiteralExtensionIV iv, final BigdataValueFactory vf) {
if (!datatypes.containsKey(iv.getExtensionIV())) {
throw new IllegalArgumentException("unrecognized datatype");
}
final BigInteger bi = iv.getDelegate().integerValue();
final BigdataURI dt = datatypes.get(iv.getExtensionIV());
final String s = bi.toString();
return (V) vf.createLiteral(s, dt);
}
}