/*
* Copyright 2015-2017 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.util.LinkedHashMap;
import java.util.Map;
/**
* An internal class to represent the substitution context for name maps and
* value maps.
* <p>
* To avoid attribute names that may conflict with the DynamoDB reserved words,
* the expressions builder will automatically transform every component of a
* document path into the use of an "expression attribute name" (that begins
* with "#") as a placeholder. The actual mapping from the
* "expression attribute name" to the actual attribute name is automatically
* taken care of by the builder in a "name map". Similarly, the actual mapping
* from the "expression attribute value" (that begins with ":") to the actual
* attribute value is automatically taken care of by the builder in a
* "value map". See more information at <a href=
* "http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ExpressionPlaceholders.html"
* >Using Placeholders for Attribute Names and Values</a>.
*/
final class SubstitutionContext {
private final Map<String, Integer> nameToToken =
new LinkedHashMap<String, Integer>();
private final Map<Object, Integer> valueToToken =
new LinkedHashMap<Object, Integer>();
/**
* Returns the name token for the given name, creating a new token as
* necessary.
*/
String nameTokenFor(String name) {
Integer token = nameToToken.get(name);
if (token == null) {
token = nameToToken.size();
nameToToken.put(name, token);
}
return "#" + token;
}
/**
* Returns the value token for the given value, creating a new token as
* necessary.
*/
String valueTokenFor(Object value) {
Integer token = valueToToken.get(value);
if (token == null) {
token = valueToToken.size();
valueToToken.put(value, token);
}
return ":" + token;
}
Map<String, String> getNameMap() {
if (nameToToken.size() == 0)
return null;
Map<String, String> out = new LinkedHashMap<String, String>();
for (Map.Entry<String,Integer> e: nameToToken.entrySet()) {
out.put("#" + e.getValue(), e.getKey());
}
return out;
}
Map<String, Object> getValueMap() {
if (valueToToken.size() == 0)
return null;
Map<String, Object> out = new LinkedHashMap<String, Object>();
for (Map.Entry<Object,Integer> e: valueToToken.entrySet()) {
out.put(":" + e.getValue(), e.getKey());
}
return out;
}
// For testing
int numNameTokens() {
return nameToToken.size();
}
// For testing
int numValueTokens() {
return valueToToken.size();
}
// For testing
String getNameByToken(int token) {
for (Map.Entry<String, Integer> e: nameToToken.entrySet()) {
if (e.getValue().intValue() == token)
return e.getKey();
}
return null;
}
// For testing
Object getValueByToken(int token) {
for (Map.Entry<Object, Integer> e: valueToToken.entrySet()) {
if (e.getValue().intValue() == token)
return e.getKey();
}
return null;
}
@Override
public String toString() {
return "name-tokens: " + nameToToken.toString() + "\n"
+ "value-tokens: " + valueToToken.toString();
}
}