package org.xmlsh.aws.util;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import net.sf.saxon.s9api.Axis;
import net.sf.saxon.s9api.QName;
import net.sf.saxon.s9api.XdmItem;
import net.sf.saxon.s9api.XdmNode;
import net.sf.saxon.s9api.XdmSequenceIterator;
import net.sf.saxon.trans.XPathException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.xmlsh.core.InvalidArgumentException;
import org.xmlsh.core.Options;
import org.xmlsh.core.UnexpectedException;
import org.xmlsh.core.UnimplementedException;
import org.xmlsh.core.XValue;
import org.xmlsh.util.Base64;
import org.xmlsh.util.JavaUtils;
import org.xmlsh.util.StringPair;
import org.xmlsh.util.Util;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.model.AttributeValue;
public class DDBTypes implements INameAttrExpr {
private static Logger mLogger = LogManager.getLogger();
public interface INameMap<T> extends Map<String,T> {
}
public static class NameMap<T> extends AbstractMap<String,T> implements INameMap<T> {
HashMap<String,T> map = new HashMap<String,T>();
NameMap() {
}
NameMap(Map<String,T> map) {
this.map.putAll( map );
}
@Override
public Set<java.util.Map.Entry<String, T>> entrySet() {
return map.entrySet();
}
@Override
public T put(String key, T value) {
// TODO Auto-generated method stub
return map.put(key, value);
}
}
// Interfaces to identify pre parsed values
public interface INameStringMap extends INameMap<String> {
}
public static class NameStringMap extends NameMap<String> implements INameStringMap {
public NameStringMap() {}
public NameStringMap(Map<String, String> map) {
super(map);
}}
public interface INameObjectMap extends INameMap<Object> { }
public static class NameObjectMap extends NameMap<Object> implements INameObjectMap {
public NameObjectMap() {}
public NameObjectMap(Map<String,Object> map) {
super(map);
}}
public interface IAttrNameExpr extends INameStringMap { }
public static class AttrNameExpr extends NameMap<String> implements IAttrNameExpr {
public AttrNameExpr() {
}
public AttrNameExpr(Map<String,String> map) {
super(map);
}
public AttrNameExpr(String name , String value ) {
super( Collections.singletonMap(name, value));
}
}
public interface INameAttrValueMap extends INameMap<AttributeValue> { }
public static class NameAttrValueMap extends NameMap<AttributeValue> implements INameAttrValueMap {
public NameAttrValueMap(Map<String, AttributeValue> map) {
super(map);
}
public NameAttrValueMap() {
}}
public interface IAttrValueExpr extends INameAttrValueMap {}
public static class AttrValueExpr extends NameMap<AttributeValue> implements IAttrValueExpr {
public AttrValueExpr(Map<String,AttributeValue> map) {
super(map);
}
public AttrValueExpr() {
}
public AttrValueExpr(String string, AttributeValue value) {
super( Collections.singletonMap(string, value));
}}
public interface IAttrObjectExpr extends INameObjectMap { }
public static class AttrObjectExpr extends NameMap<Object> implements IAttrObjectExpr {
public AttrObjectExpr(Map<String,Object> map) {
super(map);
}}
public interface IKeyAttrValueMap extends IAttrValueExpr { }
public static class KeyAttrValueMap extends NameMap<AttributeValue> implements IKeyAttrValueMap {
public KeyAttrValueMap(Map<String,AttributeValue> map) {
super(map);
}
KeyAttrValueMap() {}
}
public enum AttrType {
S, N, B, SS, NS, BS, M, L, NULL, BOOL;
public String toString() {
return this.name();
}
public static AttrType parseType(String name) {
mLogger.debug("parseType: " + name);
return parseType(name, null);
}
public static AttrType parseType(String name, AttrType def) {
if (name == null)
return def;
for (AttrType n : values())
if (n.name().equals(name))
return n;
return def;
}
public static AttrType parseType(XdmNode node, AttrType def) {
if (node == null)
return def;
mLogger.debug("parseType: " + node + "def: " + def );
switch (node.getNodeKind()) {
case ATTRIBUTE:
// if( node.getNodeName().getLocalName().equals("type"))
return parseType(node.getStringValue(), def);
case ELEMENT:
String stype = node.getAttributeValue(new QName("type"));
return parseType(stype, def);
case TEXT:
default:
return parseType(node.getStringValue(), def);
}
}
public static AttrType parseType(XdmNode node) {
mLogger.debug("parseType: " + node );
return parseType(node, S);
}
public AttributeValue newAtomicValue( String s) throws UnexpectedException, InvalidArgumentException {
assert( s != null);
if( s.isEmpty() )
throw new InvalidArgumentException("Atomic attribute values may not be empty: type: " + name() );
switch (this) {
case N:
return new AttributeValue().withN(s);
case S:
return new AttributeValue().withS(s);
case BOOL:
return new AttributeValue().withBOOL(Util.parseBoolean(s));
case NULL:
return new AttributeValue().withNULL(Util.parseBoolean(s));
default:
throw new UnexpectedException("Unexpected type for newAtomicValue: " + this.name());
}
}
public static AttrType fromValue( AttributeValue av) {
if (av.getS() != null) return S;
if (av.getN() != null) return N ;
if (av.getB() != null) return B ;
if (av.getSS() != null) return SS;
if (av.getNS() != null) return NS;
if (av.getBS() != null) return BS;
if (av.getM() != null) return M;
if (av.getL() != null) return L;
if (av.isNULL() != null)return NULL;
if (av.isBOOL() != null) return BOOL;
return S;
}
public AttributeValue validate( AttributeValue value ) throws InvalidArgumentException, UnexpectedException{
switch( this ){
case B:
notNull( value.getB() ); break ;
case BOOL:
notNull( value.getBOOL() ); break ;
case BS:
notEmpty( value.getBS() ); break ;
case L:
notNull( value.getL()); break ;
case M:
notNull( value.getM() ); break ;
case N:
notEmpty( value.getN() ); break ;
case NS:
notEmpty( value.getNS() ); break ;
case NULL:
notNull( value.getNULL() ); break ;
case S:
notEmpty( value.getS() ); break ;
case SS:
notEmpty( value.getSS() ) ;
break ;
default:
throw new UnexpectedException("Unexpected type for newAtomicValue: " + this.name());
}
return value ;
}
private void notEmpty(String s) throws InvalidArgumentException {
notNull(s);
if( s.isEmpty() )
throw new InvalidArgumentException("Attribute type is not allowed to be empty. Type: " + name() );
}
private <T> void notEmpty(Collection<T> c) throws InvalidArgumentException {
notNull(c);
if( c.isEmpty() )
throw new InvalidArgumentException("Attribute type is not allowed to be empty. Type: " + name() );
}
private <T> void notNull(T o) throws InvalidArgumentException {
if( o == null )
throw new InvalidArgumentException("Attribute type is not allowed to be null. Type: " + name() );
}
}
public static AttributeValue parseAttrValue(XValue xv) throws UnexpectedException, UnimplementedException,
IOException, InvalidArgumentException {
if( xv.isInstanceOf(AttributeValue.class))
return xv.asInstanceOf( AttributeValue.class);
if( xv.isXdmNode() )
return parseAttrValue( xv.asXdmNode() );
if( xv.isEmpty() )
return new AttributeValue().withNULL( true );
if( xv.isAtomic()) {
String value ;
if( xv.isJson() )
value = xv.asJson().toString(); // ????
else
value = xv.toString() ;
return parseAttrValue(value);
}
return parseAttrValue( parseAttrTypeFromValue(xv) , xv );
}
public static AttributeValue parseAttrValue(XdmNode node) throws UnexpectedException, UnimplementedException, IOException, InvalidArgumentException {
mLogger.debug("XdmNode:" + node.toString());
AttrType type = parseAttrType(node);
return type.validate( parseAttrValue(type, node));
}
protected static AttrType parseAttrType(XdmNode node) {
return AttrType.parseType(node);
}
public static AttributeValue parseAttrValue(AttrType type, XdmNode node) throws UnexpectedException, UnimplementedException, IOException, InvalidArgumentException {
mLogger.debug("AttrType: " + type.toString() + " XdmNode: " + node.toString());
switch (type) {
case N:
case S:
case BOOL:
case NULL:
return type.newAtomicValue( DDBTypes.parseStringValue( node ) );
case NS:
return type.validate( new AttributeValue().withNS( DDBTypes.parseNS(node) ));
case SS:
return type.validate( new AttributeValue().withSS(DDBTypes.parseSS(node)));
case B:
return type.validate( new AttributeValue().withB(DDBTypes.parseBinary(node)));
case BS:
return type.validate( new AttributeValue().withBS(DDBTypes.parseBS(node)));
case L:
return type.validate( new AttributeValue().withL(DDBTypes.parseL(node)));
case M:
return type.validate(new AttributeValue().withM(DDBTypes.parseM(node)));
default:
throw new UnexpectedException("Unknown type: " + type.toString());
}
}
private static INameAttrValueMap parseM(XdmNode node) throws UnimplementedException, UnexpectedException, InvalidArgumentException, IOException {
assert( node != null );
XdmSequenceIterator iter = node.axisIterator(Axis.CHILD);
INameAttrValueMap list = new NameAttrValueMap();
if (iter != null) {
while (iter.hasNext()){
XdmItem item = iter.next();
list.putAll( parseAttrNameValue( XValue.newXValue(item) ) );
}
}
return list ;
}
private static Collection<AttributeValue> parseL(XdmNode node) throws UnexpectedException, UnimplementedException, IOException, InvalidArgumentException {
assert( node != null );
XdmSequenceIterator iter = node.axisIterator(Axis.CHILD);
List<AttributeValue> list = new ArrayList<AttributeValue>();
if (iter != null) {
while (iter.hasNext())
list.add(parseAttrValue( (XdmNode) iter.next()));
}
return list ;
}
private static Collection<ByteBuffer> parseBS(XdmNode node) throws IOException {
return parseBS( XValue.newXValue( node )) ;
}
private static ByteBuffer parseBinary(XdmNode node) throws IOException {
return DDBTypes.parseBinary( node.getStringValue() );
}
private static Collection<String> parseSS(XdmNode node) {
assert( node != null );
Set<String> set = new HashSet<String>();
XdmSequenceIterator iter = node.axisIterator(Axis.CHILD);
if (iter != null) {
while (iter.hasNext())
set.add( iter.next().getStringValue() );
}
return set;
}
private static Collection<String> parseNS(XdmNode node) {
return parseSS(node);
}
private static String parseStringValue(XdmNode node) {
String value = null;
switch( node.getNodeKind() ){
case ATTRIBUTE:
case ELEMENT:
value = node.getAttributeValue(new QName("value"));
default:
case TEXT:
}
if( value == null )
value = node.getStringValue();
return value ;
}
/*
* Attribute Name/Type Type is optional and defaults to "S" and stored in
* Left Name is stored in right
*/
public static class NameType {
String name;
AttrType type;
private void _init( String name , AttrType type ){
mLogger.debug("_init: name: " + name + "type: " + type);
this.name = name ;
this.type = type ;
}
private void _init(String def) {
/*
* StringPair pair = new StringPair( def , ':'); name =
* pair.getRight(); type = pair.hasLeft() ? pair.getLeft() : "S";
*/
_init( def.trim(), AttrType.S);
}
NameType(String def) {
_init(def);
}
NameType(String name, AttrType type) {
_init(name,type);
}
NameType(String name, String type) {
_init(name,AttrType.parseType(type));
}
NameType(XValue xv) throws InvalidArgumentException {
_init(xv);
}
private void _init(XValue xv) throws InvalidArgumentException {
mLogger.debug("_init: " + xv );
_init( DDBTypes.parseName(xv) , parseAttrTypeFromValue(xv));
}
NameType(XdmNode node) {
_init(node);
}
public NameType(NameType nt) {
this.name = nt.name;
this.type = nt.type;
}
private void _init(XdmNode node) {
mLogger.debug("_init: " + node );
AttrType _type = AttrType.parseType(node);
String _name = parseName(node);
_init(_name,_type);
}
public static String parseName(XdmNode node) {
String _name;
switch (node.getNodeKind()) {
case ELEMENT:
_name = node.getAttributeValue(new QName("name"));
if (_name == null)
_name = node.getNodeName().getLocalName();
break;
case TEXT:
case ATTRIBUTE:
default:
_name = node.getStringValue();
}
return _name;
}
public static String parseName(String string) {
return string.trim();
}
String getName() {
return name;
}
AttrType getType() {
return type;
}
String getTypeName() {
return type.toString();
}
public String toString() {
return "{" + type.toString() + "}" + name.toString();
}
}
public static class NameTypeValue extends NameType {
AttributeValue value;
NameTypeValue(NameType nt , AttributeValue value) {
super(nt);
this.value = value ;
}
NameTypeValue(String name, AttrType type, AttributeValue value) {
super(name, type);
mLogger.debug("Value: " + value);
this.value = value;
}
public NameTypeValue(XdmNode node) throws UnexpectedException, UnimplementedException, IOException, InvalidArgumentException {
super(node);
this.value = parseAttrValue(getType(), node);
mLogger.debug("Value: " + value);
}
public INameAttrValueMap asNameValueMap(){
return new NameAttrValueMap( Collections.singletonMap(getName(), value));
}
}
/*
public static AttributeValue parseAttributeValue(XdmItem item) throws UnexpectedException {
mLogger.debug("XdmItem: " + item.toString());
if (item instanceof XdmNode)
return parseAttributeValue((XdmNode) item);
return parseAttributeValue(item.getStringValue());
}
private static AttributeValue parseAttributeValue(String s) throws UnexpectedException, InvalidArgumentException {
return parseAttributeValue(S, s);
}
*/
public static AttrType parseAttrType(XValue xv) throws InvalidArgumentException {
if( xv.isInstanceOf(AttrType.class))
return xv.asInstanceOf(AttrType.class);
mLogger.debug("XValue: " + xv.toString());
if (xv.isXdmNode())
return AttrType.parseType(xv.asXdmNode());
if (xv.isNull() || xv.isEmpty() )
return AttrType.NULL;
throw new InvalidArgumentException("Unexpected type for attribute: " + xv.toString() + " type: "
+ xv.javaTypeName());
}
public static AttrType parseAttrTypeFromValue(XValue xv) throws InvalidArgumentException {
if( xv.isInstanceOf(AttrType.class))
return xv.asInstanceOf(AttrType.class);
mLogger.debug("XValue: " + xv.toString());
if (xv.isXdmNode())
return AttrType.parseType(xv.asXdmNode());
if (xv.isString())
return guessAttrType( xv.toString() );
if (xv.isNull() || xv.isEmpty() )
return AttrType.NULL;
if( xv.isJson())
return guessAttrType( xv.asJson().toString());
if (xv.isAtomic()) {
return guessAttrType( xv.toString());
}
if( xv.javaTypeName() != null )
return AttrType.L;
throw new InvalidArgumentException("Unexpected type for attribute: " + xv.toString() + " type: "
+ xv.javaTypeName());
}
protected static AttributeValue parseAttrValue(String stype, XValue xv) throws UnexpectedException,
UnimplementedException, IOException, InvalidArgumentException {
mLogger.debug("Type: " + stype + " XValue: " + xv.toString());
return DDBTypes.parseAttrValue(AttrType.parseType(stype, AttrType.S), xv);
}
public static AttributeValue parseAttrValue(String s) throws UnexpectedException, UnimplementedException, InvalidArgumentException, IOException
{
return parseAttrValue( guessAttrType(s) , s);
}
// Guess a type from a string value
private static AttrType guessAttrType(String s) {
if( s.startsWith("{") )
return AttrType.M;
if( s.startsWith("["))
return AttrType.L;
if( JavaUtils.isNumber(s))
return AttrType.N;
return AttrType.S;
}
public static AttributeValue parseAttrValue(XValue type, XValue xv) throws UnexpectedException, UnimplementedException, InvalidArgumentException, IOException
{
return parseAttrValue( parseAttrType(type) , xv );
}
public static AttributeValue parseAttrValue(AttrType type, XValue xv) throws UnexpectedException,
UnimplementedException, IOException, InvalidArgumentException {
mLogger.debug("Type: " + type + " XValue: " + xv.toString());
if( xv.isXdmNode())
return parseAttrValue( type , xv.asXdmNode() );
switch (type) {
case N:
case S:
case BOOL:
case NULL:
return type.newAtomicValue(xv.toString());
case NS:
return new AttributeValue().withNS(DDBTypes.parseNS(xv));
case SS:
return new AttributeValue().withSS(DDBTypes.parseSS(xv));
case B:
return new AttributeValue().withB(DDBTypes.parseBinary(xv));
case BS:
return new AttributeValue().withBS(DDBTypes.parseBS(xv));
case L:
return new AttributeValue().withL(DDBTypes.parseL(xv));
case M:
return new AttributeValue().withM(DDBTypes.parseM(xv));
default:
throw new UnexpectedException("Unknown type: " + type.toString());
}
}
/*
* Parse a set of attributes [type:]Name Value ... -> any value of type
*
* <attribute name="name" type="type"> value <attribute>
*/
public static INameAttrValueMap parseAttrNameValue(List<XValue> args)
throws IOException, UnexpectedException, UnimplementedException, InvalidArgumentException {
mLogger.debug(" parseAttributeValues(List<XValue>) ");
INameAttrValueMap attrs = new NameAttrValueMap();
for (XValue arg : args) {
attrs.putAll(parseAttrNameValue(arg));
}
return attrs;
}
public static INameAttrValueMap parseAttrNameValue(XValue arg) throws UnexpectedException, InvalidArgumentException, UnimplementedException, IOException {
if( arg.isInstanceOf(INameAttrValueMap.class))
return arg.asInstanceOf(INameAttrValueMap.class);
if( arg.isXdmNode())
return parseNameTypeValue( arg.asXdmNode() ).asNameValueMap() ;
return parseNameTypeValue(arg).asNameValueMap() ;
}
// attr = name|nametype / value
public static INameAttrValueMap parseAttrNameValue(XValue name, XValue xv)
throws UnimplementedException, UnexpectedException, IOException, InvalidArgumentException {
mLogger.debug("parseAttributeValues(Name: " + name + " XValue: " + xv);
AttributeValue av = parseAttrValue(xv);
return (new NameTypeValue( name.toString() , AttrType.fromValue(av) , av )).asNameValueMap();
}
// Attribute = name , type , value
public static INameAttrValueMap parseAttrNameValue(XValue xname, XValue xtype , XValue xv)
throws UnimplementedException, UnexpectedException, IOException, InvalidArgumentException {
String name = parseName( xname );
AttrType type = parseAttrType(xtype);
AttributeValue av = parseAttrValue(xv);
return (new NameTypeValue(name , type , av )).asNameValueMap();
}
public static DDBTypes.NameTypeValue parseNameTypeValue(String s) throws InvalidArgumentException,
UnexpectedException {
mLogger.debug("parseNameTypeValue: " + s);
// Name=value
INameStringMap nv = DDBTypes.parseNameStringValue(s);
assert( nv.size() == 1);
String name = nv.keySet().iterator().next();
DDBTypes.NameType ant = new DDBTypes.NameType( name );
return new NameTypeValue(name, ant.getType(), DDBTypes.parseAttrValue(ant.type, nv.get(name)));
}
static NameTypeValue parseNameTypeValue(XValue xv) throws UnexpectedException, InvalidArgumentException, UnimplementedException, IOException {
if( xv.isInstanceOf(NameTypeValue.class))
return xv.asInstanceOf(NameTypeValue.class);
if( xv.isXdmNode())
return parseNameTypeValue(xv.asXdmNode());
return parseNameTypeValue( xv.toString() );
}
static INameAttrValueMap parseM(XValue xv)
throws UnimplementedException {
throw new UnimplementedException("Map type unimplemented");
}
static DDBTypes.NameTypeValue parseNameTypeValue(XdmNode node) throws UnexpectedException, InvalidArgumentException, UnimplementedException, IOException {
mLogger.debug("parseNameTypeValue: " + node.toString());
DDBTypes.NameType ant = new DDBTypes.NameType(node);
AttributeValue av = parseAttrValue(ant.getType(), node);
return new DDBTypes.NameTypeValue(ant.name, ant.getType(), av);
}
static Collection<AttributeValue> parseL(XValue xv)
throws UnimplementedException, UnexpectedException, InvalidArgumentException, IOException {
mLogger.debug("parseL: " + xv);
if( xv.isNull() || xv.isEmpty() )
return Collections.emptyList();
// Lists - xv is the parent - parse children if it ( using
// parseL(List<XValue> if wanting to treat xv as the list contens
if (xv.isXdmNode()) {
return parseL( xv.asXdmNode() );
}
List<XValue> list = xv.asXList() ;
List<AttributeValue> alist = new ArrayList<AttributeValue>(list.size() );
for ( XValue v : list )
alist.add( parseAttrValue(v));
return alist ;
}
protected static Collection<ByteBuffer> parseBS(XValue xv) throws IOException {
ArrayList<ByteBuffer> ret = new ArrayList<ByteBuffer>();
for (String s : xv.asStringList())
ret.add(DDBTypes.parseBinary(s));
return ret;
}
static ByteBuffer parseBinary(XValue xv) throws IOException {
if( xv.isInstanceOf(ByteBuffer.class))
return xv.asInstanceOf(ByteBuffer.class);
return DDBTypes.parseBinary(xv.toString());
}
protected static ByteBuffer parseBinary(String s) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
Base64.InputStream b64 = new Base64.InputStream(
new ByteArrayInputStream(s.getBytes("UTF8")), Base64.DECODE);
Util.copyStream(b64, bos);
b64.close();
return ByteBuffer.wrap(bos.toByteArray());
}
public static Collection<String> parseNS(XValue xv) {
return DDBTypes.parseSS(xv); // numbers
}
protected static Collection<String> parseSS(XValue xv) {
mLogger.debug("parseSS: " + xv);
return xv.asStringList();
}
public static IKeyAttrValueMap parseKey(XValue xv) throws UnexpectedException,
UnimplementedException, IOException, InvalidArgumentException {
if( xv.isInstanceOf( IKeyAttrValueMap.class))
return xv.asInstanceOf(IKeyAttrValueMap.class);
IKeyAttrValueMap attrs = new KeyAttrValueMap() { };
DDBTypes.NameTypeValue ntv = null;
mLogger.debug("parseKey: " + xv);
if (xv.isXdmNode()) {
ntv = parseNameTypeValue(xv.asXdmNode());
}
else if (xv.isAtomic() || xv.isString()) {
ntv = parseNameTypeValue(xv.toString());
} else
throw new InvalidArgumentException("Unexpected type for attribute: " + xv.javaTypeName() + " "
+ xv.toString());
attrs.put(ntv.getName(), ntv.value);
return attrs;
}
static AttributeValue parseAttrValue(AttrType type, String value) throws UnexpectedException, InvalidArgumentException {
switch( type ) {
case M :
return parseJsonM( value );
case L:
return parseL( value );
default :
return type.newAtomicValue(value);
}
}
private static AttributeValue parseL(String value) throws InvalidArgumentException {
throw new InvalidArgumentException(
"parseL not implemened : " + value );
}
private static AttributeValue parseJsonM(String value) {
return new AttributeValue().withM( com.amazonaws.services.dynamodbv2.document.internal.InternalUtils.toAttributeValues( Item.fromJSON(value) ) );
}
public static IKeyAttrValueMap parseKey(XValue name, XValue value)
throws UnexpectedException, UnimplementedException, IOException,
InvalidArgumentException {
mLogger.debug("parseKey: name: " + name + "value: " + value );
return new KeyAttrValueMap(parseAttrNameValue(name, value));
}
protected static INameStringMap parseNameValue(XValue xv) throws InvalidArgumentException {
mLogger.debug("parseNameValue: " + xv );
if( xv.isInstanceOf(INameStringMap.class))
return xv.asInstanceOf(INameStringMap.class);
// placeholder=literal
if (xv.isAtomic()) {
return parseNameStringValue(xv.toString());
} else
throw new InvalidArgumentException(
"Unexpected attribute name expression. expected 'placeholder=literal' : " + xv.toString());
}
public static INameStringMap parseNameStringValue(String s) throws InvalidArgumentException {
mLogger.debug("parseNameValue: " + s );
if( s.startsWith("{")){
Map<String, Object> map = Item.fromJSON(s).asMap();
INameStringMap smap = new NameStringMap();
for( String key : map.keySet() )
smap.put(key, map.get(key).toString() );
return smap;
}
else if( s.contains("=") ){
StringPair keypair = new StringPair(s,'=');
if( keypair.hasLeft() )
return new NameStringMap(Collections.singletonMap( keypair.getLeft() , keypair.getRight() ));
}
throw new InvalidArgumentException( "Unexpected attribute name expression. expected 'placeholder=literal' : " + s.toString());
}
public static IAttrNameExpr parseAttrNameExprs(List<XValue> nameExprs)
throws InvalidArgumentException, UnexpectedException, UnimplementedException, IOException {
mLogger.debug("parseAttrNameExprs(List<XValue>): " );
IAttrNameExpr map = new AttrNameExpr();
for (XValue v : nameExprs) {
map.putAll( parseAttrNameExpr(v));
}
return map;
}
public static IAttrNameExpr parseAttrNameExpr(XValue v) throws UnexpectedException, InvalidArgumentException, UnimplementedException, IOException {
if( v.isInstanceOf( IAttrNameExpr.class ) )
return v.asInstanceOf( IAttrNameExpr.class );
else
return new AttrNameExpr( parseNameValues(v));
}
public static INameStringMap parseNameValues(XValue xv) throws InvalidArgumentException, UnexpectedException, UnimplementedException, IOException {
if( xv.isInstanceOf(INameStringMap.class))
return xv.asInstanceOf(INameStringMap.class);
if( xv.isInstanceOf(INameStringMap.class))
return xv.asInstanceOf(INameStringMap.class);
if( xv.isAtomic() )
return parseNameValue( xv );
if( xv.isJson() ){
return parseNameStringValue( xv.asJson().toString() ) ;
}
if( xv.isXdmNode()) {
INameStringMap map = new NameStringMap();
DDBTypes.NameTypeValue ntv = DDBTypes.parseNameTypeValue(xv);
map.put( ntv.getName() ,ntv.value.toString() );
return map ;
}
throw new InvalidArgumentException("expected string , xml or json: " + xv.javaTypeName() );
}
protected static INameObjectMap parseAttrValueObjectMap(XValue v) throws InvalidArgumentException {
if( v.isInstanceOf(INameObjectMap.class))
return v.asInstanceOf(INameObjectMap.class);
if( v.isString()){
return DDBTypes.parseAttrValueObjectMap( v.toString().trim() );
} else
if( v.isJson() )
return DDBTypes.parseAttrValueObjectMap( v.asJson().toString() );
throw new InvalidArgumentException("expected string or json: " + v.javaTypeName() );
}
// Name/Values for attribute expressions in Docuemnt mode
protected static INameObjectMap parseAttrValueObjectMap(List<XValue> values) throws InvalidArgumentException {
INameObjectMap map = new NameObjectMap();
for( XValue v : values )
map.putAll( parseAttrValueObjectMap( v ) );
return map;
}
protected static INameObjectMap parseAttrValueObjectMap( String s) throws InvalidArgumentException{
if( s.startsWith("{"))
return new NameObjectMap( Item.fromJSON(s).asMap());
else if( s.contains("=") ){
StringPair keypair = new StringPair(s,'=');
if( keypair.hasLeft() )
return new NameObjectMap(Collections.singletonMap( keypair.getLeft() , AWSDDBCommand.parseToJavaValue(keypair.getRight())));
}
throw new InvalidArgumentException("name value expect name=value: " + s );
}
protected static Item parseItem(List<XValue> args) throws InvalidArgumentException {
INameObjectMap values = parseAttrValueObjectMap( args );
return Item.fromMap(values);
}
public static IAttrNameExpr parseAttrNameExprs(Options opts) throws InvalidArgumentException, UnexpectedException, UnimplementedException, IOException {
if( opts.hasOpt("attr-name-expr"))
return parseAttrNameExprs(
Util.expandSequences(
opts.getOptValues("attr-name-expr")));
return null;
}
public static INameObjectMap parseKeyValueObjectOptions(Options opts)
throws InvalidArgumentException, UnexpectedException,
UnimplementedException, IOException, XPathException {
INameObjectMap keys = new NameObjectMap();
if (opts.hasOpt("key"))
keys.putAll( parseAttrValueObjectMap( opts.getOptValue("key") ));
if (opts.hasOpt("key-name")) {
List<XValue> keyValues = opts.getOptValues("key-value");
int i = 0;
for (XValue keyName : opts.getOptValues("key-name"))
keys.put( keyName.toString() , parseToJavaValue( keyValues.get(i++) ));
}
return keys;
}
public static IAttrObjectExpr parseAttrValueObjectExprs(Options opts) throws InvalidArgumentException {
if( opts.hasOpt("attr-value-expr"))
return new AttrObjectExpr( parseAttrValueObjectMap(Util.expandSequences(opts.getOptValues("attr-value-expr"))));
return null;
}
public static IAttrValueExpr parseAttrValueExprs(Options opts) throws InvalidArgumentException, UnexpectedException, UnimplementedException, IOException {
if( opts.hasOpt("attr-value-expr"))
return new AttrValueExpr( parseAttrValueExprs(Util.expandSequences(opts.getOptValues("attr-value-expr"))));
return null;
}
public static IAttrValueExpr parseAttrValueExprs(List<XValue> valueExprs) throws InvalidArgumentException, UnexpectedException, UnimplementedException, IOException {
IAttrValueExpr map = new AttrValueExpr();
for (XValue v : valueExprs) {
map.putAll( parseAttrValueExpr(v));
}
return map;
}
public static IAttrValueExpr parseAttrValueExpr(XValue v) throws UnexpectedException, InvalidArgumentException, UnimplementedException, IOException {
if( v.isInstanceOf( IAttrValueExpr.class ) )
return v.asInstanceOf( IAttrValueExpr.class );
else
return new AttrValueExpr( parseAttrNameValue(v));
}
public static INameObjectMap parseItemValueObject(Options opts) throws InvalidArgumentException, UnexpectedException,
UnimplementedException, IOException, XPathException {
INameObjectMap item = parseKeyValueObjectOptions(opts);
if( opts.hasRemainingArgs() )
item.putAll(parseAttrValueObjectMap( opts.getRemainingArgs() ));
return item;
}
public static Object parseToJavaValue(XValue xv) throws XPathException, InvalidArgumentException, UnexpectedException {
if( xv == null || xv.isNull() )
return null ;
if( xv.isEmpty() )
return null ;
if( xv.isJson() )
return xv.asJson();
if( xv.isString())
return AWSDDBCommand.parseToJavaValue( xv.toString());
Object obj = xv.getJavaNative();
if( obj != null && JavaUtils.isStringClass(obj.getClass()))
return AWSDDBCommand.parseToJavaValue( obj.toString() );
return obj;
}
public static IAttrNameExpr addNamePrefix( IAttrNameExpr exprs ) {
IAttrNameExpr ret = null ;
for( Entry<String, String> e : exprs.entrySet() ) {
if( ! e.getKey().startsWith( "#" ) ) {
if( ret == null) ret = new AttrNameExpr();
ret.put( "#" + e.getKey() , e.getValue() );
}
}
return ret == null ? exprs : ret ;
}
public static IAttrValueExpr addValuePrefix( IAttrValueExpr exprs ) {
IAttrValueExpr ret = null ;
for( Entry<String, AttributeValue> e : exprs.entrySet() ) {
if( ! e.getKey().startsWith( ":" ) ) {
if( ret == null) ret = new AttrValueExpr();
ret.put( ":" + e.getKey() , e.getValue() );
}
}
return ret == null ? exprs : ret ;
}
public static String parseName(XValue xv) throws InvalidArgumentException {
if (xv.isXdmNode()) {
return NameType.parseName( xv.asXdmNode() );
}
else if (xv.isString())
return NameType.parseName( xv.toString() );
else
throw new InvalidArgumentException(
"Unexpected argument type for attribute: " + xv.javaTypeName());
}
}