1 /** 2 Contains a specific implementation of generic factory used solely in conjunction 3 with register api. 4 5 License: 6 Boost Software License - Version 1.0 - August 17th, 2003 7 8 Permission is hereby granted, free of charge, to any person or organization 9 obtaining a copy of the software and accompanying documentation covered by 10 this license (the "Software") to use, reproduce, display, distribute, 11 execute, and transmit the Software, and to prepare derivative works of the 12 Software, and to permit third-parties to whom the Software is furnished to 13 do so, all subject to the following: 14 15 The copyright notices in the Software and this entire statement, including 16 the above license grant, this restriction and the following disclaimer, 17 must be included in all copies of the Software, in whole or in part, and 18 all derivative works of the Software, unless such copies or derivative 19 works are solely in the form of machine-executable object code generated by 20 a source language processor. 21 22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 25 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 26 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 27 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 28 DEALINGS IN THE SOFTWARE. 29 30 Authors: 31 aermicioi 32 **/ 33 module aermicioi.aedi.configurer.register.configuration_context_factory; 34 35 import aermicioi.aedi.util.typecons : ArgsConstructor; 36 import aermicioi.aedi.factory.decorating_factory; 37 import aermicioi.aedi.factory.factory; 38 import aermicioi.aedi.factory.generic_factory; 39 import aermicioi.aedi.storage.storage; 40 import aermicioi.aedi.storage.decorator : MutableDecoratorMixin; 41 import aermicioi.aedi.storage.locator : Locator; 42 import std.experimental.allocator : RCIAllocator; 43 44 package 45 { 46 47 @safe class ConfigurableFactory(T, Policies...) : GenericFactory!T 48 { 49 50 static foreach (Policy; Policies) 51 { 52 mixin Policy!(); 53 } 54 } 55 56 mixin template DecoratingFactoryPolicy() 57 { 58 import aermicioi.aedi.storage.allocator_aware : AllocatorAwareMixin; 59 import aermicioi.aedi.storage.locator_aware : LocatorAwareMixin; 60 mixin MutableDecoratorMixin!(GenericFactory!T); 61 mixin InstanceDestructorAwareDecoratorMixin!T; 62 mixin InstanceFactoryAwareDecoratorMixin!T; 63 mixin PropertyConfigurersAwareDecoratorMixin!T; 64 65 /** 66 Instantiates component of type T. 67 68 Returns: 69 T instantiated component. 70 **/ 71 T factory() @safe { 72 return this.decorated.factory(); 73 } 74 75 /** 76 Destructs a component of type T. 77 78 Params: 79 component = component that is to ve destroyed. 80 **/ 81 void destruct(ref T component) @safe { 82 this.decorated.destruct(component); 83 } 84 85 @property { 86 87 /** 88 Get the type info of T that is created. 89 90 Returns: 91 TypeInfo object of created component. 92 **/ 93 TypeInfo type() @safe nothrow const { 94 return this.decorated.type(); 95 } 96 } 97 98 // allocator section, required due to more advanced logic that storing. 99 import std.experimental.allocator : RCIAllocator, make, theAllocator; 100 private { 101 RCIAllocator allocator_; 102 } 103 104 public { 105 @property { 106 /** 107 Set allocator 108 109 Params: 110 allocator = allocator used to create components 111 112 Returns: 113 typeof(this) 114 **/ 115 typeof(this) allocator(RCIAllocator allocator) @safe nothrow 116 in { 117 assert(!allocator.isNull, "Expected an allocator, not null."); 118 } 119 do { 120 this.allocator_ = allocator; 121 122 if (this.decorated_ !is null) { 123 this.decorated.allocator = allocator; 124 } 125 126 return this; 127 } 128 129 /** 130 Get allocator 131 132 Returns: 133 Z 134 **/ 135 inout(RCIAllocator) allocator() @safe nothrow inout 136 out(allocator) { 137 assert(!allocator.isNull, "Expected an allocator, not null."); 138 } 139 do { 140 return this.allocator_; 141 } 142 } 143 } 144 145 // Locator storage, same reason as for allocator. 146 import aermicioi.aedi.storage.locator; 147 private { 148 Locator!() locator_; 149 } 150 151 @property { 152 /** 153 Set locator 154 155 Params: 156 locator = the locator used somehow by locator aware component 157 158 Returns: 159 typeof(this) 160 **/ 161 typeof(this) locator(Locator!() locator) @safe nothrow 162 in (locator !is null, "A locator is expected not null.") 163 { 164 this.locator_ = locator; 165 166 if (this.decorated_ !is null) { 167 this.decorated.locator = locator; 168 } 169 170 return this; 171 } 172 173 /** 174 Get locator 175 176 Returns: 177 Locator!() 178 **/ 179 inout(Locator!()) locator() @safe nothrow inout 180 out(lc; lc !is null, "Cannot return a locator, when it wasn't set in first case.") { 181 return this.locator_; 182 } 183 } 184 } 185 186 mixin template RegistrationStorePolicy() 187 { 188 private string file_; 189 private size_t line_; 190 191 /** 192 Set file 193 194 Params: 195 file = location in d module where it was registered 196 Returns: 197 typeof(this) 198 **/ 199 typeof(this) file(string file) @safe nothrow pure 200 { 201 this.file_ = file; 202 203 return this; 204 } 205 206 /** 207 Get file 208 209 Returns: 210 string 211 **/ 212 inout(string) file() @safe nothrow pure inout 213 { 214 return this.file_; 215 } 216 217 /** 218 Set line 219 220 Params: 221 line = line on which registration happened 222 223 Returns: 224 typeof(this) 225 **/ 226 typeof(this) line(size_t line) @safe nothrow pure 227 { 228 this.line_ = line; 229 230 return this; 231 } 232 233 /** 234 Get line 235 236 Returns: 237 size_t 238 **/ 239 inout(size_t) line() @safe nothrow pure inout 240 { 241 return this.line_; 242 } 243 } 244 245 mixin template WrapperStorePolicy() 246 { 247 ObjectFactory wrapper_; 248 249 /** 250 Set wrapper 251 252 Params: 253 wrapper = wrapper of factory stored in storage 254 Returns: 255 typeof(this) 256 **/ 257 typeof(this) wrapper(ObjectFactory wrapper) @safe nothrow pure 258 { 259 this.wrapper_ = wrapper; 260 261 return this; 262 } 263 264 /** 265 Get wrapper 266 267 Returns: 268 ObjectFactory 269 **/ 270 inout(ObjectFactory) wrapper() @safe nothrow pure inout 271 { 272 return this.wrapper_; 273 } 274 } 275 276 mixin template StoragePolicy() 277 { 278 Storage!(ObjectFactory, string) storage_; 279 string identity_; 280 281 /** 282 Set storage 283 284 Params: 285 storage = storage that stores component factories 286 Returns: 287 typeof(this) 288 **/ 289 typeof(this) storage(Storage!(ObjectFactory, string) storage) @safe nothrow pure 290 { 291 this.storage_ = storage; 292 293 return this; 294 } 295 296 /** 297 Get storage 298 299 Returns: 300 Storage!(ObjectFactory, string) 301 **/ 302 inout(Storage!(ObjectFactory, string)) storage() @safe nothrow pure inout 303 { 304 return this.storage_; 305 } 306 307 /** 308 Set identity 309 310 Params: 311 identity = identity of component in storage 312 313 Returns: 314 typeof(this) 315 **/ 316 typeof(this) identity(string identity) @safe nothrow pure 317 { 318 this.identity_ = identity; 319 320 return this; 321 } 322 323 /** 324 Get identity 325 326 Returns: 327 string 328 **/ 329 inout(string) identity() @safe nothrow pure inout 330 { 331 return this.identity_; 332 } 333 } 334 335 template ContainsPolicy(alias Policy, Policies...) { 336 import std.traits : fullyQualifiedName; 337 static foreach (Testable; Policies) { 338 static if (!is(typeof(Result)) && __traits(isSame, Testable, Policy)) { 339 enum Result = true; 340 } 341 } 342 343 static if (!is(typeof(Result))) { 344 enum Result = false; 345 } 346 347 alias ContainsPolicy = Result; 348 } 349 }