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_property_reader.generic_convertor_container;
31 
32 import aermicioi.aedi;
33 import aermicioi.aedi_property_reader.convertor_container;
34 import aermicioi.aedi_property_reader.convertor_factory;
35 import std.range;
36 import std.typecons;
37 
38 /**
39 An implementation of ConvertorContainer.
40 
41 Params:
42     FromType = original form of data based on which components are constructed.
43     DefaultConvertorFactory = convertor factory that is used by default in this container (used for some generic stuff)
44 **/
45 class GenericConvertorContainer(FromType, alias DefaultConvertorFactory) : 
46     ConvertorContainer!(FromType, string), FactoryLocator!(Factory!Object) {
47     
48     private {
49         
50         Locator!(FromType, string) locator_;
51         ObjectStorage!() instantiated;
52         ObjectStorage!(ConvertorFactory!(FromType, Object), string) convertors;        
53     }
54     
55     public {
56         
57         /**
58         Default constructor for GenericConvertorContainer!(FromType, DefaultConvertorFactory)
59         **/
60         this() {
61             this.instantiated = new ObjectStorage!();
62             this.convertors = new ObjectStorage!(ConvertorFactory!(FromType, Object), string);
63         }
64         
65         @property {
66         	/**
67 			Set locator
68 			
69 			Params: 
70 				locator = locator that provides container with FromType data for convertor factories
71 			
72 			Returns:
73 				GenericConvertorContainer!(FromType, DefaultConvertorFactory)
74 			**/
75             GenericConvertorContainer!(FromType, DefaultConvertorFactory) locator(Locator!(FromType, string) locator) @safe nothrow {
76             	this.locator_ = locator;
77             
78             	return this;
79             }
80             
81             /**
82 			Get locator of FromType data
83 			
84 			Returns:
85 				Locator!(FromType, string)
86 			**/
87             Locator!(FromType, string) locator() @safe nothrow {
88             	return this.locator_;
89             }
90         }
91         
92         /**
93 		Save a convertor factory in GenericConvertorContainer by key identity.
94 		
95 		Params:
96 			key = identity of element in GenericConvertorContainer.
97 			factory = convertor factory which is to be saved in GenericConvertorContainer.
98 			
99 		Return:
100 			GenericConvertorContainer!(FromType, DefaultConvertorFactory) 
101 		**/
102         GenericConvertorContainer!(FromType, DefaultConvertorFactory) set(ConvertorFactory!(FromType, Object) factory, string key) {
103             this.convertors.set(factory, key);
104             
105             return this;
106         }
107         
108         /**
109         Remove an convertor factory from GenericConvertorContainer with identity.
110         
111         Remove an convertor factory from GenericConvertorContainer with identity. If there is no convertor factory by provided identity, then no action is performed.
112         
113         Params:
114         	key = the identity of convertor factory to be removed.
115         	
116     	Return:
117     		GenericConvertorContainer!(FromType, DefaultConvertorFactory)
118         **/
119         GenericConvertorContainer!(FromType, DefaultConvertorFactory) remove(string key) {
120             this.convertors.remove(key);
121             this.instantiated.remove(key);
122             
123             return this;
124         }
125         
126         /**
127 		Get a component that is associated with key.
128 		
129 		Params:
130 			key = the component id.
131 			
132 		Throws:
133 			NotFoundException in case if the component wasn't found.
134 		
135 		Returns:
136 			Object, component if it is available.
137 		**/
138         Object get(string key) {
139             
140             if (!this.instantiated.has(key)) {
141                 if (!this.convertors.has(key)) {
142                     
143                     throw new NotFoundException("Object with id " ~ key ~ " not found.");
144                 }
145                 
146                 auto factory = this.convertors.get(key);
147                 factory.convertible = this.locator.get(key);
148                 
149                 this.instantiated.set( 
150                     factory.factory(),
151                     key,
152                 );
153             }
154             
155             return this.instantiated.get(key);
156         }
157         
158         /**
159         Check if a component is present in Locator by key id.
160         
161         Params:
162         	key = identity of element.
163         	
164     	Returns:
165     		bool true if an component by key is present in Locator.
166         **/
167         bool has(in string key) inout {
168             return this.convertors.has(key) && this.locator_.has(key);
169         }
170         
171         /**
172         Sets up the internal state of container.
173         
174         Sets up the internal state of container (Ex, for singleton container it will spawn all objects that locator contains).
175         **/
176         GenericConvertorContainer!(FromType, DefaultConvertorFactory) instantiate() {
177             import std.algorithm : filter;
178             
179             return this;
180         }
181         
182         /**
183         Get factory for constructed component identified by identity.
184         
185         Get factory for constructed component identified by identity.
186         Params:
187         	identity = the identity of component that factory constructs.
188         
189         Throws:
190         	NotFoundException when factory for it is not found.
191         
192         Returns:
193         	T the factory for constructed component.
194         **/
195         ObjectFactory getFactory(string identity) {
196             return this.convertors.get(identity);
197         }
198         
199         /**
200         Get all factories available in container.
201         
202         Get all factories available in container.
203         
204         Returns:
205         	InputRange!(Tuple!(T, string)) a tuple of factory => identity.
206         **/
207         InputRange!(Tuple!(Factory!(Object), string)) getFactories() {
208             import std.algorithm;
209             
210             return this.convertors.contents.byKeyValue.map!(
211                 a => tuple(cast(Factory!Object) a.value, a.key)
212             ).inputRangeObject;
213         }
214     }
215 }