Java tutorial
/** * Copyright (c) 2014,2018 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License 2.0 which is available at * http://www.eclipse.org/legal/epl-2.0 * * SPDX-License-Identifier: EPL-2.0 */ package org.eclipse.smarthome.binding.homematic.internal.communicator.message; import java.math.BigDecimal; import java.math.RoundingMode; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Base64; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.apache.commons.lang.StringEscapeUtils; /** * A XML-RPC request for sending data to the Homematic server. * * @author Gerhard Riegler - Initial contribution */ public class XmlRpcRequest implements RpcRequest<String> { public enum TYPE { REQUEST, RESPONSE; } private String methodName; private List<Object> parms; private StringBuilder sb; private TYPE type; public static SimpleDateFormat xmlRpcDateFormat = new SimpleDateFormat("yyyyMMdd'T'HH:mm:ss"); public XmlRpcRequest(String methodName) { this(methodName, TYPE.REQUEST); } public XmlRpcRequest(String methodName, TYPE type) { this.methodName = methodName; this.type = type; parms = new ArrayList<Object>(); } @Override public void addArg(Object parameter) { parms.add(parameter); } @Override public String createMessage() { return toString(); } @Override public String getMethodName() { return methodName; } @Override public String toString() { sb = new StringBuilder(); sb.append("<?xml"); attr("version", "1.0"); attr("encoding", "ISO-8859-1"); sb.append("?>\n"); if (type == TYPE.REQUEST) { sb.append("<methodCall>"); tag("methodName", methodName); } else { sb.append("<methodResponse>"); } sb.append("\n"); sb.append("<params>"); for (Object parameter : parms) { sb.append("<param><value>"); generateValue(parameter); sb.append("</value></param>"); } sb.append("</params>"); if (type == TYPE.REQUEST) { sb.append("</methodCall>"); } else { sb.append("</methodResponse>"); } return sb.toString(); } /** * Generates a XML attribute. */ private void attr(String name, String value) { sb.append(" ").append(name).append("=\"").append(value).append("\""); } /** * Generates a XML tag. */ private void tag(String name, String value) { sb.append("<").append(name).append(">").append(value).append("</").append(name).append(">"); } /** * Generates a value tag based on the type of the value. */ private void generateValue(Object value) { if (value == null) { tag("string", "void"); } else { Class<?> clazz = value.getClass(); if (clazz == String.class || clazz == Character.class) { sb.append(StringEscapeUtils.escapeXml(value.toString())); } else if (clazz == Long.class || clazz == Integer.class || clazz == Short.class || clazz == Byte.class) { tag("int", value.toString()); } else if (clazz == Double.class) { tag("double", String.valueOf(((Double) value).doubleValue())); } else if (clazz == Float.class) { BigDecimal bd = new BigDecimal((Float) value); generateValue(bd.setScale(6, RoundingMode.HALF_DOWN).doubleValue()); } else if (clazz == BigDecimal.class) { generateValue(((BigDecimal) value).setScale(6, RoundingMode.HALF_DOWN).doubleValue()); } else if (clazz == Boolean.class) { tag("boolean", ((Boolean) value).booleanValue() ? "1" : "0"); } else if (clazz == Date.class) { tag("dateTime.iso8601", xmlRpcDateFormat.format(((Date) value))); } else if (value instanceof Calendar) { generateValue(((Calendar) value).getTime()); } else if (value instanceof byte[]) { tag("base64", Base64.getEncoder().encodeToString((byte[]) value)); } else if (clazz.isArray() || value instanceof List) { sb.append("<array><data>"); Object[] array = null; if (value instanceof List) { array = ((List<?>) value).toArray(); } else { array = (Object[]) value; } for (Object arrayObject : array) { sb.append("<value>"); generateValue(arrayObject); sb.append("</value>"); } sb.append("</data></array>"); } else if (value instanceof Map) { sb.append("<struct>"); for (Entry<?, ?> entry : ((Map<?, ?>) value).entrySet()) { sb.append("<member>"); sb.append("<name>").append(entry.getKey()).append("</name>"); sb.append("<value>"); generateValue(entry.getValue()); sb.append("</value>"); sb.append("</member>"); } sb.append("</struct>"); } else { throw new RuntimeException("Unsupported XML-RPC Type: " + value.getClass()); } } } }