]> git.basschouten.com Git - openhab-addons.git/blob
fb15998c41f27f55d8e6be95c8703afb91f77a0b
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2024 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.mqtt.generic.values;
14
15 import static java.util.function.Predicate.not;
16
17 import java.util.List;
18 import java.util.Set;
19 import java.util.stream.Collectors;
20 import java.util.stream.Stream;
21
22 import org.eclipse.jdt.annotation.NonNullByDefault;
23 import org.eclipse.jdt.annotation.Nullable;
24 import org.openhab.core.library.CoreItemFactory;
25 import org.openhab.core.library.types.StringType;
26 import org.openhab.core.types.Command;
27 import org.openhab.core.types.CommandDescriptionBuilder;
28 import org.openhab.core.types.CommandOption;
29 import org.openhab.core.types.State;
30 import org.openhab.core.types.StateDescriptionFragmentBuilder;
31 import org.openhab.core.types.StateOption;
32 import org.openhab.core.types.UnDefType;
33
34 /**
35  * Implements a text/string value. Allows to restrict the incoming value to a set of states.
36  *
37  * @author David Graeff - Initial contribution
38  */
39 @NonNullByDefault
40 public class TextValue extends Value {
41     private final @Nullable Set<String> states;
42     private final @Nullable Set<String> commands;
43
44     protected @Nullable String nullValue = null;
45
46     /**
47      * Create a string value with a limited number of allowed states and commands.
48      *
49      * @param states Allowed states. Empty states are filtered out. If the resulting set is empty, all string values
50      *            will be allowed.
51      * @param commands Allowed commands. Empty commands are filtered out. If the resulting set is empty, all string
52      *            values will be allowed.
53      */
54     public TextValue(String[] states, String[] commands) {
55         super(CoreItemFactory.STRING, List.of(StringType.class));
56         Set<String> s = Stream.of(states).filter(not(String::isBlank)).collect(Collectors.toSet());
57         if (!s.isEmpty()) {
58             this.states = s;
59         } else {
60             this.states = null;
61         }
62         Set<String> c = Stream.of(commands).filter(not(String::isBlank)).collect(Collectors.toSet());
63         if (!c.isEmpty()) {
64             this.commands = c;
65         } else {
66             this.commands = null;
67         }
68     }
69
70     /**
71      * Create a string value with a limited number of allowed states.
72      *
73      * @param states Allowed states. Empty states are filtered out. If the resulting set is empty, all string values
74      *            will be allowed. This same array is also used for allowed commands.
75      */
76     public TextValue(String[] states) {
77         this(states, states);
78     }
79
80     public TextValue() {
81         super(CoreItemFactory.STRING, List.of(StringType.class));
82         this.states = null;
83         this.commands = null;
84     }
85
86     public void setNullValue(@Nullable String nullValue) {
87         this.nullValue = nullValue;
88     }
89
90     @Override
91     public StringType parseCommand(Command command) throws IllegalArgumentException {
92         final Set<String> commands = this.commands;
93         String valueStr = command.toString();
94         if (commands != null && !commands.contains(valueStr)) {
95             throw new IllegalArgumentException("Value " + valueStr + " not within range");
96         }
97         return new StringType(valueStr);
98     }
99
100     @Override
101     public State parseMessage(Command command) throws IllegalArgumentException {
102         if (command instanceof StringType string && string.toString().equals(nullValue)) {
103             return UnDefType.NULL;
104         }
105
106         final Set<String> states = this.states;
107         String valueStr = command.toString();
108         if (states != null && !states.contains(valueStr)) {
109             throw new IllegalArgumentException("Value " + valueStr + " not within range");
110         }
111         return new StringType(valueStr);
112     }
113
114     /**
115      * @return valid states. Can be null.
116      */
117     public @Nullable Set<String> getStates() {
118         return states;
119     }
120
121     @Override
122     public StateDescriptionFragmentBuilder createStateDescription(boolean readOnly) {
123         StateDescriptionFragmentBuilder builder = super.createStateDescription(readOnly);
124         final Set<String> states = this.states;
125         if (states != null) {
126             for (String state : states) {
127                 builder = builder.withOption(new StateOption(state, state));
128             }
129         }
130         return builder;
131     }
132
133     @Override
134     public CommandDescriptionBuilder createCommandDescription() {
135         CommandDescriptionBuilder builder = super.createCommandDescription();
136         final Set<String> commands = this.commands;
137         if (commands != null) {
138             for (String command : commands) {
139                 builder = builder.withCommandOption(new CommandOption(command, command));
140             }
141         }
142         return builder;
143     }
144 }