1 /** 2 3 License: 4 Boost Software License - Version 1.0 - August 17th, 2003 5 6 Permission is hereby granted, free of charge, to any person or organization 7 obtaining a copy of the software and accompanying documentation covered by 8 this license (the "Software") to use, reproduce, display, distribute, 9 execute, and transmit the Software, and to prepare derivative works of the 10 Software, and to permit third-parties to whom the Software is furnished to 11 do so, all subject to the following: 12 13 The copyright notices in the Software and this entire statement, including 14 the above license grant, this restriction and the following disclaimer, 15 must be included in all copies of the Software, in whole or in part, and 16 all derivative works of the Software, unless such copies or derivative 17 works are solely in the form of machine-executable object code generated by 18 a source language processor. 19 20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 23 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 24 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 25 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26 DEALINGS IN THE SOFTWARE. 27 28 Authors: 29 Alexandru Ermicioi 30 **/ 31 32 module aermicioi.aedi.storage.locator; 33 34 import aermicioi.aedi.storage.storage; 35 import aermicioi.aedi.util.typecons : Pair, pair; 36 37 /** 38 Interface for objects that can serevr Type elements. 39 **/ 40 @safe interface Locator(Type = Object, KeyType = string) { 41 42 public { 43 44 /** 45 Get a Type that is associated with key. 46 47 Params: 48 identity = the element id. 49 50 Throws: 51 NotFoundException in case if the element wasn't found. 52 53 Returns: 54 Type element if it is available. 55 **/ 56 Type get(KeyType identity); 57 58 /** 59 Check if an element is present in Locator by key id. 60 61 Note: 62 This check should be done for elements that locator actually contains, and 63 not in chained locator. 64 Params: 65 identity = identity of element. 66 67 Returns: 68 bool true if an element by key is present in Locator. 69 **/ 70 bool has(in KeyType identity) inout; 71 } 72 } 73 74 /** 75 Exposes the list of locators contained in it. 76 **/ 77 @safe interface AggregateLocator(Type = Object, KeyType = string, LocatorKeyType = KeyType) : 78 Locator!(Type, KeyType) { 79 80 import std.range.interfaces : InputRange; 81 82 public { 83 84 /** 85 Get a specific locator. 86 87 Params: 88 key = the locator identity. 89 **/ 90 Locator!(Type, KeyType) getLocator(LocatorKeyType key); 91 92 /** 93 Get all locators in aggregate locator 94 95 Returns: 96 InputRange!(Tuple!(Locator!(Type, KeyType), LocatorKeyType)) a range of locator => identity 97 **/ 98 InputRange!(Pair!(Locator!(Type, KeyType), LocatorKeyType)) getLocators(); 99 100 /** 101 Check if aggregate locator contains a specific locator. 102 103 Params: 104 key = the identity of locator in aggregate locator 105 **/ 106 bool hasLocator(LocatorKeyType key) inout; 107 } 108 } 109 110 /** 111 Exposes, and allows to set a list of containers into it. 112 **/ 113 @safe interface MutableAggregateLocator(Type = Object, KeyType = string, LocatorKeyType = KeyType) : 114 AggregateLocator!(Type, KeyType, LocatorKeyType), Storage!(Locator!(Type, KeyType), LocatorKeyType) { 115 116 } 117 118 /** 119 Given a locator, locates an object and attempts to downcast to T type. 120 121 See: 122 aermicioi.aedi.storage.wrapper : unwrap for downcasting semantics. 123 124 Params: 125 locator = the locator that contains the component with id as identity 126 id = identity of object contained in locator 127 128 Throws: 129 InvalidCastException when actual type of object is not of type that is requested. 130 131 Returns: 132 Object casted to desired type. 133 **/ 134 @trusted auto ref locate(T)(Locator!(Object, string) locator, string id) { 135 import aermicioi.aedi.storage.wrapper : unwrap; 136 return locator.get(id).unwrap!T; 137 } 138 139 /** 140 ditto 141 **/ 142 @trusted auto ref locate(T)(Locator!(Object, string) locator) { 143 import std.traits : fullyQualifiedName; 144 string id = typeid(T).toString; 145 146 if (!locator.has(id)) { 147 id = fullyQualifiedName!T; 148 } 149 150 return locator.locate!T(id); 151 } 152 153 /** 154 Mix in locator interface implementation that delegates 155 the logic to decorated container. 156 **/ 157 @safe mixin template LocatorMixin(T : Locator!(W, X), W, X) { 158 mixin LocatorMixin!(W, X); 159 } 160 161 /** 162 ditto 163 **/ 164 @safe mixin template LocatorMixin(W, X) { 165 /** 166 Get object created by a factory identified by key 167 168 Params: 169 key = identity of factory 170 Returns: 171 Object 172 **/ 173 W get(X key) 174 in(decorated !is null, "Cannot get component out of decorated component container, when no container to decorate is provided.") 175 { 176 return this.decorated.get(key); 177 } 178 179 /** 180 Check if an object factory for it exists in container. 181 182 Params: 183 key = identity of factory 184 Returns: 185 bool 186 **/ 187 bool has(in X key) inout 188 in(decorated !is null, "Cannot check if component is in decorated component container, when no container to decorate is provided.") 189 { 190 return this.decorated_.has(key); 191 } 192 }