AddressTemplate implements Iterable<String> { public ResourceAddress resolve(StatementContext context, @EsParam("...string") String... wildcards) { if (isEmpty()) { return ResourceAddress.root(); } int wildcardCount = 0; ModelNode model = new ModelNode(); Memory<String[]> tupleMemory = new Memory<>(); Memory<String> valueMemory = new Memory<>(); for (Token token : tokens) { if (!token.hasKey()) { String value = token.getValue(); String[] resolvedValue; if (value.startsWith("{")) { String variable = value.substring(1, value.length() - 1); value = variable; if (!tupleMemory.contains(variable)) { String[] resolvedTuple = context.resolveTuple(variable, this); if (resolvedTuple != null) { tupleMemory.memorize(variable, singletonList(resolvedTuple)); } } resolvedValue = tupleMemory.next(value); } else { assert value.contains(EQUALS) : "Invalid token expression " + value; resolvedValue = value.split(EQUALS); } if (resolvedValue != null) { model.add(resolvedValue[0], ModelNodeHelper.decodeValue(resolvedValue[1])); } } else { String keyRef = token.getKey(); String valueRef = token.getValue(); String resolvedKey = resolveSome(context, valueMemory, keyRef); String resolvedValue = resolveSome(context, valueMemory, valueRef); if (resolvedKey == null) { resolvedKey = BLANK; } if (resolvedValue == null) { resolvedValue = BLANK; } String addressValue = resolvedValue; if ("*".equals( resolvedValue) && wildcards != null && wildcards.length > 0 && wildcardCount < wildcards.length) { addressValue = wildcards[wildcardCount]; wildcardCount++; } model.add(resolvedKey, ModelNodeHelper.decodeValue(addressValue)); } } return new ResourceAddress(model); } private  AddressTemplate(String template); @JsIgnore static AddressTemplate of(StatementContext.Expression placeholder); @JsIgnore static AddressTemplate of(StatementContext.Expression placeholder, String template); @JsIgnore static AddressTemplate of(StatementContext.Expression placeholder1,
            StatementContext.Expression placeholder2); @JsIgnore static AddressTemplate of(StatementContext.Expression placeholder1, StatementContext.Expression placeholder2,
            String template); static AddressTemplate of(String template); @JsIgnore static AddressTemplate of(ResourceAddress address); @JsIgnore static AddressTemplate of(ResourceAddress address, Unresolver unresolver); @Override @JsIgnore boolean equals(Object o); @Override @JsIgnore int hashCode(); @Override String toString(); @JsProperty boolean isEmpty(); @JsProperty(name = "size") int size(); @Override @JsIgnore Iterator<String> iterator(); @JsIgnore AddressTemplate append(String template); @JsIgnore AddressTemplate append(AddressTemplate template); @JsIgnore AddressTemplate subTemplate(int fromIndex, int toIndex); @JsProperty AddressTemplate getParent(); @JsIgnore AddressTemplate replaceWildcards(String wildcard, String... wildcards); @JsProperty(name = "firstName") String firstName(); @JsProperty(name = "firstValue") String firstValue(); @JsProperty(name = "lastName") String lastName(); @JsProperty(name = "lastValue") String lastValue(); @JsIgnore boolean isOptional(); ResourceAddress resolve(StatementContext context, @EsParam("...string") String... wildcards); @JsMethod(name = "append") AddressTemplate jsAppend(@EsParam("string|AddressTemplate") Object address); static final AddressTemplate ROOT; static final String EQUALS; @JsIgnore static final String OPTIONAL; }
@Test public void resolve() { AddressTemplate at = AddressTemplate.of("{a}/b={c}"); ResourceAddress resolved = at.resolve(StatementContext.NOOP); assertResolved(new String[][]{{"a", "a"}, {"b", "c"}}, resolved); }