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.object_storage;
32 
33 import aermicioi.aedi.storage.container;
34 import aermicioi.aedi.storage.alias_aware;
35 import aermicioi.aedi.exception.not_found_exception;
36 
37 import std.conv;
38 
39 /**
40  Implementation of Storage, Locator and AliasAware interfaces.
41  
42  Stores Type elements by KeyType identity in.
43 **/
44 class ObjectStorage(Type = Object, KeyType = string) : Container!(Type, KeyType), AliasAware!(KeyType) {
45     
46     private {
47         
48         Type[const(KeyType)] values;
49         
50         KeyType[const(KeyType)] aliasings;
51     }
52     
53     public {
54         
55         /**
56         Fetch an element by identity.
57         
58         Params:
59         	identity = the identity of element to be returned
60         
61         Throws:
62         	NotFoundException when no element is present in storage.
63         
64         Returns:
65         	Type the element with identity.
66         **/
67         Type get(KeyType identity) {
68             
69             if (!this.has(identity)) {
70                 throw new NotFoundException("Element " ~ identity.to!string ~ " not found.");
71             }
72             
73             return this.values[this.resolve(identity)];
74         }
75         
76         /**
77         Check if an element is present in storage.
78         
79         Params:
80         	identity = the identity of element.
81         
82         Returns:
83         	bool if element with identity exists in storage.
84         **/
85         bool has(in KeyType identity) inout {
86             return (this.resolve(identity) in this.values) !is null;
87         }
88         
89 		/**
90 		Save an element in storage by identity.
91 		
92 		Params:
93 			identity = the identity of element in storage.
94 			element = the element which is saved in storage.
95 		
96 		Returns:
97 			ObjectStorage
98 		**/
99         ObjectStorage set(Type element, KeyType identity) {
100             
101             this.values[identity] = element;
102             
103             return this;
104         }
105         
106 		/**
107 		Remove an element with identity from storage.
108 		
109 		Params:
110 			identity = identity of element which should be removed from storage.
111 		
112 		Returns:
113 			ObjectStorage
114 		**/
115         ObjectStorage remove(KeyType identity) {
116             
117             this.values.remove(identity);
118             
119             return this;
120         }
121         
122         /**
123         Get the contents of storage as associative array.
124         
125         Returns:
126         	Type[KeyType] the contents of storage.
127         **/
128         inout(Type[const(KeyType)]) contents() inout {
129             return this.values;
130         }
131         
132         /**
133         Iterate over elements in storage
134         
135         Params:
136         	dg = the delegate which will do something on each element.
137         
138         Returns:
139         	int
140         **/
141         int opApply(scope int delegate(Type value) dg) {
142         	
143         	foreach (value; this.contents()) {
144         		
145         		auto result = dg(value);
146         		
147         		if (result != 0) {
148         			return result;
149         		}
150         	}
151         	
152         	return 0;
153         }
154         
155         /**
156         ditto
157         **/
158         int opApply(scope int delegate(const KeyType key, Type value) dg) {
159         	
160         	foreach (key, value; this.contents()) {
161         		
162         		auto result = dg(key, value);
163         		
164         		if (result != 0) {
165         			return result;
166         		}
167         	}
168         	
169         	return 0;
170         }
171         
172         /**
173         Alias an identity with alias_/
174         
175         Params:
176         	identity = identity which will be aliased
177         	alias_ = the new alias of identity.
178         
179         Returns:
180         	ObejcStorage
181         **/
182         ObjectStorage link(KeyType identity, KeyType alias_) {
183             
184             this.aliasings[alias_] = identity;
185             
186             return this;
187         }
188         
189         /**
190         Removes alias.
191         
192         Params:
193         	alias_ = alias to remove.
194 
195         Returns:
196             this
197         	
198         **/
199         ObjectStorage unlink(KeyType alias_) {
200             this.aliasings.remove(alias_);
201             
202             return this;
203         }
204         
205         /**
206         Resolve the alias to an element identity.
207         
208         Params:
209         	alias_ = the alias to an identity.
210         Returns:
211         	KeyType the last found identity in alias chain.
212         **/
213         const(KeyType) resolve(in KeyType alias_) const {
214             import std.typecons : Rebindable;
215             Rebindable!(const(KeyType)) aliased = alias_;
216             
217             while ((aliased in this.aliasings) !is null) {
218                 aliased = this.aliasings[aliased];
219             }
220             
221             return aliased;
222         }
223     }
224 }