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.astro.internal.util;
15 import java.lang.reflect.Method;
16 import java.math.BigDecimal;
17 import java.math.RoundingMode;
18 import java.time.ZoneId;
19 import java.time.ZonedDateTime;
20 import java.util.Calendar;
21 import java.util.GregorianCalendar;
22 import java.util.TimeZone;
24 import org.eclipse.jdt.annotation.NonNullByDefault;
25 import org.eclipse.jdt.annotation.Nullable;
26 import org.openhab.binding.astro.internal.config.AstroChannelConfig;
27 import org.openhab.core.library.types.DateTimeType;
28 import org.openhab.core.library.types.DecimalType;
29 import org.openhab.core.library.types.StringType;
30 import org.openhab.core.thing.ChannelUID;
31 import org.openhab.core.types.State;
32 import org.openhab.core.types.UnDefType;
35 * Methods to get the value from a property of an object.
37 * @author Gerhard Riegler - Initial contribution
38 * @author Erdoan Hadzhiyusein - Adapted the class to work with the new DateTimeType
39 * @author Christoph Weitkamp - Introduced UoM
42 public class PropertyUtils {
45 private PropertyUtils() {
46 throw new IllegalAccessError("Non-instantiable");
50 * Returns the state of the channel.
52 public static State getState(ChannelUID channelUID, AstroChannelConfig config, Object instance, ZoneId zoneId)
54 Object value = getPropertyValue(channelUID, instance);
56 return UnDefType.UNDEF;
57 } else if (value instanceof State) {
59 } else if (value instanceof Calendar) {
60 Calendar cal = (Calendar) value;
61 GregorianCalendar gregorianCal = (GregorianCalendar) DateTimeUtils.applyConfig(cal, config);
62 cal.setTimeZone(TimeZone.getTimeZone(zoneId));
63 ZonedDateTime zoned = gregorianCal.toZonedDateTime().withFixedOffsetZone();
64 return new DateTimeType(zoned);
65 } else if (value instanceof Number) {
66 BigDecimal decimalValue = new BigDecimal(value.toString()).setScale(2, RoundingMode.HALF_UP);
67 return new DecimalType(decimalValue);
68 } else if (value instanceof String || value instanceof Enum) {
69 return new StringType(value.toString());
71 throw new IllegalStateException("Unsupported value type " + value.getClass().getSimpleName());
76 * Returns the property value from the object instance, nested properties are possible. If the propertyName is for
77 * example rise.start, the methods getRise().getStart() are called.
79 public static @Nullable Object getPropertyValue(ChannelUID channelUID, Object instance) throws Exception {
80 String[] properties = channelUID.getId().split("#");
81 return getPropertyValue(instance, properties, 0);
85 * Iterates through the nested properties and returns the getter value.
87 @SuppressWarnings("all")
88 private static @Nullable Object getPropertyValue(Object instance, String[] properties, int nestedIndex)
90 String propertyName = properties[nestedIndex];
91 Method m = instance.getClass().getMethod(toGetterString(propertyName), null);
92 Object result = m.invoke(instance, (Object[]) null);
93 if (nestedIndex + 1 < properties.length) {
95 return getPropertyValue(result, properties, nestedIndex + 1);
97 throw new NullPointerException();
104 * Converts the string to a getter property.
106 private static String toGetterString(String str) {
107 StringBuilder sb = new StringBuilder();
109 sb.append(Character.toTitleCase(str.charAt(0)));
110 sb.append(str.substring(1));
111 return sb.toString();