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.factory.wrapping_factory; 31 32 import aermicioi.aedi.factory.factory; 33 import aermicioi.aedi.factory.generic_factory; 34 import aermicioi.aedi.storage.decorator; 35 import aermicioi.aedi.storage.locator; 36 import aermicioi.aedi.storage.wrapper; 37 import std.traits; 38 39 /** 40 Wraps up the result of some factory in Wrapper object if component is not 41 derived from Object. 42 **/ 43 class WrappingFactory(T : Factory!Z, Z) : ObjectFactory, MutableDecorator!T { 44 45 private { 46 T decorated_; 47 } 48 49 public { 50 51 /** 52 Constructor for WrappingFactory!(T, Z) 53 54 Params: 55 factory = factory that is wrapped 56 **/ 57 this(T factory) { 58 this.decorated = factory; 59 } 60 61 @property { 62 63 /** 64 Set the decorated object for decorator. 65 66 Params: 67 decorated = decorated data 68 69 Returns: 70 this 71 **/ 72 WrappingFactory!(T, Z) decorated(T decorated) @safe nothrow { 73 this.decorated_ = decorated; 74 75 return this; 76 } 77 78 /** 79 Get the decorated object. 80 81 Returns: 82 T decorated object 83 **/ 84 T decorated() @safe nothrow { 85 return this.decorated_; 86 } 87 88 /** 89 Get the type info of T that is created. 90 91 Returns: 92 TypeInfo object of created component. 93 **/ 94 TypeInfo type() { 95 return this.decorated.type; 96 } 97 98 /** 99 Set a locator to object. 100 101 Params: 102 locator = the locator that is set to oject. 103 104 Returns: 105 LocatorAware. 106 **/ 107 WrappingFactory!T locator(Locator!() locator) { 108 this.decorated.locator = locator; 109 110 return this; 111 } 112 113 } 114 115 /** 116 Instantiates component of type T. 117 118 Returns: 119 Object instantiated component and probably wrapped if not derived from Object. 120 **/ 121 Object factory() { 122 static if (is(Z : Object)) { 123 124 return this.decorated.factory; 125 } else { 126 import aermicioi.aedi.storage.wrapper : WrapperImpl; 127 return new WrapperImpl!Z(this.decorated.factory); 128 } 129 } 130 } 131 } 132 133 /** 134 Wrapping factory that will wrap the result depending on runtime type information 135 instead of compile time information. 136 **/ 137 class RuntimeWrappingFactory(T : Factory!Z, Z) : WrappingFactory!(T) { 138 139 public { 140 141 /** 142 Constructor for RuntimeWrappingFactory!(T, Z) 143 144 Params: 145 factory = factory that is to be wrapped up in 146 **/ 147 this(T factory) { 148 super(factory); 149 } 150 151 /** 152 Instantiates component of type T. 153 154 Returns: 155 Object instantiated component and probably wrapped if not derived from Object. 156 **/ 157 override Object factory() { 158 static if (is(Z == interface) || is(Z == class)) { 159 if (this.decorated.type.isDerived(typeid(Object))) { 160 return cast(Object) this.decorated.factory; 161 } 162 } 163 164 { 165 return new WrapperImpl!Z(this.decorated.factory); 166 } 167 } 168 } 169 } 170 171 /** 172 A factory that coerces an object from object factory to 173 some T type. 174 175 A factory that coerces an object from object factory to 176 some T type. If T is not rooted in Object class it is 177 assumed by convention that Wrapper!T object is returned 178 by object factory. 179 **/ 180 class UnwrappingFactory(T) : Factory!T { 181 182 private { 183 ObjectFactory decorated_; 184 } 185 186 public { 187 188 /** 189 Constructor for UnwrappingFactory 190 191 Params: 192 factory = factory from which created components will be coerced to T type if possible 193 **/ 194 this(ObjectFactory factory) { 195 this.decorated = factory; 196 } 197 198 @property { 199 /** 200 Set the decorated object for decorator. 201 202 Throws: 203 InvalidCastException when created type of object factory mismatches type of unwrapping factory. 204 205 Params: 206 decorated = decorated data 207 208 Returns: 209 this 210 **/ 211 UnwrappingFactory!T decorated(ObjectFactory decorated) 212 in { 213 if (decorated.type != typeid(T)) { 214 import aermicioi.aedi.exception.invalid_cast_exception : InvalidCastException; 215 216 throw new InvalidCastException( 217 "Cannot unwrap a type " ~ 218 decorated.type.toString() ~ 219 " and cast it to " ~ 220 typeid(T).toString() 221 ); 222 } 223 } 224 body { 225 this.decorated_ = decorated; 226 227 return this; 228 } 229 230 /** 231 Get the decorated object. 232 233 Returns: 234 ObjectFactory decorated object 235 **/ 236 ObjectFactory decorated() { 237 return this.decorated_; 238 } 239 240 /** 241 Get the type info of T that is created. 242 243 Returns: 244 TypeInfo object of created object. 245 **/ 246 TypeInfo type() { 247 return this.decorated.type; 248 } 249 250 /** 251 Set a locator to object. 252 253 Params: 254 locator = the locator that is set to oject. 255 256 Returns: 257 LocatorAware. 258 **/ 259 UnwrappingFactory!T locator(Locator!() locator) { 260 this.decorated.locator = locator; 261 262 return this; 263 } 264 } 265 266 /** 267 Instantiates something of type T. 268 269 Returns: 270 T instantiated data of type T. 271 **/ 272 T factory() { 273 Object wrapped = this.decorated.factory; 274 275 static if (is(T : Object)) { 276 T component = cast(T) wrapped; 277 278 if (component !is null) { 279 return component; 280 } 281 } else { 282 Wrapper!T component = cast(Wrapper!T) wrapped; 283 284 if (component !is null) { 285 return component; 286 } 287 } 288 289 assert(0, "Fatal error, application logic never should reach this region"); 290 } 291 } 292 } 293 294 /** 295 A factory that coerces an object from object factory to 296 some T type. 297 298 A factory that coerces an object from object factory to 299 some T type. It will attempt as well to safely object to 300 type T if it is possible to prove that created object 301 is a derivation of type T. If T is not rooted in Object 302 class it is assumed by convention that Wrapper!T object 303 is returned by object factory. 304 **/ 305 class ClassUnwrappingFactory(T) : Factory!T { 306 307 private { 308 ObjectFactory decorated_; 309 } 310 311 public { 312 313 /** 314 Constructor for ClassUnwrappingFactory 315 316 Params: 317 factory = factory from which created components will be coerced to T type if possible 318 **/ 319 this(ObjectFactory factory) { 320 this.decorated = factory; 321 } 322 323 @property { 324 /** 325 Set the decorated object for decorator. 326 327 Throws: 328 InvalidCastException when created type of object factory mismatches type of unwrapping factory. 329 330 Params: 331 decorated = decorated data 332 333 Returns: 334 this 335 **/ 336 ClassUnwrappingFactory!T decorated(ObjectFactory decorated) 337 in { 338 if (!decorated.type.isDerived(typeid(T))) { 339 import aermicioi.aedi.exception.invalid_cast_exception; 340 341 throw new InvalidCastException("Cannot unwrap a type " ~ decorated.type.toString() ~ " and cast it to " ~ typeid(T).toString()); 342 } 343 } 344 body { 345 this.decorated_ = decorated; 346 347 return this; 348 } 349 350 /** 351 Get the decorated object. 352 353 Returns: 354 ObjectFactory decorated object 355 **/ 356 ObjectFactory decorated() { 357 return this.decorated_; 358 } 359 360 /** 361 Get the type info of T that is created. 362 363 Returns: 364 TypeInfo object of created object. 365 **/ 366 TypeInfo type() { 367 return this.decorated.type; 368 } 369 370 /** 371 Set a locator to object. 372 373 Params: 374 locator = the locator that is set to oject. 375 376 Returns: 377 LocatorAware. 378 **/ 379 ClassUnwrappingFactory!T locator(Locator!() locator) { 380 this.decorated.locator = locator; 381 382 return this; 383 } 384 } 385 386 /** 387 Instantiates something of type T. 388 389 Returns: 390 T instantiated data of type T. 391 **/ 392 T factory() { 393 Object wrapped = this.decorated.factory; 394 395 { 396 static if (is(T : Object)) { 397 398 T component = cast(T) wrapped; 399 400 if (component !is null) { 401 return component; 402 } 403 } 404 } 405 406 { 407 static if (is(T == interface) || is(T == class)) { 408 409 T component = cast(T) wrapped; 410 411 if (component !is null) { 412 return component; 413 } 414 } 415 } 416 417 Wrapper!T component = cast(Wrapper!T) wrapped; 418 419 if (component !is null) { 420 return component; 421 } 422 423 assert(0, "Fatal error, application logic never should reach this region"); 424 } 425 } 426 } 427 428 private { 429 import std.stdio; 430 431 bool isDerived(TypeInfo subject, TypeInfo derivation) { 432 if (subject == derivation) { 433 return true; 434 } 435 436 if ((cast(ClassInfo) subject !is null) && (cast(ClassInfo) derivation !is null)) { 437 return isDerived(cast(ClassInfo) subject, cast(ClassInfo) derivation); 438 } 439 440 if ((cast(ClassInfo) subject !is null) && (cast(TypeInfo_Interface) derivation !is null)) { 441 return isDerived(cast(ClassInfo) subject, cast(TypeInfo_Interface) derivation); 442 } 443 444 if ((cast(TypeInfo_Interface) subject !is null) && (cast(TypeInfo_Interface) derivation !is null)) { 445 return isDerived(cast(TypeInfo_Interface) subject, cast(TypeInfo_Interface) derivation); 446 } 447 448 return false; 449 } 450 451 bool isDerived(ClassInfo subject, ClassInfo derivation) { 452 if ( 453 (subject == derivation) || 454 ( 455 (subject.base !is null) && 456 subject.base.isDerived(derivation) 457 ) 458 ) { 459 return true; 460 } 461 462 foreach (iface; subject.interfaces) { 463 if (iface.classinfo.isDerived(derivation)) { 464 return true; 465 } 466 } 467 468 return false; 469 } 470 471 bool isDerived(ClassInfo subject, TypeInfo_Interface iface) { 472 return subject.isDerived(iface.info); 473 } 474 475 bool isDerived(TypeInfo_Interface subject, TypeInfo_Interface iface) { 476 return subject.info.isDerived(iface.info); 477 } 478 }