1 /** 2 License: 3 Boost Software License - Version 1.0 - August 17th, 2003 4 5 Permission is hereby granted, free of charge, to any person or organization 6 obtaining a copy of the software and accompanying documentation covered by 7 this license (the "Software") to use, reproduce, display, distribute, 8 execute, and transmit the Software, and to prepare derivative works of the 9 Software, and to permit third-parties to whom the Software is furnished to 10 do so, all subject to the following: 11 12 The copyright notices in the Software and this entire statement, including 13 the above license grant, this restriction and the following disclaimer, 14 must be included in all copies of the Software, in whole or in part, and 15 all derivative works of the Software, unless such copies or derivative 16 works are solely in the form of machine-executable object code generated by 17 a source language processor. 18 19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 22 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 23 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 24 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 DEALINGS IN THE SOFTWARE. 26 27 Authors: 28 aermicioi 29 **/ 30 module aermicioi.aedi.container.proxy_container; 31 32 import aermicioi.aedi.container.container; 33 import aermicioi.aedi.storage.storage; 34 import aermicioi.aedi.storage.object_storage; 35 import aermicioi.aedi.factory.proxy_factory; 36 import aermicioi.aedi.exception.not_found_exception; 37 import aermicioi.aedi.storage.locator; 38 import aermicioi.aedi.storage.decorator; 39 import aermicioi.aedi.storage.alias_aware; 40 import aermicioi.aedi.factory.factory; 41 import std.range; 42 import std.typecons; 43 import std.meta; 44 import std.traits; 45 import aermicioi.util.traits; 46 47 /** 48 TODO: Add description of what this is and why it was designed as such. 49 **/ 50 interface ProxyContainer : Container, Storage!(ProxyObjectFactory, string), 51 Decorator!(Locator!()) 52 { 53 54 } 55 56 /** 57 Templated switchable container. 58 59 Templated switchable container. This container will 60 decorate another container, and add switching logic 61 to it. Depending in which state (on/off) the switching 62 container is. It will instantiate if the container is on, 63 and not if container is in off mode. This container will 64 inherit following interfaces only and only if the 65 T also implements them: 66 $(OL 67 $(LI Storage!(ObjectFactory, string)) 68 $(LI Container) 69 $(LI AliasAware!string) 70 ) 71 72 Params: 73 T = The container that switchable container will decorate. 74 75 **/ 76 template ProxyContainerImpl(T) 77 { 78 /** 79 Set which the switchable container will decorate for T. By default 80 Locator!() and Switchable is included. 81 **/ 82 alias InheritanceSet = 83 NoDuplicates!( 84 Filter!( 85 templateOr!( 86 partialSuffixed!( 87 isDerived, 88 Storage!(ObjectFactory, 89 string) 90 ), 91 partialSuffixed!( 92 isDerived, 93 AliasAware!string 94 ), 95 partialSuffixed!( 96 isDerived, 97 FactoryLocator!ObjectFactory 98 ) 99 ), 100 InterfacesTuple!T 101 ), 102 ProxyContainer, 103 MutableDecorator!T 104 ); 105 106 /** 107 Templated proxy container. 108 **/ 109 class ProxyContainerImpl : InheritanceSet 110 { 111 private 112 { 113 T decorated_; 114 115 ObjectStorage!(ProxyObjectFactory, string) proxyFactories; 116 } 117 118 public 119 { 120 121 /** 122 * Default constructor for ProxyContainerImpl 123 **/ 124 this() { 125 126 this.proxyFactories = new ObjectStorage!(ProxyObjectFactory, string); 127 } 128 129 @property 130 { 131 /** 132 Set the decorated object for decorator. 133 134 Params: 135 decorated = decorated data 136 137 Returns: 138 typeof(this) 139 **/ 140 ProxyContainerImpl decorated(T decorated) @safe nothrow 141 { 142 this.decorated_ = decorated; 143 144 return this; 145 } 146 147 /** 148 Get the decorated object. 149 150 Returns: 151 T decorated object 152 **/ 153 T decorated() @safe nothrow 154 { 155 return this.decorated_; 156 } 157 } 158 159 /** 160 * Set object factory 161 * 162 * Params: 163 * factory = factory for a object that is to be managed by prototype container. 164 * identity = identity by which a factory is identified 165 * Returns: 166 * typeof(this) 167 **/ 168 ProxyContainerImpl set(ProxyObjectFactory factory, string identity) 169 { 170 this.proxyFactories.set(factory, identity); 171 172 return this; 173 } 174 175 static if (is(T : Container)) 176 { 177 178 /** 179 Prepare container to be used. 180 181 Prepare container to be used. 182 183 Returns: 184 ProxyContainer decorating container 185 **/ 186 ProxyContainerImpl instantiate() 187 { 188 decorated.instantiate(); 189 190 return this; 191 } 192 } 193 194 static if (is(T : Storage!(ObjectFactory, string))) 195 { 196 /** 197 Set factory in container by identity. 198 199 Params: 200 identity = identity of factory. 201 element = factory that is to be saved in container. 202 203 Return: 204 ProxyContainer decorating container. 205 **/ 206 ProxyContainerImpl set(ObjectFactory element, string identity) 207 { 208 decorated.set(element, identity); 209 210 return this; 211 } 212 213 /** 214 Remove factory from container with identity. 215 216 Remove factory from container with identity. 217 218 Params: 219 identity = the identity of factory to be removed. 220 221 Return: 222 ProxyContainer decorating container 223 **/ 224 ProxyContainerImpl remove(string identity) 225 { 226 this.decorated.remove(identity); 227 this.proxyFactories.remove(identity); 228 229 return this; 230 } 231 } 232 else 233 { 234 /** 235 Remove factory from container with identity. 236 237 Remove factory from container with identity. 238 239 Params: 240 identity = the identity of factory to be removed. 241 242 Return: 243 ProxyContainer decorating container 244 **/ 245 ProxyContainerImpl remove(string identity) 246 { 247 this.proxyFactories.remove(identity); 248 249 return this; 250 } 251 } 252 253 static if (is(T : AliasAware!string)) 254 { 255 /** 256 Alias identity to an alias_. 257 258 Params: 259 identity = originial identity which is to be aliased. 260 alias_ = alias of identity. 261 262 Returns: 263 ProxyContainer decorating container 264 **/ 265 ProxyContainerImpl link(string identity, string alias_) 266 { 267 this.decorated.link(identity, alias_); 268 this.proxyFactories.link(identity, alias_); 269 270 return this; 271 } 272 273 /** 274 Removes alias. 275 276 Params: 277 alias_ = alias to remove. 278 279 Returns: 280 ProxyContainer decorating container 281 **/ 282 ProxyContainerImpl unlink(string alias_) 283 { 284 this.decorated.unlink(alias_); 285 this.proxyFactories.unlink(alias_); 286 287 return this; 288 } 289 290 /** 291 Resolve an alias to original identity, if possible. 292 293 Params: 294 alias_ = alias of original identity 295 296 Returns: 297 const(string) the last identity in alias chain if container is enabled, or alias_ when not. 298 299 **/ 300 const(string) resolve(in string alias_) const 301 { 302 return this.proxyFactories.resolve(alias_); 303 } 304 } 305 306 static if (is(T : FactoryLocator!ObjectFactory)) 307 { 308 309 /** 310 Get factory for constructed data identified by identity. 311 312 Get factory for constructed data identified by identity. 313 Params: 314 identity = the identity of data that factory constructs. 315 316 Throws: 317 NotFoundException when factory for it is not found. 318 319 Returns: 320 ObjectFactory the factory for constructed data. 321 **/ 322 ObjectFactory getFactory(string identity) 323 { 324 return this.decorated.getFactory(identity); 325 } 326 327 /** 328 Get all factories available in container. 329 330 Get all factories available in container. 331 332 Returns: 333 InputRange!(Tuple!(ObjectFactory, string)) a tuple of factory => identity. 334 **/ 335 InputRange!(Tuple!(ObjectFactory, string)) getFactories() 336 { 337 return this.decorated.getFactories(); 338 } 339 } 340 341 /** 342 Get object that is associated with identity. 343 344 Params: 345 identity = the object identity. 346 347 Throws: 348 NotFoundException in case if the object wasn't found or container is not enabled. 349 350 Returns: 351 Object if it is available. 352 **/ 353 Object get(string identity) 354 { 355 return proxyFactories.get(identity).factory(); 356 } 357 358 /** 359 Check if object is present in ProxyContainer by key identity. 360 361 Note: 362 This check should be done for elements that locator actually contains, and 363 not in chained locator (when locator is also a DelegatingLocator) for example. 364 Params: 365 identity = identity of object. 366 367 Returns: 368 bool true if container is enabled and has object by identity. 369 **/ 370 bool has(in string identity) inout 371 { 372 return proxyFactories.has(identity); 373 } 374 } 375 } 376 }