1 /** 2 3 License: 4 Boost Software License - Version 1.0 - August 17th, 2003 5 6 Permission is hereby granted, free of charge, to any person or organization 7 obtaining a copy of the software and accompanying documentation covered by 8 this license (the "Software") to use, reproduce, display, distribute, 9 execute, and transmit the Software, and to prepare derivative works of the 10 Software, and to permit third-parties to whom the Software is furnished to 11 do so, all subject to the following: 12 13 The copyright notices in the Software and this entire statement, including 14 the above license grant, this restriction and the following disclaimer, 15 must be included in all copies of the Software, in whole or in part, and 16 all derivative works of the Software, unless such copies or derivative 17 works are solely in the form of machine-executable object code generated by 18 a source language processor. 19 20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 23 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 24 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 25 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26 DEALINGS IN THE SOFTWARE. 27 28 Authors: 29 Alexandru Ermicioi 30 **/ 31 module aermicioi.aedi.storage.object_storage; 32 33 import aermicioi.aedi.exception.not_found_exception; 34 import aermicioi.aedi.storage.alias_aware; 35 import aermicioi.aedi.storage.locator; 36 import aermicioi.aedi.storage.storage; 37 38 import std.conv; 39 40 /** 41 Implementation of Storage, Locator and AliasAware interfaces. 42 43 Stores Type elements by KeyType identity in. 44 **/ 45 @safe class ObjectStorage(Type = Object, KeyType = string) : Locator!(Type, KeyType), Storage!(Type, KeyType), AliasAware!(KeyType) { 46 47 private { 48 49 Type[const(KeyType)] values; 50 51 KeyType[const(KeyType)] aliasings; 52 } 53 54 public { 55 56 /** 57 Fetch an element by identity. 58 59 Params: 60 identity = the identity of element to be returned 61 62 Throws: 63 NotFoundException when no element is present in storage. 64 65 Returns: 66 Type the element with identity. 67 **/ 68 Type get(KeyType identity) { 69 70 if (!this.has(identity)) { 71 throw new NotFoundException("Element ${identity} not found.", identity.to!string); 72 } 73 74 return this.values[this.resolve(identity)]; 75 } 76 77 /** 78 Check if an element is present in storage. 79 80 Params: 81 identity = the identity of element. 82 83 Returns: 84 bool if element with identity exists in storage. 85 **/ 86 bool has(in KeyType identity) inout { 87 return (this.resolve(identity) in this.values) !is null; 88 } 89 90 /** 91 Save an element in storage by identity. 92 93 Params: 94 identity = the identity of element in storage. 95 element = the element which is saved in storage. 96 97 Returns: 98 ObjectStorage 99 **/ 100 ObjectStorage set(Type element, KeyType identity) { 101 102 this.values[identity] = element; 103 104 return this; 105 } 106 107 /** 108 Remove an element with identity from storage. 109 110 Params: 111 identity = identity of element which should be removed from storage. 112 113 Returns: 114 ObjectStorage 115 **/ 116 ObjectStorage remove(KeyType identity) { 117 118 this.values.remove(identity); 119 120 return this; 121 } 122 123 /** 124 Get the contents of storage as associative array. 125 126 Returns: 127 Type[KeyType] the contents of storage. 128 **/ 129 inout(Type[const(KeyType)]) contents() inout { 130 return this.values; 131 } 132 133 /** 134 Iterate over elements in storage 135 136 Params: 137 dg = the delegate which will do something on each element. 138 139 Returns: 140 int 141 **/ 142 int opApply(scope int delegate(Type value) dg) @trusted { 143 144 foreach (value; this.contents()) { 145 146 auto result = dg(value); 147 148 if (result != 0) { 149 return result; 150 } 151 } 152 153 return 0; 154 } 155 156 /** 157 ditto 158 **/ 159 int opApply(scope int delegate(const KeyType key, Type value) dg) @trusted { 160 161 foreach (key, value; this.contents()) { 162 163 auto result = dg(key, value); 164 165 if (result != 0) { 166 return result; 167 } 168 } 169 170 return 0; 171 } 172 173 /** 174 Alias an identity with alias_/ 175 176 Params: 177 identity = identity which will be aliased 178 alias_ = the new alias of identity. 179 180 Returns: 181 ObejcStorage 182 **/ 183 ObjectStorage link(KeyType identity, KeyType alias_) { 184 185 this.aliasings[alias_] = identity; 186 187 return this; 188 } 189 190 /** 191 Removes alias. 192 193 Params: 194 alias_ = alias to remove. 195 196 Returns: 197 this 198 199 **/ 200 ObjectStorage unlink(KeyType alias_) { 201 this.aliasings.remove(alias_); 202 203 return this; 204 } 205 206 /** 207 Resolve the alias to an element identity. 208 209 Params: 210 alias_ = the alias to an identity. 211 Returns: 212 KeyType the last found identity in alias chain. 213 **/ 214 const(KeyType) resolve(in KeyType alias_) const { 215 if (alias_ in this.aliasings) { 216 return this.resolve(this.aliasings[alias_]); 217 } 218 219 return alias_; 220 } 221 } 222 }