Skip to content

Commit 6a696f9

Browse files
committed
new update method. add listing by moderation kind and status. add moderation status in listing. add moderation flag in upload. add moderation_status in update. add ocr, raw_conversion, categorization, detection, similarity_search and auto_tagging parameters in update and upload. add support for uploading large raw files
1 parent 13b4977 commit 6a696f9

File tree

9 files changed

+424
-34
lines changed

9 files changed

+424
-34
lines changed

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

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -121,23 +121,29 @@ 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", "direction", "max_results", "prefix", "tags", "context"), options);
124+
return callApi(HttpMethod.GET, uri, only(options, "next_cursor", "direction", "max_results", "prefix", "tags", "context", "moderations"), options);
125125
}
126-
126+
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", "direction", "max_results", "tags", "context"), options);
130+
return callApi(HttpMethod.GET, Arrays.asList("resources", resourceType, "tags", tag), only(options, "next_cursor", "direction", "max_results", "tags", "context", "moderations"), options);
131131
}
132132

133133
public Map resourcesByIds(Iterable<String> publicIds, Map options) throws Exception {
134134
if (options == null) options = Cloudinary.emptyMap();
135135
String resourceType = Cloudinary.asString(options.get("resource_type"), "image");
136136
String type = Cloudinary.asString(options.get("type"), "upload");
137-
Map params = only(options, "tags", "context");
137+
Map params = only(options, "tags", "context", "moderations");
138138
params.put("public_ids", publicIds);
139139
return callApi(HttpMethod.GET, Arrays.asList("resources", resourceType, type), params, options);
140140
}
141+
142+
public Map resourcesByModeration(String kind, String status, Map options) throws Exception {
143+
if (options == null) options = Cloudinary.emptyMap();
144+
String resourceType = Cloudinary.asString(options.get("resource_type"), "image");
145+
return callApi(HttpMethod.GET, Arrays.asList("resources", resourceType, "moderations", kind, status), only(options, "next_cursor", "direction", "max_results", "tags", "context", "moderations"), options);
146+
}
141147

142148
public Map resource(String public_id, Map options) throws Exception {
143149
if (options == null) options = Cloudinary.emptyMap();
@@ -146,6 +152,17 @@ public Map resource(String public_id, Map options) throws Exception {
146152
return callApi(HttpMethod.GET, Arrays.asList("resources", resourceType, type, public_id),
147153
only(options, "exif", "colors", "faces", "image_metadata", "pages", "max_results"), options);
148154
}
155+
156+
public Map update(String public_id, Map options) throws Exception {
157+
if (options == null) options = Cloudinary.emptyMap();
158+
String resourceType = Cloudinary.asString(options.get("resource_type"), "image");
159+
String type = Cloudinary.asString(options.get("type"), "upload");
160+
Map params = new HashMap<String, Object>();
161+
Util.processWriteParameters(options, params);
162+
params.put("moderation_status", options.get("moderation_status"));
163+
return callApi(HttpMethod.POST, Arrays.asList("resources", resourceType, type, public_id),
164+
params, options);
165+
}
149166

150167
public Map deleteResources(Iterable<String> publicIds, Map options) throws Exception {
151168
if (options == null) options = Cloudinary.emptyMap();

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,16 @@ public static Boolean asBoolean(Object value, Boolean defaultValue) {
241241
}
242242
}
243243

244+
public static Float asFloat(Object value) {
245+
if (value == null) {
246+
return null;
247+
} else if (value instanceof Float) {
248+
return (Float) value;
249+
} else {
250+
return Float.parseFloat(value.toString());
251+
}
252+
}
253+
244254
public static Map asMap(Object...values) {
245255
if (values.length % 2 != 0) throw new RuntimeException("Usage - (key, value, key, value, ...)");
246256
Map result = new HashMap(values.length / 2);

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

Lines changed: 61 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
import java.io.File;
55
import java.io.IOException;
66
import java.io.InputStream;
7+
import java.io.FileInputStream;
8+
import java.io.ByteArrayInputStream;
79
import java.util.ArrayList;
810
import java.util.Arrays;
911
import java.util.Collection;
@@ -57,17 +59,14 @@ public Map<String, Object> buildUploadParams(Map options) {
5759
params.put(attr, value.toString());
5860
}
5961
params.put("eager", buildEager((List<Transformation>) options.get("eager")));
60-
params.put("headers", buildCustomHeaders(options.get("headers")));
6162
params.put("notification_url", (String) options.get("notification_url"));
6263
params.put("eager_notification_url", (String) options.get("eager_notification_url"));
6364
params.put("proxy", (String) options.get("proxy"));
6465
params.put("folder", (String) options.get("folder"));
65-
params.put("tags", StringUtils.join(Cloudinary.asArray(options.get("tags")), ","));
66-
if (options.get("face_coordinates") != null) {
67-
params.put("face_coordinates", options.get("face_coordinates").toString());
68-
}
6966
params.put("allowed_formats", StringUtils.join(Cloudinary.asArray(options.get("allowed_formats")), ","));
70-
params.put("context", Cloudinary.encodeMap(options.get("context")));
67+
params.put("moderation", options.get("moderation"));
68+
69+
Util.processWriteParameters(options, params);
7170
return params;
7271
}
7372

@@ -76,6 +75,61 @@ public Map upload(Object file, Map options) throws IOException {
7675
Map<String, Object> params = buildUploadParams(options);
7776
return callApi("upload", params, options, file);
7877
}
78+
79+
public Map uploadLargeRaw(Object file, Map options) throws IOException {
80+
return uploadLargeRaw(file, options, 20000000);
81+
}
82+
83+
public Map uploadLargeRaw(Object file, Map options, int bufferSize) throws IOException {
84+
InputStream input;
85+
if (file instanceof InputStream) {
86+
input = (InputStream) file;
87+
} else if (file instanceof File) {
88+
input = new FileInputStream((File) file);
89+
} else if (file instanceof byte[]) {
90+
input = new ByteArrayInputStream((byte[]) file);
91+
} else {
92+
input = new FileInputStream(new File(file.toString()));
93+
}
94+
try {
95+
Map result = uploadLargeRawPart(input, buildUploadParams(options), bufferSize);
96+
return result;
97+
} finally {
98+
input.close();
99+
}
100+
}
101+
102+
private Map uploadLargeRawPart(InputStream input, Map params, int bufferSize) throws IOException {
103+
Map nextParams = new HashMap();
104+
Map sentParams = new HashMap();
105+
nextParams.putAll(params);
106+
byte[] buffer = new byte[bufferSize];
107+
Map options = Cloudinary.asMap("resource_type", "raw");
108+
int bytesRead;
109+
int partNumber = 1;
110+
while ((bytesRead = input.read(buffer)) != -1) {
111+
if (bufferSize > bytesRead && bytesRead != -1) {
112+
byte[] shortBuffer = new byte[bytesRead];
113+
System.arraycopy(buffer, 0, shortBuffer, 0, bytesRead);
114+
buffer = shortBuffer;
115+
}
116+
nextParams.put("part_number", Integer.toString(partNumber));
117+
sentParams.clear();
118+
sentParams.putAll(nextParams);
119+
if (partNumber == 1) {
120+
Map response = callApi("upload_large", sentParams, options, buffer);
121+
nextParams.put("public_id", response.get("public_id"));
122+
nextParams.put("upload_id", response.get("upload_id"));
123+
} else {
124+
callApi("upload_large", sentParams, options, buffer);
125+
}
126+
partNumber++;
127+
}
128+
nextParams.put("final", true);
129+
nextParams.put("part_number", Integer.toString(partNumber));
130+
return callApi("upload_large", nextParams, options, new byte[0]);
131+
}
132+
79133

80134
public Map destroy(String publicId, Map options) throws IOException {
81135
if (options == null) options = Cloudinary.emptyMap();
@@ -103,7 +157,7 @@ public Map explicit(String publicId, Map options) throws IOException {
103157
params.put("callback", (String) options.get("callback"));
104158
params.put("type", (String) options.get("type"));
105159
params.put("eager", buildEager((List<Transformation>) options.get("eager")));
106-
params.put("headers", buildCustomHeaders(options.get("headers")));
160+
params.put("headers", Util.buildCustomHeaders(options.get("headers")));
107161
params.put("tags", StringUtils.join(Cloudinary.asArray(options.get("tags")), ","));
108162
if (options.get("face_coordinates") != null) {
109163
params.put("face_coordinates", options.get("face_coordinates").toString());
@@ -377,20 +431,4 @@ protected String buildEager(List<? extends Transformation> transformations) {
377431
return StringUtils.join(eager, "|");
378432
}
379433

380-
protected String buildCustomHeaders(Object headers) {
381-
if (headers == null) {
382-
return null;
383-
} else if (headers instanceof String) {
384-
return (String) headers;
385-
} else if (headers instanceof Object[]) {
386-
return StringUtils.join((Object[]) headers, "\n") + "\n";
387-
} else {
388-
Map<String, String> headersMap = (Map<String, String>) headers;
389-
StringBuilder builder = new StringBuilder();
390-
for (Map.Entry<String, String> header : headersMap.entrySet()) {
391-
builder.append(header.getKey()).append(": ").append(header.getValue()).append("\n");
392-
}
393-
return builder.toString();
394-
}
395-
}
396434
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package com.cloudinary;
2+
3+
import org.apache.commons.lang.StringUtils;
4+
5+
import java.util.Map;
6+
7+
public class Util {
8+
protected static final void processWriteParameters(
9+
Map<String, Object> options, Map<String, Object> params) {
10+
if (options.get("headers") != null)
11+
params.put("headers", buildCustomHeaders(options.get("headers")));
12+
if (options.get("tags") != null)
13+
params.put("tags", StringUtils.join(
14+
Cloudinary.asArray(options.get("tags")), ","));
15+
if (options.get("face_coordinates") != null)
16+
params.put("face_coordinates", options.get("face_coordinates")
17+
.toString());
18+
if (options.get("context") != null)
19+
params.put("context", Cloudinary.encodeMap(options.get("context")));
20+
if (options.get("ocr") != null)
21+
params.put("ocr", options.get("ocr"));
22+
if (options.get("raw_convert") != null)
23+
params.put("raw_convert", options.get("raw_convert"));
24+
if (options.get("categorization") != null)
25+
params.put("categorization", options.get("categorization"));
26+
if (options.get("detection") != null)
27+
params.put("detection", options.get("detection"));
28+
if (options.get("similarity_search") != null)
29+
params.put("similarity_search", options.get("similarity_search"));
30+
if (options.get("auto_tagging") != null)
31+
params.put("auto_tagging",
32+
Cloudinary.asFloat(options.get("auto_tagging")));
33+
}
34+
35+
protected static final String buildCustomHeaders(Object headers) {
36+
if (headers == null) {
37+
return null;
38+
} else if (headers instanceof String) {
39+
return (String) headers;
40+
} else if (headers instanceof Object[]) {
41+
return StringUtils.join((Object[]) headers, "\n") + "\n";
42+
} else {
43+
Map<String, String> headersMap = (Map<String, String>) headers;
44+
StringBuilder builder = new StringBuilder();
45+
for (Map.Entry<String, String> header : headersMap.entrySet()) {
46+
builder.append(header.getKey()).append(": ")
47+
.append(header.getValue()).append("\n");
48+
}
49+
return builder.toString();
50+
}
51+
}
52+
}

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

Lines changed: 128 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import static org.junit.Assert.assertEquals;
44
import static org.junit.Assert.assertNotNull;
5+
import static org.junit.Assert.assertNull;
56
import static org.junit.Assert.assertNotSame;
67
import static org.junit.Assert.assertTrue;
78
import static org.junit.Assume.assumeNotNull;
@@ -359,19 +360,140 @@ public void test19Ping() throws Exception {
359360
assertEquals(result.get("status"), "ok");
360361
}
361362

362-
private void assertContains(Object object, Collection list) {
363-
assertTrue(list.contains(object));
364-
}
365-
366363
// This test must be last because it deletes (potentially) all dependent transformations which some tests rely on.
367364
// Add @Test if you really want to test it - This test deletes derived resources!
368365
public void testDeleteAllResources() throws Exception {
369366
// should allow deleting all resources
370367
cloudinary.uploader().upload("src/test/resources/logo.png", Cloudinary.asMap("public_id", "api_test5", "eager", Collections.singletonList(new Transformation().crop("scale").width(2.0))));
371-
Map result = cloudinary.api().resource("api_test5", Cloudinary.emptyMap());
368+
Map result = api.resource("api_test5", Cloudinary.emptyMap());
372369
assertEquals(1, ((org.json.simple.JSONArray) result.get("derived")).size());
373370
api.deleteAllResources(Cloudinary.asMap("keep_original", true));
374-
result = cloudinary.api().resource("api_test5", Cloudinary.emptyMap());
371+
result = api.resource("api_test5", Cloudinary.emptyMap());
375372
//assertEquals(0, ((org.json.simple.JSONArray) result.get("derived")).size());
376373
}
374+
375+
376+
@Test
377+
public void testManualModeration() throws Exception {
378+
// should support setting manual moderation status
379+
Map uploadResult = cloudinary.uploader().upload("src/test/resources/logo.png", Cloudinary.asMap("moderation","manual"));
380+
Map apiResult = api.update((String) uploadResult.get("public_id"), Cloudinary.asMap("moderation_status", "approved"));
381+
assertEquals("approved", ((Map) ((List<Map>) apiResult.get("moderation")).get(0)).get("status"));
382+
}
383+
384+
@Test
385+
public void testOcrUpdate() {
386+
// should support requesting ocr info
387+
try {
388+
Map uploadResult = cloudinary.uploader().upload(
389+
"src/test/resources/logo.png", Cloudinary.emptyMap());
390+
api.update((String) uploadResult.get("public_id"),
391+
Cloudinary.asMap("ocr", "illegal"));
392+
} catch (Exception e) {
393+
assertTrue(e instanceof com.cloudinary.Api.BadRequest);
394+
assertTrue(e.getMessage().matches("^Illegal value(.*)"));
395+
}
396+
}
397+
398+
@Test
399+
public void testRawConvertUpdate() {
400+
// should support requesting raw conversion
401+
try {
402+
Map uploadResult = cloudinary.uploader().upload(
403+
"src/test/resources/logo.png", Cloudinary.emptyMap());
404+
api.update((String) uploadResult.get("public_id"),
405+
Cloudinary.asMap("raw_convert", "illegal"));
406+
} catch (Exception e) {
407+
assertTrue(e instanceof com.cloudinary.Api.BadRequest);
408+
assertTrue(e.getMessage().matches("^Illegal value(.*)"));
409+
}
410+
}
411+
412+
@Test
413+
public void testCategorizationUpdate() {
414+
// should support requesting categorization
415+
try {
416+
Map uploadResult = cloudinary.uploader().upload(
417+
"src/test/resources/logo.png", Cloudinary.emptyMap());
418+
api.update((String) uploadResult.get("public_id"),
419+
Cloudinary.asMap("categorization", "illegal"));
420+
} catch (Exception e) {
421+
assertTrue(e instanceof com.cloudinary.Api.BadRequest);
422+
assertTrue(e.getMessage().matches("^Illegal value(.*)"));
423+
}
424+
}
425+
426+
@Test
427+
public void testDetectionUpdate() {
428+
// should support requesting detection
429+
try {
430+
Map uploadResult = cloudinary.uploader().upload(
431+
"src/test/resources/logo.png", Cloudinary.emptyMap());
432+
api.update((String) uploadResult.get("public_id"),
433+
Cloudinary.asMap("detection", "illegal"));
434+
} catch (Exception e) {
435+
assertTrue(e instanceof com.cloudinary.Api.BadRequest);
436+
assertTrue(e.getMessage().matches("^Illegal value(.*)"));
437+
}
438+
}
439+
440+
@Test
441+
public void testSimilaritySearchUpdate() {
442+
// should support requesting similarity search
443+
try {
444+
Map uploadResult = cloudinary.uploader().upload(
445+
"src/test/resources/logo.png", Cloudinary.emptyMap());
446+
api.update((String) uploadResult.get("public_id"),
447+
Cloudinary.asMap("similarity_search", "illegal"));
448+
} catch (Exception e) {
449+
assertTrue(e instanceof com.cloudinary.Api.BadRequest);
450+
assertTrue(e.getMessage().matches("^Illegal value(.*)"));
451+
}
452+
}
453+
454+
@Test
455+
public void testListByModerationUpdate() throws Exception {
456+
// "should support listing by moderation kind and value
457+
Map result1 = cloudinary.uploader().upload(
458+
"src/test/resources/logo.png",
459+
Cloudinary.asMap("moderation", "manual"));
460+
Map result2 = cloudinary.uploader().upload(
461+
"src/test/resources/logo.png",
462+
Cloudinary.asMap("moderation", "manual"));
463+
Map result3 = cloudinary.uploader().upload(
464+
"src/test/resources/logo.png",
465+
Cloudinary.asMap("moderation", "manual"));
466+
api.update((String) result1.get("public_id"),
467+
Cloudinary.asMap("moderation_status", "approved"));
468+
api.update((String) result2.get("public_id"),
469+
Cloudinary.asMap("moderation_status", "rejected"));
470+
Map approved = api.resourcesByModeration("manual", "approved",
471+
Cloudinary.asMap("max_results", 1000));
472+
Map rejected = api.resourcesByModeration("manual", "rejected",
473+
Cloudinary.asMap("max_results", 1000));
474+
Map pending = api.resourcesByModeration("manual", "pending",
475+
Cloudinary.asMap("max_results", 1000));
476+
assertNotNull(findByAttr((List<Map>) approved.get("resources"),
477+
"public_id", (String) result1.get("public_id")));
478+
assertNull(findByAttr((List<Map>) approved.get("resources"),
479+
"public_id", (String) result2.get("public_id")));
480+
assertNull(findByAttr((List<Map>) approved.get("resources"),
481+
"public_id", (String) result2.get("public_id")));
482+
assertNotNull(findByAttr((List<Map>) rejected.get("resources"),
483+
"public_id", (String) result2.get("public_id")));
484+
assertNull(findByAttr((List<Map>) rejected.get("resources"),
485+
"public_id", (String) result1.get("public_id")));
486+
assertNull(findByAttr((List<Map>) rejected.get("resources"),
487+
"public_id", (String) result3.get("public_id")));
488+
assertNotNull(findByAttr((List<Map>) pending.get("resources"),
489+
"public_id", (String) result3.get("public_id")));
490+
assertNull(findByAttr((List<Map>) pending.get("resources"),
491+
"public_id", (String) result1.get("public_id")));
492+
assertNull(findByAttr((List<Map>) pending.get("resources"),
493+
"public_id", (String) result2.get("public_id")));
494+
}
495+
496+
private void assertContains(Object object, Collection list) {
497+
assertTrue(list.contains(object));
498+
}
377499
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy