2 * Copyright (c) 2010-2023 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.persistence.dynamodb.internal;
15 import java.math.BigDecimal;
16 import java.math.MathContext;
17 import java.time.ZonedDateTime;
19 import org.eclipse.jdt.annotation.NonNullByDefault;
20 import org.eclipse.jdt.annotation.Nullable;
22 import software.amazon.awssdk.enhanced.dynamodb.mapper.StaticTableSchema;
25 * DynamoDBItem for items that can be serialized as DynamoDB number
27 * @author Sami Salonen - Initial contribution
30 public class DynamoDBBigDecimalItem extends AbstractDynamoDBItem<BigDecimal> {
32 private static Class<@Nullable BigDecimal> NULLABLE_BIGDECIMAL = (Class<@Nullable BigDecimal>) BigDecimal.class;
34 public static StaticTableSchema<DynamoDBBigDecimalItem> TABLE_SCHEMA_LEGACY = getBaseSchemaBuilder(
35 DynamoDBBigDecimalItem.class, true).newItemSupplier(DynamoDBBigDecimalItem::new)
36 .addAttribute(NULLABLE_BIGDECIMAL, a -> a.name(ATTRIBUTE_NAME_ITEMSTATE_LEGACY)
37 .getter(DynamoDBBigDecimalItem::getState).setter(DynamoDBBigDecimalItem::setState))
40 public static StaticTableSchema<DynamoDBBigDecimalItem> TABLE_SCHEMA_NEW = getBaseSchemaBuilder(
41 DynamoDBBigDecimalItem.class, false)
42 .newItemSupplier(DynamoDBBigDecimalItem::new)
43 .addAttribute(NULLABLE_BIGDECIMAL,
44 a -> a.name(ATTRIBUTE_NAME_ITEMSTATE_NUMBER).getter(DynamoDBBigDecimalItem::getState)
45 .setter(DynamoDBBigDecimalItem::setState))
46 .addAttribute(NULLABLE_LONG, a -> a.name(ATTRIBUTE_NAME_EXPIRY).getter(AbstractDynamoDBItem::getExpiryDate)
47 .setter(AbstractDynamoDBItem::setExpiry))
51 * We get the following error if the BigDecimal has too many digits
52 * "Attempting to store more than 38 significant digits in a Number"
54 * See "Data types" section in
55 * http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Limits.html
57 private static final int MAX_DIGITS_SUPPORTED_BY_AMAZON = 38;
59 public DynamoDBBigDecimalItem() {
60 this("", null, ZonedDateTime.now(), null);
63 public DynamoDBBigDecimalItem(String name, @Nullable BigDecimal state, ZonedDateTime time,
64 @Nullable Integer expireDays) {
65 super(name, state, time, expireDays);
69 public @Nullable BigDecimal getState() {
70 // When serializing this to the wire, we round the number in order to ensure
71 // that it is within the dynamodb limits
72 BigDecimal localState = state;
73 if (localState == null) {
76 return loseDigits(localState);
80 public void setState(@Nullable BigDecimal state) {
85 public <T> T accept(DynamoDBItemVisitor<T> visitor) {
86 return visitor.visit(this);
89 static BigDecimal loseDigits(BigDecimal number) {
90 return number.round(new MathContext(MAX_DIGITS_SUPPORTED_BY_AMAZON));