package org.openprovenance.prov.model;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import org.apache.commons.io.IOUtils;
import org.openprovenance.prov.model.exception.ConverterException;
import org.xml.sax.SAXException;
/**
* Conversion from String to Object and vice-versa for common xsd types.
*
* @author lavm
*
*/
public class ValueConverter {
final private LiteralConstructor pFactory;
final private Name name;
public ValueConverter(ProvFactory pFactory) {
this.pFactory = pFactory;
this.name = pFactory.getName();
}
// should be implemented with a hash table of converters
/**
* Converts a string into a Java object, according to type provided. This
* function does not convert to QualifiedName since this requires access to
* a prefix-namespace mapping.
*
* @param datatype
* any xsd datatype, provided it is not xsd:QName
* @param value
* is a String
* @return an object
*/
public Object convertToJava(QualifiedName datatype, String value) {
if (datatype.equals(name.XSD_STRING))
return value;
if (datatype.equals(name.XSD_INT))
return Integer.parseInt(value);
if (datatype.equals(name.XSD_LONG))
return Long.parseLong(value);
if (datatype.equals(name.XSD_SHORT))
return Short.parseShort(value);
if (datatype.equals(name.XSD_DOUBLE))
return Double.parseDouble(value);
if (datatype.equals(name.XSD_FLOAT))
return Float.parseFloat(value);
if (datatype.equals(name.XSD_DECIMAL))
return new java.math.BigDecimal(value);
if (datatype.equals(name.XSD_BOOLEAN))
return Boolean.parseBoolean(value);
if (datatype.equals(name.XSD_BYTE))
return Byte.parseByte(value);
if (datatype.equals(name.XSD_UNSIGNED_INT))
return Long.parseLong(value);
if (datatype.equals(name.XSD_UNSIGNED_SHORT))
return Integer.parseInt(value);
if (datatype.equals(name.XSD_UNSIGNED_BYTE))
return Short.parseShort(value);
if (datatype.equals(name.XSD_UNSIGNED_LONG))
return new java.math.BigInteger(value);
if (datatype.equals(name.XSD_INTEGER))
return new java.math.BigInteger(value);
if (datatype.equals(name.XSD_NON_NEGATIVE_INTEGER))
return new java.math.BigInteger(value);
if (datatype.equals(name.XSD_NON_POSITIVE_INTEGER))
return new java.math.BigInteger(value);
if (datatype.equals(name.XSD_POSITIVE_INTEGER))
return new java.math.BigInteger(value);
if (datatype.equals(name.XSD_ANY_URI)) {
return value;
}
if (datatype.equals(name.PROV_QUALIFIED_NAME)) {
throw new ConverterException("Not conversion to xsd:QName");
}
if (datatype.equals(name.XSD_DATETIME)) {
return pFactory.newISOTime(value);
}
if (datatype.equals(name.XSD_GYEAR)) {
return pFactory.newGYear(new Integer(value));
}
if (datatype.equals(name.XSD_GMONTH)) {
// format is --02
return pFactory.newGMonth(new Integer(value.substring(2)));
}
if (datatype.equals(name.XSD_GMONTH_DAY)) {
// format is --12-25
return pFactory.newGMonthDay(new Integer(value.substring(2, 4)),
new Integer(value.substring(5, 7)));
}
if (datatype.equals(name.XSD_GDAY)) {
// format is ---30
return pFactory.newGDay(new Integer(value.substring(3)));
}
if (datatype.equals(name.XSD_DURATION)) {
return pFactory.newDuration(value);
}
if (datatype.equals(name.XSD_DAY_TIME_DURATION)) {
return pFactory.newDuration(value);
}
if (datatype.equals(name.XSD_YEAR_MONTH_DURATION)) {
return pFactory.newDuration(value);
}
if (datatype.equals(name.XSD_LANGUAGE)) {
return value;
}
if (datatype.equals(name.XSD_TOKEN)) {
return value;
}
if (datatype.equals(name.XSD_NMTOKEN)) {
return value;
}
if (datatype.equals(name.XSD_NAME)) {
return value;
}
if (datatype.equals(name.XSD_NCNAME)) {
return value;
}
if (datatype.equals(name.XSD_NORMALIZED_STRING)) {
return value;
}
if (datatype.equals(name.XSD_HEX_BINARY)) {
return pFactory.hexDecoding(value);
}
if (datatype.equals(name.XSD_BASE64_BINARY)) {
return pFactory.base64Decoding(value);
}
if (datatype.equals(name.RDF_LITERAL)) {
return convertXMLLiteral(value);
}
throw new UnsupportedOperationException("UNKNOWN literal type " + datatype);
}
public org.w3c.dom.Element convertXMLLiteral(String value) {
DOMProcessing dp=new DOMProcessing((ProvFactory)pFactory);
DocumentBuilder db=dp.builder;
InputStream in;
org.w3c.dom.Document doc=null;
try {
in = IOUtils.toInputStream(value, "UTF-8");
doc=db.parse(in);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (doc==null) return null;
return doc.getDocumentElement();
}
public QualifiedName getXsdType(Object o) {
if (o instanceof Integer)
return name.XSD_INT;
if (o instanceof String)
return name.XSD_STRING;
if (o instanceof LangString)
return name.XSD_STRING;
if (o instanceof BigInteger)
return name.XSD_INTEGER;
if (o instanceof Long)
return name.XSD_LONG;
if (o instanceof Short)
return name.XSD_SHORT;
if (o instanceof Double)
return name.XSD_DOUBLE;
if (o instanceof Float)
return name.XSD_FLOAT;
if (o instanceof java.math.BigDecimal)
return name.XSD_DECIMAL;
if (o instanceof Boolean)
return name.XSD_BOOLEAN;
if (o instanceof Byte)
return name.XSD_BYTE;
if (o instanceof QualifiedName)
return name.PROV_QUALIFIED_NAME;
if (o instanceof XMLGregorianCalendar) {
XMLGregorianCalendar cal = (XMLGregorianCalendar) o;
QName t = cal.getXMLSchemaType();
if (t.getLocalPart().equals(name.XSD_GYEAR.getLocalPart()))
return name.XSD_GYEAR;
if (t.getLocalPart().equals(name.XSD_DATETIME.getLocalPart()))
return name.XSD_DATETIME;
// TODO: need to support all time related xsd types
// default, return xsd:datetime
return name.XSD_DATETIME;
}
// issue #54 flagged a concern: value can be an element, when xsi:type
// was unspecified.
// this is no longer the case
// System.out.println("getXsdType() " + o.getClass());
// Let's be permissive, and return the unknown qualified name
return name.QUALIFIED_NAME_UNKNOWN_TYPE;
}
}