1 package com.atlassian.marketplace.client.impl;
2
3 import java.net.URI;
4
5 import com.atlassian.fugue.Either;
6 import com.atlassian.fugue.Option;
7 import com.atlassian.marketplace.client.MpacException;
8 import com.atlassian.marketplace.client.api.AddonQuery;
9 import com.atlassian.marketplace.client.api.AddonVersionSpecifier;
10 import com.atlassian.marketplace.client.api.AddonVersionsQuery;
11 import com.atlassian.marketplace.client.api.Addons;
12 import com.atlassian.marketplace.client.api.Page;
13 import com.atlassian.marketplace.client.api.PageReference;
14 import com.atlassian.marketplace.client.api.PricingType;
15 import com.atlassian.marketplace.client.api.UriTemplate;
16 import com.atlassian.marketplace.client.http.SimpleHttpResponse;
17 import com.atlassian.marketplace.client.model.Addon;
18 import com.atlassian.marketplace.client.model.AddonPricing;
19 import com.atlassian.marketplace.client.model.AddonReference;
20 import com.atlassian.marketplace.client.model.AddonSummary;
21 import com.atlassian.marketplace.client.model.AddonVersion;
22 import com.atlassian.marketplace.client.model.AddonVersionSummary;
23 import com.atlassian.marketplace.client.util.UriBuilder;
24
25 import com.google.common.base.Function;
26 import com.google.common.collect.ImmutableMap;
27
28 import org.apache.commons.io.input.NullInputStream;
29
30 import static com.atlassian.fugue.Option.none;
31 import static com.atlassian.fugue.Option.some;
32 import static com.atlassian.marketplace.client.impl.ApiHelper.JSON;
33 import static com.atlassian.marketplace.client.impl.ApiHelper.getTemplatedLink;
34 import static com.atlassian.marketplace.client.impl.ApiHelper.withAccessToken;
35 import static com.atlassian.marketplace.client.impl.ApiHelper.withZeroLimit;
36
37 final class AddonsImpl extends ApiImplBase implements Addons
38 {
39 AddonsImpl(ApiHelper apiHelper, InternalModel.MinimalLinks root) throws MpacException
40 {
41 super(apiHelper, root, "addons");
42 }
43
44 @Override
45 public Option<Addon> getByKey(String addonKey, AddonQuery query) throws MpacException
46 {
47 InternalModel.Addons collectionRep = getEmptyBaseCollectionRep();
48 UriTemplate byKeyTemplate = ApiHelper.requireLinkUriTemplate(collectionRep.getLinks(), "byKey", InternalModel.Addons.class);
49 UriBuilder uri = UriBuilder.fromUri(byKeyTemplate.resolve(ImmutableMap.of("addonKey", addonKey)));
50 ApiHelper.addAddonQueryParams(query, uri);
51 return apiHelper.getOptionalEntity(uri.build(), Addon.class);
52 }
53
54 @Override
55 public Page<AddonSummary> find(AddonQuery query) throws MpacException
56 {
57 final UriBuilder uri = fromApiRoot();
58 ApiHelper.addAddonQueryParams(query, uri);
59 return apiHelper.getMore(new PageReference<AddonSummary>(
60 uri.build(), query.getBounds(), pageReader(InternalModel.Addons.class)));
61 }
62
63 @Override
64 public Addon createAddon(Addon addon) throws MpacException
65 {
66
67
68 Function<URI, URI> resultUriTransform = new Function<URI, URI>()
69 {
70 @Override
71 public URI apply(URI uri)
72 {
73 return UriBuilder.fromUri(uri).queryParam("withVersion", true).build();
74 }
75 };
76 return genericCreate(getApiRoot(), addon, resultUriTransform);
77 }
78
79 @Override
80 public Addon updateAddon(Addon original, Addon updated) throws MpacException
81 {
82 return genericUpdate(original.getSelfUri(), original, updated);
83 }
84
85 @Override
86 public Option<AddonVersion> getVersion(String addonKey, AddonVersionSpecifier version, AddonVersionsQuery query) throws MpacException
87 {
88 for (Addon a: getByKey(addonKey, AddonQuery.builder().accessToken(query.getAccessToken()).build()))
89 {
90 UriBuilder uri = UriBuilder.fromUri(getVersionUri(a, version));
91 ApiHelper.addAddonVersionsQueryParams(query, uri);
92 return apiHelper.getOptionalEntity(uri.build(), AddonVersion.class);
93 }
94 return none();
95 }
96
97 @Override
98 public Page<AddonVersionSummary> getVersions(String addonKey, AddonVersionsQuery query) throws MpacException
99 {
100 for (Addon a: getByKey(addonKey, AddonQuery.builder().accessToken(query.getAccessToken()).build()))
101 {
102 UriBuilder uri = UriBuilder.fromUri(getVersionsUri(a));
103 ApiHelper.addAddonVersionsQueryParams(query, uri);
104 return apiHelper.getMore(new PageReference<AddonVersionSummary>(
105 uri.build(), query.getBounds(), pageReader(InternalModel.AddonVersions.class)));
106 }
107 return Page.empty();
108 }
109
110 @Override
111 public AddonVersion createVersion(String addonKey, AddonVersion version) throws MpacException
112 {
113 for (Addon a: getByKey(addonKey, AddonQuery.any()))
114 {
115 return genericCreate(getVersionsUri(a), version);
116 }
117 throw new MpacException.ServerError(404);
118 }
119
120 @Override
121 public AddonVersion updateVersion(AddonVersion original, AddonVersion updated) throws MpacException
122 {
123 return genericUpdate(original.getSelfUri(), original, updated);
124 }
125
126 @Override
127 public Option<AddonPricing> getPricing(String addonKey, PricingType pricingType) throws MpacException
128 {
129 for (Addon a: getByKey(addonKey, AddonQuery.any()))
130 {
131 for (URI uri: a.getPricingUri(pricingType))
132 {
133 return apiHelper.getOptionalEntity(uri, AddonPricing.class);
134 }
135 }
136 return none();
137 }
138
139 @Override
140 public Page<AddonReference> findBanners(AddonQuery query) throws MpacException
141 {
142 InternalModel.Addons collectionRep = getEmptyBaseCollectionRep();
143 final UriBuilder uri = UriBuilder.fromUri(apiHelper.requireLinkUri(collectionRep.getLinks(), "banners", collectionRep.getClass()));
144 ApiHelper.addAddonQueryParams(query, uri);
145 return apiHelper.getMore(new PageReference<AddonReference>(uri.build(), query.getBounds(),
146 pageReader(InternalModel.AddonReferences.class)));
147 }
148
149 @Override
150 public Page<AddonReference> findRecommendations(String addonKey, AddonQuery query) throws MpacException
151 {
152 for (Addon a: getByKey(addonKey, AddonQuery.any()))
153 {
154 for (URI u: a.getLinks().getUri("recommendations"))
155 {
156 final UriBuilder uri = UriBuilder.fromUri(u);
157 ApiHelper.addAddonQueryParams(query, uri);
158 return apiHelper.getMore(new PageReference<AddonReference>(uri.build(), query.getBounds(),
159 pageReader(InternalModel.AddonReferences.class)));
160 }
161 }
162 return Page.empty();
163 }
164
165 @Override
166 public boolean claimAccessToken(String addonKey, String token) throws MpacException
167 {
168 for (Addon a: getByKey(addonKey, AddonQuery.builder().accessToken(some(token)).build()))
169 {
170 for (URI collUri: a.getLinks().getUri("tokens"))
171 {
172 InternalModel.MinimalLinks rep = apiHelper.getEntity(withZeroLimit(withAccessToken(collUri, token)),
173 InternalModel.MinimalLinks.class);
174 UriTemplate t = ApiHelper.requireLinkUriTemplate(rep.getLinks(), "byToken", rep.getClass());
175 URI uri = apiHelper.resolveLink(t.resolve(ImmutableMap.of("token", token)));
176 SimpleHttpResponse r = apiHelper.getHttp().post(uri, new NullInputStream(0), 0, JSON, JSON);
177 try
178 {
179 switch (r.getStatus())
180 {
181 case 200:
182 case 204:
183 return true;
184 case 400:
185 case 403:
186 case 404:
187 return false;
188 default:
189 throw apiHelper.responseException(r);
190 }
191 }
192 finally
193 {
194 r.close();
195 }
196 }
197 }
198 return false;
199 }
200
201 private InternalModel.Addons getEmptyBaseCollectionRep() throws MpacException
202 {
203 return apiHelper.getEntity(withZeroLimit(getApiRoot()), InternalModel.Addons.class);
204 }
205
206 private InternalModel.AddonVersions getEmptyVersionCollectionRep(Addon a) throws MpacException
207 {
208 URI uri = withZeroLimit(getVersionsUri(a));
209 return apiHelper.getEntity(uri, InternalModel.AddonVersions.class);
210 }
211
212 private URI getVersionsUri(Addon a) throws MpacException
213 {
214 return apiHelper.requireLinkUri(a.getLinks(), "versions", Addon.class);
215 }
216
217 private URI getVersionUri(Addon a, AddonVersionSpecifier v) throws MpacException
218 {
219 InternalModel.AddonVersions collectionRep = getEmptyVersionCollectionRep(a);
220 for (Either<String, Integer> specifiedVersion: v.getSpecifiedVersion())
221 {
222 for (String name: specifiedVersion.left())
223 {
224 return getTemplatedLink(collectionRep, "byName", "name", name);
225 }
226 for (Integer build: specifiedVersion.right())
227 {
228 return getTemplatedLink(collectionRep, "byBuild", "pluginBuildNumber", String.valueOf(build));
229 }
230 }
231 return apiHelper.requireLinkUri(collectionRep.getLinks(), "latest", InternalModel.AddonVersions.class);
232 }
233 }