1 package com.atlassian.plugins.rest.common;
2
3 import com.google.common.base.Preconditions;
4 import com.google.common.collect.Lists;
5 import org.apache.commons.lang.builder.EqualsBuilder;
6 import org.apache.commons.lang.builder.HashCodeBuilder;
7
8 import javax.ws.rs.core.CacheControl;
9 import javax.ws.rs.core.Response;
10 import javax.xml.bind.annotation.XmlAttribute;
11 import javax.xml.bind.annotation.XmlElement;
12 import javax.xml.bind.annotation.XmlElementWrapper;
13 import javax.xml.bind.annotation.XmlRootElement;
14 import java.util.Collection;
15 import java.util.Collections;
16 import java.util.List;
17
18
19
20
21 @XmlRootElement
22 public class Status
23 {
24
25
26
27 @XmlElement
28 private final Plugin plugin;
29
30
31
32
33
34 @XmlElement(name = "status-code")
35 private final Integer code;
36
37
38
39
40 @XmlElement(name = "sub-code")
41 private final Integer subCode;
42
43
44
45
46 @XmlElement
47 private final String message;
48
49
50
51
52
53 @XmlElement(name = "etag")
54 private final String eTag;
55
56
57
58
59 @XmlElementWrapper(name = "resources-created")
60 @XmlElement(name = "link")
61 private final Collection<Link> resourcesCreated;
62
63
64
65
66 @XmlElementWrapper(name = "resources-updated")
67 @XmlElement(name = "link")
68 private final Collection<Link> resourcesUpdated;
69
70
71 private Status()
72 {
73 this.plugin = null;
74 this.code = -1;
75 this.subCode = -1;
76 this.message = null;
77 this.eTag = null;
78 this.resourcesCreated = null;
79 this.resourcesUpdated = null;
80 }
81
82 private Status(Plugin plugin, Integer code, Integer subCode, String message, String eTag, Collection<Link> resourcesCreated, Collection<Link> resourcesUpdated)
83 {
84 this.plugin = plugin;
85 this.code = code;
86 this.subCode = subCode;
87 this.message = message;
88 this.eTag = eTag;
89 this.resourcesCreated = resourcesCreated;
90 this.resourcesUpdated = resourcesUpdated;
91 }
92
93 public static StatusResponseBuilder ok()
94 {
95 return new StatusResponseBuilder(Response.Status.OK);
96 }
97
98 public static StatusResponseBuilder notFound()
99 {
100 return new StatusResponseBuilder(Response.Status.NOT_FOUND);
101 }
102
103 public static StatusResponseBuilder error()
104 {
105
106 return new StatusResponseBuilder(Response.Status.INTERNAL_SERVER_ERROR).noCache().noStore();
107 }
108
109 public static StatusResponseBuilder badRequest()
110 {
111
112 return new StatusResponseBuilder(Response.Status.BAD_REQUEST).noCache().noStore();
113 }
114
115 public static StatusResponseBuilder forbidden()
116 {
117 return new StatusResponseBuilder(Response.Status.FORBIDDEN);
118 }
119
120 public static StatusResponseBuilder unauthorized()
121 {
122 return new StatusResponseBuilder(Response.Status.UNAUTHORIZED);
123 }
124
125 public static StatusResponseBuilder created(Link link)
126 {
127 return new StatusResponseBuilder(Response.Status.CREATED).created(Preconditions.checkNotNull(link));
128 }
129
130 public Plugin getPlugin()
131 {
132 return plugin;
133 }
134
135 public int getCode()
136 {
137 return code;
138 }
139
140 public int getSubCode()
141 {
142 return subCode;
143 }
144
145 public String getMessage()
146 {
147 return message;
148 }
149
150 public String getETag()
151 {
152 return eTag;
153 }
154
155 public Collection<Link> getResourcesCreated()
156 {
157 return Collections.unmodifiableCollection(resourcesCreated);
158 }
159
160 public Collection<Link> getResourcesUpdated()
161 {
162 return Collections.unmodifiableCollection(resourcesUpdated);
163 }
164
165 @XmlRootElement
166 public static class Plugin
167 {
168 @XmlAttribute
169 private final String key;
170
171 @XmlAttribute
172 private final String version;
173
174
175 private Plugin()
176 {
177 this.key = null;
178 this.version = null;
179 }
180
181 public Plugin(String key, String version)
182 {
183 this.key = Preconditions.checkNotNull(key);
184 this.version = Preconditions.checkNotNull(version);
185 }
186
187 public String getKey()
188 {
189 return key;
190 }
191
192 public String getVersion()
193 {
194 return version;
195 }
196
197 @Override
198 public int hashCode()
199 {
200 return new HashCodeBuilder(3, 5).append(key).append(version).toHashCode();
201 }
202
203 @Override
204 public boolean equals(Object obj)
205 {
206 if (obj == null)
207 {
208 return false;
209 }
210 if (obj == this)
211 {
212 return true;
213 }
214 if (obj.getClass() != getClass())
215 {
216 return false;
217 }
218 final Plugin plugin = (Plugin) obj;
219 return new EqualsBuilder().append(key, plugin.key).append(version, plugin.version).isEquals();
220 }
221 }
222
223 public static class StatusResponseBuilder
224 {
225 private final CacheControl cacheControl;
226 private final Response.Status status;
227 private String eTag;
228 private Plugin plugin;
229 private String message;
230 private List<Link> created;
231 private List<Link> updated;
232
233 private StatusResponseBuilder(Response.Status status)
234 {
235 this(status, new CacheControl());
236 }
237
238 private StatusResponseBuilder(Response.Status status, CacheControl cacheControl)
239 {
240 this.status = Preconditions.checkNotNull(status);
241 this.cacheControl = Preconditions.checkNotNull(cacheControl);
242 }
243
244 public StatusResponseBuilder plugin(String key, String version)
245 {
246 plugin = new Plugin(key, version);
247 return this;
248 }
249
250 public StatusResponseBuilder message(String message)
251 {
252 this.message = message;
253 return this;
254 }
255
256 public StatusResponseBuilder tag(String eTag)
257 {
258 this.eTag = eTag;
259 return this;
260 }
261
262 public StatusResponseBuilder noCache()
263 {
264 cacheControl.setNoCache(true);
265 return this;
266 }
267
268 public StatusResponseBuilder noStore()
269 {
270 cacheControl.setNoStore(true);
271 return this;
272 }
273
274 public Status build()
275 {
276 return new Status(plugin, status.getStatusCode(), null, message, eTag, created, updated);
277 }
278
279 public Response response()
280 {
281 return responseBuilder().build();
282 }
283
284 public Response.ResponseBuilder responseBuilder()
285 {
286 final Response.ResponseBuilder builder = Response.status(status).cacheControl(cacheControl).tag(eTag).entity(build());
287
288 final List<Link> c = getCreated();
289 final List<Link> u = getUpdated();
290 if (c.size() == 1 && u.isEmpty())
291 {
292 builder.location(c.get(0).getHref());
293 }
294 else if (u.size() == 1 && c.isEmpty())
295 {
296 builder.location(u.get(0).getHref());
297 }
298 return builder;
299 }
300
301 public StatusResponseBuilder created(final Link link)
302 {
303 getCreated().add(link);
304 return this;
305 }
306
307 public StatusResponseBuilder updated(final Link link)
308 {
309 getUpdated().add(link);
310 return this;
311 }
312
313 private List<Link> getCreated()
314 {
315 if (created == null)
316 {
317 created = Lists.newLinkedList();
318 }
319 return created;
320 }
321
322 private List<Link> getUpdated()
323 {
324 if (updated == null)
325 {
326 updated = Lists.newLinkedList();
327 }
328 return updated;
329 }
330 }
331 }