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.exception.di_exception; 33 import aermicioi.aedi.factory.factory; 34 import aermicioi.aedi.factory.generic_factory; 35 import aermicioi.aedi.storage.decorator; 36 import aermicioi.aedi.storage.allocator_aware; 37 import aermicioi.aedi.storage.locator; 38 import aermicioi.aedi.storage.wrapper; 39 import std.traits; 40 41 /** 42 Wraps up the result of some factory in Wrapper object if component is not 43 derived from Object. 44 **/ 45 @safe class WrappingFactory(T : Factory!Z, Z) : ObjectFactory, MutableDecorator!T { 46 47 private { 48 RCIAllocator allocator_; 49 50 T decorated_; 51 } 52 53 public { 54 55 /** 56 Constructor for WrappingFactory!(T, Z) 57 58 Params: 59 factory = factory that is wrapped 60 **/ 61 this(T factory) { 62 import std.experimental.allocator : theAllocator; 63 64 this.decorated = factory; 65 this.allocator = theAllocator; 66 } 67 68 @property { 69 /** 70 Set allocator 71 72 Params: 73 allocator = allocator used to allocate wrappers when needed. 74 75 Returns: 76 typeof(this) 77 **/ 78 typeof(this) allocator(RCIAllocator allocator) @safe nothrow 79 in (allocator !is null, "Expected an allocator, not null.") { 80 this.allocator_ = allocator; 81 this.decorated.allocator = allocator; 82 83 return this; 84 } 85 86 /** 87 Get allocator 88 89 Returns: 90 RCIAllocator 91 **/ 92 RCIAllocator allocator() @safe nothrow { 93 return this.allocator_; 94 } 95 /** 96 Set the decorated object for decorator. 97 98 Params: 99 decorated = decorated component 100 101 Returns: 102 this 103 **/ 104 WrappingFactory!(T, Z) decorated(T decorated) @safe nothrow pure 105 in (decorated !is null, "Expected a factory to decorate for type " ~ typeid(T).toString ~ " not null.") { 106 this.decorated_ = decorated; 107 108 return this; 109 } 110 111 /** 112 Get the decorated object. 113 114 Returns: 115 T decorated object 116 **/ 117 inout(T) decorated() @safe nothrow inout { 118 return this.decorated_; 119 } 120 121 /** 122 Get the type info of T that is created. 123 124 Returns: 125 TypeInfo object of created component. 126 **/ 127 TypeInfo type() @safe nothrow const { 128 return this.decorated.type; 129 } 130 131 /** 132 Set a locator to object. 133 134 Params: 135 locator = the locator that is set to oject. 136 137 Returns: 138 LocatorAware. 139 **/ 140 WrappingFactory!T locator(Locator!() locator) { 141 this.decorated.locator = locator; 142 143 return this; 144 } 145 146 } 147 148 /** 149 Instantiates component of type T. 150 151 Returns: 152 Object instantiated component and probably wrapped if not derived from Object. 153 **/ 154 Object factory() @trusted { 155 static if (is(Z : Object)) { 156 157 return this.decorated.factory; 158 } else static if (is(Z == class)) { 159 import aermicioi.aedi.storage.wrapper : CastableWrapperImpl; 160 return this.allocator.make!(CastableWrapperImpl!(Z, InterfacesTuple!Z))(this.decorated.factory); 161 // return this.allocator.make!(CastableWrapperImpl!(Z, InterfacesTuple!Z, BaseClassesTuple!Z))(this.decorated.factory); /// Nope not working with extern classes 162 } else static if (is(Z == ubyte)) { 163 return this.allocator.make!(CastableWrapperImpl!(Z, ushort, uint, ulong, short, int, long, float, double))(this.decorated.factory); 164 } else static if (is(Z == ushort)) { 165 return this.allocator.make!(CastableWrapperImpl!(Z, uint, ulong, int, long, float, double))(this.decorated.factory); 166 } else static if (is(Z == uint)) { 167 return this.allocator.make!(CastableWrapperImpl!(Z, ulong, long, float, double))(this.decorated.factory); 168 } else static if (is(Z == ulong)) { 169 return this.allocator.make!(CastableWrapperImpl!(Z, double))(this.decorated.factory); 170 } else static if (is(Z == byte)) { 171 return this.allocator.make!(CastableWrapperImpl!(Z, short, int, long, float, double))(this.decorated.factory); 172 } else static if (is(Z == short)) { 173 return this.allocator.make!(CastableWrapperImpl!(Z, int, long, float, double))(this.decorated.factory); 174 } else static if (is(Z == int)) { 175 return this.allocator.make!(CastableWrapperImpl!(Z, long, float, double))(this.decorated.factory); 176 } else static if (is(Z == long)) { 177 return this.allocator.make!(CastableWrapperImpl!(Z, double))(this.decorated.factory); 178 } else static if (is(Z == float)) { 179 return this.allocator.make!(CastableWrapperImpl!(Z, double))(this.decorated.factory); 180 } else static if (is(Z == double)) { 181 return this.allocator.make!(WrapperImpl!(Z))(this.decorated.factory); 182 } else { 183 return this.allocator.make!(WrapperImpl!Z)(this.decorated.factory); 184 } 185 } 186 187 /** 188 Destructs a component of type T. 189 190 Params: 191 component = component that is to ve destroyed. 192 193 Returns: 194 195 **/ 196 void destruct(ref Object component) @trusted { 197 static if (is(Z : Object)) { 198 199 Z casted = cast(Z) component; 200 201 if (casted !is null) { 202 203 this.decorated.destruct(casted); 204 return; 205 } 206 } else { 207 208 Wrapper!Z casted = cast(Wrapper!Z) component; 209 210 if (casted !is null) { 211 this.decorated.destruct(casted.value); 212 this.allocator.dispose(component); 213 return; 214 } 215 } 216 217 import aermicioi.aedi.exception.invalid_cast_exception : InvalidCastException; 218 throw new InvalidCastException( 219 "Cannot destruct component of type ${actual} expected component of ${expected} type", null, typeid(Z), component.classinfo 220 ); 221 } 222 223 } 224 }