001package gudusoft.gsqlparser.common.structured;
002
003import java.util.Objects;
004
005public final class StructuredPathSegment {
006
007    private final StructuredPathSegmentKind kind;
008    private final String name;
009
010    private StructuredPathSegment(StructuredPathSegmentKind kind, String name) {
011        this.kind = kind;
012        this.name = name;
013    }
014
015    public static StructuredPathSegment arrayElement() {
016        return new StructuredPathSegment(StructuredPathSegmentKind.ARRAY_ELEMENT, null);
017    }
018
019    public static StructuredPathSegment field(String name) {
020        if (name == null || name.isEmpty()) {
021            throw new IllegalArgumentException("field name must be non-empty");
022        }
023        return new StructuredPathSegment(StructuredPathSegmentKind.FIELD, name);
024    }
025
026    public static StructuredPathSegment mapKey() {
027        return new StructuredPathSegment(StructuredPathSegmentKind.MAP_KEY, null);
028    }
029
030    public static StructuredPathSegment mapValue() {
031        return new StructuredPathSegment(StructuredPathSegmentKind.MAP_VALUE, null);
032    }
033
034    /** A subscript whose container (array or map) is not known yet; see {@link StructuredPathSegmentKind#SUBSCRIPT}. */
035    public static StructuredPathSegment subscript() {
036        return new StructuredPathSegment(StructuredPathSegmentKind.SUBSCRIPT, null);
037    }
038
039    /** The wildcard of {@code customer.*}: every field of the path before it. */
040    public static StructuredPathSegment star() {
041        return new StructuredPathSegment(StructuredPathSegmentKind.STAR, null);
042    }
043
044    public StructuredPathSegmentKind getKind() {
045        return kind;
046    }
047
048    public String getName() {
049        return name;
050    }
051
052    public String toDisplayString() {
053        switch (kind) {
054            case ARRAY_ELEMENT: return "[*]";
055            case FIELD:         return "." + name;
056            case MAP_KEY:       return "[key]";
057            // a map value displays as an element, as every map read of the tree has: m['k'] reads m[*]
058            case MAP_VALUE:     return "[*]";
059            case SUBSCRIPT:     return "[*]";
060            case STAR:          return ".*";
061            default: throw new IllegalStateException("unknown kind " + kind);
062        }
063    }
064
065    @Override
066    public boolean equals(Object o) {
067        if (this == o) return true;
068        if (!(o instanceof StructuredPathSegment)) return false;
069        StructuredPathSegment other = (StructuredPathSegment) o;
070        return kind == other.kind && Objects.equals(name, other.name);
071    }
072
073    @Override
074    public int hashCode() {
075        return Objects.hash(kind, name);
076    }
077
078    @Override
079    public String toString() {
080        return toDisplayString();
081    }
082}