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 module aermicioi.aedi.storage.aggregate_locator; 32 33 import aermicioi.aedi.storage.locator; 34 import aermicioi.aedi.exception.not_found_exception; 35 import std.conv : to; 36 import std.range.interfaces; 37 import std.typecons; 38 39 /** 40 An implementation of AggregateLocator. 41 **/ 42 class AggregateLocatorImpl(Type = Object, KeyType = string, LocatorKeyType = KeyType) : MutableAggregateLocator!(Type, KeyType, LocatorKeyType) { 43 44 protected { 45 46 Locator!(Type, KeyType)[LocatorKeyType] locators; 47 } 48 49 public { 50 51 /** 52 Add a Locator by key. 53 54 Params: 55 key = key by which to identify the locator. 56 locator = the Locator that will be added to AggregateLocator 57 **/ 58 AggregateLocatorImpl!(Type, KeyType, LocatorKeyType) set(Locator!(Type, KeyType) locator, LocatorKeyType key) { 59 60 this.locators[key] = locator; 61 62 return this; 63 } 64 65 /** 66 Removes a Locator by key. 67 68 Params: 69 key = the identity of locator that should be removed. 70 **/ 71 AggregateLocatorImpl!(Type, KeyType, LocatorKeyType) remove(LocatorKeyType key) { 72 73 this.locators.remove(key); 74 75 return this; 76 } 77 78 /** 79 Get an Type that is associated with key. 80 81 Params: 82 identity = the element id. 83 84 Throws: 85 NotFoundException in case if the element wasn't found. 86 87 Returns: 88 Type element if it is available. 89 **/ 90 Type get(KeyType identity) { 91 92 foreach (locator; this.locators) { 93 94 if (locator.has(identity)) { 95 return locator.get(identity); 96 } 97 } 98 99 import std.traits; 100 101 if ((identity in this.locators) !is null) { 102 auto result = cast(Type) this.locators[identity]; 103 104 if (result !is null) { 105 return result; 106 } 107 } 108 109 throw new NotFoundException("Could not find an object with " ~ identity.to!string ~ " identity."); 110 } 111 112 /** 113 Check if an element is present in Locator by key id. 114 115 Note: 116 This check should be done for elements that locator actually contains, and 117 not in chained locator (when locator is also a DelegatingLocator) for example. 118 Params: 119 identity = identity of element. 120 121 Returns: 122 bool true if an element by key is present in Locator. 123 **/ 124 bool has(in KeyType identity) inout { 125 126 if ((identity in this.locators) !is null) { 127 return true; 128 } 129 130 foreach (locator; this.locators) { 131 132 if (locator.has(identity)) { 133 return true; 134 } 135 } 136 137 return false; 138 } 139 140 /** 141 Get a specific locator. 142 143 Params: 144 key = the locator identity. 145 **/ 146 Locator!(Type, KeyType) getLocator(LocatorKeyType key) { 147 148 if (this.hasLocator(key)) { 149 return this.locators[key]; 150 } 151 152 throw new NotFoundException("Could not find any locator with identity of " ~ key); 153 } 154 155 /** 156 Get all locators in aggregate locator 157 158 Returns: 159 InputRange!(Tuple!(Locator!(Type, KeyType), LocatorKeyType)) a range of locator => identity 160 **/ 161 InputRange!(Tuple!(Locator!(Type, KeyType), LocatorKeyType)) getLocators() { 162 import std.algorithm; 163 164 return this.locators.byKeyValue.map!( 165 a => tuple(a.value, a.key) 166 ).inputRangeObject; 167 } 168 169 /** 170 Check if aggregate locator contains a specific locator. 171 172 Params: 173 key = the identity of locator in aggregate locator 174 **/ 175 bool hasLocator(LocatorKeyType key) inout { 176 177 return (key in this.locators) !is null; 178 } 179 } 180 }