2 * Copyright (c) 2010-2020 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
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
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.tr064.internal.phonebook;
16 import java.util.Optional;
18 import org.eclipse.jdt.annotation.NonNullByDefault;
19 import org.eclipse.jdt.annotation.Nullable;
20 import org.openhab.core.config.core.Configuration;
21 import org.openhab.core.library.types.StringType;
22 import org.openhab.core.thing.ThingUID;
23 import org.openhab.core.thing.profiles.*;
24 import org.openhab.core.transform.TransformationService;
25 import org.openhab.core.types.Command;
26 import org.openhab.core.types.State;
27 import org.openhab.core.util.UIDUtils;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
32 * The {@link PhonebookProfile} class provides a profile for resolving phone number strings to names
34 * @author Jan N. Klug - Initial contribution
37 public class PhonebookProfile implements StateProfile {
38 public static final ProfileTypeUID PHONEBOOK_PROFILE_TYPE_UID = new ProfileTypeUID(
39 TransformationService.TRANSFORM_PROFILE_SCOPE, "PHONEBOOK");
40 public static final ProfileType PHONEBOOK_PROFILE_TYPE = ProfileTypeBuilder
41 .newState(PhonebookProfile.PHONEBOOK_PROFILE_TYPE_UID, "Phonebook").build();
43 public static final String PHONEBOOK_PARAM = "phonebook";
44 private static final String MATCH_COUNT_PARAM = "matchCount";
46 private final Logger logger = LoggerFactory.getLogger(PhonebookProfile.class);
48 private final ProfileCallback callback;
50 private final @Nullable String phonebookName;
51 private final @Nullable ThingUID thingUID;
52 private final Map<ThingUID, PhonebookProvider> phonebookProviders;
53 private final int matchCount;
55 public PhonebookProfile(ProfileCallback callback, ProfileContext context,
56 Map<ThingUID, PhonebookProvider> phonebookProviders) {
57 this.callback = callback;
58 this.phonebookProviders = phonebookProviders;
60 Configuration configuration = context.getConfiguration();
61 Object phonebookParam = configuration.get(PHONEBOOK_PARAM);
62 Object matchCountParam = configuration.get(MATCH_COUNT_PARAM);
64 logger.debug("Profile configured with '{}'='{}', '{}'='{}'", PHONEBOOK_PARAM, phonebookParam, MATCH_COUNT_PARAM,
68 String phonebookName = null;
72 if (!(phonebookParam instanceof String)
73 || ((matchCountParam != null) && !(matchCountParam instanceof String))) {
74 throw new IllegalArgumentException("Parameters need to be Strings");
76 String[] phonebookParams = ((String) phonebookParam).split(":");
77 if (phonebookParams.length > 2) {
78 throw new IllegalArgumentException("Could not split 'phonebook' parameter");
80 thingUID = new ThingUID(UIDUtils.decode(phonebookParams[0]));
81 if (phonebookParams.length == 2) {
82 phonebookName = UIDUtils.decode(phonebookParams[1]);
84 if (matchCountParam != null) {
85 matchCount = Integer.parseInt((String) matchCountParam);
87 } catch (IllegalArgumentException e) {
88 logger.warn("Could not initialize PHONEBOOK transformation profile: {}. Profile will be inactive.",
93 this.thingUID = thingUID;
94 this.phonebookName = phonebookName;
95 this.matchCount = matchCount;
99 public void onCommandFromItem(Command command) {
103 public void onCommandFromHandler(Command command) {
107 public void onStateUpdateFromHandler(State state) {
108 if (state instanceof StringType) {
109 PhonebookProvider provider = phonebookProviders.get(thingUID);
110 if (provider == null) {
111 logger.warn("Could not get phonebook provider with thing UID '{}'.", thingUID);
114 final String phonebookName = this.phonebookName;
115 Optional<String> match;
116 if (phonebookName != null) {
117 match = provider.getPhonebookByName(phonebookName).or(() -> {
118 logger.warn("Could not get phonebook '{}' from provider '{}'", phonebookName, thingUID);
119 return Optional.empty();
120 }).flatMap(phonebook -> phonebook.lookupNumber(state.toString(), matchCount));
122 match = provider.getPhonebooks().stream().map(p -> p.lookupNumber(state.toString(), matchCount))
123 .filter(Optional::isPresent).map(Optional::get).findAny();
125 State newState = match.map(name -> (State) new StringType(name)).orElse(state);
126 if (newState == state) {
127 logger.debug("Number '{}' not found in phonebook '{}' from provider '{}'", state, phonebookName,
130 callback.sendUpdate(newState);
135 public ProfileTypeUID getProfileTypeUID() {
136 return PHONEBOOK_PROFILE_TYPE_UID;
140 public void onStateUpdateFromItem(State state) {