1 /**
2 License:
3 	Boost Software License - Version 1.0 - August 17th, 2003
4 
5 	Permission is hereby granted, free of charge, to any person or organization
6 	obtaining a copy of the software and accompanying documentation covered by
7 	this license (the "Software") to use, reproduce, display, distribute,
8 	execute, and transmit the Software, and to prepare derivative works of the
9 	Software, and to permit third-parties to whom the Software is furnished to
10 	do so, all subject to the following:
11 	
12 	The copyright notices in the Software and this entire statement, including
13 	the above license grant, this restriction and the following disclaimer,
14 	must be included in all copies of the Software, in whole or in part, and
15 	all derivative works of the Software, unless such copies or derivative
16 	works are solely in the form of machine-executable object code generated by
17 	a source language processor.
18 	
19 	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 	FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
22 	SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
23 	FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
24 	ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 	DEALINGS IN THE SOFTWARE.
26 
27 Authors:
28 	aermicioi
29 **/
30 module aermicioi.aedi.container.aggregate_container;
31 
32 import aermicioi.aedi.container.container;
33 import aermicioi.aedi.storage.storage;
34 import aermicioi.aedi.storage.locator;
35 import aermicioi.aedi.storage.object_storage;
36 import aermicioi.aedi.exception.not_found_exception;
37 import std.range.interfaces;
38 import std.typecons;
39 
40 /**
41 Aggregate container, that delegates the task of locating to containers
42 managed by it.
43 
44 **/
45 class AggregateContainer : Container, Storage!(Container, string), AggregateLocator!(Object, string) {
46     
47     private {
48         ObjectStorage!(Container, string) containers;
49     }
50     
51     public {
52         
53         /**
54          * Default constructor for AggregateContainer
55         **/
56         this() {
57             this.containers = new ObjectStorage!(Container, string);
58         }
59         
60         /**
61         Set a container into aggregate container
62         
63         Set a container into aggregate container
64         Description
65         
66         Params:
67         	container = container that is added to aggregate container
68         	identity = identity by which container is identified in aggregate container
69         
70         Returns:
71         	AggregateContainer
72         **/
73         AggregateContainer set(Container container, string identity) {
74         	this.containers.set(container, identity);
75         
76         	return this;
77         }
78         
79         /**
80         Remove a container from aggregate container.
81         
82         Remove a container from aggregate container.
83 
84         Params:
85         	identity = identity of container to be removed
86         
87         Returns:
88         	AggregateContainer
89         **/
90         AggregateContainer remove(string identity) {
91         	this.containers.remove(identity);
92         
93         	return this;
94         }
95         
96         /**
97         Get a container, or an object that is contained by managed containers.
98         
99         Get a container, or an object that is contained by managed containers.
100         
101         Params:
102         	identity = identity of object that is to be supplied.
103         
104         Throws:
105         	NotFoundException when no requested object by identity is present in container
106         
107         Returns:
108         	Object the object contained in one of containers or a container itself.
109         **/
110         Object get(string identity) {
111             if (this.containers.has(identity)) {
112                 Object container = cast(Object) this.containers.get(identity); 
113                 
114                 if (container !is null) {
115                     return container;
116                 }
117             }
118             
119         	foreach (container; this.containers) {
120         	    if (container.has(identity)) {
121         	        return container.get(identity);
122         	    }
123         	}
124         	
125         	throw new NotFoundException("Object by id " ~ identity ~ " not found.");
126         }
127         
128         /**
129         Check if an object is present in one of containers, or it is a container itself.
130         
131         Check if an object is present in one of containers, or it is a container itself.
132         
133         Params:
134         	identity = identity of object to be checked
135         
136         Returns:
137         	bool true if exists, false otherwise
138         **/
139         bool has(in string identity) inout {
140             if (this.containers.has(identity)) {
141                 return true;
142             }
143             
144             foreach (container; this.containers.contents) {
145                 if (container.has(identity)) {
146                     return true;
147                 }
148             }
149             
150             return false;
151         }
152         
153         /**
154         Finalize all unfinished initialization work in containers.
155         
156         Finalize all unfinished initialization work in containers.
157         
158         Returns:
159         	AggregateContainer
160         **/
161         AggregateContainer instantiate() {
162             
163             foreach (container; this.containers) {
164                 container.instantiate;
165             }
166             
167             return this;
168         }
169         
170         /**
171         Get a specific container.
172         
173         Params:
174             key = the container identity.
175         **/
176         Locator!(Object, string) getLocator(string key) {
177             
178             return this.containers.get(key);
179         }
180         
181         /**
182         Get all containers in aggregate container
183         
184         Returns:
185         	InputRange!(Tuple!(Locator!(Object, string), string)) a range of container => identity
186         **/
187         InputRange!(Tuple!(Locator!(Object, string), string)) getLocators() {
188             import std.algorithm;
189             
190             return this.containers.contents.byKeyValue.map!(
191                 a => tuple(cast(Locator!()) a.value, a.key)
192             ).inputRangeObject;
193         }
194         
195         /**
196         Check if aggregate container contains a specific container.
197         
198         Params:
199         	key = the identity of container in aggregate container
200         **/
201         bool hasLocator(string key) inout {
202             
203             return this.containers.has(key);
204         }
205     }
206 }