-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathPath.java
More file actions
150 lines (124 loc) · 3.87 KB
/
Path.java
File metadata and controls
150 lines (124 loc) · 3.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
package com.deblock.jsondiff.matcher;
import java.util.Objects;
/**
* Represents a JSON path (e.g., $.property.0.subproperty).
* Stored in reverse order (last element at head) for O(1) add operations
* and efficient end-matching in PathMatcher.
*/
public class Path {
public static final Path ROOT = new Path();
private final PathItem last;
private final Path previous;
public Path() {
this(null, null);
}
private Path(PathItem last, Path previous) {
this.last = last;
this.previous = previous;
}
public Path add(PathItem item) {
if (this.last == null) {
return new Path(item, null);
}
return new Path(item, this);
}
public PathItem item() {
return last;
}
/**
* Returns the path without its last element.
*/
public Path previous() {
return previous == null ? ROOT : previous;
}
/**
* Returns the path items in natural order (from root to leaf).
* This is useful for traversing the path from start to end.
*/
public java.util.List<PathItem> toList() {
java.util.List<PathItem> result = new java.util.ArrayList<>();
collectItems(result);
return result;
}
private void collectItems(java.util.List<PathItem> result) {
if (last == null) return;
if (previous != null) {
previous.collectItems(result);
}
result.add(last);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("$");
appendReversed(sb);
return sb.toString();
}
private void appendReversed(StringBuilder sb) {
if (last == null) return;
if (previous != null) {
previous.appendReversed(sb);
}
sb.append(".").append(last);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Path path = (Path) o;
return Objects.equals(last, path.last) && Objects.equals(previous, path.previous);
}
@Override
public int hashCode() {
return Objects.hash(last, previous);
}
public interface PathItem {
static PathItem of(String property) {
return new ObjectProperty(property);
}
static PathItem of(Integer index) {
return new ArrayIndex(index);
}
class ArrayIndex implements PathItem {
public final int index;
public ArrayIndex(int index) {
this.index = index;
}
@Override
public String toString() {
return String.valueOf(index);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ArrayIndex that = (ArrayIndex) o;
return index == that.index;
}
@Override
public int hashCode() {
return Objects.hash(index);
}
}
class ObjectProperty implements PathItem {
public final String property;
public ObjectProperty(String property) {
this.property = property;
}
@Override
public String toString() {
return this.property;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ObjectProperty that = (ObjectProperty) o;
return Objects.equals(property, that.property);
}
@Override
public int hashCode() {
return Objects.hash(property);
}
}
}
}