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 * Returns the scope. 066 * @return the scope. 067 */ 068 public String getScope() { 069 return this.get("/$scope"); 070 } 071 072 /** 073 * Returns the template name. 074 * @return the template name. 075 */ 076 public String getTemplateName() { 077 return this.get("/$template"); 078 } 079 080 /** 081 * Adds a new metdata value. 082 * @param path the path that designates the key. Must be prefixed with a "/". 083 * @param value the value. 084 * @return this metadata object. 085 */ 086 public Metadata add(String path, String value) { 087 this.values.add(this.pathToProperty(path), value); 088 this.addOp("add", path, value); 089 return this; 090 } 091 092 /** 093 * Replaces an existing metdata value. 094 * @param path the path that designates the key. Must be prefixed with a "/". 095 * @param value the value. 096 * @return this metadata object. 097 */ 098 public Metadata replace(String path, String value) { 099 this.values.set(this.pathToProperty(path), value); 100 this.addOp("replace", path, value); 101 return this; 102 } 103 104 /** 105 * Removes an existing metadata value. 106 * @param path the path that designates the key. Must be prefixed with a "/". 107 * @return this metadata object. 108 */ 109 public Metadata remove(String path) { 110 this.values.remove(this.pathToProperty(path)); 111 this.addOp("remove", path, null); 112 return this; 113 } 114 115 /** 116 * Tests that a property has the expected value. 117 * @param path the path that designates the key. Must be prefixed with a "/". 118 * @param value the expected value. 119 * @return this metadata object. 120 */ 121 public Metadata test(String path, String value) { 122 this.addOp("test", path, value); 123 return this; 124 } 125 126 /** 127 * Returns a value. 128 * @param path the path that designates the key. Must be prefixed with a "/". 129 * @return the metadata property value. 130 */ 131 public String get(String path) { 132 final JsonValue value = this.values.get(this.pathToProperty(path)); 133 if (value == null) { 134 return null; 135 } 136 return value.asString(); 137 } 138 139 /** 140 * Returns the JSON patch string with all operations. 141 * @return the JSON patch string. 142 */ 143 public String getPatch() { 144 if (this.operations == null) { 145 return "[]"; 146 } 147 return this.operations.toString(); 148 } 149 150 /** 151 * Returns the JSON representation of this metadata. 152 * @return the JSON representation of this metadata. 153 */ 154 @Override 155 public String toString() { 156 return this.values.toString(); 157 } 158 159 /** 160 * Converts a JSON patch path to a JSON property name. 161 * Currently the metadata API only supports flat maps. 162 * @param path the path that designates the key. Must be prefixed with a "/". 163 * @return the JSON property name. 164 */ 165 private String pathToProperty(String path) { 166 if (path == null || !path.startsWith("/")) { 167 throw new IllegalArgumentException("Path must be prefixed with a \"/\"."); 168 } 169 return path.substring(1); 170 } 171 172 /** 173 * Adds a patch operation. 174 * @param op the operation type. Must be add, replace, remove, or test. 175 * @param path the path that designates the key. Must be prefixed with a "/". 176 * @param value the value to be set. 177 */ 178 private void addOp(String op, String path, String value) { 179 if (this.operations == null) { 180 this.operations = new JsonArray(); 181 } 182 183 this.operations.add(new JsonObject() 184 .add("op", op) 185 .add("path", path) 186 .add("value", value)); 187 } 188}