IndexedAccessExpression extends BaseExpression { @Override public Object evaluateUnsafe(EvaluationContext context) { final Object idxObj = this.index.evaluateUnsafe(context); final Object indexable = indexableObject.evaluateUnsafe(context); if (idxObj == null || indexable == null) { return null; } if (idxObj instanceof Long) { int idx = Ints.saturatedCast((long) idxObj); if (indexable.getClass().isArray()) { return Array.get(indexable, idx); } else if (indexable instanceof List) { return ((List) indexable).get(idx); } else if (indexable instanceof Iterable) { return Iterables.get((Iterable) indexable, idx); } throw new IllegalArgumentException("Object '" + indexable + "' is not an Array, List or Iterable."); } else if (idxObj instanceof String) { final String idx = idxObj.toString(); if (indexable instanceof Map) { return ((Map) indexable).get(idx); } throw new IllegalArgumentException("Object '" + indexable + "' is not a Map."); } throw new IllegalArgumentException("Index '" + idxObj + "' is not a Long or String."); } IndexedAccessExpression(Token start, Expression indexableObject, Expression index); @Override boolean isConstant(); @Override Object evaluateUnsafe(EvaluationContext context); @Override Class getType(); @Override String toString(); Expression getIndexableObject(); Expression getIndex(); @Override Iterable<Expression> children();  }
@Test public void accessArray() { int ary[] = new int[] {23}; final IndexedAccessExpression idxExpr = new IndexedAccessExpression(START, obj(ary), num(0)); final Object evaluate = idxExpr.evaluateUnsafe(context); assertThat(evaluate).isOfAnyClassIn(Integer.class); assertThat(evaluate).isEqualTo(23); }
@Test public void accessList() { final ImmutableList<Integer> list = ImmutableList.of(23); final IndexedAccessExpression idxExpr = new IndexedAccessExpression(START, obj(list), num(0)); final Object evaluate = idxExpr.evaluateUnsafe(context); assertThat(evaluate).isOfAnyClassIn(Integer.class); assertThat(evaluate).isEqualTo(23); }
@Test public void accessIterable() { final Iterable<Integer> iterable = () -> new AbstractIterator<Integer>() { private boolean done = false; @Override protected Integer computeNext() { if (done) { return endOfData(); } done = true; return 23; } }; final IndexedAccessExpression idxExpr = new IndexedAccessExpression(START, obj(iterable), num(0)); final Object evaluate = idxExpr.evaluateUnsafe(context); assertThat(evaluate).isOfAnyClassIn(Integer.class); assertThat(evaluate).isEqualTo(23); }
@Test public void accessMap() { final ImmutableMap<String, Integer> map = ImmutableMap.of("string", 23); final IndexedAccessExpression idxExpr = new IndexedAccessExpression(START, obj(map), string("string")); final Object evaluate = idxExpr.evaluateUnsafe(context); assertThat(evaluate).isEqualTo(23); }
@Test public void invalidObject() { final IndexedAccessExpression expression = new IndexedAccessExpression(START, obj(23), num(0)); assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> expression.evaluateUnsafe(context)); }