]> git.basschouten.com Git - openhab-addons.git/blob
7f25342e15f3dab326e76e3268965784a219959b
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 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.net.URLDecoder;
16 import java.nio.charset.StandardCharsets;
17 import java.util.Arrays;
18 import java.util.Collections;
19 import java.util.Map;
20 import java.util.Objects;
21 import java.util.stream.Collectors;
22
23 import org.eclipse.jdt.annotation.NonNullByDefault;
24 import org.eclipse.jdt.annotation.Nullable;
25 import org.openhab.binding.heos.internal.json.dto.HeosCommandTuple;
26 import org.openhab.binding.heos.internal.json.dto.HeosEvent;
27 import org.openhab.binding.heos.internal.json.dto.HeosEventObject;
28 import org.openhab.binding.heos.internal.json.dto.HeosResponseObject;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31
32 import com.google.gson.FieldNamingPolicy;
33 import com.google.gson.Gson;
34 import com.google.gson.GsonBuilder;
35
36 /**
37  * Parser used for parsing the responses of JSON cli
38  *
39  * @author Martin van Wingerden - Initial contribution
40  */
41 @NonNullByDefault
42 public class HeosJsonParser {
43     private final Logger logger = LoggerFactory.getLogger(HeosJsonParser.class);
44
45     private final Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
46             .create();
47
48     public HeosEventObject parseEvent(String jsonBody) {
49         HeosJsonWrapper wrapper = gson.fromJson(jsonBody, HeosJsonWrapper.class);
50
51         return postProcess(wrapper.heos);
52     }
53
54     private HeosEventObject postProcess(HeosJsonObject heos) {
55         return new HeosEventObject(HeosEvent.valueOfString(heos.command), heos.command, splitQuery(heos.message));
56     }
57
58     public <T> HeosResponseObject<T> parseResponse(String jsonBody, Class<T> clazz) {
59         HeosJsonWrapper wrapper = gson.fromJson(jsonBody, HeosJsonWrapper.class);
60         return postProcess(Objects.requireNonNull(wrapper), clazz);
61     }
62
63     private <T> HeosResponseObject<T> postProcess(HeosJsonWrapper wrapper, Class<T> clazz) {
64         T payload = gson.fromJson(wrapper.payload, clazz);
65
66         return new HeosResponseObject<>(HeosCommandTuple.valueOf(wrapper.heos.command), wrapper.heos.command,
67                 wrapper.heos.result, splitQuery(wrapper.heos.message), payload, wrapper.options);
68     }
69
70     private Map<String, String> splitQuery(@Nullable String url) {
71         if (url == null) {
72             return Collections.emptyMap();
73         }
74
75         return Arrays.stream(url.split("&")).map(p -> p.split("=", 2))
76                 .collect(Collectors.toMap(v -> decode(v[0]), v -> v.length == 1 ? "" : decode(v[1]), this::merge));
77     }
78
79     /**
80      * for duplicates we ignore the first one
81      *
82      * @param v1 first occurrence
83      * @param v2 second occurrence
84      * @return second occurrence
85      */
86     private String merge(String v1, String v2) {
87         logger.debug("Ignoring first occurrence '{}' in favor of '{}'", v1, v2);
88         return v2;
89     }
90
91     private static String decode(String encoded) {
92         return URLDecoder.decode(encoded, StandardCharsets.UTF_8);
93     }
94 }