All Downloads are FREE. Search and download functionalities are using the official Maven repository.

software.amazon.awssdk.services.amp.endpoints.internal.GetAttr Maven / Gradle / Ivy

Go to download

The AWS Java SDK for Amp module holds the client classes that are used for communicating with Amp.

There is a newer version: 2.29.39
Show newest version
/*
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with
 * the License. A copy of the License is located at
 * 
 * http://aws.amazon.com/apache2.0
 * 
 * or in the "license" file accompanying this file. 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 software.amazon.awssdk.services.amp.endpoints.internal;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import software.amazon.awssdk.annotations.SdkInternalApi;

@SdkInternalApi
public class GetAttr extends Fn {
    public static final String ID = "getAttr";

    public GetAttr(FnNode node) {
        super(node);
    }

    @Override
    public Value eval(Scope scope) {
        Value root = target().eval(scope);
        List path;
        try {
            path = path();
        } catch (InnerParseError e) {
            throw new RuntimeException(e);
        }
        for (Part part : path) {
            root = part.eval(root);
        }
        return root;
    }

    public interface Part {

        Value eval(Value container);

        final class Key implements Part {
            private final Identifier key;

            public Key(Identifier key) {
                this.key = key;
            }

            @Override
            public String toString() {
                return key.asString();
            }

            public static Key of(String key) {
                return new Key(Identifier.of(key));
            }

            @Override
            public Value eval(Value container) {
                return container.expectRecord().get(key);
            }

            public Identifier key() {
                return key;
            }

            @Override
            public boolean equals(Object obj) {
                if (obj == this) {
                    return true;
                }
                if (obj == null || obj.getClass() != this.getClass()) {
                    return false;
                }
                Key that = (Key) obj;
                return Objects.equals(this.key, that.key);
            }

            @Override
            public int hashCode() {
                return key != null ? key.hashCode() : 0;
            }
        }

        final class Index implements Part {
            private final int index;

            public Index(int index) {
                this.index = index;
            }

            @Override
            public Value eval(Value container) {
                return container.expectArray().get(index);
            }

            @Override
            public String toString() {
                return String.format("[%s]", index);
            }

            public int index() {
                return index;
            }

            @Override
            public boolean equals(Object obj) {
                if (obj == this) {
                    return true;
                }
                if (obj == null || obj.getClass() != this.getClass()) {
                    return false;
                }
                Index that = (Index) obj;
                return this.index == that.index;
            }

            @Override
            public int hashCode() {
                return index;
            }
        }
    }

    private static GetAttr fromBuilder(Builder builder) {
        return new GetAttr(FnNode.builder().fn("getAttr")
                .argv(Arrays.asList(builder.target, Literal.fromStr(String.join(".", builder.path)))).build());
    }

    public static Builder builder() {
        return new Builder();
    }

    public Expr target() {
        return expectTwoArgs().left();
    }

    public List path() throws InnerParseError {
        Expr right = expectTwoArgs().right();
        if (right instanceof Literal) {
            Literal path = (Literal) right;
            return parse(path.expectLiteralString());
        } else {
            throw SourceException.builder().message("second argument must be a string literal").build();
        }
    }

    private static List parse(String path) throws InnerParseError {
        String[] components = path.split("\\.");
        List result = new ArrayList<>();
        for (String component : components) {
            if (component.contains("[")) {
                int slicePartIndex = component.indexOf("[");
                String slicePart = component.substring(slicePartIndex);
                if (!slicePart.endsWith("]")) {
                    throw new InnerParseError("Invalid path component: %s. Must end with `]`");
                }
                try {
                    String number = slicePart.substring(1, slicePart.length() - 1);
                    int slice = Integer.parseInt(number);
                    if (slice < 0) {
                        throw new InnerParseError("Invalid path component: slice index must be >= 0");
                    }
                    if (slicePartIndex > 0) {
                        result.add(Part.Key.of(component.substring(0, slicePartIndex)));
                    }
                    result.add(new Part.Index(slice));
                } catch (NumberFormatException ex) {
                    throw new InnerParseError(String.format("%s could not be parsed as a number", slicePart));
                }
            } else {
                result.add(Part.Key.of(component));
            }
        }
        if (result.isEmpty()) {
            throw new InnerParseError("Invalid argument to GetAttr: path may not be empty");
        }
        return result;
    }

    @Override
    public  T acceptFnVisitor(FnVisitor visitor) {
        return visitor.visitGetAttr(this);
    }

    @Override
    public String toString() {
        StringBuilder out = new StringBuilder();
        out.append(target());
        try {
            for (Part part : path()) {
                out.append(".");
                out.append(part);
            }
        } catch (InnerParseError e) {
            throw new RuntimeException(e);
        }
        return out.toString();
    }

    @Override
    public String template() {
        String target = ((Ref) this.target()).getName().asString();
        StringBuilder pathPart = new StringBuilder();

        List partList;
        try {
            partList = path();
        } catch (InnerParseError e) {
            throw new RuntimeException(e);
        }
        for (int i = 0; i < partList.size(); i++) {
            if (i != 0) {
                if (partList.get(i) instanceof Part.Key) {
                    pathPart.append(".");
                }
            }
            pathPart.append(partList.get(i).toString());
        }
        return "{" + target + "#" + pathPart + "}";
    }

    public static class Builder {
        Expr target;
        String path;

        public Builder target(Expr target) {
            this.target = target;
            return this;
        }

        public Builder path(String path) {
            this.path = path;
            return this;
        }

        public GetAttr build() {
            return GetAttr.fromBuilder(this);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy