001package com.box.sdk; 002 003import com.eclipsesource.json.JsonArray; 004import com.eclipsesource.json.JsonObject; 005import com.eclipsesource.json.JsonValue; 006 007/** 008 * The Metadata class represents one type instance of Box metadata. 009 * 010 * Learn more about Box metadata: 011 * https://developers.box.com/metadata-api/ 012 */ 013public class Metadata { 014 private final JsonObject values; 015 private JsonArray operations; 016 017 /** 018 * Creates an empty metadata. 019 */ 020 public Metadata() { 021 this.values = new JsonObject(); 022 } 023 024 /** 025 * Creates a new metadata. 026 * @param values the initial metadata values. 027 */ 028 Metadata(JsonObject values) { 029 this.values = values; 030 } 031 032 /** 033 * Creates a copy of another metadata. 034 * @param other the other metadata object to copy. 035 */ 036 public Metadata(Metadata other) { 037 this.values = new JsonObject(other.values); 038 } 039 040 /** 041 * Returns the 36 character UUID to identify the metadata object. 042 * @return the metadata ID. 043 */ 044 public String getID() { 045 return this.get("/$id"); 046 } 047 048 /** 049 * Returns the metadata type. 050 * @return the metadata type. 051 */ 052 public String getTypeName() { 053 return this.get("/$type"); 054 } 055 056 /** 057 * Returns the parent object ID (typically the file ID). 058 * @return the parent object ID. 059 */ 060 public String getParentID() { 061 return this.get("/$parent"); 062 } 063 064 /** 065 * Adds a new metdata value. 066 * @param path the path that designates the key. Must be prefixed with a "/". 067 * @param value the value. 068 * @return this metadata object. 069 */ 070 public Metadata add(String path, String value) { 071 this.values.add(this.pathToProperty(path), value); 072 this.addOp("add", path, value); 073 return this; 074 } 075 076 /** 077 * Replaces an existing metdata value. 078 * @param path the path that designates the key. Must be prefixed with a "/". 079 * @param value the value. 080 * @return this metadata object. 081 */ 082 public Metadata replace(String path, String value) { 083 this.values.set(this.pathToProperty(path), value); 084 this.addOp("replace", path, value); 085 return this; 086 } 087 088 /** 089 * Removes an existing metadata value. 090 * @param path the path that designates the key. Must be prefixed with a "/". 091 * @return this metadata object. 092 */ 093 public Metadata remove(String path) { 094 this.values.remove(this.pathToProperty(path)); 095 this.addOp("remove", path, null); 096 return this; 097 } 098 099 /** 100 * Tests that a property has the expected value. 101 * @param path the path that designates the key. Must be prefixed with a "/". 102 * @param value the expected value. 103 * @return this metadata object. 104 */ 105 public Metadata test(String path, String value) { 106 this.addOp("test", path, value); 107 return this; 108 } 109 110 /** 111 * Returns a value. 112 * @param path the path that designates the key. Must be prefixed with a "/". 113 * @return the metadata property value. 114 */ 115 public String get(String path) { 116 final JsonValue value = this.values.get(this.pathToProperty(path)); 117 if (value == null) { 118 return null; 119 } 120 return value.asString(); 121 } 122 123 /** 124 * Returns the JSON patch string with all operations. 125 * @return the JSON patch string. 126 */ 127 public String getPatch() { 128 if (this.operations == null) { 129 return "[]"; 130 } 131 return this.operations.toString(); 132 } 133 134 /** 135 * Returns the JSON representation of this metadata. 136 * @return the JSON representation of this metadata. 137 */ 138 @Override 139 public String toString() { 140 return this.values.toString(); 141 } 142 143 /** 144 * Converts a JSON patch path to a JSON property name. 145 * Currently the metadata API only supports flat maps. 146 * @param path the path that designates the key. Must be prefixed with a "/". 147 * @return the JSON property name. 148 */ 149 private String pathToProperty(String path) { 150 if (path == null || !path.startsWith("/")) { 151 throw new IllegalArgumentException("Path must be prefixed with a \"/\"."); 152 } 153 return path.substring(1); 154 } 155 156 /** 157 * Adds a patch operation. 158 * @param op the operation type. Must be add, replace, remove, or test. 159 * @param path the path that designates the key. Must be prefixed with a "/". 160 * @param value the value to be set. 161 */ 162 private void addOp(String op, String path, String value) { 163 if (this.operations == null) { 164 this.operations = new JsonArray(); 165 } 166 167 this.operations.add(new JsonObject() 168 .add("op", op) 169 .add("path", path) 170 .add("value", value)); 171 } 172}