All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.amazonaws.services.dynamodbv2.document.internal.InternalUtils Maven / Gradle / Ivy

Go to download

The AWS SDK for Java with support for OSGi. The AWS SDK for Java provides Java APIs for building software on AWS' cost-effective, scalable, and reliable infrastructure products. The AWS Java SDK allows developers to code against APIs for all of Amazon's infrastructure web services (Amazon S3, Amazon EC2, Amazon SQS, Amazon Relational Database Service, Amazon AutoScaling, etc).

There is a newer version: 1.11.60
Show newest version
/*
 * Copyright 2014-2016 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.internal;

import static com.amazonaws.util.BinaryUtils.copyAllBytesFrom;

import java.math.BigDecimal;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.amazonaws.AmazonWebServiceRequest;
import com.amazonaws.services.dynamodbv2.document.AttributeUpdate;
import com.amazonaws.services.dynamodbv2.document.Expected;
import com.amazonaws.services.dynamodbv2.document.IncompatibleTypeException;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.KeyAttribute;
import com.amazonaws.services.dynamodbv2.document.PrimaryKey;
import com.amazonaws.services.dynamodbv2.model.AttributeValue;
import com.amazonaws.services.dynamodbv2.model.AttributeValueUpdate;
import com.amazonaws.services.dynamodbv2.model.ComparisonOperator;
import com.amazonaws.services.dynamodbv2.model.Condition;
import com.amazonaws.services.dynamodbv2.model.ExpectedAttributeValue;
import com.amazonaws.util.VersionInfoUtils;

/**
 * Internal utilities.  Not meant for general use.  May change without notice.
 */
public enum InternalUtils {
    ;

    /**
     * Returns a non-null list of Item's given the low level
     * list of item information.
     */
    public static List toItemList(List> items) {
        if (items == null)
            return Collections.emptyList();
        List result = new ArrayList(items.size());
        for (Map item : items)
            result.add(Item.fromMap(toSimpleMapValue(item)));
        return result;
    }

    /**
     * Converts an Item into the low-level representation;
     * or null if the input is null.
     */
    public static Map toAttributeValues(Item item) {
        if (item == null)
            return null;
        // row with multiple attributes
        Map result = new LinkedHashMap();
        for (Map.Entry entry : item.attributes())
            result.put(entry.getKey(), toAttributeValue(entry.getValue()));
        return result;
    }

    /**
     * Converts a map of string to simple objects into the low-level
     * representation; or null if the input is null.
     */
    public static Map fromSimpleMap(
            Map map) {
        if (map == null)
            return null;
        // row with multiple attributes
        Map result = new LinkedHashMap();
        for (Map.Entry entry : map.entrySet())
            result.put(entry.getKey(), toAttributeValue(entry.getValue()));
        return result;
    }

    /**
     * Converts a list of AttributeUpdate into the low-level
     * representation; or null if the input is null.
     */
    public static Map toAttributeValueUpdate(
            List attributesToUpdate) {
        if (attributesToUpdate == null)
            return null;

        Map result = new LinkedHashMap();

        for (AttributeUpdate attribute : attributesToUpdate) {
            AttributeValueUpdate attributeToUpdate = new AttributeValueUpdate()
                    .withAction(attribute.getAction());
            if (attribute.getValue() != null) {
                attributeToUpdate.withValue(toAttributeValue(attribute
                        .getValue()));
            } else if (attribute.getAttributeValues() != null) {
                attributeToUpdate.withValue(toAttributeValue(attribute
                        .getAttributeValues()));
            }
            result.put(attribute.getAttributeName(), attributeToUpdate);
        }

        return result;
    }

    /**
     * Converts a simple value into the low-level 
     * representation.
     *
     * @param value
     *            the given value which 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
  • *
* @return a non-null low level representation of the input object value * * @throws UnsupportedOperationException * if the input object type is not supported */ public static AttributeValue toAttributeValue(Object value) { AttributeValue result = new AttributeValue(); if (value == null) { return result.withNULL(Boolean.TRUE); } else if (value instanceof Boolean) { return result.withBOOL((Boolean)value); } else if (value instanceof String) { return result.withS((String) value); } else if (value instanceof BigDecimal) { BigDecimal bd = (BigDecimal) value; return result.withN(bd.toPlainString()); } else if (value instanceof Number) { return result.withN(value.toString()); } else if (value instanceof byte[]) { return result.withB(ByteBuffer.wrap((byte[]) value)); } else if (value instanceof ByteBuffer) { return result.withB((ByteBuffer) value); } else if (value instanceof Set) { // default to an empty string set if there is no element @SuppressWarnings("unchecked") Set set = (Set) value; if (set.size() == 0) { result.setSS(new LinkedHashSet()); return result; } Object element = set.iterator().next(); if (element instanceof String) { @SuppressWarnings("unchecked") Set ss = (Set) value; result.setSS(new ArrayList(ss)); } else if (element instanceof Number) { @SuppressWarnings("unchecked") Set in = (Set) value; List out = new ArrayList(set.size()); for (Number n : in) { BigDecimal bd = InternalUtils.toBigDecimal(n); out.add(bd.toPlainString()); } result.setNS(out); } else if (element instanceof byte[]) { @SuppressWarnings("unchecked") Set in = (Set) value; List out = new ArrayList(set.size()); for (byte[] buf : in) { out.add(ByteBuffer.wrap(buf)); } result.setBS(out); } else if (element instanceof ByteBuffer) { @SuppressWarnings("unchecked") Set bs = (Set) value; result.setBS(bs); } else { throw new UnsupportedOperationException("element type: " + element.getClass()); } } else if (value instanceof List) { @SuppressWarnings("unchecked") List in = (List) value; List out = new ArrayList(); for (Object v : in) { out.add(toAttributeValue(v)); } result.setL(out); } else if (value instanceof Map) { @SuppressWarnings("unchecked") Map in = (Map) value; if (in.size() > 0) { for (Map.Entry e : in.entrySet()) { result.addMEntry(e.getKey(), toAttributeValue(e.getValue())); } } else { // empty map result.setM(new LinkedHashMap()); } } else { throw new UnsupportedOperationException("value type: " + value.getClass()); } return result; } /** * Converts a list of low-level AttributeValue into a list of * simple values. Each value in the returned list 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
  • *
*/ public static List toSimpleList(List attrValues) { if (attrValues == null) return null; List result = new ArrayList(attrValues.size()); for (AttributeValue attrValue : attrValues) { Object value = toSimpleValue(attrValue); result.add(value); } return result; } /** * Convenient method to convert a list of low-level * AttributeValue into a list of values of the same type T. * Each value in the returned list 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
  • *
*/ public static List toSimpleListValue(List values) { if (values == null) { return null; } List result = new ArrayList(values.size()); for (AttributeValue v : values) { T t = toSimpleValue(v); result.add(t); } return result; } public static Map toSimpleMapValue( Map values) { if (values == null) { return null; } Map result = new LinkedHashMap(values.size()); for (Map.Entry entry : values.entrySet()) { T t = toSimpleValue(entry.getValue()); result.put(entry.getKey(), t); } return result; } /** * Returns the string representation of the given value; or null if the * value is null. For BigDecimal it will be the string * representation without an exponent field. */ public static String valToString(Object val) { if (val instanceof BigDecimal) { BigDecimal bd = (BigDecimal)val; return bd.toPlainString(); } if (val == null) return null; if (val instanceof String || val instanceof Boolean || val instanceof Number) return val.toString(); throw new IncompatibleTypeException("Cannot convert " + val.getClass() + " into a string"); } /** * Converts a low-level AttributeValue into a simple value, * which 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
  • *
* * @throws IllegalArgumentException * if an empty AttributeValue value is specified */ static T toSimpleValue(AttributeValue value) { if (value == null) { return null; } if (Boolean.TRUE.equals(value.getNULL())) { return null; } else if (Boolean.FALSE.equals(value.getNULL())) { throw new UnsupportedOperationException("False-NULL is not supported in DynamoDB"); } else if (value.getBOOL() != null) { @SuppressWarnings("unchecked") T t = (T) value.getBOOL(); return t; } else if (value.getS() != null) { @SuppressWarnings("unchecked") T t = (T) value.getS(); return t; } else if (value.getN() != null) { @SuppressWarnings("unchecked") T t = (T) new BigDecimal(value.getN()); return t; } else if (value.getB() != null) { @SuppressWarnings("unchecked") T t = (T) copyAllBytesFrom(value.getB()); return t; } else if (value.getSS() != null) { @SuppressWarnings("unchecked") T t = (T) new LinkedHashSet(value.getSS()); return t; } else if (value.getNS() != null) { Set set = new LinkedHashSet(value.getNS().size()); for (String s : value.getNS()) { set.add(new BigDecimal(s)); } @SuppressWarnings("unchecked") T t = (T) set; return t; } else if (value.getBS() != null) { Set set = new LinkedHashSet(value.getBS().size()); for (ByteBuffer bb : value.getBS()) { set.add(copyAllBytesFrom(bb)); } @SuppressWarnings("unchecked") T t = (T) set; return t; } else if (value.getL() != null) { @SuppressWarnings("unchecked") T t = (T) toSimpleList(value.getL()); return t; } else if (value.getM() != null) { @SuppressWarnings("unchecked") T t = (T) toSimpleMapValue(value.getM()); return t; } else { throw new IllegalArgumentException( "Attribute value must not be empty: " + value); } } /** * Returns the minimum of the two input integers taking null into account. * Returns null if both integers are null. Otherwise, a null Integer is * treated as infinity. */ public static Integer minimum(Integer one, Integer two) { if (one == null) { return two; } else if (two == null) { return one; } else if (one < two) { return one; } else { return two; } } /** * Returns the low level representation of a collection of Expected. */ public static Map toExpectedAttributeValueMap( Collection expectedSet) { if (expectedSet == null) return null; Map expectedMap = new LinkedHashMap(); for (Expected expected : expectedSet) { final String attr = expected.getAttribute(); final Object[] values = expected.getValues(); ExpectedAttributeValue eav = new ExpectedAttributeValue(); if (values != null) { if (values.length > 0) { // convert from list of object values to list of AttributeValues AttributeValue[] avs = InternalUtils.toAttributeValues(values); eav.withAttributeValueList(avs); } else { throw new IllegalStateException("Bug!"); } } ComparisonOperator op = expected.getComparisonOperator(); if (op == null) { throw new IllegalArgumentException( "Comparison operator for attribute " + expected.getAttribute() + " must be specified"); } eav.withComparisonOperator(op); expectedMap.put(attr, eav); } if (expectedSet.size() != expectedMap.size()) throw new IllegalArgumentException("duplicates attribute names not allowed in input"); return Collections.unmodifiableMap(expectedMap); } /** * Returns the low level representation of a collection of Filter. */ public static Map toAttributeConditionMap(Collection> filters) { if (filters == null) return null; Map conditionMap = new LinkedHashMap(); for (Filter filter : filters) { final String attr = filter.getAttribute(); final Object[] values = filter.getValues(); Condition condition = new Condition(); if (values != null) { if (values.length > 0) { // convert from list of object values to list of AttributeValues AttributeValue[] avs = InternalUtils.toAttributeValues(values); condition.withAttributeValueList(avs); } else { throw new IllegalStateException("Bug!"); } } ComparisonOperator op = filter.getComparisonOperator(); if (op == null) { throw new IllegalArgumentException( "Comparison operator for attribute " + filter.getAttribute() + " must be specified"); } condition.withComparisonOperator(op); conditionMap.put(attr, condition); } if (filters.size() != conditionMap.size()) throw new IllegalArgumentException("duplicates attribute names not allowed in input"); return Collections.unmodifiableMap(conditionMap); } /** * Converts the input array of values into an array of low level * representation of those values. * * A value in the input array 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
  • *
*/ public static AttributeValue[] toAttributeValues(Object[] values) { AttributeValue[] attrValues = new AttributeValue[values.length]; for (int i=0; i < values.length; i++) attrValues[i] = InternalUtils.toAttributeValue(values[i]); return attrValues; } /** * Converts the specified primary key into the low-level representation. */ public static Map toAttributeValueMap( Collection primaryKey) { if (primaryKey == null) return null; Map keys = new LinkedHashMap(); for (KeyAttribute keyAttr : primaryKey) keys.put(keyAttr.getName(), InternalUtils.toAttributeValue(keyAttr.getValue())); return Collections.unmodifiableMap(keys); } /** * Converts the specified primary key into the low-level representation. */ public static Map toAttributeValueMap( PrimaryKey primaryKey) { if (primaryKey == null) return null; return toAttributeValueMap(primaryKey.getComponents()); } /** * Converts the specified primary key into the low-level representation. */ public static Map toAttributeValueMap( KeyAttribute ... primaryKey) { if (primaryKey == null) return null; return toAttributeValueMap(Arrays.asList(primaryKey)); } /** * Converts a number into BigDecimal representation. */ public static BigDecimal toBigDecimal(Number n) { if (n instanceof BigDecimal) return (BigDecimal)n; return new BigDecimal(n.toString()); } public static Set toBigDecimalSet(Number ... val) { Set set = new LinkedHashSet(val.length); for (Number n: val) set.add(InternalUtils.toBigDecimal(n)); return set; } public static Set toBigDecimalSet(Set vals) { Set set = new LinkedHashSet(vals.size()); for (Number n: vals) set.add(InternalUtils.toBigDecimal(n)); return set; } /** * Append the custom user-agent string. */ public static X applyUserAgent(X request) { final String USER_AGENT = "dynamodb-table-api/" + VersionInfoUtils.getVersion(); request.getRequestClientOptions().appendUserAgent(USER_AGENT); return request; } public static void rejectNullValue(Object val) { if (val == null) throw new IllegalArgumentException("Input value must not be null"); } public static void rejectNullInput(Object input) { if (input == null) throw new IllegalArgumentException("Input must not be null"); } public static void rejectEmptyInput(Object[] input) { if (input.length == 0) throw new IllegalArgumentException("At least one input must be specified"); } public static void rejectNullOrEmptyInput(Object[] input) { rejectNullInput(input); rejectEmptyInput(input); } public static void checkInvalidAttrName(String attrName) { if (attrName == null || attrName.trim().length() == 0) throw new IllegalArgumentException("Attribute name must not be null or empty"); } public static void checkInvalidAttribute(String attrName, Object val) { checkInvalidAttrName(attrName); rejectNullValue(val); } }