/* * ==================================================================== * ======== The Apache Software License, Version 1.1 * ================== * ========================================================== * Copyright (C) 2002 The Apache Software Foundation. All rights * reserved. Redistribution and use in source and binary forms, with * or without modifica- tion, are permitted provided that the * following conditions are met: 1. Redistributions of source code * must retain the above copyright notice, this list of conditions and * the following disclaimer. 2. Redistributions in binary form must * reproduce the above copyright notice, this list of conditions and * the following disclaimer in the documentation and/or other * materials provided with the distribution. 3. The end-user * documentation included with the redistribution, if any, must * include the following acknowledgment: "This product includes * software developed by SuperBonBon Industries * (http://www.sbbi.net/)." Alternately, this acknowledgment may * appear in the software itself, if and wherever such third-party * acknowledgments normally appear. 4. The names "UPNPLib" and * "SuperBonBon Industries" must not be used to endorse or promote * products derived from this software without prior written * permission. For written permission, please contact info@sbbi.net. * 5. Products derived from this software may not be called * "SuperBonBon Industries", nor may "SBBI" appear in their name, * without prior written permission of SuperBonBon Industries. THIS * SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR ITS * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- DING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. This software consists of voluntary contributions made * by many individuals on behalf of SuperBonBon Industries. For more * information on SuperBonBon Industries, please see * <http://www.sbbi.net/>. */ package net.tomp2p.upnp; import java.io.IOException; import java.net.URI; import java.util.Date; import java.util.HashSet; import java.util.Set; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpressionException; import org.w3c.dom.Node; /** * Class to contain a service state variable definition * * @author <a href="mailto:superbonbon@sbbi.net">SuperBonBon</a> * @version 1.0 */ public class StateVariable implements StateVariableTypes { private StateVariableMessage stateVarMsg = null; /** * State variable name */ public final String name; /** * Boolean to indicate if the variable is sending events when value of the * var is changing. */ public final boolean sendEvents; /** * The variable UPNP data type */ public final String dataType; /** * The default value of the state variable */ public final String defaultValue; /** * The minimum value as a string */ public final String minimumRangeValue; /** * The maximum value as a string */ public final String maximumRangeValue; /** * The value step range as a string */ public final String stepRangeValue; /** * A set of allowed values (String objects) for the variable */ public final Set<String> allowedvalues = new HashSet<String>(); /** * The parent {@link Service} Object */ public final Service parent; StateVariable(Service parent, Node xml) throws XPathExpressionException { this.parent = parent; sendEvents = Boolean.parseBoolean(XMLUtil.xpath.evaluate("/@sendEvents", xml)); name = XMLUtil.xpath.evaluate("name", xml); dataType = XMLUtil.xpath.evaluate("dataType", xml); defaultValue = XMLUtil.xpath.evaluate("defaultValue", xml); minimumRangeValue = XMLUtil.xpath.evaluate("allowedValueRange/minimum", xml); maximumRangeValue = XMLUtil.xpath.evaluate("allowedValueRange/maximum", xml); stepRangeValue = XMLUtil.xpath.evaluate("allowedValueRange/step", xml); Node allowedXML = (Node) XMLUtil.xpath.evaluate("allowedValueList", xml, XPathConstants.NODE); if (allowedXML != null) { int count = Integer.parseInt(XMLUtil.xpath.evaluate("count( allowedValue )", allowedXML)); for (int i = 1; i <= count; i++) { String av = XMLUtil.xpath.evaluate("allowedValue[ " + i + " ]", allowedXML); allowedvalues.add(av); } } } /** * Call to the UPNP device to retrieve the state variable actual value * * @return the state variable actual value on the device, should be never * null, an empty string could be returned by the device * @throws UPNPResponseException * if the device throws an exception during query * @throws IOException * if some IO error with device occurs during query */ public String getValue() throws UPNPResponseException, IOException { if (stateVarMsg == null) { synchronized (this) { if (stateVarMsg == null) { UPNPMessageFactory factory = new UPNPMessageFactory(parent); stateVarMsg = factory.getStateVariableMessage(name); } } } return stateVarMsg.service().getStateVariableValue(); } /** * The variable JAVA data type (using an UPNP->Java mapping) * * @return the class mapped */ public Class<?> getDataTypeAsClass() { return getDataTypeClassMapping(dataType); } static Class<?> getDataTypeClassMapping(String dataType) { int hash = dataType.hashCode(); if (hash == UI1_INT) { return Short.class; } else if (hash == UI2_INT) { return Integer.class; } else if (hash == UI4_INT) { return Long.class; } else if (hash == I1_INT) { return Byte.class; } else if (hash == I2_INT) { return Short.class; } else if (hash == I4_INT) { return Integer.class; } else if (hash == INT_INT) { return Integer.class; } else if (hash == R4_INT) { return Float.class; } else if (hash == R8_INT) { return Double.class; } else if (hash == NUMBER_INT) { return Double.class; } else if (hash == FIXED_14_4_INT) { return Double.class; } else if (hash == FLOAT_INT) { return Float.class; } else if (hash == CHAR_INT) { return Character.class; } else if (hash == STRING_INT) { return String.class; } else if (hash == DATE_INT) { return Date.class; } else if (hash == DATETIME_INT) { return Date.class; } else if (hash == DATETIME_TZ_INT) { return Date.class; } else if (hash == TIME_INT) { return Date.class; } else if (hash == TIME_TZ_INT) { return Date.class; } else if (hash == BOOLEAN_INT) { return Boolean.class; } else if (hash == BIN_BASE64_INT) { return String.class; } else if (hash == BIN_HEX_INT) { return String.class; } else if (hash == URI_INT) { return URI.class; } else if (hash == UUID_INT) { return String.class; } return null; } static String getUPNPDataTypeMapping(String className) { if (className.equals(Short.class.getName()) || className.equals("short")) { return I2; } else if (className.equals(Byte.class.getName()) || className.equals("byte")) { return I1; } else if (className.equals(Integer.class.getName()) || className.equals("int")) { return INT; } else if (className.equals(Long.class.getName()) || className.equals("long")) { return UI4; } else if (className.equals(Float.class.getName()) || className.equals("float")) { return FLOAT; } else if (className.equals(Double.class.getName()) || className.equals("double")) { return NUMBER; } else if (className.equals(Character.class.getName()) || className.equals("char")) { return CHAR; } else if (className.equals(String.class.getName()) || className.equals("string")) { return STRING; } else if (className.equals(Date.class.getName())) { return DATETIME; } else if (className.equals(Boolean.class.getName()) || className.equals("boolean")) { return BOOLEAN; } else if (className.equals(URI.class.getName())) { return URI; } return null; } static Object UPNPToJavaObject(String dataType, String value) throws Throwable { if (value == null) { throw new Exception("null value"); } if (dataType == null) { throw new Exception("null dataType"); } int hash = dataType.hashCode(); if (hash == UI1_INT) { return new Short(value); } else if (hash == UI2_INT) { return new Integer(value); } else if (hash == UI4_INT) { return new Long(value); } else if (hash == I1_INT) { return new Byte(value); } else if (hash == I2_INT) { return new Short(value); } else if (hash == I4_INT) { return new Integer(value); } else if (hash == INT_INT) { return new Integer(value); } else if (hash == R4_INT) { return new Float(value); } else if (hash == R8_INT) { return new Double(value); } else if (hash == NUMBER_INT) { return new Double(value); } else if (hash == FIXED_14_4_INT) { return new Double(value); } else if (hash == FLOAT_INT) { return new Float(value); } else if (hash == CHAR_INT) { return new Character(value.charAt(0)); } else if (hash == STRING_INT) { return value; } else if (hash == DATE_INT) { return ISO8601Date.parse(value); } else if (hash == DATETIME_INT) { return ISO8601Date.parse(value); } else if (hash == DATETIME_TZ_INT) { return ISO8601Date.parse(value); } else if (hash == TIME_INT) { return ISO8601Date.parse(value); } else if (hash == TIME_TZ_INT) { return ISO8601Date.parse(value); } else if (hash == BOOLEAN_INT) { if (value.equals("1") || value.equalsIgnoreCase("yes") || value.equals("true")) { return Boolean.TRUE; } return Boolean.FALSE; } else if (hash == BIN_BASE64_INT) { return value; } else if (hash == BIN_HEX_INT) { return value; } else if (hash == URI_INT) { return new URI(value); } else if (hash == UUID_INT) { return value; } throw new Exception("Unhandled data type " + dataType); } @Override public String toString() { return name + ":" + dataType; } }