1 package com.atlassian.marketplace.client.impl;
2
3 import java.io.ByteArrayInputStream;
4 import java.io.ByteArrayOutputStream;
5 import java.io.InputStream;
6 import java.net.URI;
7
8 import com.atlassian.marketplace.client.MpacException;
9 import com.atlassian.marketplace.client.api.Page;
10 import com.atlassian.marketplace.client.api.PageReader;
11 import com.atlassian.marketplace.client.api.PageReference;
12 import com.atlassian.marketplace.client.http.SimpleHttpResponse;
13 import com.atlassian.marketplace.client.model.Links;
14 import com.atlassian.marketplace.client.model.TestModelBuilders;
15 import com.atlassian.marketplace.client.util.UriBuilder;
16
17 import com.google.common.base.Function;
18 import com.google.common.base.Functions;
19
20 import static com.atlassian.marketplace.client.impl.ApiHelper.JSON;
21 import static com.atlassian.marketplace.client.impl.ApiHelper.closeQuietly;
22
23 abstract class ApiImplBase
24 {
25 protected final ApiHelper apiHelper;
26 protected final InternalModel.MinimalLinks root;
27 protected final URI apiRoot;
28
29 protected ApiImplBase(ApiHelper apiHelper, InternalModel.MinimalLinks root, String rootLinkRel) throws MpacException
30 {
31 this.apiHelper = apiHelper;
32 this.root = root;
33 this.apiRoot = apiHelper.requireLinkUri(root.getLinks(), rootLinkRel, root.getClass());
34 }
35
36 protected URI getApiRoot()
37 {
38 return apiRoot;
39 }
40
41 protected UriBuilder fromApiRoot()
42 {
43 return UriBuilder.fromUri(apiRoot);
44 }
45
46 protected Links getLinksOnly(URI uri) throws MpacException
47 {
48 InternalModel.MinimalLinks rep = apiHelper.getEntity(uri, InternalModel.MinimalLinks.class);
49 return rep.getLinks();
50 }
51
52 protected <T> T genericCreate(URI collectionUri, T entity) throws MpacException
53 {
54 return genericCreate(collectionUri, entity, Functions.<URI>identity());
55 }
56
57 protected <T> T genericCreate(URI collectionUri, T entity, Function<URI, URI> resultUriTransform) throws MpacException
58 {
59 ByteArrayOutputStream bos = new ByteArrayOutputStream();
60 apiHelper.getEncoding().encode(bos, entity, false);
61 byte[] bytes = bos.toByteArray();
62 return createdOrUpdatedEntityResult(apiHelper.getHttp().post(apiHelper.resolveLink(collectionUri),
63 new ByteArrayInputStream(bytes), bytes.length, JSON, JSON),
64 entity.getClass(),
65 resultUriTransform);
66 }
67
68 protected <T> T genericUpdate(URI uri, T original, T updated) throws MpacException
69 {
70 if (uri == TestModelBuilders.DEFAULT_URI)
71 {
72
73
74
75 throw new MpacException.CannotUpdateNonServerSideEntity();
76 }
77 ByteArrayOutputStream bos = new ByteArrayOutputStream();
78 apiHelper.getEncoding().encodeChanges(bos, original, updated);
79 byte[] bytes = bos.toByteArray();
80 return createdOrUpdatedEntityResult(apiHelper.getHttp().patch(apiHelper.resolveLink(uri), bytes),
81 original.getClass(), Functions.<URI>identity());
82 }
83
84 @SuppressWarnings("unchecked")
85 private <T> T createdOrUpdatedEntityResult(SimpleHttpResponse response, Class<?> entityClass,
86 Function<URI, URI> resultUriTransform) throws MpacException
87 {
88 try
89 {
90 int status = response.getStatus();
91 if (status == 200 || status == 201 || status == 204)
92 {
93 for (String location: response.getHeader("Location"))
94 {
95 return apiHelper.getEntityUncached(resultUriTransform.apply(URI.create(location)), (Class<T>) entityClass);
96 }
97 throw new MpacException("Server did not return expected Location header");
98 }
99 throw apiHelper.responseException(response);
100 }
101 finally
102 {
103 closeQuietly(response);
104 }
105 }
106
107 protected <T, U extends InternalModel.EntityCollection<T>> PageReader<T> pageReader(final Class<U> collectionRepClass)
108 {
109 return new PageReader<T>()
110 {
111 @Override
112 public Page<T> readPage(PageReference<T> ref, InputStream in) throws MpacException
113 {
114 U rep = apiHelper.decode(in, collectionRepClass);
115 return new PageImpl<T>(ref, rep.getLinks(), rep.getItems(), rep.getCount(), this);
116 }
117 };
118 }
119 }