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 31 module aermicioi.aedi.container.application_container; 32 33 import aermicioi.aedi.container; 34 import aermicioi.aedi.storage; 35 import aermicioi.aedi.exception; 36 37 import std.range.interfaces; 38 import std.typecons; 39 40 /** 41 Application container 42 43 A default container that provides singleton, and prototype containers as well as a storage for 44 already instantiated data. It should be sufficient for usages, when no specific hierarchy of storages 45 is required. 46 47 **/ 48 class ApplicationContainer : Container, Storage!(Container, string), AggregateLocator!() { 49 50 private { 51 ObjectStorage!(Container, string) containers; 52 ObjectStorage!() parameters; 53 } 54 55 public { 56 57 this() { 58 this.containers = new ObjectStorage!(Container, string); 59 this.containers.set(new SingletonContainer, "singleton"); 60 this.containers.set(new PrototypeContainer, "prototype"); 61 62 this.parameters = new ObjectStorage!(); 63 } 64 65 /** 66 Sets up the internal state of container. 67 68 Sets up the internal state of container (Ex, for singleton container it will spawn all objects that locator contains). 69 **/ 70 ApplicationContainer instantiate() { 71 72 foreach (container; this.containers) { 73 container.instantiate(); 74 } 75 76 return this; 77 } 78 79 /** 80 Get an Type that is associated with key. 81 82 Params: 83 identity = the element id. 84 85 Throws: 86 NotFoundException in case if the element wasn't found. 87 88 Returns: 89 Type element if it is available. 90 **/ 91 Object get(string identity) { 92 if (this.containers.has(identity)) { 93 return cast(Object) this.containers.get(identity); 94 } 95 96 foreach (container; this.containers) { 97 if (container.has(identity)) { 98 return container.get(identity); 99 } 100 } 101 102 if (identity == "parameters") { 103 return this.parameters; 104 } 105 106 if (this.parameters.has(identity)) { 107 return this.parameters.get(identity); 108 } 109 110 throw new NotFoundException("Object by id " ~ identity ~ " not found"); 111 } 112 113 /** 114 Check if an element is present in Locator by key id. 115 116 Note: 117 This check should be done for elements that locator actually contains, and 118 not in chained locator (when locator is also a DelegatingLocator) for example. 119 Params: 120 identity = identity of element. 121 122 Returns: 123 bool true if an element by key is present in Locator. 124 **/ 125 bool has(in string identity) inout { 126 127 if (this.containers.has(identity)) { 128 return true; 129 } 130 131 if (identity == "parameters") { 132 return true; 133 } 134 135 foreach (container; this.containers.contents) { 136 if (container.has(identity)) { 137 return true; 138 } 139 } 140 141 return false; 142 } 143 144 ApplicationContainer set(Container container, string identity) { 145 this.containers.set(container, identity); 146 147 return this; 148 } 149 150 ApplicationContainer remove(string identity) { 151 this.containers.remove(identity); 152 153 return this; 154 } 155 156 /** 157 Get a specific locator. 158 159 Params: 160 key = the locator identity. 161 **/ 162 Locator!(Object, string) getLocator(string key) { 163 164 return this.containers.get(key); 165 } 166 167 /** 168 Get all locators in aggregate locator 169 170 Returns: 171 InputRange!(Tuple!(Locator!(Type, KeyType), LocatorKeyType)) a range of locator => identity 172 **/ 173 InputRange!(Tuple!(Locator!(Object, string), string)) getLocators() { 174 import std.algorithm; 175 176 return this.containers.contents.byKeyValue.map!( 177 a => tuple(cast(Locator!()) a.value, a.key) 178 ).inputRangeObject; 179 } 180 181 /** 182 Check if aggregate locator contains a specific locator. 183 184 Params: 185 key = the identity of locator in aggregate locator 186 **/ 187 bool hasLocator(string key) inout { 188 189 return this.containers.has(key); 190 } 191 } 192 }