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.container.prototype_container;
32 
33 import aermicioi.aedi.container.container;
34 import aermicioi.aedi.storage.object_storage;
35 import aermicioi.aedi.factory.factory;
36 import aermicioi.aedi.exception;
37 import aermicioi.aedi.container.factory;
38 
39 import std.range.interfaces;
40 import std.typecons;
41 
42 /**
43  Prototype container.
44  
45  Instantiates a new object using passed ObjectFactory implementation, on each request of it by some part of an application.
46 **/
47 class PrototypeContainer : ConfigurableContainer {
48     
49     private {
50         
51         ObjectStorage!(ObjectFactory, string) factories;
52     }
53     
54     public {
55         
56         /**
57          * Default constructor for PrototypeContainer
58         **/
59         this() {
60             this.factories = new ObjectStorage!(ObjectFactory, string);
61         }
62         
63         /**
64          * Set object factory
65          * 
66          * Params: 
67          * 	object = factory for a object that is to be managed by prototype container.
68          *  key = identity of factory
69          * Returns:
70          * 	typeof(this)
71         **/
72         PrototypeContainer set(ObjectFactory object, string key) {
73             this.factories.set(new ExceptionChainingObjectFactory(new InProcessObjectFactoryDecorator(object), key), key);
74             
75             return this;
76         }
77         
78         /**
79          * Remove an object factory from container.
80          * 
81          * Params: 
82          * 	key = identity of factory to be removed
83          * Returns:
84          * 	typeof(this)
85         **/
86         PrototypeContainer remove(string key) {
87             this.factories.remove(key);
88             
89             return this;
90         }
91         
92         /**
93          * Get object created by a factory identified by key
94          * 
95          * Params:
96          *  key = identity of factory
97          * Returns:
98          * 	Object
99         **/
100         Object get(string key) {
101             if (this.factories.has(key)) {
102                 
103                 return this.factories.get(key).factory();
104             }
105             
106             throw new NotFoundException("Object by id " ~ key ~ " not found");
107         }
108         
109         /**
110          * Check if an object factory for it exists in container.
111          * 
112          * Params: 
113          * 	key = identity of factory
114          * Returns:
115          * 	bool
116         **/
117         bool has(in string key) inout {
118             return this.factories.has(key);
119         }
120         
121         /**
122         Sets up the internal state of container.
123         
124         Sets up the internal state of container (Ex, for singleton container it will spawn all objects that locator contains).
125         **/
126         PrototypeContainer instantiate() {
127             
128             return this;
129         }
130         /**
131         Alias a key to an alias_.
132                 
133         Params:
134         	key = the originial identity which is to be aliased.
135         	alias_ = the alias of identity.
136         	
137 		Returns:
138 			this
139         **/
140         PrototypeContainer link(string key, string alias_) {
141             this.factories.link(key, alias_);
142             
143             return this;
144         }
145         
146         /**
147         Removes alias.
148         
149         Params:
150         	alias_ = alias to remove.
151 
152         Returns:
153             this
154         	
155         **/
156         PrototypeContainer unlink(string alias_) {
157             this.factories.unlink(alias_);
158             
159             return this;
160         }
161         
162         /**
163         Resolve an alias to original identity, if possible.
164         
165         Params:
166         	key = alias of original identity
167         
168         Returns:
169         	Type the last identity in alias chain.
170         
171         **/
172         const(string) resolve(in string key) const {
173             return this.factories.resolve(key);
174         }
175         
176         /**
177         Get factory for constructed data identified by identity.
178         
179         Get factory for constructed data identified by identity.
180         Params:
181         	identity = the identity of data that factory constructs.
182         
183         Throws:
184         	NotFoundException when factory for it is not found.
185         
186         Returns:
187         	ObjectFactory the factory for constructed data.
188         **/
189         ObjectFactory getFactory(string identity) {
190             return this.factories.get(identity);
191         }
192         
193         /**
194         Get all factories available in container.
195         
196         Get all factories available in container.
197         
198         Returns:
199         	InputRange!(Tuple!(ObjectFactory, string)) a tuple of factory => identity.
200         **/
201         InputRange!(Tuple!(ObjectFactory, string)) getFactories() {
202             import std.algorithm;
203             
204             return this.factories.contents.byKeyValue.map!(
205                 a => tuple(a.value, a.key)
206             ).inputRangeObject;
207         }
208     }
209 }