]> git.basschouten.com Git - openhab-addons.git/blob
85b1934e973d11a70c0e7d2115c1227d86f8f010
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2021 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
7  * This program and the accompanying materials are made available under the
8  * terms of the Eclipse Public License 2.0 which is available at
9  * http://www.eclipse.org/legal/epl-2.0
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.heos.internal.json;
14
15 import java.io.UnsupportedEncodingException;
16 import java.net.URLDecoder;
17 import java.nio.charset.StandardCharsets;
18 import java.util.Arrays;
19 import java.util.Collections;
20 import java.util.Map;
21 import java.util.Objects;
22 import java.util.stream.Collectors;
23
24 import org.eclipse.jdt.annotation.NonNullByDefault;
25 import org.eclipse.jdt.annotation.Nullable;
26 import org.openhab.binding.heos.internal.json.dto.HeosCommandTuple;
27 import org.openhab.binding.heos.internal.json.dto.HeosEvent;
28 import org.openhab.binding.heos.internal.json.dto.HeosEventObject;
29 import org.openhab.binding.heos.internal.json.dto.HeosResponseObject;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32
33 import com.google.gson.FieldNamingPolicy;
34 import com.google.gson.Gson;
35 import com.google.gson.GsonBuilder;
36
37 /**
38  * Parser used for parsing the responses of JSON cli
39  *
40  * @author Martin van Wingerden - Initial contribution
41  */
42 @NonNullByDefault
43 public class HeosJsonParser {
44     private final Logger logger = LoggerFactory.getLogger(HeosJsonParser.class);
45
46     private final Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
47             .create();
48
49     public HeosEventObject parseEvent(String jsonBody) {
50         HeosJsonWrapper wrapper = gson.fromJson(jsonBody, HeosJsonWrapper.class);
51
52         return postProcess(wrapper.heos);
53     }
54
55     private HeosEventObject postProcess(HeosJsonObject heos) {
56         return new HeosEventObject(HeosEvent.valueOfString(heos.command), heos.command, splitQuery(heos.message));
57     }
58
59     public <T> HeosResponseObject<T> parseResponse(String jsonBody, Class<T> clazz) {
60         HeosJsonWrapper wrapper = gson.fromJson(jsonBody, HeosJsonWrapper.class);
61         return postProcess(Objects.requireNonNull(wrapper), clazz);
62     }
63
64     private <T> HeosResponseObject<T> postProcess(HeosJsonWrapper wrapper, Class<T> clazz) {
65         T payload = gson.fromJson(wrapper.payload, clazz);
66
67         return new HeosResponseObject<>(HeosCommandTuple.valueOf(wrapper.heos.command), wrapper.heos.command,
68                 wrapper.heos.result, splitQuery(wrapper.heos.message), payload, wrapper.options);
69     }
70
71     private Map<String, String> splitQuery(@Nullable String url) {
72         if (url == null) {
73             return Collections.emptyMap();
74         }
75
76         return Arrays.stream(url.split("&")).map(p -> p.split("=", 2))
77                 .collect(Collectors.toMap(v -> decode(v[0]), v -> v.length == 1 ? "" : decode(v[1]), this::merge));
78     }
79
80     /**
81      * for duplicates we ignore the first one
82      *
83      * @param v1 first occurrence
84      * @param v2 second occurrence
85      * @return second occurrence
86      */
87     private String merge(String v1, String v2) {
88         logger.debug("Ignoring first occurrence '{}' in favor of '{}'", v1, v2);
89         return v2;
90     }
91
92     private static String decode(String encoded) {
93         try {
94             return URLDecoder.decode(encoded, StandardCharsets.UTF_8.name());
95         } catch (UnsupportedEncodingException e) {
96             throw new IllegalStateException("Impossible: UTF-8 is a required encoding", e);
97         }
98     }
99 }