/* * Copyright 2015-2023 Amazon Technologies, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://aws.amazon.com/apache2.0 * * 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.xspec; import java.nio.ByteBuffer; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import com.amazonaws.annotation.Beta; /** * A request-centric Expression Specification Builder that can be used to * construct valid expressions, and the respective name maps and value maps, for * various DynamoDB requests in a typeful manner. This includes Update expression, Condition expression (including Filter expression and Key Condition * expression), and Projection expression. This class is the API entry point to this * library. *
* This builder object is not thread-safe but you can reuse or build on (the * specific states of) a builder by cloning it into separate instances for use * in a concurrent environment. * *
* import static com.amazonaws.services.dynamodbv2.xspec.ExpressionSpecBuilder.*; * ... * Table table = dynamo.getTable(TABLE_NAME); * * UpdateItemExpressionSpec xspec = new ExpressionSpecBuilder() * // SET num1 = num1 + 20 * .addUpdate( * N("num1").set(N("num1").plus(20))) * // SET string-attr = "string-value" * .addUpdate( * S("string-attr").set("string-value") * ) * // num2 BETWEEN 0 AND 100 * .withCondition( * N("num2").between(0, 100) * ).buildForUpdate(); * * table.updateItem(HASH_KEY_NAME, "hashKeyValue", RANGE_KEY_NAME, 0, xspec); ** *
* Let's say you want to include a complex condition expression such as: * *
* (attribute_not_exists(item_version) AND attribute_not_exists(config_id) AND attribute_not_exists(config_version)) OR * (item_version < 123) OR * (item_version = 123 AND config_id < 456) OR * (item_version = 123 AND config_id = 456 AND config_version < 999) ** * Here is how: *
* *
* import static com.amazonaws.services.dynamodbv2.xspec.ExpressionSpecBuilder.*; * ... * Table table = dynamo.getTable(TABLE_NAME); * * UpdateItemExpressionSpec xspec = new ExpressionSpecBuilder() * // SET num1 = num1 + 20 * .addUpdate( * N("num1").set(N("num1").plus(20))) * // SET string-attr = "string-value" * .addUpdate( * S("string-attr").set("string-value") * ) * // a complex condition expression (as shown above) * .withCondition( * // add explicit parenthesis * parenthesize( attribute_not_exists("item_version") * .and( attribute_not_exists("config_id") ) * .and( attribute_not_exists("config_version") ) * ).or( N("item_version").lt(123) ) * .or( N("item_version").eq(123) * .and( N("config_id").lt(456) ) ) * .or( N("item_version").eq(123) * .and( N("config_id").eq(456) ) * .and( N("config_version").lt(999) )) * ).buildForUpdate(); * * table.updateItem(HASH_KEY_NAME, "hashKeyValue", RANGE_KEY_NAME, 0, xspec); ** *
* Without ExpressionSpecBuilder, the code (using the DynamoDB Document API) * could be something like: * *
* ItemCollection<?> col = table.scan( * "(#hk = :hashkeyAttrValue) AND (#rk BETWEEN :lo AND :hi)", * new NameMap().with("#hk", HASH_KEY_NAME).with("#rk", RANGE_KEY_NAME), * new ValueMap().withString(":hashkeyAttrValue", "allDataTypes") * .withInt(":lo", 1).withInt(":hi", 10)); ** * In contrast, using ExpressionSpecBuilder: *
* *
* import static com.amazonaws.services.dynamodbv2.xspec.ExpressionSpecBuilder.*; * ... * ScanExpressionSpec xspec = new ExpressionSpecBuilder() * .withCondition( * S(HASH_KEY_NAME).eq("allDataTypes") * .and(N(RANGE_KEY_NAME).between(1, 10)) * ).buildForScan(); * * ItemCollection> col = table.scan(xspec); ** *
* import static com.amazonaws.services.dynamodbv2.xspec.ExpressionSpecBuilder.*; * ... * Table table = dynamo.getTable(TABLE_NAME); * * UpdateItemExpressionSpec xspec = new ExpressionSpecBuilder() * .addUpdate(S("mapAttr.colors[0]").set("red")) * .addUpdate(S("mapAttr.colors[1]").set("blue")) * .addUpdate(L("mapAttr.members").set( * L("mapAttr.members").listAppend("marry", "liza"))) * .addUpdate(SS("mapAttr.countries").append("cn", "uk")) * .addUpdate(SS("mapAttr.brands").delete("Facebook", "LinkedIn")) * .addUpdate(attribute("mapAttr.foo").remove()) * .buildForUpdate(); * * assertEquals("SET #0.#1[0] = :0, #0.#1[1] = :1, #0.#2 = list_append(#0.#2, :2) ADD #0.#3 :3 DELETE #0.#4 :4 REMOVE #0.#5", * xspec.getUpdateExpression()); * * final String hashkey = "addRemoveDeleteColors"; * table.updateItem(HASH_KEY_NAME, hashkey, RANGE_KEY_NAME, 0, xspec); ** * @see PathOperand */ @Beta public final class ExpressionSpecBuilder implements Cloneable { private final Map
* This builder object is not thread-safe but you can reuse or build on (the * specific states of) a builder by cloning it into separate instances for use * in a concurrent environment. *
*
* import static com.amazonaws.services.dynamodbv2.xspec.ExpressionSpecBuilder.*; * ... * Table table = dynamo.getTable(TABLE_NAME); * * QueryExpressionSpec xspec = new ExpressionSpecBuilder() * .addProjections("numberAttr", "stringAttr") * .withCondition(BOOL("booleanTrue").eq(true) * .and(S("mapAttr.key1").eq("value1")) * ).buildForQuery(); * * ItemCollection> col = table.query(HASH_KEY_NAME, "allDataTypes", * new RangeKeyCondition("range_key_name").between(1, 10), xspec); ** *
* import static com.amazonaws.services.dynamodbv2.xspec.ExpressionSpecBuilder.*; * ... * Table table = dynamo.getTable(TABLE_NAME); * * UpdateItemExpressionSpec xspec = new ExpressionSpecBuilder() * // SET num1 = num1 + 20 * .addUpdate( * N("num1").set(N("num1").plus(20))) * // SET string-attr = "string-value" * .addUpdate( * S("string-attr").set("string-value") * ) * // num2 BETWEEN 0 AND 100 * .withCondition( * N("num2").between(0, 100) * ).buildForUpdate(); * * table.updateItem(HASH_KEY_NAME, "hashKeyValue", RANGE_KEY_NAME, 0, xspec); **
* Without ExpressionSpecBuilder, the code (using the DynamoDB Document API) * could be something like: * *
* ItemCollection<?> col = table.scan( * "(#hk = :hashkeyAttrValue) AND (#rk BETWEEN :lo AND :hi)", * new NameMap().with("#hk", HASH_KEY_NAME).with("#rk", RANGE_KEY_NAME), * new ValueMap().withString(":hashkeyAttrValue", "allDataTypes") * .withInt(":lo", 1).withInt(":hi", 10)); ** * In contrast, using ExpressionSpecBuilder: *
* *
* import static com.amazonaws.services.dynamodbv2.xspec.ExpressionSpecBuilder.*; * ... * ScanExpressionSpec xspec = new ExpressionSpecBuilder() * .withCondition( * S(HASH_KEY_NAME).eq("allDataTypes") * .and(N(RANGE_KEY_NAME).between(1, 10)) * ).buildForScan(); * * ItemCollection> col = table.scan(xspec); ** *
* import static com.amazonaws.services.dynamodbv2.xspec.ExpressionSpecBuilder.*; * ... * Table table = dynamo.getTable(TABLE_NAME); * * UpdateItemExpressionSpec xspec = new ExpressionSpecBuilder() * // SET num1 = num1 + 20 * .addUpdate( * N("num1").set(N("num1").plus(20))) * // SET string-attr = "string-value" * .addUpdate( * S("string-attr").set("string-value") * ) * // num2 BETWEEN 0 AND 100 * .withCondition( * N("num2").between(0, 100) * ).buildForUpdate(); * * table.updateItem(HASH_KEY_NAME, "hashKeyValue", RANGE_KEY_NAME, 0, xspec); ** *
* Let's say you want to include a complex condition expression such as: * *
* (attribute_not_exists(item_version) AND attribute_not_exists(config_id) AND attribute_not_exists(config_version)) OR * (item_version < 123) OR * (item_version = 123 AND config_id < 456) OR * (item_version = 123 AND config_id = 456 AND config_version < 999) ** * Here is how: *
* *
* import static com.amazonaws.services.dynamodbv2.xspec.ExpressionSpecBuilder.*; * ... * Table table = dynamo.getTable(TABLE_NAME); * * UpdateItemExpressionSpec xspec = new ExpressionSpecBuilder() * // SET num1 = num1 + 20 * .addUpdate( * N("num1").set(N("num1").plus(20))) * // SET string-attr = "string-value" * .addUpdate( * S("string-attr").set("string-value") * ) * // a complex condition expression (as shown above) * .withCondition( * // add explicit parenthesis * parenthesize( attribute_not_exists("item_version") * .and( attribute_not_exists("config_id") ) * .and( attribute_not_exists("config_version") ) * ).or( N("item_version").lt(123) ) * .or( N("item_version").eq(123) * .and( N("config_id").lt(456) ) ) * .or( N("item_version").eq(123) * .and( N("config_id").eq(456) ) * .and( N("config_version").lt(999) )) * ).buildForUpdate(); * * table.updateItem(HASH_KEY_NAME, "hashKeyValue", RANGE_KEY_NAME, 0, xspec); ** *
* import static com.amazonaws.services.dynamodbv2.xspec.ExpressionSpecBuilder.*; * ... * Table table = dynamo.getTable(TABLE_NAME); * * UpdateItemExpressionSpec xspec = new ExpressionSpecBuilder() * .addUpdate(S("mapAttr.colors[0]").set("red")) * .addUpdate(S("mapAttr.colors[1]").set("blue")) * .addUpdate(L("mapAttr.members").set( * L("mapAttr.members").listAppend("marry", "liza"))) * .addUpdate(SS("mapAttr.countries").append("cn", "uk")) * .addUpdate(SS("mapAttr.brands").delete("Facebook", "LinkedIn")) * .addUpdate(attribute("mapAttr.foo").remove()) * .buildForUpdate(); * * assertEquals("SET #0.#1[0] = :0, #0.#1[1] = :1, #0.#2 = list_append(#0.#2, :2) ADD #0.#3 :3 DELETE #0.#4 :4 REMOVE #0.#5", * xspec.getUpdateExpression()); * * final String hashkey = "addRemoveDeleteColors"; * table.updateItem(HASH_KEY_NAME, hashkey, RANGE_KEY_NAME, 0, xspec); ** * @see PathOperand */ public ExpressionSpecBuilder() { this.updates = new LinkedHashMap
* For example: *
* import static com.amazonaws.services.dynamodbv2.xspec.ExpressionSpecBuilder.*; * ... * builder * // SET num1 = num1 + 20 * .addUpdate( * N("num1").set(N("num1").plus(20))) * // SET string-attr = "string-value" * .addUpdate( * S("string-attr").set("string-value") * ) */ public ExpressionSpecBuilder addUpdate(UpdateAction updateAction) { final String operator = updateAction.getOperator(); Listlist = updates.get(operator); if (list == null) { list = new LinkedList (); updates.put(operator, list); } list.add(updateAction); return this; } /** * Fluent API to set the condition expression for a request. * * For example: *
* import static com.amazonaws.services.dynamodbv2.xspec.ExpressionSpecBuilder.*; * ... * builder.withCondition( * // num2 BETWEEN 0 AND 100 * ExpressionSpecBuilder.N("num2").between(0, 100) * ) * ... ** Example of specifying a complex condition: ** import static com.amazonaws.services.dynamodbv2.xspec.ExpressionSpecBuilder.*; * ... * // A complex condition expression: * // * // (attribute_not_exists(item_version) AND attribute_not_exists(config_id) AND attribute_not_exists(config_version)) OR * // (item_version < 123) OR * // (item_version = 123 AND config_id < 456) OR * // (item_version = 123 AND config_id = 456 AND config_version < 999) * // * builder.withCondition( * // add explicit parenthesis * parenthesize( attribute_not_exists("item_version") * .and( attribute_not_exists("config_id") ) * .and( attribute_not_exists("config_version") ) * ).or( N("item_version").lt(123) ) * .or( N("item_version").eq(123) * .and( N("config_id").lt(456) ) ) * .or( N("item_version").eq(123) * .and( N("config_id").eq(456) ) * .and( N("config_version").lt(999) )) * ) * ... **/ public ExpressionSpecBuilder withCondition(Condition condition) { this.condition = condition; return this; } public ExpressionSpecBuilder withKeyCondition(Condition keyCondition) { this.keyCondition = keyCondition; return this; } /** * Fluent API to add the given attribute to the list of projection of a request. * For example: ** builder.addProjection("binarySetAttribute") * .addProjection("listAttr[0]") * .addProjection("mapAttr.name") * .addProjection("stringSetAttr") * ; **/ public ExpressionSpecBuilder addProjection(String path) { projections.add(new PathOperand(path)); return this; } /** * Fluent API to add the given attributes to the list of projection of a request. * For example: ** builder.addProjections("binarySetAttribute", "listAttr[0]", "mapAttr.name", "stringSetAttr"); **/ public ExpressionSpecBuilder addProjections(String ... paths) { for (String path: paths) addProjection(path); return this; } /** * Returns an expression specification for use in aDeleteItem
* request to DynamoDB. */ public DeleteItemExpressionSpec buildForDeleteItem() { return new DeleteItemExpressionSpec(this); } /** * Returns an expression specification for use in aGetItem
* request to DynamoDB. */ public GetItemExpressionSpec buildForGetItem() { return new GetItemExpressionSpec(this); } /** * Returns an expression specification for use in a query * request to DynamoDB. */ public QueryExpressionSpec buildForQuery() { return new QueryExpressionSpec(this); } /** * Returns an expression specification for use in a scan * request to DynamoDB. */ public ScanExpressionSpec buildForScan() { return new ScanExpressionSpec(this); } /** * Returns an expression specification for use in anUpdateItem
* request to DynamoDB. */ public UpdateItemExpressionSpec buildForUpdate() { return new UpdateItemExpressionSpec(this); } /** * Returns an expression specification for use in aPutItem
* request to DynamoDB. */ public PutItemExpressionSpec buildForPut() { return new PutItemExpressionSpec(this); } /** * Builds and returns the update expression to be used in a dynamodb * request; or null if there is none. */ String buildUpdateExpression(SubstitutionContext context) { StringBuilder sb = new StringBuilder(); for (Map.Entry> e: updates.entrySet()) { boolean firstOfUpdateType = true; for (UpdateAction expr: e.getValue()) { if (firstOfUpdateType) { firstOfUpdateType = false; final String operator = e.getKey(); if (sb.length() > 0) sb.append(" "); sb.append(operator).append(" "); } else { sb.append(", "); } sb.append(expr.asSubstituted(context)); } } return sb.toString(); } /** * Builds and returns the projection expression to be used in a dynamodb * GetItem request; or null if there is none. */ String buildProjectionExpression(SubstitutionContext context) { if (projections.size() == 0) return null; StringBuilder sb = new StringBuilder(); for (PathOperand projection : projections) { if (sb.length() > 0) sb.append(", "); sb.append(projection.asSubstituted(context)); } return sb.toString(); } /** * Builds and returns the condition expression to be used in a dynamodb * request; or null if there is none. */ String buildConditionExpression(SubstitutionContext context) { return condition == null ? null : condition.asSubstituted(context); } /** * Builds and returns the key condition expression to be used in a dynamodb * query request; or null if there is none. */ String buildKeyConditionExpression(SubstitutionContext context) { return keyCondition == null ? null : keyCondition.asSubstituted(context); } @Override public ExpressionSpecBuilder clone() { return new ExpressionSpecBuilder(this); } ////////////// static factory methods ////////////// /** * Returns an IfNotExists
object which represents an if_not_exists(path, operand) function call; used for building * expression. * ** "if_not_exists (path, operand) – If the item does not contain an attribute * at the specified path, then if_not_exists evaluates to operand; otherwise, * it evaluates to path. You can use this function to avoid overwriting an * attribute already present in the item." ** * @param pathOperand * path operand that refers to the attribute * @param operand * default value if the attribute doesn't exist */ staticIfNotExistsFunction if_not_exists( PathOperand pathOperand, Operand operand) { return new IfNotExistsFunction (pathOperand, operand); } /** * Returns an IfNotExists
object which represents an if_not_exists(path, operand) function call; used for building * expression. * ** "if_not_exists (path, operand) – If the item does not contain an attribute * at the specified path, then if_not_exists evaluates to operand; otherwise, * it evaluates to path. You can use this function to avoid overwriting an * attribute already present in the item." ** * @param path * document path to an attribute * @param defaultValue * default value if the attribute doesn't exist * * @return anIfNotExists
object for number (N) attribute. */ public static IfNotExistsFunctionif_not_exists(String path, Number defaultValue) { return if_not_exists(new PathOperand(path), new LiteralOperand( defaultValue)); } /** * Returns an IfNotExists
object which represents an if_not_exists(path, operand) function call; used for building * expression. * ** "if_not_exists (path, operand) – If the item does not contain an attribute * at the specified path, then if_not_exists evaluates to operand; otherwise, * it evaluates to path. You can use this function to avoid overwriting an * attribute already present in the item." ** * @param path * document path to an attribute * @param defaultValue * default value if the attribute doesn't exist * * @return anIfNotExists
object for binary (B) attribute. */ public static IfNotExistsFunction if_not_exists(String path, byte[] defaultValue) { return if_not_exists(new PathOperand(path), new LiteralOperand( defaultValue)); } /** * Returns anIfNotExists
object which represents an if_not_exists(path, operand) function call; used for building * expression. * ** "if_not_exists (path, operand) – If the item does not contain an attribute * at the specified path, then if_not_exists evaluates to operand; otherwise, * it evaluates to path. You can use this function to avoid overwriting an * attribute already present in the item." ** * @param path * document path to an attribute * @param defaultValue * default value if the attribute doesn't exist * * @return anIfNotExists
object for binary (B) attribute. */ public static IfNotExistsFunction if_not_exists(String path, ByteBuffer defaultValue) { return if_not_exists(new PathOperand(path), new LiteralOperand( defaultValue)); } /** * Returns anIfNotExists
object which represents an if_not_exists(path, operand) function call; used for building * expression. * ** "if_not_exists (path, operand) – If the item does not contain an attribute * at the specified path, then if_not_exists evaluates to operand; otherwise, * it evaluates to path. You can use this function to avoid overwriting an * attribute already present in the item." ** * @param path * document path to an attribute * @param defaultValue * default value if the attribute doesn't exist * * @return anIfNotExists
object for boolean (BOOL) attribute. */ public static IfNotExistsFunctionif_not_exists(String path, boolean defaultValue) { return if_not_exists(new PathOperand(path), new LiteralOperand( defaultValue)); } /** * Returns an IfNotExists
object which represents an if_not_exists(path, operand) function call; used for building * expression. * ** "if_not_exists (path, operand) – If the item does not contain an attribute * at the specified path, then if_not_exists evaluates to operand; otherwise, * it evaluates to path. You can use this function to avoid overwriting an * attribute already present in the item." ** * @param path * document path to an attribute * @param defaultValue * default value if the attribute doesn't exist * * @return anIfNotExists
object for binary set (BS) attribute. */ public static IfNotExistsFunctionif_not_exists(String path, byte[] ... defaultValue) { return if_not_exists(new PathOperand(path), new LiteralOperand( defaultValue)); } /** * Returns an IfNotExists
object which represents an if_not_exists(path, operand) function call; used for building * expression. * ** "if_not_exists (path, operand) – If the item does not contain an attribute * at the specified path, then if_not_exists evaluates to operand; otherwise, * it evaluates to path. You can use this function to avoid overwriting an * attribute already present in the item." ** * @param path * document path to an attribute * @param defaultValue * default value if the attribute doesn't exist * * @return anIfNotExists
object for binary set (BS) attribute. */ public static IfNotExistsFunctionif_not_exists(String path, ByteBuffer ... defaultValue) { return if_not_exists(new PathOperand(path), new LiteralOperand( defaultValue)); } /** * Returns an IfNotExists
object which represents an if_not_exists(path, operand) function call; used for building * expression. * ** "if_not_exists (path, operand) – If the item does not contain an attribute * at the specified path, then if_not_exists evaluates to operand; otherwise, * it evaluates to path. You can use this function to avoid overwriting an * attribute already present in the item." ** * @param path * document path to an attribute * @param defaultValue * default value if the attribute doesn't exist * * @return anIfNotExists
object for list (L) attribute. */ public static IfNotExistsFunctionif_not_exists(String path, List> defaultValue) { return if_not_exists(new PathOperand(path), new LiteralOperand( defaultValue)); } /** * Returns an IfNotExists
object which represents an if_not_exists(path, operand) function call; used for building * expression. * ** "if_not_exists (path, operand) – If the item does not contain an attribute * at the specified path, then if_not_exists evaluates to operand; otherwise, * it evaluates to path. You can use this function to avoid overwriting an * attribute already present in the item." ** * @param path * document path to an attribute * @param defaultValue * default value if the attribute doesn't exist * * @return anIfNotExists
object for map (M) attribute. */ public static IfNotExistsFunctionif_not_exists(String path, Map defaultValue) { return if_not_exists(new PathOperand(path), new LiteralOperand( defaultValue)); } /** * Returns an IfNotExists
object which represents an if_not_exists(path, operand) function call; used for building * expression. * ** "if_not_exists (path, operand) – If the item does not contain an attribute * at the specified path, then if_not_exists evaluates to operand; otherwise, * it evaluates to path. You can use this function to avoid overwriting an * attribute already present in the item." ** * @param path * document path to an attribute * @param defaultValue * default value if the attribute doesn't exist * * @return anIfNotExists
object for number set (NS) attribute. */ public static IfNotExistsFunctionif_not_exists(String path, Number ... defaultValue) { return if_not_exists(new PathOperand(path), new LiteralOperand( defaultValue)); } /** * Returns an IfNotExists
object which represents an if_not_exists(path, operand) function call; used for building * expression. * ** "if_not_exists (path, operand) – If the item does not contain an attribute * at the specified path, then if_not_exists evaluates to operand; otherwise, * it evaluates to path. You can use this function to avoid overwriting an * attribute already present in the item." ** * @param path * document path to an attribute * @param defaultValue * default value if the attribute doesn't exist * * @return anIfNotExists
object for string (S) attribute. */ public static IfNotExistsFunctionif_not_exists(String path, String defaultValue) { return if_not_exists(new PathOperand(path), new LiteralOperand( defaultValue)); } /** * Returns anIfNotExists
object which represents an if_not_exists(path, operand) function call; used for building * expression. * ** "if_not_exists (path, operand) – If the item does not contain an attribute * at the specified path, then if_not_exists evaluates to operand; otherwise, * it evaluates to path. You can use this function to avoid overwriting an * attribute already present in the item." ** * @param path * document path to an attribute * @param defaultValue * default value if the attribute doesn't exist * * @return anIfNotExists
object for string set (SS) attribute. */ public static IfNotExistsFunctionif_not_exists(String path, String ... defaultValue) { return if_not_exists(new PathOperand(path), new LiteralOperand( defaultValue)); } /** * Returns a ListAppend
object which represents a list_append(operand, operand) function call; used for building * expression. * ** "list_append(operand, operand) – This function evaluates to a list with a * new element added to it. You can append the new element to the start or * the end of the list by reversing the order of the operands." ** * @param path * document path to a list attribute * @param value * single value to be appended to the list attribute */ public staticListAppendFunction list_append(String path, T value) { LinkedList list = new LinkedList (); list.add(value); return list_append(path, list); } /** * Returns a ListAppend
object which represents a list_append(operand, operand) function call; used for building * expression. * ** "list_append(operand, operand) – This function evaluates to a list with a * new element added to it. You can append the new element to the start or * the end of the list by reversing the order of the operands." ** * @param path * document path to a list attribute * @param value * list of values to be appended to the list attribute */ public staticListAppendFunction list_append(String path, List extends T> value) { return new ListAppendFunction(L(path), new ListLiteralOperand(new LinkedList ( value))); } /** * Returns a ListAppend
object which represents a list_append(operand, operand) function call; used for building * expression. * ** "list_append(operand, operand) – This function evaluates to a list with a * new element added to it. You can append the new element to the start or * the end of the list by reversing the order of the operands." ** * @param value * list of values to be appended to * @param path * document path to a list attribute */ public staticListAppendFunction list_append(List extends T> value, String path) { return new ListAppendFunction(new ListLiteralOperand(new LinkedList (value)), L(path)); } // ///////////////////////// FunctionCondition factory methods /** * Returns a function condition (that evaluates to true if the attribute of the * specified path operand exists) for building condition expression. */ public static FunctionCondition attribute_exists( PathOperand pathOperand) { return new FunctionCondition("attribute_exists", pathOperand); } /** * Returns a function condition (that evaluates to true if the attribute at the * specified path exists) for building condition expression. */ public static FunctionCondition attribute_exists(String path) { return attribute_exists(new PathOperand(path)); } /** * Returns a function condition (that evaluates to true if the attribute of the * specified path operand does not exist) for building condition expression. */ public static FunctionCondition attribute_not_exists( PathOperand pathOperand) { return new FunctionCondition("attribute_not_exists", pathOperand); } /** * Returns a function condition (that evaluates to true if the attribute at the * specified path does not exist) for building condition expression. */ public static FunctionCondition attribute_not_exists(String path) { return attribute_not_exists(new PathOperand(path)); } /** * Returns a negation of the specified condition; used for building condition * expression. */ public static NegationCondition not(Condition cond) { return new NegationCondition(cond); } /** * Returns a RemoveAction
for removing the attribute with the * specified path from an item; used for building update expression. * * @param path * the document path to the attribute, where nested path elements * are assumed to be delimited by either "." or array indexing * such as "[1]". */ public static RemoveAction remove(String path) { return new PathOperand(path).remove(); } /** * Returns a path operand that refers to an attribute of some unspecified * data type; used for building expressions. * * @param path * the document path to the attribute, where nested path elements * are assumed to be delimited by either "." or array indexing * such as "[1]". */ public static PathOperand attribute(String path) { return new PathOperand(path); } /** * Creates a path operand that refers to a boolean attribute for the purpose of building expressions. * * @param path * the document path to the attribute, where nested path elements * are assumed to be delimited by either "." or array indexing * such as "[1]". */ public static BOOL BOOL(String path) { return new BOOL(path); } /** * Creates a path operand that refers to a NULL attribute for the purpose of building expressions. * * @param path * the document path to the attribute, where nested path elements * are assumed to be delimited by either "." or array indexing * such as "[1]". */ public static NULL NULL(String path) { return new NULL(path); } /** * Creates a path operand that refers to a binary attribute for the purpose of building expressions. * * @param path * the document path to the attribute, where nested path elements * are assumed to be delimited by either "." or array indexing * such as "[1]". */ public static B B(String path) { return new B(path); } /** * Creates a path operand that refers to a number attribute for the purpose of building expressions. * * @param path * the document path to the attribute, where nested path elements * are assumed to be delimited by either "." or array indexing * such as "[1]". */ public static N N(String path) { return new N(path); } /** * Creates a path operand that refers to a string attribute for the purpose of building expressions. * * @param path * the document path to the attribute, where nested path elements * are assumed to be delimited by either "." or array indexing * such as "[1]". */ public static S S(String path) { return new S(path); } /** * Creates a path operand that refers to a binary-set attribute for the purpose of building expressions. * * @param path * the document path to the attribute, where nested path elements * are assumed to be delimited by either "." or array indexing * such as "[1]". */ public static BS BS(String path) { return new BS(path); } /** * Creates a path operand that refers to a number-set attribute for the purpose of building expressions. * * @param path * the document path to the attribute, where nested path elements * are assumed to be delimited by either "." or array indexing * such as "[1]". */ public static NS NS(String path) { return new NS(path); } /** * Creates a path operand that refers to a string-set attribute for the purpose of building expressions. * * @param path * the document path to the attribute, where nested path elements * are assumed to be delimited by either "." or array indexing * such as "[1]". */ public static SS SS(String path) { return new SS(path); } /** * Creates a path operand that refers to a list attribute for the purpose of building expressions. * * @param path * the document path to the attribute, where nested path elements * are assumed to be delimited by either "." or array indexing * such as "[1]". */ public static L L(String path) { return new L(path); } /** * Creates a path operand that refers to a map attribute for the purpose of building expressions. * * @param path * the document path to the attribute, where nested path elements * are assumed to be delimited by either "." or array indexing * such as "[1]". */ public static M M(String path) { return new M(path); } /** * Returns an explicitly parenthesized condition, ie '(' condition ')' used * in building condition expressions. * * @see #_(Condition) */ public staticParenthesizedCondition parenthesize(Condition condition) { return ParenthesizedCondition.getInstance(condition); } /** * A short hand for calling {@link #parenthesize(Condition)} to explicitly * parenthesize a given condition for building condition expressions. */ public static ParenthesizedCondition _(Condition condition) { return parenthesize(condition); } }