/** * Copyright 2015 Santhosh Kumar Tekuri * * The JLibs authors license this file to you 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 * * 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 jlibs.xml.sax.dog; import jlibs.core.lang.ImpossibleException; import javax.xml.namespace.QName; import javax.xml.xpath.XPathConstants; import java.util.Collections; import java.util.List; /** * This class represents various possible datatypes of the xpath result. * * This class also has methods to convert result from one datatype to * another. Note that convertion of NodeSet to another and viceversa * is unsupported. * * @author Santhosh Kumar T */ public enum DataType{ /** * following are standard datatypes */ NODESET(XPathConstants.NODESET, Collections.emptyMap()), STRING(XPathConstants.STRING, ""), NUMBER(XPathConstants.NUMBER, 0d), BOOLEAN(XPathConstants.BOOLEAN, false), /** * these are extra datatypes that are used internally */ STRINGS(new QName("http://jlibs.org", "strings"), Collections.emptyList()), NUMBERS(new QName("http://jlibs.org", "numbers"), Collections.emptyList()), PRIMITIVE(new QName("http://jlibs.org", "primitive"), null); public final QName qname; public final Object defaultValue; private DataType(QName qname, Object defaultValue){ this.qname = qname; this.defaultValue = defaultValue; } /*-------------------------------------------------[ Convertions ]---------------------------------------------------*/ public Object convert(Object result){ switch(this){ case STRING: return asString(result); case BOOLEAN: return asBoolean(result); case NUMBER: return asNumber(result); } throw new UnsupportedOperationException("can't be converted to "+this); } public static boolean asBoolean(Object obj){ if(obj instanceof String) return ((String)obj).length()>0; else if(obj instanceof Double){ double number = (Double)obj; return number!=0 && !Double.isNaN(number); }else if(obj instanceof Boolean) return (Boolean)obj; else throw new ImpossibleException(obj.getClass().getName()); } public static final Double ZERO = 0d; public static final Double ONE = 1d; public static double asNumber(Object obj){ if(obj instanceof String){ try{ return Double.parseDouble((String)obj); }catch(NumberFormatException ex){ return Double.NaN; } }else if(obj instanceof Double) return (Double)obj; else if(obj instanceof Boolean) return (Boolean)obj ? ONE : ZERO; else throw new ImpossibleException(obj.getClass().getName()); } public static String asString(Object obj){ return String.valueOf(obj); } /*-------------------------------------------------[ Guessing Datatype ]---------------------------------------------------*/ public static DataType valueOf(Object literal){ if(literal instanceof String) return DataType.STRING; else if(literal instanceof Number) return DataType.NUMBER; else if(literal instanceof Boolean) return DataType.BOOLEAN; else{ assert literal instanceof List; return DataType.NODESET; } } }