Skip to content

Commit c2284f0

Browse files
committed
delete all + cursors, tag and context flags in lists, list by public ids, add support in upload for: face_coordinates, alowed_formats, context
1 parent 49a5ffa commit c2284f0

File tree

7 files changed

+207
-9
lines changed

7 files changed

+207
-9
lines changed

cloudinary-core/src/main/java/com/cloudinary/Api.java

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -121,13 +121,22 @@ public Map resources(Map options) throws Exception {
121121
uri.add(resourceType);
122122
if (type != null)
123123
uri.add(type);
124-
return callApi(HttpMethod.GET, uri, only(options, "next_cursor", "max_results", "prefix"), options);
124+
return callApi(HttpMethod.GET, uri, only(options, "next_cursor", "max_results", "prefix", "tags", "context"), options);
125125
}
126126

127127
public Map resourcesByTag(String tag, Map options) throws Exception {
128128
if (options == null) options = Cloudinary.emptyMap();
129129
String resourceType = Cloudinary.asString(options.get("resource_type"), "image");
130-
return callApi(HttpMethod.GET, Arrays.asList("resources", resourceType, "tags", tag), only(options, "next_cursor", "max_results"), options);
130+
return callApi(HttpMethod.GET, Arrays.asList("resources", resourceType, "tags", tag), only(options, "next_cursor", "max_results", "tags", "context"), options);
131+
}
132+
133+
public Map resourcesByIds(Iterable<String> publicIds, Map options) throws Exception {
134+
if (options == null) options = Cloudinary.emptyMap();
135+
String resourceType = Cloudinary.asString(options.get("resource_type"), "image");
136+
String type = Cloudinary.asString(options.get("type"), "upload");
137+
Map params = only(options, "tags", "context");
138+
params.put("public_ids", publicIds);
139+
return callApi(HttpMethod.GET, Arrays.asList("resources", resourceType, type), params, options);
131140
}
132141

133142
public Map resource(String public_id, Map options) throws Exception {
@@ -142,7 +151,7 @@ public Map deleteResources(Iterable<String> publicIds, Map options) throws Excep
142151
if (options == null) options = Cloudinary.emptyMap();
143152
String resourceType = Cloudinary.asString(options.get("resource_type"), "image");
144153
String type = Cloudinary.asString(options.get("type"), "upload");
145-
Map params = only(options, "keep_original");
154+
Map params = only(options, "keep_original", "next_cursor");
146155
params.put("public_ids", publicIds);
147156
return callApi(HttpMethod.DELETE, Arrays.asList("resources", resourceType, type), params, options);
148157
}
@@ -151,15 +160,24 @@ public Map deleteResourcesByPrefix(String prefix, Map options) throws Exception
151160
if (options == null) options = Cloudinary.emptyMap();
152161
String resourceType = Cloudinary.asString(options.get("resource_type"), "image");
153162
String type = Cloudinary.asString(options.get("type"), "upload");
154-
Map params = only(options, "keep_original");
163+
Map params = only(options, "keep_original", "next_cursor");
155164
params.put("prefix", prefix);
156165
return callApi(HttpMethod.DELETE, Arrays.asList("resources", resourceType, type), params, options);
157166
}
158167

159168
public Map deleteResourcesByTag(String tag, Map options) throws Exception {
160169
if (options == null) options = Cloudinary.emptyMap();
161170
String resourceType = Cloudinary.asString(options.get("resource_type"), "image");
162-
return callApi(HttpMethod.DELETE, Arrays.asList("resources", resourceType, "tags", tag), only(options, "keep_original"), options);
171+
return callApi(HttpMethod.DELETE, Arrays.asList("resources", resourceType, "tags", tag), only(options, "keep_original", "next_cursor"), options);
172+
}
173+
174+
public Map deleteAllResources(Map options) throws Exception {
175+
if (options == null) options = Cloudinary.emptyMap();
176+
String resourceType = Cloudinary.asString(options.get("resource_type"), "image");
177+
String type = Cloudinary.asString(options.get("type"), "upload");
178+
Map filtered = only(options, "keep_original", "next_cursor");
179+
filtered.put("all", true);
180+
return callApi(HttpMethod.DELETE, Arrays.asList("resources", resourceType, type), filtered, options);
163181
}
164182

165183
public Map deleteDerivedResources(Iterable<String> derivedResourceIds, Map options) throws Exception {

cloudinary-core/src/main/java/com/cloudinary/Cloudinary.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,12 @@ public static String asString(Object value, String defaultValue) {
210210
public static List asArray(Object value) {
211211
if (value == null) {
212212
return Collections.EMPTY_LIST;
213+
} else if (value instanceof int[]){
214+
List array = new ArrayList();
215+
for (int i: (int[]) value) {
216+
array.add(new Integer(i));
217+
}
218+
return array;
213219
} else if (value instanceof Object[]){
214220
return Arrays.asList((Object[]) value);
215221
} else if (value instanceof List) {

cloudinary-core/src/main/java/com/cloudinary/Uploader.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import java.util.Arrays;
99
import java.util.Collection;
1010
import java.util.HashMap;
11+
import java.util.HashSet;
1112
import java.util.Iterator;
1213
import java.util.List;
1314
import java.util.Map;
@@ -62,6 +63,21 @@ public Map<String, Object> buildUploadParams(Map options) {
6263
params.put("proxy", (String) options.get("proxy"));
6364
params.put("folder", (String) options.get("folder"));
6465
params.put("tags", StringUtils.join(Cloudinary.asArray(options.get("tags")), ","));
66+
params.put("face_coordinates", StringUtils.join(Cloudinary.asArray(options.get("face_coordinates")), ","));
67+
params.put("allowed_formats", StringUtils.join(Cloudinary.asArray(options.get("allowed_formats")), ","));
68+
Map<String,String> inputContext = null;
69+
if (options.get("context") != null && options.get("context") instanceof Map) {
70+
inputContext = ((Map<String,String>) options.get("context"));
71+
}
72+
if (inputContext != null) {
73+
HashSet context = new HashSet();
74+
for (Map.Entry<String, String> entry : inputContext.entrySet()) {
75+
context.add(entry.getKey() + "=" + entry.getValue());
76+
}
77+
params.put("context", StringUtils.join(context.toArray(), "|"));
78+
} else {
79+
params.put("context", options.get("context"));
80+
}
6581
return params;
6682
}
6783

@@ -99,6 +115,7 @@ public Map explicit(String publicId, Map options) throws IOException {
99115
params.put("eager", buildEager((List<Transformation>) options.get("eager")));
100116
params.put("headers", buildCustomHeaders(options.get("headers")));
101117
params.put("tags", StringUtils.join(Cloudinary.asArray(options.get("tags")), ","));
118+
params.put("face_coordinates", StringUtils.join(Cloudinary.asArray(options.get("face_coordinates")), ","));
102119
return callApi("explicit", params, options, null);
103120
}
104121

cloudinary-core/src/test/java/com/cloudinary/test/ApiTest.java

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ public static void setUpClass() throws IOException {
5555
Map options = Cloudinary.asMap(
5656
"public_id", "api_test",
5757
"tags", "api_test_tag",
58+
"context", "key=value",
5859
"eager", Collections.singletonList(new Transformation().width(100).crop("scale")));
5960
cloudinary.uploader().upload("src/test/resources/logo.png", options);
6061
options.put("public_id", "api_test1");
@@ -123,18 +124,51 @@ public void test04ResourcesByType() throws Exception {
123124
@Test
124125
public void test05ResourcesByPrefix() throws Exception {
125126
// should allow listing resources by prefix
126-
Map result = api.resources(Cloudinary.asMap("type", "upload", "prefix", "api_test"));
127+
Map result = api.resources(Cloudinary.asMap("type", "upload", "prefix", "api_test", "tags", true, "context", true));
127128
List<Map> resources = (List<Map>) result.get("resources");
128129
assertNotNull(findByAttr(resources, "public_id", "api_test"));
129130
assertNotNull(findByAttr(resources, "public_id", "api_test1"));
131+
assertNotNull(findByAttr((List<Map>) result.get("resources"), "context", Cloudinary.asMap("custom", Cloudinary.asMap("key", "value"))));
132+
boolean found = false;
133+
for (Map r: resources) {
134+
org.json.simple.JSONArray tags = (org.json.simple.JSONArray) r.get("tags");
135+
found = found || tags.contains("api_test_tag");
136+
}
137+
assertTrue(found);
130138
}
131-
139+
140+
@Test
141+
public void testResourcesByPublicIds() throws Exception {
142+
// should allow listing resources by public ids
143+
Map result = api.resourcesByIds(Arrays.asList("api_test", "api_test1", "bogus"), Cloudinary.asMap("type", "upload", "tags", true, "context", true));
144+
List<Map> resources = (List<Map>) result.get("resources");
145+
assertEquals(2, resources.size());
146+
assertNotNull(findByAttr(resources, "public_id", "api_test"));
147+
assertNotNull(findByAttr(resources, "public_id", "api_test1"));
148+
assertNotNull(findByAttr((List<Map>) result.get("resources"), "context", Cloudinary.asMap("custom", Cloudinary.asMap("key", "value"))));
149+
boolean found = false;
150+
for (Map r: resources) {
151+
org.json.simple.JSONArray tags = (org.json.simple.JSONArray) r.get("tags");
152+
found = found || tags.contains("api_test_tag");
153+
}
154+
assertTrue(found);
155+
}
156+
132157
@Test
133158
public void test06ResourcesTag() throws Exception {
134159
// should allow listing resources by tag
135-
Map result = api.resourcesByTag("api_test_tag", Cloudinary.emptyMap());
160+
Map result = api.resourcesByTag("api_test_tag", Cloudinary.asMap("tags", true, "context", true));
136161
Map resource = findByAttr((List<Map>) result.get("resources"), "public_id", "api_test");
137162
assertNotNull(resource);
163+
resource = findByAttr((List<Map>) result.get("resources"), "context", Cloudinary.asMap("custom", Cloudinary.asMap("key", "value")));
164+
assertNotNull(resource);
165+
List<Map> resources = (List<Map>) result.get("resources");
166+
boolean found = false;
167+
for (Map r: resources) {
168+
org.json.simple.JSONArray tags = (org.json.simple.JSONArray) r.get("tags");
169+
found = found || tags.contains("api_test_tag");
170+
}
171+
assertTrue(found);
138172
}
139173

140174
@Test
@@ -317,4 +351,16 @@ public void test19Ping() throws Exception {
317351
private void assertContains(Object object, Collection list) {
318352
assertTrue(list.contains(object));
319353
}
354+
355+
//this test must be last because it deletes (potentially) all dependent transformations which some tests rely on.
356+
@Test
357+
public void testDeleteAllResources() throws Exception {
358+
// should allow deleting all resources
359+
cloudinary.uploader().upload("src/test/resources/logo.png", Cloudinary.asMap("public_id", "api_test5", "eager", Collections.singletonList(new Transformation().crop("scale").width(2.0))));
360+
Map result = cloudinary.api().resource("api_test5", Cloudinary.emptyMap());
361+
assertEquals(1, ((org.json.simple.JSONArray) result.get("derived")).size());
362+
api.deleteAllResources(Cloudinary.asMap("keep_original", true));
363+
result = cloudinary.api().resource("api_test5", Cloudinary.emptyMap());
364+
//assertEquals(0, ((org.json.simple.JSONArray) result.get("derived")).size());
365+
}
320366
}

cloudinary-core/src/test/java/com/cloudinary/test/UploaderTest.java

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,9 @@ public void testUniqueFilename() throws Exception {
105105
public void testExplicit() throws IOException {
106106
Map result = cloudinary.uploader().explicit("cloudinary", Cloudinary.asMap("eager", Collections.singletonList(new Transformation().crop("scale").width(2.0)), "type", "twitter_name"));
107107
String url = cloudinary.url().type("twitter_name").transformation(new Transformation().crop("scale").width(2.0)).format("png").version(result.get("version")).generate("cloudinary");
108-
assertEquals(((Map) ((List)result.get("eager")).get(0)).get("url"), url);
108+
String eagerUrl = (String) ((Map) ((List)result.get("eager")).get(0)).get("url");
109+
String cloudName = cloudinary.getStringConfig("cloud_name");
110+
assertEquals(eagerUrl.substring(eagerUrl.indexOf(cloudName)), url.substring(url.indexOf(cloudName)));
109111
}
110112

111113
@Test
@@ -181,4 +183,68 @@ public void testTags() throws Exception {
181183
tags = (List<String>) cloudinary.api().resource(public_id, Cloudinary.emptyMap()).get("tags");
182184
assertEquals(tags, Cloudinary.asArray(new String[]{"tag3"}));
183185
}
186+
187+
@Test
188+
public void testAllowedFormats() throws Exception {
189+
//should allow whitelisted formats if allowed_formats
190+
String[] formats = {"png"};
191+
Map result = cloudinary.uploader().upload("src/test/resources/logo.png", Cloudinary.asMap("allowed_formats", formats));
192+
assertEquals(result.get("format"), "png");
193+
}
194+
195+
@Test
196+
public void testAllowedFormatsWithIllegalFormat() throws Exception {
197+
//should prevent non whitelisted formats from being uploaded if allowed_formats is specified
198+
boolean error_found = false;
199+
String[] formats = {"jpg"};
200+
try{
201+
cloudinary.uploader().upload("src/test/resources/logo.png", Cloudinary.asMap("allowed_formats", formats));
202+
} catch(Exception e) {
203+
error_found=true;
204+
}
205+
assertTrue(error_found);
206+
}
207+
208+
@Test
209+
public void testAllowedFormatsWithFormat() throws Exception {
210+
//should allow non whitelisted formats if type is specified and convert to that type
211+
String[] formats = {"jpg"};
212+
Map result = cloudinary.uploader().upload("src/test/resources/logo.png", Cloudinary.asMap("allowed_formats", formats, "format", "jpg"));
213+
assertEquals("jpg", result.get("format"));
214+
}
215+
216+
@Test
217+
public void testFaceCoordinates() throws Exception {
218+
//should allow sending face coordinates
219+
Long[] coordinates = new Long[]{120L,30L,109L,150L};
220+
Map result = cloudinary.uploader().upload("src/test/resources/logo.png", Cloudinary.asMap("face_coordinates", coordinates, "faces", true));
221+
org.json.simple.JSONArray resultFaces = (org.json.simple.JSONArray) result.get("faces");
222+
assertEquals(1, resultFaces.size());
223+
Object[] resultCoordinates = ((org.json.simple.JSONArray) resultFaces.get(0)).toArray();
224+
assertEquals(4, resultCoordinates.length);
225+
for (int i=0; i < resultCoordinates.length; i++) {
226+
assertEquals(coordinates[i], resultCoordinates[i]);
227+
}
228+
229+
Long[] differentCoordinates = new Long[]{121L,31L,110L,151L};
230+
cloudinary.uploader().explicit((String) result.get("public_id"), Cloudinary.asMap("face_coordinates", differentCoordinates, "faces", true, "type", "upload"));
231+
Map info = cloudinary.api().resource((String) result.get("public_id"), Cloudinary.asMap("faces", true));
232+
233+
resultFaces = (org.json.simple.JSONArray) info.get("faces");
234+
assertEquals(1, resultFaces.size());
235+
resultCoordinates = ((org.json.simple.JSONArray) resultFaces.get(0)).toArray();
236+
assertEquals(4, resultCoordinates.length);
237+
for (int i=0; i < resultCoordinates.length; i++) {
238+
assertEquals(differentCoordinates[i], resultCoordinates[i]);
239+
}
240+
}
241+
242+
@Test
243+
public void testContext() throws Exception {
244+
//should allow sending context
245+
Map context = Cloudinary.asMap("caption", "some caption", "alt", "alternative");
246+
Map result = cloudinary.uploader().upload("src/test/resources/logo.png", Cloudinary.asMap("context", context));
247+
Map info = cloudinary.api().resource((String) result.get("public_id"), Cloudinary.asMap("context", true));
248+
assertEquals(Cloudinary.asMap("custom", context), info.get("context"));
249+
}
184250
}

cloudinary-taglib/src/main/java/com/cloudinary/taglib/CloudinaryUploadTag.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ public class CloudinaryUploadTag extends SimpleTagSupport {
3131
private String eagerNotificationUrl = null;
3232
private String proxy = null;
3333
private String folder = null;
34+
private String faceCoordinates = null;
35+
private String allowedFormats = null;
36+
private String context = null;
3437
private boolean backup = false;
3538
private boolean exif = false;
3639
private boolean faces = false;
@@ -76,6 +79,9 @@ public void doTag() throws JspException, IOException {
7679
options.put("unique_filename", uniqueFilename);
7780
options.put("eager_async", eagerAsync);
7881
options.put("invalidate", invalidate);
82+
options.put("face_coordinates", faceCoordinates);
83+
options.put("allowed_formats", allowedFormats);
84+
options.put("context", context);
7985

8086
buildCallbackUrl(options);
8187

@@ -284,6 +290,30 @@ public String getCallback() {
284290
public void setCallback(String callback) {
285291
this.callback = callback;
286292
}
293+
294+
public String getFaceCoordinates() {
295+
return faceCoordinates;
296+
}
297+
298+
public void setFaceCoordinates(String faceCoordinates) {
299+
this.faceCoordinates = faceCoordinates;
300+
}
301+
302+
public String getAllowedFormats() {
303+
return allowedFormats;
304+
}
305+
306+
public void setAllowedFormats(String allowedFormats) {
307+
this.allowedFormats = allowedFormats;
308+
}
309+
310+
public String getContext() {
311+
return context;
312+
}
313+
314+
public void setContext(String context) {
315+
this.context = context;
316+
}
287317

288318
private void buildCallbackUrl(Map options) {
289319
String callback = (String) options.get("callback");

cloudinary-taglib/src/main/resources/META-INF/cloudinary.tld

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,21 @@
135135
<required>false</required>
136136
<rtexprvalue>true</rtexprvalue>
137137
</attribute>
138+
<attribute>
139+
<name>faceCoordinates</name>
140+
<required>false</required>
141+
<rtexprvalue>true</rtexprvalue>
142+
</attribute>
143+
<attribute>
144+
<name>allowedFormats</name>
145+
<required>false</required>
146+
<rtexprvalue>true</rtexprvalue>
147+
</attribute>
148+
<attribute>
149+
<name>context</name>
150+
<required>false</required>
151+
<rtexprvalue>true</rtexprvalue>
152+
</attribute>
138153
</tag>
139154
<tag>
140155
<name>transformation</name>

0 commit comments

Comments
 (0)