Skip to content

Commit f265be4

Browse files
committed
Merge pull request #65 from codyebberson/cody-metadata
Fixes #63 - added metadata support
2 parents ba94103 + cb85f4f commit f265be4

File tree

3 files changed

+286
-0
lines changed

3 files changed

+286
-0
lines changed

src/main/java/com/box/sdk/BoxFile.java

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ public class BoxFile extends BoxItem {
3737
private static final URLTemplate COPY_URL_TEMPLATE = new URLTemplate("files/%s/copy");
3838
private static final URLTemplate ADD_COMMENT_URL_TEMPLATE = new URLTemplate("comments");
3939
private static final URLTemplate GET_COMMENTS_URL_TEMPLATE = new URLTemplate("files/%s/comments");
40+
private static final URLTemplate METADATA_URL_TEMPLATE = new URLTemplate("files/%s/metadata/%s");
41+
private static final String DEFAULT_METADATA_TYPE = "properties";
4042
private static final int BUFFER_SIZE = 8192;
4143

4244
/**
@@ -389,6 +391,81 @@ public List<BoxComment.Info> getComments() {
389391
return comments;
390392
}
391393

394+
/**
395+
* Creates metadata on this file.
396+
* @param metadata The new metadata values.
397+
* @return the metadata returned from the server.
398+
*/
399+
public Metadata createMetadata(Metadata metadata) {
400+
return this.createMetadata(DEFAULT_METADATA_TYPE, metadata);
401+
}
402+
403+
/**
404+
* Creates the metadata of specified type.
405+
* @param typeName the metadata type name.
406+
* @param metadata the new metadata values.
407+
* @return the metadata returned from the server.
408+
*/
409+
public Metadata createMetadata(String typeName, Metadata metadata) {
410+
URL url = METADATA_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID(), typeName);
411+
BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "POST");
412+
request.addHeader("Content-Type", "application/json");
413+
request.setBody(metadata.toString());
414+
BoxJSONResponse response = (BoxJSONResponse) request.send();
415+
return new Metadata(JsonObject.readFrom(response.getJSON()));
416+
}
417+
418+
/**
419+
* Gets the file properties metadata.
420+
* @return the metadata returned from the server.
421+
*/
422+
public Metadata getMetadata() {
423+
return this.getMetadata(DEFAULT_METADATA_TYPE);
424+
}
425+
426+
/**
427+
* Gets the file metadata of specified type.
428+
* @param typeName the metadata type name.
429+
* @return the metadata returned from the server.
430+
*/
431+
public Metadata getMetadata(String typeName) {
432+
URL url = METADATA_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID(), typeName);
433+
BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET");
434+
BoxJSONResponse response = (BoxJSONResponse) request.send();
435+
return new Metadata(JsonObject.readFrom(response.getJSON()));
436+
}
437+
438+
/**
439+
* Updates the file metadata.
440+
* @param metadata the new metadata values.
441+
* @return the metadata returned from the server.
442+
*/
443+
public Metadata updateMetadata(Metadata metadata) {
444+
URL url = METADATA_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID(), metadata.getTypeName());
445+
BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "PUT");
446+
request.addHeader("Content-Type", "application/json-patch+json");
447+
request.setBody(metadata.getPatch());
448+
BoxJSONResponse response = (BoxJSONResponse) request.send();
449+
return new Metadata(JsonObject.readFrom(response.getJSON()));
450+
}
451+
452+
/**
453+
* Deletes the file properties metadata.
454+
*/
455+
public void deleteMetadata() {
456+
this.deleteMetadata(DEFAULT_METADATA_TYPE);
457+
}
458+
459+
/**
460+
* Deletes the file metadata of specified type.
461+
* @param typeName the metadata type name.
462+
*/
463+
public void deleteMetadata(String typeName) {
464+
URL url = METADATA_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID(), typeName);
465+
BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "DELETE");
466+
request.send();
467+
}
468+
392469
/**
393470
* Contains information about a BoxFile.
394471
*/
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
package com.box.sdk;
2+
3+
import com.eclipsesource.json.JsonArray;
4+
import com.eclipsesource.json.JsonObject;
5+
6+
/**
7+
* The Metadata class represents one type instance of Box metadata.
8+
*
9+
* Learn more about Box metadata:
10+
* https://developers.box.com/metadata-api/
11+
*/
12+
public class Metadata {
13+
private final JsonObject values;
14+
private JsonArray operations;
15+
16+
/**
17+
* Creates an empty metadata.
18+
*/
19+
public Metadata() {
20+
this.values = new JsonObject();
21+
}
22+
23+
/**
24+
* Creates a new metadata.
25+
* @param values the initial metadata values.
26+
*/
27+
Metadata(JsonObject values) {
28+
this.values = values;
29+
}
30+
31+
/**
32+
* Creates a copy of another metadata.
33+
* @param other the other metadata object to copy.
34+
*/
35+
public Metadata(Metadata other) {
36+
this.values = new JsonObject(other.values);
37+
}
38+
39+
/**
40+
* Returns the 36 character UUID to identify the metadata object.
41+
* @return the metadata ID.
42+
*/
43+
public String getID() {
44+
return this.values.get("$id").asString();
45+
}
46+
47+
/**
48+
* Returns the metadata type.
49+
* @return the metadata type.
50+
*/
51+
public String getTypeName() {
52+
return this.values.get("$type").asString();
53+
}
54+
55+
/**
56+
* Returns the parent object ID (typically the file ID).
57+
* @return the parent object ID.
58+
*/
59+
public String getParentID() {
60+
return this.values.get("$parent").asString();
61+
}
62+
63+
/**
64+
* Adds a new metdata value.
65+
* @param path the path that designates the key. Must be prefixed with a "/".
66+
* @param value the value.
67+
* @return this metadata object.
68+
*/
69+
public Metadata add(String path, String value) {
70+
this.values.add(this.pathToProperty(path), value);
71+
this.addOp("add", path, value);
72+
return this;
73+
}
74+
75+
/**
76+
* Replaces an existing metdata value.
77+
* @param path the path that designates the key. Must be prefixed with a "/".
78+
* @param value the value.
79+
* @return this metadata object.
80+
*/
81+
public Metadata replace(String path, String value) {
82+
this.values.set(this.pathToProperty(path), value);
83+
this.addOp("replace", path, value);
84+
return this;
85+
}
86+
87+
/**
88+
* Removes an existing metadata value.
89+
* @param path the path that designates the key. Must be prefixed with a "/".
90+
* @return this metadata object.
91+
*/
92+
public Metadata remove(String path) {
93+
this.values.remove(this.pathToProperty(path));
94+
this.addOp("remove", path, null);
95+
return this;
96+
}
97+
98+
/**
99+
* Tests that a property has the expected value.
100+
* @param path the path that designates the key. Must be prefixed with a "/".
101+
* @param value the expected value.
102+
* @return this metadata object.
103+
*/
104+
public Metadata test(String path, String value) {
105+
this.addOp("test", path, value);
106+
return this;
107+
}
108+
109+
/**
110+
* Returns a value.
111+
* @param key the metadata property name.
112+
* @return the metadata property value.
113+
*/
114+
public String get(String key) {
115+
return this.values.get(key).asString();
116+
}
117+
118+
/**
119+
* Returns the JSON patch string with all operations.
120+
* @return the JSON patch string.
121+
*/
122+
public String getPatch() {
123+
if (this.operations == null) {
124+
return "[]";
125+
}
126+
return this.operations.toString();
127+
}
128+
129+
/**
130+
* Returns the JSON representation of this metadata.
131+
* @return the JSON representation of this metadata.
132+
*/
133+
@Override
134+
public String toString() {
135+
return this.values.toString();
136+
}
137+
138+
/**
139+
* Converts a JSON patch path to a JSON property name.
140+
* Currently the metadata API only supports flat maps.
141+
* @param path the path that designates the key. Must be prefixed with a "/".
142+
* @return the JSON property name.
143+
*/
144+
private String pathToProperty(String path) {
145+
return path.substring(1);
146+
}
147+
148+
/**
149+
* Adds a patch operation.
150+
* @param op the operation type. Must be add, replace, remove, or test.
151+
* @param path the path that designates the key. Must be prefixed with a "/".
152+
* @param value the value to be set.
153+
*/
154+
private void addOp(String op, String path, String value) {
155+
if (this.operations == null) {
156+
this.operations = new JsonArray();
157+
}
158+
159+
this.operations.add(new JsonObject()
160+
.add("op", op)
161+
.add("path", path)
162+
.add("value", value));
163+
}
164+
}

src/test/java/com/box/sdk/BoxFileTest.java

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import static org.mockito.Mockito.verify;
3030

3131
import org.hamcrest.Matchers;
32+
import org.junit.Assert;
3233
import org.junit.Test;
3334
import org.junit.experimental.categories.Category;
3435

@@ -356,4 +357,48 @@ public void addCommentWithMentionSucceeds() {
356357

357358
uploadedFile.delete();
358359
}
360+
361+
@Test
362+
@Category(IntegrationTest.class)
363+
public void createMetadataSucceeds() {
364+
BoxAPIConnection api = new BoxAPIConnection(TestConfig.getAccessToken());
365+
BoxFolder rootFolder = BoxFolder.getRootFolder(api);
366+
String fileName = "[createMetadataSucceeds] Test File.txt";
367+
byte[] fileBytes = "Non-empty string".getBytes(StandardCharsets.UTF_8);
368+
369+
InputStream uploadStream = new ByteArrayInputStream(fileBytes);
370+
BoxFile uploadedFile = rootFolder.uploadFile(uploadStream, fileName).getResource();
371+
uploadedFile.createMetadata(new Metadata().add("foo", "bar"));
372+
373+
Metadata check1 = uploadedFile.getMetadata();
374+
Assert.assertNotNull(check1);
375+
Assert.assertEquals("bar", check1.get("foo"));
376+
377+
uploadedFile.delete();
378+
}
379+
380+
@Test
381+
@Category(IntegrationTest.class)
382+
public void updateMetadataSucceeds() {
383+
BoxAPIConnection api = new BoxAPIConnection(TestConfig.getAccessToken());
384+
BoxFolder rootFolder = BoxFolder.getRootFolder(api);
385+
String fileName = "[updateMetadataSucceeds] Test File.txt";
386+
byte[] fileBytes = "Non-empty string".getBytes(StandardCharsets.UTF_8);
387+
388+
InputStream uploadStream = new ByteArrayInputStream(fileBytes);
389+
BoxFile uploadedFile = rootFolder.uploadFile(uploadStream, fileName).getResource();
390+
uploadedFile.createMetadata(new Metadata().add("foo", "bar"));
391+
392+
Metadata check1 = uploadedFile.getMetadata();
393+
Assert.assertNotNull(check1);
394+
Assert.assertEquals("bar", check1.get("foo"));
395+
396+
uploadedFile.updateMetadata(check1.replace("/foo", "baz"));
397+
398+
Metadata check2 = uploadedFile.getMetadata();
399+
Assert.assertNotNull(check2);
400+
Assert.assertEquals("baz", check2.get("foo"));
401+
402+
uploadedFile.delete();
403+
}
359404
}

0 commit comments

Comments
 (0)