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 36 /** 37 Interface for objects that can serevr Type elements. 38 **/ 39 interface Locator(Type = Object, KeyType = string) { 40 41 public { 42 43 /** 44 Get a Type that is associated with key. 45 46 Params: 47 identity = the element id. 48 49 Throws: 50 NotFoundException in case if the element wasn't found. 51 52 Returns: 53 Type element if it is available. 54 **/ 55 Type get(KeyType identity); 56 57 /** 58 Check if an element is present in Locator by key id. 59 60 Note: 61 This check should be done for elements that locator actually contains, and 62 not in chained locator. 63 Params: 64 identity = identity of element. 65 66 Returns: 67 bool true if an element by key is present in Locator. 68 **/ 69 bool has(in KeyType identity) inout; 70 } 71 } 72 73 /** 74 Exposes the list of locators contained in it. 75 **/ 76 interface AggregateLocator(Type = Object, KeyType = string, LocatorKeyType = KeyType) : 77 Locator!(Type, KeyType) { 78 79 import std.range.interfaces : InputRange; 80 import std.typecons : Tuple; 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!(Tuple!(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 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 convert to T type. 120 121 Given a locator, locates an object and attempts to convert to T type. 122 When an object of T type is located, it is simply casted to T type. 123 When an value of T type is located, the func attempts to cast the requested object to 124 Wrapper!T, and will return it, instead of T directly. 125 In case of failure an InvalidCastException is thrown in debug environment. 126 127 Params: 128 locator = the locator that contains the data with id as identity 129 id = identity of object contained in locator 130 131 Throws: 132 InvalidCastException in debug mode when actual type of object is not of type that is requested. 133 134 Returns: 135 Object casted to desired type. 136 **/ 137 @trusted auto ref locate(T : Object)(Locator!(Object, string) locator, string id) { 138 import aermicioi.aedi.exception.invalid_cast_exception : InvalidCastException; 139 140 auto result = cast(T) locator.get(id); 141 142 if (result is null) { 143 throw new InvalidCastException("Requested object " ~ id ~ " is not of type " ~ typeid(T).toString()); 144 } 145 146 return result; 147 } 148 149 /** 150 ditto 151 **/ 152 @trusted auto ref locate(T)(Locator!(Object, string) locator, string id) 153 if (is(T == interface)) { 154 import aermicioi.aedi.exception.invalid_cast_exception : InvalidCastException; 155 import aermicioi.aedi.storage.wrapper : Wrapper; 156 157 auto casted = cast(T) locator.get(id); 158 159 if (casted !is null) { 160 return casted; 161 } 162 163 auto wrapper = cast(Wrapper!T) locator.get(id); 164 165 if (wrapper !is null) { 166 return wrapper; 167 } 168 169 throw new InvalidCastException("Requested object " ~ id ~ " is not of type " ~ typeid(T).toString()); 170 } 171 172 /** 173 ditto 174 **/ 175 @trusted auto ref locate(T)(Locator!(Object, string) locator, string id) 176 if(!is(T == interface)) { 177 import aermicioi.aedi.exception.invalid_cast_exception : InvalidCastException; 178 import aermicioi.aedi.storage.wrapper : Wrapper; 179 180 auto wrapper = (cast(Wrapper!T) locator.get(id)); 181 182 if (wrapper is null) { 183 throw new InvalidCastException("Requested object " ~ id ~ " is not of type " ~ typeid(T).toString()); 184 } 185 186 return wrapper; 187 } 188 189 /** 190 ditto 191 **/ 192 @trusted auto ref locate(T)(Locator!(Object, string) locator) { 193 import aermicioi.aedi.factory.reference : name; 194 195 return locate!T(locator, name!T); 196 }