/*
* Copyright 2011-16 Fraunhofer ISE
*
* This file is part of OpenMUC.
* For more information visit http://www.openmuc.org
*
* OpenMUC is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OpenMUC is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenMUC. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openmuc.framework.lib.json;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.openmuc.framework.config.ChannelConfig;
import org.openmuc.framework.config.ChannelScanInfo;
import org.openmuc.framework.config.DeviceConfig;
import org.openmuc.framework.config.DeviceScanInfo;
import org.openmuc.framework.config.DriverConfig;
import org.openmuc.framework.config.IdCollisionException;
import org.openmuc.framework.data.BooleanValue;
import org.openmuc.framework.data.ByteArrayValue;
import org.openmuc.framework.data.ByteValue;
import org.openmuc.framework.data.DoubleValue;
import org.openmuc.framework.data.FloatValue;
import org.openmuc.framework.data.IntValue;
import org.openmuc.framework.data.LongValue;
import org.openmuc.framework.data.Record;
import org.openmuc.framework.data.ShortValue;
import org.openmuc.framework.data.StringValue;
import org.openmuc.framework.data.Value;
import org.openmuc.framework.data.ValueType;
import org.openmuc.framework.dataaccess.DeviceState;
import org.openmuc.framework.lib.json.exceptions.MissingJsonObjectException;
import org.openmuc.framework.lib.json.exceptions.RestConfigIsNotCorrectException;
import org.openmuc.framework.lib.json.restObjects.RestChannel;
import org.openmuc.framework.lib.json.restObjects.RestChannelConfig;
import org.openmuc.framework.lib.json.restObjects.RestChannelConfigMapper;
import org.openmuc.framework.lib.json.restObjects.RestDeviceConfig;
import org.openmuc.framework.lib.json.restObjects.RestDeviceConfigMapper;
import org.openmuc.framework.lib.json.restObjects.RestDriverConfig;
import org.openmuc.framework.lib.json.restObjects.RestDriverConfigMapper;
import org.openmuc.framework.lib.json.restObjects.RestRecord;
import org.openmuc.framework.lib.json.restObjects.RestUserConfig;
import org.openmuc.framework.lib.json.restObjects.RestValue;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonSyntaxException;
public class FromJson {
private final Gson gson;
private final JsonObject jsonObject;
public FromJson(String jsonString) {
GsonBuilder gsonBuilder = new GsonBuilder().serializeSpecialFloatingPointValues();
gson = gsonBuilder.create();
jsonObject = gson.fromJson(jsonString, JsonObject.class);
}
public Gson getGson() {
return gson;
}
public JsonObject getJsonObject() {
return jsonObject;
}
public Record getRecord(ValueType valueType) throws ClassCastException {
Record record = null;
JsonElement jse = jsonObject.get(Const.RECORD);
if (!jse.isJsonNull()) {
record = getRecord(gson.fromJson(jse, RestRecord.class), valueType);
}
return record;
}
public ArrayList<Record> getRecordArrayList(ValueType valueType) throws ClassCastException {
ArrayList<Record> recordList = new ArrayList<>();
JsonElement jse = jsonObject.get(Const.RECORDS);
if (jse != null && jse.isJsonArray()) {
JsonArray jsa = jse.getAsJsonArray();
Iterator<JsonElement> iteratorJsonArray = jsa.iterator();
while (iteratorJsonArray.hasNext()) {
recordList.add(getRecord(valueType));
}
}
if (recordList.size() == 0) {
recordList = null;
}
return recordList;
}
public Value getValue(ValueType valueType) throws ClassCastException {
Value value = null;
JsonElement jse = jsonObject.get(Const.RECORD);
if (!jse.isJsonNull()) {
Record record = getRecord(valueType);
if (record != null) {
value = record.getValue();
}
}
return value;
}
public boolean isRunning() {
return jsonObject.get(Const.RUNNING).getAsBoolean();
}
public DeviceState getDeviceState() {
DeviceState ret = null;
JsonElement jse = jsonObject.get(Const.STATE);
if (!jse.isJsonNull()) {
ret = gson.fromJson(jse, DeviceState.class);
}
return ret;
}
public void setChannelConfig(ChannelConfig channelConfig, String id) throws JsonSyntaxException,
IdCollisionException, RestConfigIsNotCorrectException, MissingJsonObjectException {
JsonElement jse = jsonObject.get(Const.CONFIGS);
if (!jse.isJsonNull()) {
RestChannelConfigMapper.setChannelConfig(channelConfig, gson.fromJson(jse, RestChannelConfig.class), id);
}
else {
throw new MissingJsonObjectException();
}
}
public void setDeviceConfig(DeviceConfig deviceConfig, String id) throws JsonSyntaxException, IdCollisionException,
RestConfigIsNotCorrectException, MissingJsonObjectException {
JsonElement jse = jsonObject.get(Const.CONFIGS);
if (!jse.isJsonNull()) {
RestDeviceConfigMapper.setDeviceConfig(deviceConfig, gson.fromJson(jse, RestDeviceConfig.class), id);
}
else {
throw new MissingJsonObjectException();
}
}
public void setDriverConfig(DriverConfig driverConfig, String id) throws JsonSyntaxException, IdCollisionException,
RestConfigIsNotCorrectException, MissingJsonObjectException {
JsonElement jse = jsonObject.get(Const.CONFIGS);
if (!jse.isJsonNull()) {
RestDriverConfigMapper.setDriverConfig(driverConfig, gson.fromJson(jse, RestDriverConfig.class), id);
}
else {
throw new MissingJsonObjectException();
}
}
public ArrayList<String> getStringArrayList(String listName) {
ArrayList<String> resultList = new ArrayList<>();
JsonElement jse = jsonObject.get(listName);
if (jse != null && jse.isJsonArray()) {
JsonArray jsa = jse.getAsJsonArray();
Iterator<JsonElement> iteratorJsonArray = jsa.iterator();
while (iteratorJsonArray.hasNext()) {
resultList.add(iteratorJsonArray.next().toString());
}
}
if (resultList.size() == 0) {
resultList = null;
}
return resultList;
}
public String[] getStringArray(String listName) {
String stringArray[] = null;
JsonElement jse = jsonObject.get(listName);
if (!jse.isJsonNull() && jse.isJsonArray()) {
stringArray = gson.fromJson(jse, String[].class);
}
return stringArray;
}
public ArrayList<RestChannel> getRestChannelArrayList() throws ClassCastException {
ArrayList<RestChannel> recordList = new ArrayList<>();
JsonElement jse = jsonObject.get("records");
JsonArray jsa;
if (!jse.isJsonNull() && jse.isJsonArray()) {
jsa = jse.getAsJsonArray();
Iterator<JsonElement> jseIterator = jsa.iterator();
while (jseIterator.hasNext()) {
JsonObject jsoIterated = jseIterator.next().getAsJsonObject();
RestChannel rc = gson.fromJson(jsoIterated, RestChannel.class);
recordList.add(rc);
}
}
if (recordList.size() == 0) {
return null;
}
return recordList;
}
public RestUserConfig getRestUserConfig() {
JsonObject jso = jsonObject.get(Const.CONFIGS).getAsJsonObject();
return gson.fromJson(jso, RestUserConfig.class);
}
public List<DeviceScanInfo> getDeviceScanInfoList() {
List<DeviceScanInfo> returnValue = new ArrayList<>();
JsonElement jse = jsonObject.get(Const.CHANNELS); // TODO: another name?
JsonArray jsa;
if (jse.isJsonArray()) {
jsa = jse.getAsJsonArray();
Iterator<JsonElement> jseIterator = jsa.iterator();
while (jseIterator.hasNext()) {
JsonObject jso = jseIterator.next().getAsJsonObject();
String id = getString(jso.get(Const.ID));
String deviceAddress = getString(jso.get(Const.DEVICEADDRESS));
String settings = getString(jso.get(Const.SETTINGS));
String description = getString(jso.get(Const.DESCRIPTION));
returnValue.add(new DeviceScanInfo(id, deviceAddress, settings, description));
}
}
else {
returnValue = null;
}
return returnValue;
}
public List<ChannelScanInfo> getChannelScanInfoList() {
List<ChannelScanInfo> returnValue = new ArrayList<>();
JsonElement jse = jsonObject.get(Const.CHANNELS); // TODO: another name?
JsonArray jsa;
if (jse.isJsonArray()) {
jsa = jse.getAsJsonArray();
Iterator<JsonElement> jseIterator = jsa.iterator();
while (jseIterator.hasNext()) {
JsonObject jso = jseIterator.next().getAsJsonObject();
String channelAddress = getString(jso.get(Const.CHANNELADDRESS));
ValueType valueType = ValueType.valueOf(getString(jso.get(Const.VALUETYPE)));
int valueTypeLength = getInt(jso.get(Const.VALUETYPELENGTH));
String description = getString(jso.get(Const.DESCRIPTION));
boolean readable = getBoolean(jso.get(Const.READABLE));
boolean writeable = getBoolean(jso.get(Const.WRITEABLE));
String metadata = getString(jso.get(Const.METADATA));
returnValue.add(new ChannelScanInfo(channelAddress, description, valueType, valueTypeLength, readable,
writeable, metadata));
}
}
else {
returnValue = null;
}
return returnValue;
}
private String getString(JsonElement jse) {
if (jse != null) {
return jse.getAsString();
}
else {
return "";
}
}
private int getInt(JsonElement jse) {
if (jse != null) {
return jse.getAsInt();
}
else {
return 0;
}
}
private boolean getBoolean(JsonElement jse) {
if (jse != null) {
return jse.getAsBoolean();
}
else {
return true;
}
}
private Record getRecord(RestRecord rrc, ValueType type) throws ClassCastException {
Object value = rrc.getValue();
Value retValue = null;
if (value != null) {
retValue = getValue(type, value);
}
return new Record(retValue, rrc.getTimestamp(), rrc.getFlag());
}
private Value getValue(ValueType type, Object value) throws ClassCastException {
// TODO: check all value types, if it is really a float, double, ...
if (value.getClass().isInstance(new RestValue())) {
value = ((RestValue) value).getValue();
}
Value retValue = null;
switch (type) {
case FLOAT:
FloatValue fvalue = new FloatValue(((Double) value).floatValue());
retValue = fvalue;
break;
case DOUBLE:
DoubleValue dValue = new DoubleValue((Double) value);
retValue = dValue;
break;
case SHORT:
ShortValue shValue = new ShortValue(((Double) value).shortValue());
retValue = shValue;
break;
case INTEGER:
IntValue iValue = new IntValue(((Double) value).intValue());
retValue = iValue;
break;
case LONG:
LongValue lValue = new LongValue(((Double) value).longValue());
retValue = lValue;
break;
case BYTE:
ByteValue byValue = new ByteValue(((Double) value).byteValue());
retValue = byValue;
break;
case BOOLEAN:
BooleanValue boValue = new BooleanValue((Boolean) value);
retValue = boValue;
break;
case BYTE_ARRAY:
@SuppressWarnings("unchecked")
ArrayList<Double> arrayList = ((ArrayList<Double>) value);
byte[] byteArray = new byte[arrayList.size()];
for (int i = 0; i < arrayList.size(); ++i) {
byteArray[i] = arrayList.get(i).byteValue();
}
ByteArrayValue baValue = new ByteArrayValue(byteArray);
retValue = baValue;
break;
case STRING:
StringValue stValue = new StringValue((String) value);
retValue = stValue;
break;
default:
break;
}
return retValue;
}
}