1 /** 2 Contains factories and primitives used for building proxy objects. 3 4 License: 5 Boost Software License - Version 1.0 - August 17th, 2003 6 7 Permission is hereby granted, free of charge, to any person or organization 8 obtaining a copy of the software and accompanying documentation covered by 9 this license (the "Software") to use, reproduce, display, distribute, 10 execute, and transmit the Software, and to prepare derivative works of the 11 Software, and to permit third-parties to whom the Software is furnished to 12 do so, all subject to the following: 13 14 The copyright notices in the Software and this entire statement, including 15 the above license grant, this restriction and the following disclaimer, 16 must be included in all copies of the Software, in whole or in part, and 17 all derivative works of the Software, unless such copies or derivative 18 works are solely in the form of machine-executable object code generated by 19 a source language processor. 20 21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 24 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 25 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 26 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 27 DEALINGS IN THE SOFTWARE. 28 29 Authors: 30 aermicioi 31 **/ 32 module aermicioi.aedi.factory.proxy_factory; 33 34 import aermicioi.aedi.factory.factory; 35 import aermicioi.aedi.factory.generic_factory; 36 import aermicioi.aedi.storage.locator; 37 import aermicioi.aedi.storage.decorator; 38 import std.traits; 39 import std.typecons; 40 import std.range; 41 import std.algorithm; 42 import std.meta; 43 44 import aermicioi.util.traits; 45 46 /** 47 Creates a proxy to an object or interface of type T, 48 that is located in source locator by some identity. 49 **/ 50 class ProxyFactory(T) : Factory!T 51 if ( 52 ( 53 is(T == class) && 54 !isFinalClass!T && 55 !isAbstractClass!T 56 ) || 57 (is(T == interface)) 58 ) { 59 60 private { 61 string identity_; 62 Locator!() source_; 63 } 64 65 public { 66 67 this(string identity, Locator!() original) { 68 this.identity = identity; 69 this.source = source; 70 } 71 72 T factory() { 73 auto proxy = new Proxy!T; 74 proxy.__id__ = this.identity; 75 proxy.__locator__ = this.source; 76 77 return proxy; 78 } 79 80 @property { 81 /** 82 Set the identity of proxied object 83 84 Params: 85 identity = the identity of proxied object 86 87 Returns: 88 this 89 **/ 90 ProxyFactory!T identity(string identity) { 91 this.identity_ = identity; 92 93 return this; 94 } 95 96 /** 97 Get the identity of proxied object. 98 99 Returns: 100 string identity 101 **/ 102 string identity() { 103 return this.identity_; 104 } 105 106 /** 107 Set the source of proxied object. 108 109 Params: 110 source = source locator where proxied object resides. 111 112 Returns: 113 this 114 **/ 115 ProxyFactory!T source(Locator!() source) { 116 this.source_ = source; 117 118 return this; 119 } 120 121 /** 122 Get the source of proxied object. 123 124 Returns: 125 Locator!() source 126 **/ 127 Locator!() source() { 128 return this.source_; 129 } 130 } 131 } 132 } 133 134 /** 135 Auto implements a proxy for object or interface of type T which 136 is not a final or abstract class. 137 138 Warning: 139 Current implmentation uses AutoImplement from phobos which 140 has some unfixed bugs. 141 **/ 142 template ProxyImpl(T) 143 if ( 144 ( 145 is(T == class) && 146 !isFinalClass!T && 147 !isAbstractClass!T 148 ) || 149 is(T == interface) 150 ) { 151 152 static class ProxyImpl : T { 153 private { 154 155 Locator!() __locator_; 156 string __id_; 157 } 158 159 public { 160 161 this() { 162 super(); 163 } 164 } 165 166 @property public { 167 ProxyImpl __locator__(Locator!() locator) @safe nothrow @nogc { 168 this.__locator_ = locator; 169 170 return this; 171 } 172 173 Locator!() __locator__() @safe nothrow @nogc { 174 return this.__locator_; 175 } 176 177 ProxyImpl __id__(string id) @safe nothrow @nogc { 178 this.__id_ = id; 179 180 return this; 181 } 182 183 string __id__() @safe nothrow @nogc { 184 return this.__id_; 185 } 186 } 187 } 188 } 189 190 template how(T) { 191 static string how(C, alias fun)() { 192 string stmt = " 193 import aermicioi.aedi.storage.locator; 194 import aermicioi.aedi.exception.di_exception; 195 import aermicioi.aedi.factory.proxy_factory; 196 " ~ identifier!C ~ " original; 197 try { 198 original = this.__locator__.locate!(" ~ fullyQualifiedName!T ~ ")(this.__id__); 199 } catch (AediException e) { 200 assert(false, \"Failed to fetch \" ~ __id__ ~ \" in proxy object.\"); 201 } 202 "; 203 204 static if (!is(ReturnType!fun == void)) { 205 stmt ~= " 206 return original." ~ __traits(identifier, fun) ~ "(args); 207 "; 208 } else { 209 stmt ~= " 210 original." ~ __traits(identifier, fun) ~ "(args); 211 "; 212 } 213 214 return stmt; 215 } 216 } 217 218 alias Proxy(T) = AutoImplement!(ProxyImpl!T, how!T, templateAnd!( 219 templateNot!isFinalFunction 220 )); 221 222 /** 223 A ProxyObjectFactory instantiates a proxy to some type of object located in source locator. 224 **/ 225 interface ProxyObjectFactory : ObjectFactory { 226 227 @property { 228 229 /** 230 Get the identity of original object that proxy factory will intantiate proxy object. 231 232 Returns: 233 string the original object identity 234 **/ 235 string identity() @safe nothrow; 236 237 /** 238 Get the original locator that is used by proxy to fetch the proxied object. 239 240 Returns: 241 Locator!() original locator containing the proxied object. 242 **/ 243 Locator!() source() @safe nothrow; 244 } 245 } 246 247 class ProxyObjectWrappingFactory(T) : ProxyObjectFactory, MutableDecorator!(Factory!T) 248 if (is(T : Object) && !isFinalClass!T) { 249 250 private { 251 ProxyFactory!T decorated_; 252 253 string identity_; 254 Locator!() source_; 255 Locator!() locator_; 256 } 257 258 public { 259 this(ProxyFactory!T factory) { 260 this.decorated = factory; 261 } 262 263 @property { 264 ProxyObjectWrappingFactory!T identity(string identity) @safe nothrow { 265 this.identity_ = identity; 266 267 return this; 268 } 269 270 string identity() @safe nothrow { 271 return this.identity_; 272 } 273 274 ProxyObjectWrappingFactory!T source(Locator!() source) @safe nothrow { 275 this.source_ = source; 276 277 return this; 278 } 279 280 Locator!() source() @safe nothrow { 281 return this.source_; 282 } 283 284 ProxyObjectWrappingFactory!T decorated(ProxyFactory!T decorated) @safe nothrow { 285 this.decorated_ = decorated; 286 287 return this; 288 } 289 290 ProxyFactory!T decorated() @safe nothrow { 291 return this.decorated_; 292 } 293 294 ProxyObjectWrappingFactory!T locator(Locator!() locator) @safe nothrow { 295 this.locator_ = locator; 296 297 return this; 298 } 299 300 Locator!() locator() @safe nothrow { 301 return this.locator_; 302 } 303 304 TypeInfo type() { 305 return this.decorated.type; 306 } 307 } 308 309 Object factory() { 310 return this.decorated.factory(); 311 } 312 } 313 }