/* * Copyright 2010-2017 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.datamodeling; import static org.junit.Assert.assertEquals; import java.lang.reflect.Method; import java.math.BigDecimal; import java.math.BigInteger; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Collections; import java.util.Date; import java.util.GregorianCalendar; import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import java.util.TreeSet; import java.util.UUID; import org.junit.Assert; import org.junit.Test; import com.amazonaws.auth.AWSCredentialsProvider; import com.amazonaws.services.dynamodbv2.model.AttributeValue; import com.amazonaws.services.dynamodbv2.pojos.SubClass; import com.amazonaws.services.dynamodbv2.pojos.TestClass; import com.amazonaws.services.dynamodbv2.pojos.UnannotatedSubClass; public class StandardModelFactoriesV2Test { protected static final DynamoDBMapperConfig CONFIG = new DynamoDBMapperConfig.Builder() .withTypeConverterFactory(DynamoDBMapperConfig.DEFAULT.getTypeConverterFactory()) .withConversionSchema(ConversionSchemas.V2) .build(); private static final DynamoDBMapperModelFactory factory = StandardModelFactories.of(S3Link.Factory.of(null)); private static final DynamoDBMapperModelFactory.TableFactory models = factory.getTableFactory(CONFIG); protected <T> AttributeValue convert(Class<T> clazz, Method getter, Object value) { final StandardAnnotationMaps.FieldMap<Object> map = StandardAnnotationMaps.of(getter, null); return models.getTable(clazz).field(map.attributeName()).convert(value); } @Test public void testBoolean() { // These are all native booleans by default in the v2 schema assertEquals(true, convert("getBoolean", true).getBOOL()); assertEquals(false, convert("getBoolean", false).getBOOL()); assertEquals(true, convert("getBoxedBoolean", true).getBOOL()); assertEquals(false, convert("getBoxedBoolean", false).getBOOL()); assertEquals(true, convert("getNativeBoolean", true).getBOOL()); assertEquals(false, convert("getNativeBoolean", false).getBOOL()); } @Test public void testString() { assertEquals("abc", convert("getString", "abc").getS()); assertEquals(RandomUUIDMarshaller.randomUUID, convert("getCustomString", "abc").getS()); } @Test public void testUuid() { UUID uuid = UUID.randomUUID(); assertEquals(uuid.toString(), convert("getUuid", uuid).getS()); } @Test public void testDate() { assertEquals("1970-01-01T00:00:00.000Z", convert("getDate", new Date(0)).getS()); Calendar c = GregorianCalendar.getInstance(); c.setTimeInMillis(0); assertEquals("1970-01-01T00:00:00.000Z", convert("getCalendar", c).getS()); } @Test public void testNumbers() { assertEquals("0", convert("getByte", (byte) 0).getN()); assertEquals("1", convert("getByte", (byte) 1).getN()); assertEquals("0", convert("getBoxedByte", (byte) 0).getN()); assertEquals("1", convert("getBoxedByte", (byte) 1).getN()); assertEquals("0", convert("getShort", (short) 0).getN()); assertEquals("1", convert("getShort", (short) 1).getN()); assertEquals("0", convert("getBoxedShort", (short) 0).getN()); assertEquals("1", convert("getBoxedShort", (short) 1).getN()); assertEquals("0", convert("getInt", 0).getN()); assertEquals("1", convert("getInt", 1).getN()); assertEquals("0", convert("getBoxedInt", 0).getN()); assertEquals("1", convert("getBoxedInt", 1).getN()); assertEquals("0", convert("getLong", 0l).getN()); assertEquals("1", convert("getLong", 1l).getN()); assertEquals("0", convert("getBoxedLong", 0l).getN()); assertEquals("1", convert("getBoxedLong", 1l).getN()); assertEquals("0", convert("getBigInt", BigInteger.ZERO).getN()); assertEquals("1", convert("getBigInt", BigInteger.ONE).getN()); assertEquals("0.0", convert("getFloat", 0f).getN()); assertEquals("1.0", convert("getFloat", 1f).getN()); assertEquals("0.0", convert("getBoxedFloat", 0f).getN()); assertEquals("1.0", convert("getBoxedFloat", 1f).getN()); assertEquals("0.0", convert("getDouble", 0d).getN()); assertEquals("1.0", convert("getDouble", 1d).getN()); assertEquals("0.0", convert("getBoxedDouble", 0d).getN()); assertEquals("1.0", convert("getBoxedDouble", 1d).getN()); assertEquals("0", convert("getBigDecimal", BigDecimal.ZERO).getN()); assertEquals("1", convert("getBigDecimal", BigDecimal.ONE).getN()); } @Test public void testBinary() { ByteBuffer value = ByteBuffer.wrap("value".getBytes()); assertEquals(value.slice(), convert("getByteArray", "value".getBytes()).getB()); assertEquals(value.slice(), convert("getByteBuffer", value.slice()).getB()); } @Test public void testBooleanSet() { // Set<Boolean> (which is silly but technically valid) gets mapped to // a List of Booleans now via the ObjectSetToListMarshaller. AttributeValue value = convert("getBooleanSet", Collections.singleton(true)); Assert.assertEquals(1, value.getL().size()); Assert.assertEquals(true, value.getL().get(0).getBOOL()); } @Test public void testStringSet() { assertEquals(Collections.singletonList("a"), convert("getStringSet", Collections.singleton("a")).getSS()); assertEquals(Collections.singletonList("b"), convert("getStringSet", Collections.singleton("b")).getSS()); assertEquals(Arrays.asList("a", "b", "c"), convert("getStringSet", new TreeSet<String>() {{ add("a"); add("b"); add("c"); }}).getSS()); } @Test public void testUuidSet() { final UUID one = UUID.randomUUID(); final UUID two = UUID.randomUUID(); final UUID three = UUID.randomUUID(); assertEquals(Collections.singletonList(one.toString()), convert("getUuidSet", Collections.singleton(one)).getSS()); assertEquals(Collections.singletonList(two.toString()), convert("getUuidSet", Collections.singleton(two)).getSS()); assertEquals( Arrays.asList( one.toString(), two.toString(), three.toString()), convert("getUuidSet", new LinkedHashSet<UUID>() {{ add(one); add(two); add(three); }}).getSS()); } @Test public void testDateSet() { assertEquals(Collections.singletonList("1970-01-01T00:00:00.000Z"), convert("getDateSet", Collections.singleton(new Date(0))) .getSS()); Calendar c = GregorianCalendar.getInstance(); c.setTimeInMillis(0); assertEquals(Collections.singletonList("1970-01-01T00:00:00.000Z"), convert("getCalendarSet", Collections.singleton(c)) .getSS()); } @Test public void testNumberSet() { assertEquals(Collections.singletonList("0"), convert("getByteSet", Collections.singleton((byte) 0)).getNS()); assertEquals(Collections.singletonList("0"), convert("getShortSet", Collections.singleton((short) 0)).getNS()); assertEquals(Collections.singletonList("0"), convert("getIntSet", Collections.singleton(0)).getNS()); assertEquals(Collections.singletonList("0"), convert("getLongSet", Collections.singleton(0l)).getNS()); assertEquals(Collections.singletonList("0"), convert("getBigIntegerSet", Collections.singleton(BigInteger.ZERO)) .getNS()); assertEquals(Collections.singletonList("0.0"), convert("getFloatSet", Collections.singleton(0f)).getNS()); assertEquals(Collections.singletonList("0.0"), convert("getDoubleSet", Collections.singleton(0d)).getNS()); assertEquals(Collections.singletonList("0"), convert("getBigDecimalSet", Collections.singleton(BigDecimal.ZERO)) .getNS()); assertEquals(Arrays.asList("0", "1", "2"), convert("getLongSet", new TreeSet<Number>() {{ add(0); add(1); add(2); }}).getNS()); } @Test public void testBinarySet() { final ByteBuffer test = ByteBuffer.wrap("test".getBytes()); final ByteBuffer test2 = ByteBuffer.wrap("test2".getBytes()); assertEquals(Collections.singletonList(test.slice()), convert("getByteArraySet", Collections.singleton("test".getBytes())) .getBS()); assertEquals(Collections.singletonList(test.slice()), convert("getByteBufferSet", Collections.singleton(test.slice())) .getBS()); assertEquals(Arrays.asList(test.slice(), test2.slice()), convert("getByteBufferSet",new TreeSet<ByteBuffer>() {{ add(test.slice()); add(test2.slice()); }}).getBS()); } @Test public void testObjectSet() { AttributeValue value = convert("getObjectSet", Collections.singleton(new SubClass())); assertEquals(1, value.getL().size()); assertEquals(new HashMap<String, AttributeValue>() {{ put("name", new AttributeValue("name")); put("value", new AttributeValue().withN("123")); }}, value.getL().get(0).getM()); assertEquals(Arrays.asList(new AttributeValue().withNULL(true)), convert("getObjectSet", Collections.<SubClass>singleton(null)).getL()); } @Test public void testList() { assertEquals(Arrays.asList( new AttributeValue("a"), new AttributeValue("b"), new AttributeValue("c")), convert("getList", Arrays.asList("a", "b", "c")).getL()); assertEquals(Arrays.asList(new AttributeValue().withNULL(true)), convert("getList", Collections.<String>singletonList(null)).getL()); } @Test public void testObjectList() { AttributeValue value = convert( "getObjectList", Collections.singletonList(new SubClass())); assertEquals(1, value.getL().size()); assertEquals(new HashMap<String, AttributeValue>() {{ put("name", new AttributeValue("name")); put("value", new AttributeValue().withN("123")); }}, value.getL().get(0).getM()); } @Test public void testSetList() { assertEquals( Arrays.asList(new AttributeValue().withSS("a")), convert("getSetList", Arrays.asList( Collections.<String>singleton("a"))).getL()); List<Set<String>> list = new ArrayList<Set<String>>(); list.add(null); assertEquals( Arrays.asList(new AttributeValue().withNULL(true)), convert("getSetList", list).getL()); } @Test public void testMap() { assertEquals(new HashMap<String, AttributeValue>() {{ put("a", new AttributeValue("b")); put("c", new AttributeValue("d")); put("e", new AttributeValue("f")); }}, convert("getMap", new HashMap<String, String>() {{ put("a", "b"); put("c", "d"); put("e", "f"); }}).getM()); assertEquals(Collections.singletonMap("a", new AttributeValue().withNULL(true)), convert("getMap", Collections.<String, String>singletonMap("a", null)).getM()); } @Test public void testSetMap() { assertEquals(new HashMap<String, AttributeValue>() {{ put("a", new AttributeValue().withSS("a", "b")); }}, convert("getSetMap", new HashMap<String, Set<String>>() {{ put("a", new TreeSet<String>(Arrays.asList("a", "b"))); }}).getM()); assertEquals(new HashMap<String, AttributeValue>() {{ put("a", new AttributeValue().withSS("a")); put("b", new AttributeValue().withNULL(true)); }}, convert("getSetMap", new HashMap<String, Set<String>>() {{ put("a", new TreeSet<String>(Arrays.asList("a"))); put("b", null); }}).getM()); } @Test public void testObject() { assertEquals(new HashMap<String, AttributeValue>() {{ put("name", new AttributeValue("name")); put("value", new AttributeValue().withN("123")); }}, convert("getObject", new SubClass()).getM()); } @Test public void testUnannotatedObject() throws Exception { try { convert(UnannotatedSubClass.class, UnannotatedSubClass.class.getMethod("getChild"), new UnannotatedSubClass()); Assert.fail("Expected DynamoDBMappingException"); } catch (DynamoDBMappingException e) { } } @Test public void testS3Link() { S3ClientCache cache = new S3ClientCache((AWSCredentialsProvider) null); S3Link link = new S3Link(cache, "bucket", "key"); assertEquals("{\"s3\":{" + "\"bucket\":\"bucket\"," + "\"key\":\"key\"," + "\"region\":null}}", convert("getS3Link", link).getS()); } private AttributeValue convert(String getter, Object value) { try { return convert(TestClass.class, TestClass.class.getMethod(getter), value); } catch (RuntimeException e) { throw e; } catch (Exception e) { throw new RuntimeException(e); } } }