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.storage.container; 34 import aermicioi.aedi.storage.alias_aware; 35 import aermicioi.aedi.exception.not_found_exception; 36 37 import std.conv; 38 39 /** 40 Implementation of Storage, Locator and AliasAware interfaces. 41 42 Stores Type elements by KeyType identity in. 43 **/ 44 class ObjectStorage(Type = Object, KeyType = string) : Container!(Type, KeyType), AliasAware!(KeyType) { 45 46 private { 47 48 Type[const(KeyType)] values; 49 50 KeyType[const(KeyType)] aliasings; 51 } 52 53 public { 54 55 /** 56 Fetch an element by identity. 57 58 Params: 59 identity = the identity of element to be returned 60 61 Throws: 62 NotFoundException when no element is present in storage. 63 64 Returns: 65 Type the element with identity. 66 **/ 67 Type get(KeyType identity) { 68 69 if (!this.has(identity)) { 70 throw new NotFoundException("Element " ~ identity.to!string ~ " not found."); 71 } 72 73 return this.values[this.resolve(identity)]; 74 } 75 76 /** 77 Check if an element is present in storage. 78 79 Params: 80 identity = the identity of element. 81 82 Returns: 83 bool if element with identity exists in storage. 84 **/ 85 bool has(in KeyType identity) inout { 86 return (this.resolve(identity) in this.values) !is null; 87 } 88 89 /** 90 Save an element in storage by identity. 91 92 Params: 93 identity = the identity of element in storage. 94 element = the element which is saved in storage. 95 96 Returns: 97 ObjectStorage 98 **/ 99 ObjectStorage set(Type element, KeyType identity) { 100 101 this.values[identity] = element; 102 103 return this; 104 } 105 106 /** 107 Remove an element with identity from storage. 108 109 Params: 110 identity = identity of element which should be removed from storage. 111 112 Returns: 113 ObjectStorage 114 **/ 115 ObjectStorage remove(KeyType identity) { 116 117 this.values.remove(identity); 118 119 return this; 120 } 121 122 /** 123 Get the contents of storage as associative array. 124 125 Returns: 126 Type[KeyType] the contents of storage. 127 **/ 128 inout(Type[const(KeyType)]) contents() inout { 129 return this.values; 130 } 131 132 /** 133 Iterate over elements in storage 134 135 Params: 136 dg = the delegate which will do something on each element. 137 138 Returns: 139 int 140 **/ 141 int opApply(scope int delegate(Type value) dg) { 142 143 foreach (value; this.contents()) { 144 145 auto result = dg(value); 146 147 if (result != 0) { 148 return result; 149 } 150 } 151 152 return 0; 153 } 154 155 /** 156 ditto 157 **/ 158 int opApply(scope int delegate(const KeyType key, Type value) dg) { 159 160 foreach (key, value; this.contents()) { 161 162 auto result = dg(key, value); 163 164 if (result != 0) { 165 return result; 166 } 167 } 168 169 return 0; 170 } 171 172 /** 173 Alias an identity with alias_/ 174 175 Params: 176 identity = identity which will be aliased 177 alias_ = the new alias of identity. 178 179 Returns: 180 ObejcStorage 181 **/ 182 ObjectStorage link(KeyType identity, KeyType alias_) { 183 184 this.aliasings[alias_] = identity; 185 186 return this; 187 } 188 189 /** 190 Removes alias. 191 192 Params: 193 alias_ = alias to remove. 194 195 Returns: 196 this 197 198 **/ 199 ObjectStorage unlink(KeyType alias_) { 200 this.aliasings.remove(alias_); 201 202 return this; 203 } 204 205 /** 206 Resolve the alias to an element identity. 207 208 Params: 209 alias_ = the alias to an identity. 210 Returns: 211 KeyType the last found identity in alias chain. 212 **/ 213 const(KeyType) resolve(in KeyType alias_) const { 214 import std.typecons : Rebindable; 215 Rebindable!(const(KeyType)) aliased = alias_; 216 217 while ((aliased in this.aliasings) !is null) { 218 aliased = this.aliasings[aliased]; 219 } 220 221 return aliased; 222 } 223 } 224 }