/*
* ====================================================================
* ======== 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;
}
}