class 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()) {
                // a single token, something like "{foo}" of "bar"
                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 {
                // a key/value token, something like "foo=bar", "foo=*", "{foo}=bar" or "foo={bar}"
                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;
                }

                // wildcards
                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);

}