|
15 | 15 | */
|
16 | 16 | package org.springframework.hateoas;
|
17 | 17 |
|
| 18 | +import lombok.EqualsAndHashCode; |
| 19 | +import lombok.Getter; |
| 20 | +import lombok.ToString; |
| 21 | +import lombok.experimental.Wither; |
| 22 | + |
18 | 23 | import java.util.ArrayList;
|
19 | 24 | import java.util.Arrays;
|
20 |
| -import java.util.Iterator; |
| 25 | +import java.util.Collection; |
21 | 26 | import java.util.List;
|
| 27 | +import java.util.Objects; |
22 | 28 |
|
| 29 | +import org.springframework.hateoas.core.Relation; |
23 | 30 | import org.springframework.util.Assert;
|
24 | 31 | import org.springframework.util.StringUtils;
|
25 | 32 |
|
26 | 33 | import com.fasterxml.jackson.annotation.JsonCreator;
|
| 34 | +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; |
| 35 | +import com.fasterxml.jackson.annotation.JsonInclude; |
27 | 36 | import com.fasterxml.jackson.annotation.JsonProperty;
|
28 |
| -import com.fasterxml.jackson.annotation.JsonValue; |
| 37 | +import com.fasterxml.jackson.annotation.JsonPropertyOrder; |
29 | 38 |
|
30 | 39 | /**
|
31 |
| - * A representation model class to be rendered as specified for the media type {@code application/vnd.error}. |
| 40 | + * A representation model class to be rendered as specified for the media type {@code application/vnd.error+json}. |
32 | 41 | *
|
33 | 42 | * @see https://github.com/blongden/vnd.error
|
34 | 43 | * @author Oliver Gierke
|
35 | 44 | * @author Greg Turnquist
|
36 | 45 | */
|
37 |
| -public class VndErrors implements Iterable<VndErrors.VndError> { |
| 46 | +@JsonPropertyOrder({"message", "logref", "total", "_links", "_embedded"}) |
| 47 | +@JsonIgnoreProperties(ignoreUnknown = true) |
| 48 | +@EqualsAndHashCode |
| 49 | +@ToString |
| 50 | +public class VndErrors extends Resources<VndErrors.VndError> { |
38 | 51 |
|
39 |
| - private final List<VndError> vndErrors; |
| 52 | + public static final String REL_HELP = "help"; |
| 53 | + public static final String REL_DESCRIBES = "describes"; |
| 54 | + public static final String REL_ABOUT = "about"; |
40 | 55 |
|
41 |
| - /** |
42 |
| - * Creates a new {@link VndErrors} instance containing a single {@link VndError} with the given logref, message and |
43 |
| - * optional {@link Link}s. |
44 |
| - * |
45 |
| - * @param logref must not be {@literal null} or empty. |
46 |
| - * @param message must not be {@literal null} or empty. |
47 |
| - * @param links |
48 |
| - */ |
49 |
| - public VndErrors(String logref, String message, Link... links) { |
50 |
| - this(new VndError(logref, message, links)); |
51 |
| - } |
| 56 | + private final List<VndError> errors; |
52 | 57 |
|
53 |
| - /** |
54 |
| - * Creates a new {@link VndErrors} wrapper for at least one {@link VndError}. |
55 |
| - * |
56 |
| - * @param errors must not be {@literal null}. |
57 |
| - * @param errors |
58 |
| - */ |
59 |
| - public VndErrors(VndError error, VndError... errors) { |
| 58 | + @Getter |
| 59 | + @JsonInclude(value = JsonInclude.Include.NON_EMPTY) |
| 60 | + private final String message; |
60 | 61 |
|
61 |
| - Assert.notNull(error, "Error must not be null"); |
62 |
| - |
63 |
| - this.vndErrors = new ArrayList<VndError>(errors.length + 1); |
64 |
| - this.vndErrors.add(error); |
65 |
| - this.vndErrors.addAll(Arrays.asList(errors)); |
66 |
| - } |
| 62 | + @Getter |
| 63 | + @JsonInclude(value = JsonInclude.Include.NON_EMPTY) |
| 64 | + private final Integer logref; |
67 | 65 |
|
68 | 66 | /**
|
69 | 67 | * Creates a new {@link VndErrors} wrapper for the given {@link VndErrors}.
|
70 | 68 | *
|
71 | 69 | * @param errors must not be {@literal null} or empty.
|
72 | 70 | */
|
73 | 71 | @JsonCreator
|
74 |
| - public VndErrors(List<VndError> errors) { |
| 72 | + public VndErrors(@JsonProperty("_embedded") List<VndError> errors, @JsonProperty("message") String message, |
| 73 | + @JsonProperty("logref") Integer logref, @JsonProperty("_links") List<Link> links) { |
75 | 74 |
|
76 | 75 | Assert.notNull(errors, "Errors must not be null!");
|
77 |
| - Assert.isTrue(!errors.isEmpty(), "Errors must not be empty!"); |
78 |
| - this.vndErrors = errors; |
| 76 | + Assert.notEmpty(errors, "Errors must not be empty!"); |
| 77 | + |
| 78 | + this.errors = errors; |
| 79 | + this.message = message; |
| 80 | + this.logref = logref; |
| 81 | + if (links != null && !links.isEmpty()) { |
| 82 | + add(links); |
| 83 | + } |
79 | 84 | }
|
80 | 85 |
|
81 |
| - /** |
82 |
| - * Protected default constructor to allow JAXB marshalling. |
83 |
| - */ |
84 |
| - protected VndErrors() { |
85 |
| - this.vndErrors = new ArrayList<VndError>(); |
| 86 | + public VndErrors() { |
| 87 | + |
| 88 | + this.errors = new ArrayList<>(); |
| 89 | + this.message = null; |
| 90 | + this.logref = null; |
86 | 91 | }
|
87 | 92 |
|
88 |
| - /** |
89 |
| - * Adds an additional {@link VndError} to the wrapper. |
90 |
| - * |
91 |
| - * @param error |
92 |
| - */ |
93 |
| - public VndErrors add(VndError error) { |
94 |
| - this.vndErrors.add(error); |
95 |
| - return this; |
| 93 | + public VndErrors withMessage(String message) { |
| 94 | + return new VndErrors(this.errors, message, this.logref, this.getLinks()); |
96 | 95 | }
|
97 | 96 |
|
98 |
| - /** |
99 |
| - * Dummy method to allow {@link JsonValue} to be configured. |
100 |
| - * |
101 |
| - * @return the vndErrors |
102 |
| - */ |
103 |
| - @JsonValue |
104 |
| - private List<VndError> getErrors() { |
105 |
| - return vndErrors; |
| 97 | + public VndErrors withLogref(Integer logref) { |
| 98 | + return new VndErrors(this.errors, this.message, logref, this.getLinks()); |
106 | 99 | }
|
107 | 100 |
|
108 |
| - /* |
109 |
| - * (non-Javadoc) |
110 |
| - * @see java.lang.Iterable#iterator() |
111 |
| - */ |
112 |
| - @Override |
113 |
| - public Iterator<VndErrors.VndError> iterator() { |
114 |
| - return this.vndErrors.iterator(); |
| 101 | + public VndErrors withErrors(List<VndError> errors) { |
| 102 | + |
| 103 | + Assert.notNull(errors, "errors must not be null!"); |
| 104 | + Assert.notEmpty(errors, "errors must not empty!"); |
| 105 | + |
| 106 | + return new VndErrors(errors, this.message, this.logref, this.getLinks()); |
115 | 107 | }
|
116 | 108 |
|
117 |
| - /* |
118 |
| - * (non-Javadoc) |
119 |
| - * @see java.lang.Object#toString() |
120 |
| - */ |
121 |
| - @Override |
122 |
| - public String toString() { |
123 |
| - return String.format("VndErrors[%s]", StringUtils.collectionToCommaDelimitedString(vndErrors)); |
| 109 | + public VndErrors withError(VndError error) { |
| 110 | + |
| 111 | + this.errors.add(error); |
| 112 | + return new VndErrors(this.errors, this.message, this.logref, this.getLinks()); |
124 | 113 | }
|
125 | 114 |
|
126 |
| - /* |
127 |
| - * (non-Javadoc) |
128 |
| - * @see java.lang.Object#hashCode() |
129 |
| - */ |
130 |
| - @Override |
131 |
| - public int hashCode() { |
132 |
| - return vndErrors.hashCode(); |
| 115 | + public VndErrors withLink(Link link) { |
| 116 | + |
| 117 | + add(link); |
| 118 | + return new VndErrors(this.errors, this.message, this.logref, this.getLinks()); |
133 | 119 | }
|
134 | 120 |
|
135 |
| - /* |
136 |
| - * (non-Javadoc) |
137 |
| - * @see java.lang.Object#equals(java.lang.Object) |
| 121 | + /** |
| 122 | + * Returns the underlying elements. |
| 123 | + * |
| 124 | + * @return the content will never be {@literal null}. |
138 | 125 | */
|
139 | 126 | @Override
|
140 |
| - public boolean equals(Object obj) { |
141 |
| - |
142 |
| - if (this == obj) { |
143 |
| - return true; |
144 |
| - } |
145 |
| - |
146 |
| - if (!(obj instanceof VndErrors)) { |
147 |
| - return false; |
148 |
| - } |
| 127 | + public Collection<VndError> getContent() { |
| 128 | + return this.errors; |
| 129 | + } |
149 | 130 |
|
150 |
| - VndErrors that = (VndErrors) obj; |
151 |
| - return this.vndErrors.equals(that.vndErrors); |
| 131 | + /** |
| 132 | + * Virtual attribute to generate JSON field of {@literal total}. |
| 133 | + */ |
| 134 | + public int getTotal() { |
| 135 | + return this.errors.size(); |
152 | 136 | }
|
153 | 137 |
|
154 | 138 | /**
|
155 | 139 | * A single {@link VndError}.
|
156 | 140 | *
|
157 | 141 | * @author Oliver Gierke
|
| 142 | + * @author Greg Turnquist |
158 | 143 | */
|
| 144 | + @JsonPropertyOrder({"message", "path", "logref"}) |
| 145 | + @Relation(collectionRelation = "errors") |
| 146 | + @EqualsAndHashCode |
159 | 147 | public static class VndError extends ResourceSupport {
|
160 | 148 |
|
161 |
| - @JsonProperty private final String logref; |
162 |
| - @JsonProperty private final String message; |
| 149 | + @Getter |
| 150 | + private final String message; |
| 151 | + |
| 152 | + @Getter |
| 153 | + @JsonInclude(value = JsonInclude.Include.NON_EMPTY) |
| 154 | + private final String path; |
| 155 | + |
| 156 | + @Getter |
| 157 | + @JsonInclude(value = JsonInclude.Include.NON_EMPTY) |
| 158 | + private final Integer logref; |
163 | 159 |
|
164 | 160 | /**
|
165 |
| - * Creates a new {@link VndError} with the given logref, a message as well as some {@link Link}s. |
| 161 | + * Creates a new {@link VndError} with a message and optional a path and a logref. |
166 | 162 | *
|
167 |
| - * @param logref must not be {@literal null} or empty. |
168 | 163 | * @param message must not be {@literal null} or empty.
|
169 |
| - * @param links |
170 | 164 | */
|
171 |
| - public VndError(String logref, String message, Link... links) { |
| 165 | + @JsonCreator |
| 166 | + public VndError(@JsonProperty("message") String message, @JsonProperty("path") String path, |
| 167 | + @JsonProperty("logref") Integer logref, @JsonProperty("_links") List<Link> links) { |
172 | 168 |
|
173 |
| - Assert.hasText(logref, "Logref must not be null or empty!"); |
174 | 169 | Assert.hasText(message, "Message must not be null or empty!");
|
175 | 170 |
|
176 |
| - this.logref = logref; |
177 | 171 | this.message = message;
|
178 |
| - this.add(Arrays.asList(links)); |
179 |
| - } |
180 |
| - |
181 |
| - /** |
182 |
| - * Protected default constructor to allow JAXB marshalling. |
183 |
| - */ |
184 |
| - protected VndError() { |
185 |
| - |
186 |
| - this.logref = null; |
187 |
| - this.message = null; |
188 |
| - } |
| 172 | + this.path = path; |
| 173 | + this.logref = logref; |
189 | 174 |
|
190 |
| - /** |
191 |
| - * Returns the logref of the error. |
192 |
| - * |
193 |
| - * @return the logref |
194 |
| - */ |
195 |
| - public String getLogref() { |
196 |
| - return logref; |
| 175 | + this.add(links); |
197 | 176 | }
|
198 | 177 |
|
199 | 178 | /**
|
200 |
| - * Returns the message of the error. |
201 |
| - * |
202 |
| - * @return the message |
| 179 | + * Convenience constructor |
203 | 180 | */
|
204 |
| - public String getMessage() { |
205 |
| - return message; |
| 181 | + public VndError(String message, String path, Integer logref, Link... links) { |
| 182 | + this(message, path, logref, Arrays.asList(links)); |
206 | 183 | }
|
207 | 184 |
|
208 |
| - /* |
209 |
| - * (non-Javadoc) |
210 |
| - * @see org.springframework.hateoas.ResourceSupport#toString() |
211 |
| - */ |
212 | 185 | @Override
|
213 | 186 | public String toString() {
|
214 |
| - return String.format("VndError[logref: %s, message: %s, links: [%s]]", logref, message, |
215 |
| - StringUtils.collectionToCommaDelimitedString(getLinks())); |
216 |
| - } |
217 |
| - |
218 |
| - /* |
219 |
| - * (non-Javadoc) |
220 |
| - * @see org.springframework.hateoas.ResourceSupport#hashCode() |
221 |
| - */ |
222 |
| - @Override |
223 |
| - public int hashCode() { |
224 |
| - |
225 |
| - int result = 17; |
226 |
| - |
227 |
| - result += 31 * logref.hashCode(); |
228 |
| - result += 31 * message.hashCode(); |
229 |
| - |
230 |
| - return result; |
231 |
| - } |
232 |
| - |
233 |
| - /* |
234 |
| - * (non-Javadoc) |
235 |
| - * @see org.springframework.hateoas.ResourceSupport#equals(java.lang.Object) |
236 |
| - */ |
237 |
| - @Override |
238 |
| - public boolean equals(Object obj) { |
239 |
| - |
240 |
| - if (obj == this) { |
241 |
| - return true; |
242 |
| - } |
243 |
| - |
244 |
| - if (!(obj instanceof VndError)) { |
245 |
| - return false; |
246 |
| - } |
247 |
| - |
248 |
| - VndError that = (VndError) obj; |
249 |
| - |
250 |
| - return this.logref.equals(that.logref) && this.message.equals(that.message); |
| 187 | + return "VndError{" + |
| 188 | + "message='" + message + '\'' + |
| 189 | + ", path='" + path + '\'' + |
| 190 | + ", logref=" + logref + |
| 191 | + ", links=" + getLinks() + |
| 192 | + '}'; |
251 | 193 | }
|
252 | 194 | }
|
253 | 195 | }
|
0 commit comments