com.amazonaws.services.dynamodbv2.document.Item Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aws-java-sdk-dynamodb Show documentation
Show all versions of aws-java-sdk-dynamodb Show documentation
The AWS Java SDK for Amazon DynamoDB module holds the client classes that are used for communicating with Amazon DynamoDB Service
/*
* Copyright 2014-2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package com.amazonaws.services.dynamodbv2.document;
import static com.amazonaws.services.dynamodbv2.document.internal.InternalUtils.checkInvalidAttrName;
import static com.amazonaws.services.dynamodbv2.document.internal.InternalUtils.checkInvalidAttribute;
import static com.amazonaws.services.dynamodbv2.document.internal.InternalUtils.rejectNullInput;
import static com.amazonaws.services.dynamodbv2.document.internal.InternalUtils.rejectNullOrEmptyInput;
import static com.amazonaws.services.dynamodbv2.document.internal.InternalUtils.rejectNullValue;
import static com.amazonaws.services.dynamodbv2.document.internal.InternalUtils.valToString;
import static com.amazonaws.util.BinaryUtils.copyAllBytesFrom;
import static com.amazonaws.util.BinaryUtils.copyBytesFrom;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import com.amazonaws.services.dynamodbv2.document.internal.InternalUtils;
import com.amazonaws.services.dynamodbv2.document.internal.ItemValueConformer;
import com.amazonaws.util.Base64;
import com.amazonaws.util.json.Jackson;
/**
* An item in DynamoDB. An item is a collection of attributes. Each attribute
* has a name and a value. An attribute value can be one of the followings:
*
* - String
* - Set<String>
* - Number (including any subtypes and primitive types)
* - Set<Number>
* - byte[]
* - Set<byte[]>
* - ByteBuffer
* - Set<ByteBuffer>
* - Boolean or boolean
* - null
* - Map<String,T>, where T can be any type on this list but must not
* induce any circular reference
* - List<T>, where T can be any type on this list but must not induce
* any circular reference
*
* For an Item
to be successfully persisted in DynamoDB, at a
* minimum the respective attributes for the primary key must be specified.
*/
public class Item {
private static final String DUPLICATE_VALUES_FOUND_IN_INPUT = "Duplicate values found in input";
private final Map attributes = new LinkedHashMap();
private static final ItemValueConformer valueConformer = new ItemValueConformer();
/**
* Returns true if the specified attribute exists with a null value; false
* otherwise.
*/
public boolean isNull(String attrName) {
return attributes.containsKey(attrName)
&& attributes.get(attrName) == null;
}
/**
* Returns true if this item contains the specified attribute; false
* otherwise.
*/
public boolean isPresent(String attrName) {
return attributes.containsKey(attrName);
}
/**
* Returns the value of the specified attribute in the current item as a
* string; or null if the attribute either doesn't exist or the attribute
* value is null.
*
* @see #isNull(String) #isNull(String) to check if the attribute value is
* null.
* @see #isPresent(String) #isPresent(String) to check if the attribute
* value is present.
*/
public String getString(String attrName) {
Object val = attributes.get(attrName);
return valToString(val);
}
/**
* Sets the value of the specified attribute in the current item to the
* given string value.
*/
public Item withString(String attrName, String val) {
checkInvalidAttribute(attrName, val);
attributes.put(attrName, val);
return this;
}
/**
* Returns the value of the specified attribute in the current item as a
* BigDecimal
; or null if the attribute either doesn't exist or
* the attribute value is null.
*
* @see #isNull(String) #isNull(String) to check if the attribute value is
* null.
* @see #isPresent(String) #isPresent(String) to check if the attribute
* value is present.
*
* @throws NumberFormatException if the attribute value is not a valid
* representation of a {@code BigDecimal}.
*/
public BigDecimal getNumber(String attrName) {
Object val = attributes.get(attrName);
return toBigDecimal(val);
}
private BigDecimal toBigDecimal(Object val) {
if (val == null)
return null;
return val instanceof BigDecimal
? (BigDecimal) val
: new BigDecimal(val.toString())
;
}
/**
* Returns the value of the specified attribute in the current item as an
* BigInteger
; or null if the attribute doesn't exist.
*
* @see #isNull(String) #isNull(String) to check if the attribute value is
* null.
* @see #isPresent(String) #isPresent(String) to check if the attribute
* value is present.
*
* @throws NumberFormatException
* if the attribute value is null or not a valid representation
* of a {@code BigDecimal}.
*/
public BigInteger getBigInteger(String attrName) {
BigDecimal bd = getNumber(attrName);
return bd == null ? null : bd.toBigInteger();
}
/**
* Returns the value of the specified attribute in the current item as a
* short
.
*
* @see #isNull(String) #isNull(String) to check if the attribute value is
* null.
* @see #isPresent(String) #isPresent(String) to check if the attribute
* value is present.
*
* @throws NumberFormatException
* if the attribute value is null or not a valid representation
* of a {@code BigDecimal}.
*/
public short getShort(String attrName) {
BigDecimal bd = getNumber(attrName);
if (bd == null)
throw new NumberFormatException
("value of " + attrName + " is null");
return bd.shortValue();
}
/**
* Returns the value of the specified attribute in the current item as an
* int
.
*
* @see #isNull(String) #isNull(String) to check if the attribute value is
* null.
* @see #isPresent(String) #isPresent(String) to check if the attribute
* value is present.
*
* @throws NumberFormatException
* if the attribute value is null or not a valid representation
* of a {@code BigDecimal}.
*/
public int getInt(String attrName) {
BigDecimal bd = getNumber(attrName);
if (bd == null)
throw new NumberFormatException
("value of " + attrName + " is null");
return bd.intValue();
}
/**
* Returns the value of the specified attribute in the current item as an
* long
.
*
* @see #isNull(String) #isNull(String) to check if the attribute value is
* null.
* @see #isPresent(String) #isPresent(String) to check if the attribute
* value is present.
*
* @throws NumberFormatException
* if the attribute value is null or not a valid representation
* of a {@code BigDecimal}.
*/
public long getLong(String attrName) {
BigDecimal bd = getNumber(attrName);
if (bd == null)
throw new NumberFormatException
("value of " + attrName + " is null");
return bd.longValue();
}
/**
* Returns the value of the specified attribute in the current item as a
* float
.
*
* @see #isNull(String) #isNull(String) to check if the attribute value is
* null.
* @see #isPresent(String) #isPresent(String) to check if the attribute
* value is present.
*
* @throws NumberFormatException
* if the attribute value is null or not a valid representation
* of a {@code BigDecimal}.
*/
public float getFloat(String attrName) {
BigDecimal bd = getNumber(attrName);
if (bd == null)
throw new NumberFormatException
("value of " + attrName + " is null");
return bd.floatValue();
}
/**
* Returns the value of the specified attribute in the current item as a
* double
.
*
* @see #isNull(String) #isNull(String) to check if the attribute value is
* null.
* @see #isPresent(String) #isPresent(String) to check if the attribute
* value is present.
*
* @throws NumberFormatException
* if the attribute value is null or not a valid representation
* of a {@code BigDecimal}.
*/
public double getDouble(String attrName) {
BigDecimal bd = getNumber(attrName);
if (bd == null)
throw new NumberFormatException
("value of " + attrName + " is null");
return bd.doubleValue();
}
/**
* Sets the value of the specified attribute in the current item to the
* given value.
*/
public Item withNumber(String attrName, BigDecimal val) {
checkInvalidAttribute(attrName, val);
attributes.put(attrName, val);
return this;
}
/**
* Sets the value of the specified attribute in the current item to the
* given value.
*/
public Item withNumber(String attrName, Number val) {
checkInvalidAttribute(attrName, val);
attributes.put(attrName, toBigDecimal(val));
return this;
}
/**
* Sets the value of the specified attribute in the current item to the
* given value.
*/
public Item withInt(String attrName, int val) {
checkInvalidAttrName(attrName);
return withNumber(attrName, Integer.valueOf(val));
}
/**
* Sets the value of the specified attribute in the current item to the
* given value.
*/
public Item withBigInteger(String attrName, BigInteger val) {
checkInvalidAttrName(attrName);
return withNumber(attrName, val);
}
/**
* Sets the value of the specified attribute in the current item to the
* given value.
*/
public Item withShort(String attrName, short val) {
checkInvalidAttrName(attrName);
return withNumber(attrName, Short.valueOf(val));
}
/**
* Sets the value of the specified attribute in the current item to the
* given value.
*/
public Item withFloat(String attrName, float val) {
checkInvalidAttrName(attrName);
return withNumber(attrName, Float.valueOf(val));
}
/**
* Sets the value of the specified attribute in the current item to the
* given value.
*/
public Item withDouble(String attrName, double val) {
checkInvalidAttrName(attrName);
return withNumber(attrName, Double.valueOf(val));
}
/**
* Sets the value of the specified attribute in the current item to the
* given value.
*/
public Item withLong(String attrName, long val) {
checkInvalidAttrName(attrName);
return withNumber(attrName, Long.valueOf(val));
}
/**
* Returns the value of the specified attribute in the current item as a
* byte array; or null if the attribute either doesn't exist or the
* attribute value is null.
*
* @throws UnsupportedOperationException
* If the attribute value involves a byte buffer which is not
* backed by an accessible array
*
* @throws IncompatibleTypeException
* if the attribute value cannot be converted into a byte array
*
* @see #isNull(String) #isNull(String) to check if the attribute value is
* null.
* @see #isPresent(String) #isPresent(String) to check if the attribute
* value is present.
*/
public byte[] getBinary(String attrName) {
Object val = attributes.get(attrName);
return toByteArray(val);
}
/**
* Returns the value of the specified attribute in the current item as a
* ByteBuffer
; or null if the attribute either doesn't exist or
* the attribute value is null.
*
* @throws IncompatibleTypeException
* if the attribute value cannot be converted into a byte array
*
* @see #isNull(String) #isNull(String) to check if the attribute value is
* null.
* @see #isPresent(String) #isPresent(String) to check if the attribute
* value is present.
*/
public ByteBuffer getByteBuffer(String attrName) {
Object val = attributes.get(attrName);
return toByteBuffer(val);
}
/**
* This method is assumed to be only called from a getter method, but NOT
* from a setter method.
*/
private byte[] toByteArray(Object val) {
if (val == null)
return null;
if (val instanceof byte[])
return (byte[]) val;
if (val instanceof ByteBuffer) {
// Defensive code but execution should never get here. The internal
// representation of binary should always be
// byte[], not ByteBuffer. This allows Item to be converted into
// a JSON string via Jackson without causing trouble.
return copyAllBytesFrom((ByteBuffer)val);
}
throw new IncompatibleTypeException(val.getClass()
+ " cannot be converted into a byte array");
}
private ByteBuffer toByteBuffer(Object val) {
if (val == null)
return null;
if (val instanceof byte[])
return ByteBuffer.wrap((byte[])val);
if (val instanceof ByteBuffer) {
// Defensive code but execution should never get here. The internal
// representation of binary should always be
// byte[], not ByteBuffer. This allows Item to be converted into
// a JSON string via Jackson without causing trouble.
return (ByteBuffer)val;
}
throw new IncompatibleTypeException(val.getClass()
+ " cannot be converted into a ByteBuffer");
}
/**
* Sets the value of the specified attribute in the current item to the
* given value.
*/
public Item withBinary(String attrName, byte[] val) {
checkInvalidAttribute(attrName, val);
attributes.put(attrName, val);
return this;
}
/**
* Sets the value of the specified attribute in the current item to the
* given value.
*/
public Item withBinary(String attrName, ByteBuffer val) {
checkInvalidAttribute(attrName, val);
// convert ByteBuffer to bytes to keep Jackson happy
attributes.put(attrName, copyBytesFrom(val));
return this;
}
/**
* Returns the value of the specified attribute in the current item as a set
* of strings; or null if the attribute either doesn't exist or the
* attribute value is null.
*
* @throws IncompatibleTypeException
* if the attribute value cannot be converted into a set of
* strings because of duplicate elements
*
* @see #isNull(String) #isNull(String) to check if the attribute value is
* null.
* @see #isPresent(String) #isPresent(String) to check if the attribute
* value is present.
*/
public Set getStringSet(String attrName) {
Object val = attributes.get(attrName);
if (val == null)
return null;
Set stringSet = new LinkedHashSet();
if (val instanceof Collection) {
Collection> col = (Collection>) val;
if (col.size() == 0)
return stringSet;
for (Object element: col) {
String s = element == null ? null : valToString(element);
if (!stringSet.add(s))
throw new IncompatibleTypeException(val.getClass()
+ " cannot be converted into a set of strings because of duplicate elements");
}
return stringSet;
}
stringSet.add(valToString(val));
return stringSet;
}
/**
* Sets the value of the specified attribute in the current item to the
* given value.
*/
public Item withStringSet(String attrName, Set val) {
checkInvalidAttribute(attrName, val);
attributes.put(attrName, val);
return this;
}
/**
* Sets the value of the specified attribute in the current item to the
* given value.
*/
public Item withStringSet(String attrName, String ...val) {
checkInvalidAttribute(attrName, val);
Set strSet = new LinkedHashSet(Arrays.asList(val));
if (strSet.size() != val.length)
throw new IllegalArgumentException(DUPLICATE_VALUES_FOUND_IN_INPUT);
attributes.put(attrName, strSet);
return this;
}
/**
* Returns the value of the specified attribute in the current item as a set
* of BigDecimal's; or null if the attribute either doesn't exist or the
* attribute value is null.
*
* @throws NumberFormatException
* if the attribute involves a value that is not a valid
* representation of a {@code BigDecimal}.
*
* @throws IncompatibleTypeException
* if the attribute value cannot be converted into a set of
* BigDecimal
's because of duplicate elements
*
* @see #isNull(String) #isNull(String) to check if the attribute value is
* null.
* @see #isPresent(String) #isPresent(String) to check if the attribute
* value is present.
*/
public Set getNumberSet(String attrName) {
Object val = attributes.get(attrName);
if (val == null)
return null;
Set numSet = new LinkedHashSet();
if (val instanceof Collection) {
Collection> col = (Collection>) val;
if (col.size() == 0)
return numSet;
for (Object element: col) {
BigDecimal bd = toBigDecimal(element);
if (!numSet.add(bd))
throw new IncompatibleTypeException(val.getClass()
+ " cannot be converted into a set of BigDecimal's because of duplicate elements");
}
return numSet;
} else if (val instanceof BigDecimal) {
numSet.add((BigDecimal)val);
return numSet;
} else {
numSet.add(new BigDecimal(val.toString()));
return numSet;
}
}
/**
* Sets the value of the specified attribute in the current item to the
* given value.
*/
public Item withBigDecimalSet(String attrName, Set val) {
checkInvalidAttribute(attrName, val);
attributes.put(attrName, val);
return this;
}
/**
* Sets the value of the specified attribute in the current item to the
* given value.
*/
public Item withBigDecimalSet(String attrName, BigDecimal ... vals) {
checkInvalidAttribute(attrName, vals);
Set set = new LinkedHashSet(Arrays.asList(vals));
if (set.size() != vals.length)
throw new IllegalArgumentException(DUPLICATE_VALUES_FOUND_IN_INPUT);
attributes.put(attrName, set);
return this;
}
/**
* Sets the value of the specified attribute in the current item to the
* given value.
*/
public Item withNumberSet(String attrName, Number ... vals) {
checkInvalidAttribute(attrName, vals);
Set set = InternalUtils.toBigDecimalSet(vals);
if (set.size() != vals.length)
throw new IllegalArgumentException(DUPLICATE_VALUES_FOUND_IN_INPUT);
return withBigDecimalSet(attrName, set);
}
/**
* Sets the value of the specified attribute in the current item to the
* given value.
*/
public Item withNumberSet(String attrName, Set vals) {
checkInvalidAttribute(attrName, vals);
Set set = InternalUtils.toBigDecimalSet(vals);
if (set.size() != vals.size())
throw new IllegalArgumentException(DUPLICATE_VALUES_FOUND_IN_INPUT);
return withBigDecimalSet(attrName, set);
}
/**
* Returns the value of the specified attribute in the current item as a set
* of byte arrays; or null if the attribute either doesn't exist or the
* attribute value is null.
*
* @throws IncompatibleTypeException
* if the attribute value cannot be converted into a set of byte
* arrays
*
* @see #isNull(String) #isNull(String) to check if the attribute value is
* null.
* @see #isPresent(String) #isPresent(String) to check if the attribute
* value is present.
*/
public Set getBinarySet(String attrName) {
Object val = attributes.get(attrName);
if (val == null)
return null;
Set binarySet = new LinkedHashSet();
if (val instanceof Collection) {
Collection> col = (Collection>) val;
if (col.size() == 0)
return binarySet;
for (Object element: col) {
byte[] ba = toByteArray(element);
if (!binarySet.add(ba))
throw new IncompatibleTypeException(val.getClass()
+ " cannot be converted into a set of byte arrays because of duplicate elements");
}
return binarySet;
} else if (val instanceof byte[]) {
binarySet.add((byte[])val);
return binarySet;
} else if (val instanceof ByteBuffer) {
// Defensive code but execution should never get here. The internal
// representation of binary should always be
// byte[], not ByteBuffer. This allows Item to be converted into
// a JSON string via Jackson without causing trouble.
ByteBuffer bb = (ByteBuffer) val;
binarySet.add(copyAllBytesFrom(bb));
return binarySet;
}
throw new IncompatibleTypeException(val.getClass()
+ " cannot be converted into a set of byte arrays");
}
/**
* Returns the value of the specified attribute in the current item as a set
* of ByteBuffer
; or null if the attribute either doesn't exist
* or the attribute value is null.
*
* @throws IncompatibleTypeException
* if the attribute value cannot be converted into a set of
* ByteBuffer
*
* @see #isNull(String) #isNull(String) to check if the attribute value is
* null.
* @see #isPresent(String) #isPresent(String) to check if the attribute
* value is present.
*/
public Set getByteBufferSet(String attrName) {
Object val = attributes.get(attrName);
if (val == null)
return null;
Set binarySet = new LinkedHashSet();
if (val instanceof Collection) {
Collection> col = (Collection>) val;
if (col.size() == 0)
return binarySet;
for (Object element: col) {
ByteBuffer ba = toByteBuffer(element);
if (!binarySet.add(ba))
throw new IncompatibleTypeException(val.getClass()
+ " cannot be converted into a set of ByteBuffer because of duplicate elements");
}
return binarySet;
} else if (val instanceof ByteBuffer) {
// Defensive code but execution should never get here. The internal
// representation of binary should always be
// byte[], not ByteBuffer. This allows Item to be converted into
// a JSON string via Jackson without causing trouble.
binarySet.add((ByteBuffer)val);
return binarySet;
} else if (val instanceof byte[]) {
binarySet.add(ByteBuffer.wrap((byte[])val));
return binarySet;
}
throw new IncompatibleTypeException(val.getClass()
+ " cannot be converted into a set of ByteBuffer");
}
/**
* Sets the value of the specified attribute in the current item to the
* given value.
*/
public Item withBinarySet(String attrName, Set val) {
checkInvalidAttribute(attrName, val);
attributes.put(attrName, val);
return this;
}
/**
* Sets the value of the specified attribute in the current item to the
* given value.
*/
public Item withByteBufferSet(String attrName, Set val) {
checkInvalidAttribute(attrName, val);
// convert ByteBuffer to bytes to keep Jackson happy
Set set = new LinkedHashSet(val.size());
for (ByteBuffer bb: val)
set.add(copyBytesFrom(bb));
attributes.put(attrName, set);
return this;
}
/**
* Sets the value of the specified attribute in the current item to the
* given value.
*/
public Item withBinarySet(String attrName, byte[] ... vals) {
checkInvalidAttribute(attrName, vals);
Set set = new LinkedHashSet(Arrays.asList(vals));
if (set.size() != vals.length)
throw new IllegalArgumentException(DUPLICATE_VALUES_FOUND_IN_INPUT);
attributes.put(attrName, set);
return this;
}
/**
* Sets the value of the specified attribute in the current item to the
* given value.
*/
public Item withBinarySet(String attrName, ByteBuffer ... vals) {
checkInvalidAttribute(attrName, vals);
// convert ByteBuffer to bytes to keep Jackson happy
Set set = new LinkedHashSet(vals.length);
for (ByteBuffer bb: vals)
set.add(copyBytesFrom(bb));
if (set.size() != vals.length)
throw new IllegalArgumentException(DUPLICATE_VALUES_FOUND_IN_INPUT);
attributes.put(attrName, set);
return this;
}
/**
* Returns the value of the specified attribute in the current item as a set
* of T
's.; or null if the attribute either doesn't exist or
* the attribute value is null.
*
* @throws ClassCastException
* if the attribute involves a value that cannot be casted to
* T
*
* @see #isNull(String) #isNull(String) to check if the attribute value is
* null.
* @see #isPresent(String) #isPresent(String) to check if the attribute
* value is present.
*/
public List getList(String attrName) {
Object val = attributes.get(attrName);
if (val == null)
return null;
if (val instanceof List) {
@SuppressWarnings("unchecked")
List ret = (List)val;
return ret;
}
List list = new ArrayList();
if (val instanceof Collection) {
Collection> col = (Collection>)val;
for (Object element: col) {
@SuppressWarnings("unchecked")
T t = (T)element;
list.add(t);
}
return list;
}
@SuppressWarnings("unchecked")
T t = (T)val;
list.add(t);
return list;
}
/**
* Sets the value of the specified attribute in the current item to the
* given value.
*/
public Item withList(String attrName, List> val) {
checkInvalidAttribute(attrName, val);
attributes.put(attrName, valueConformer.transform(val));
return this;
}
/**
* Sets the value of the specified attribute in the current item to the
* given values as a list.
*/
public Item withList(String attrName, Object ... vals) {
checkInvalidAttribute(attrName, vals);
List