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 an 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 (when locator is also a DelegatingLocator) for example. 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; 80 import std.typecons; 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) : AggregateLocator!(Type, KeyType, LocatorKeyType), Storage!(Locator!(Type, KeyType), LocatorKeyType) { 114 115 } 116 117 /** 118 Given a locator, locates an object and attempts to convert to T type. 119 120 Given a locator, locates an object and attempts to convert to T type. 121 When an object of T type is located, it is simply casted to T type. 122 When an value of T type is located, the func attempts to cast the requested object to 123 Wrapper!T, and will return it, instead of T directly. 124 In case of failure an InvalidCastException is thrown in debug environment. 125 126 Params: 127 locator = the locator that contains the data with id as identity 128 id = identity of object contained in locator 129 130 Throws: 131 InvalidCastException in debug mode when actual type of object is not of type that is requested. 132 133 Returns: 134 Object casted to desired type. 135 **/ 136 @trusted auto ref locate(T : Object)(Locator!(Object, string) locator, string id) { 137 import aermicioi.aedi.exception.invalid_cast_exception; 138 139 auto result = cast(T) locator.get(id); 140 141 if (result is null) { 142 throw new InvalidCastException("Requested object " ~ id ~ " is not of type " ~ typeid(T).toString()); 143 } 144 145 return result; 146 } 147 148 @trusted auto ref locate(T)(Locator!(Object, string) locator, string id) 149 if (is(T == interface)) { 150 import aermicioi.aedi.exception.invalid_cast_exception; 151 import aermicioi.aedi.storage.wrapper; 152 153 auto casted = cast(T) locator.get(id); 154 155 if (casted !is null) { 156 return casted; 157 } 158 159 auto wrapper = cast(Wrapper!T) locator.get(id); 160 161 if (wrapper !is null) { 162 return wrapper; 163 } 164 165 throw new InvalidCastException("Requested object " ~ id ~ " is not of type " ~ typeid(T).toString()); 166 } 167 168 /** 169 ditto 170 **/ 171 @trusted auto ref locate(T)(Locator!(Object, string) locator, string id) 172 if(!is(T == interface)) { 173 import aermicioi.aedi.exception.invalid_cast_exception; 174 import aermicioi.aedi.storage.wrapper; 175 176 auto wrapper = (cast(Wrapper!T) locator.get(id)); 177 178 if (wrapper is null) { 179 throw new InvalidCastException("Requested object " ~ id ~ " is not of type " ~ typeid(T).toString()); 180 } 181 182 return wrapper; 183 } 184 185 /** 186 ditto 187 **/ 188 @trusted auto ref locate(T)(Locator!(Object, string) locator) { 189 import aermicioi.aedi.factory.reference : name; 190 191 return locate!T(locator, name!T); 192 }