1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package io.wcm.caravan.hal.comparison.impl.context;
21
22 import java.util.Collections;
23 import java.util.HashMap;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Map.Entry;
27
28 import com.fasterxml.jackson.databind.node.ObjectNode;
29 import com.google.common.collect.ImmutableMap;
30
31 import io.wcm.caravan.hal.comparison.HalComparisonContext;
32 import io.wcm.caravan.hal.comparison.impl.PairWithRelation;
33 import io.wcm.caravan.hal.resource.HalResource;
34 import io.wcm.caravan.hal.resource.Link;
35
36
37
38
39 public class HalComparisonContextImpl implements HalComparisonContext {
40
41 private final HalPathImpl halPath;
42
43 private final String expectedUrl;
44 private final String actualUrl;
45
46 private final Map<HalPathImpl, HalResource> parentResources;
47
48
49
50
51
52
53
54 public HalComparisonContextImpl(String expectedUrl, String actualUrl) {
55 this.halPath = new HalPathImpl();
56 this.expectedUrl = expectedUrl;
57 this.actualUrl = actualUrl;
58 this.parentResources = Collections.emptyMap();
59 }
60
61 private HalComparisonContextImpl(HalPathImpl halPath, String expectedUrl, String actualUrl, Map<HalPathImpl, HalResource> parentResources) {
62 this.halPath = halPath;
63 this.expectedUrl = expectedUrl;
64 this.actualUrl = actualUrl;
65 this.parentResources = ImmutableMap.copyOf(parentResources);
66 }
67
68 @Override
69 public String getExpectedUrl() {
70 return this.expectedUrl;
71 }
72
73 @Override
74 public String getActualUrl() {
75 return this.actualUrl;
76 }
77
78
79
80
81
82 public HalComparisonContextImpl withAppendedHalPath(String relation, HalResource contextResource) {
83
84 HalPathImpl newHalPath = halPath.append(relation, null, null);
85 return new HalComparisonContextImpl(newHalPath, expectedUrl, actualUrl, createNewParentResourceMap(contextResource));
86 }
87
88 private Map<HalPathImpl, HalResource> createNewParentResourceMap(HalResource contextResource) {
89 Map<HalPathImpl, HalResource> newParents = new HashMap<>(parentResources);
90 newParents.put(halPath, contextResource);
91 return newParents;
92 }
93
94
95
96
97
98
99 public HalComparisonContextImpl withHalPathOfEmbeddedResource(PairWithRelation<HalResource> pair, HalResource contextResource) {
100
101 String relation = pair.getRelation();
102 List<HalResource> originalEmbedded = contextResource.getEmbedded(relation);
103
104 Integer originalIndex = null;
105 if (originalEmbedded.size() > 1) {
106 originalIndex = findOriginalIndex(pair, originalEmbedded);
107 }
108
109 HalPathImpl newHalPath = halPath.append(relation, originalIndex, null);
110 return new HalComparisonContextImpl(newHalPath, expectedUrl, actualUrl, createNewParentResourceMap(contextResource));
111 }
112
113
114 private Integer findOriginalIndex(PairWithRelation<HalResource> pair, List<HalResource> originalEmbedded) {
115 for (int i = 0; i < originalEmbedded.size(); i++) {
116 ObjectNode originalModel = originalEmbedded.get(i).getModel();
117 if (originalModel == pair.getExpected().getModel()) {
118 return i;
119 }
120 }
121 throw new IllegalArgumentException("The resource from the given pair is not actually embedded in the context resource");
122 }
123
124
125
126
127
128
129 public HalComparisonContextImpl withHalPathOfLinkedResource(PairWithRelation<Link> pair, HalResource contextResource) {
130
131 String relation = pair.getRelation();
132 List<Link> originalLinks = contextResource.getLinks(relation);
133
134 Integer originalIndex = null;
135 String name = pair.getExpected().getName();
136 if (originalLinks.size() > 1) {
137 originalIndex = originalLinks.indexOf(pair.getExpected());
138 }
139
140 HalPathImpl newHalPath = halPath.append(relation, originalIndex, name);
141 Map<HalPathImpl, HalResource> newParents = new HashMap<>(parentResources);
142 newParents.put(halPath, contextResource);
143 return new HalComparisonContextImpl(newHalPath, expectedUrl, actualUrl, createNewParentResourceMap(contextResource));
144 }
145
146
147
148
149
150 public HalComparisonContextImpl withHalPathIndex(int indexInArray) {
151 HalPathImpl newHalPath = halPath.replaceHalPathIndex(indexInArray);
152 return new HalComparisonContextImpl(newHalPath, expectedUrl, actualUrl, parentResources);
153 }
154
155
156
157
158
159 public HalComparisonContextImpl withAppendedJsonPath(String fieldName) {
160 HalPathImpl newHalPath = halPath.appendJsonPath(fieldName);
161 return new HalComparisonContextImpl(newHalPath, expectedUrl, actualUrl, parentResources);
162 }
163
164
165
166
167
168 public HalComparisonContextImpl withJsonPathIndex(int indexInArray) {
169 HalPathImpl newHalPath = halPath.replaceJsonPathIndex(indexInArray);
170 return new HalComparisonContextImpl(newHalPath, expectedUrl, actualUrl, parentResources);
171 }
172
173
174
175
176
177 public HalComparisonContextImpl withNewExpectedUrl(String newUrl) {
178 return new HalComparisonContextImpl(halPath, newUrl, actualUrl, parentResources);
179 }
180
181
182
183
184
185 public HalComparisonContextImpl withNewActualUrl(String newUrl) {
186 return new HalComparisonContextImpl(halPath, expectedUrl, newUrl, parentResources);
187 }
188
189 @Override
190 public String getLastRelation() {
191 return halPath.getLastRelation();
192 }
193
194 @Override
195 public List<String> getAllRelations() {
196 return halPath.getAllRelations();
197 }
198
199 @Override
200 public String getLastProperyName() {
201 return halPath.getLastProperyName();
202 }
203
204 @Override
205 public List<String> getAllPropertyNames() {
206 return halPath.getAllPropertyNames();
207 }
208
209 @Override
210 public HalResource getParentResourceWithRelation(String relation) {
211 return parentResources.entrySet().stream()
212 .filter(entry -> entry.getKey().getLastRelation().equals(relation))
213 .sorted(HalComparisonContextImpl::longestHalPathFirstComparator)
214 .map(Entry::getValue)
215 .findFirst()
216 .orElse(null);
217 }
218
219 private static int longestHalPathFirstComparator(Entry<HalPathImpl, HalResource> entry1, Entry<HalPathImpl, HalResource> entry2) {
220 String firstHalPath = entry1.getKey().toString();
221 String secondHalPath = entry2.getKey().toString();
222
223 return -Integer.compare(firstHalPath.length(), secondHalPath.length());
224 }
225
226 @Override
227 public String toString() {
228 return halPath.toString();
229 }
230 }