1 /**
2 Provides an interface for registering components into containers.
3 
4 License:
5 	Boost Software License - Version 1.0 - August 17th, 2003
6 
7 	Permission is hereby granted, free of charge, to any person or organization
8 	obtaining a copy of the software and accompanying documentation covered by
9 	this license (the "Software") to use, reproduce, display, distribute,
10 	execute, and transmit the Software, and to prepare derivative works of the
11 	Software, and to permit third-parties to whom the Software is furnished to
12 	do so, all subject to the following:
13 	
14 	The copyright notices in the Software and this entire statement, including
15 	the above license grant, this restriction and the following disclaimer,
16 	must be included in all copies of the Software, in whole or in part, and
17 	all derivative works of the Software, unless such copies or derivative
18 	works are solely in the form of machine-executable object code generated by
19 	a source language processor.
20 	
21 	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 	FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
24 	SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
25 	FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
26 	ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 	DEALINGS IN THE SOFTWARE.
28 
29 Authors:
30 	aermicioi
31 **/
32 module aermicioi.aedi.configurer.register.register;
33 
34 import aermicioi.aedi.configurer.register.configuration_context_factory;
35 import aermicioi.aedi.storage.storage;
36 import aermicioi.aedi.storage.locator;
37 import aermicioi.aedi.factory;
38 import aermicioi.aedi.factory.generic_factory;
39 import aermicioi.aedi.factory.wrapping_factory : WrappingFactory;
40 import aermicioi.aedi.factory.proxy_factory;
41 import aermicioi.aedi.container.proxy_container;
42 import aermicioi.aedi.container.container;
43 import aermicioi.util.traits : isReferenceType;
44 import aermicioi.aedi.exception;
45 
46 /**
47 Register a new factory for type T object into storage/DI container by id.
48 
49 Params:
50     Type = the type of object registered in storage
51 	storage = the storage where factory will be stored.
52 	locator = the locator that will be used by GenericFactory implementation to fetch required objects.
53 	id = the identity by which to register the factory in storage.
54 	
55 Returns:
56 	GenericFactory implementation for further configuration.
57 **/
58 auto register(Type)(Storage!(ObjectFactory, string) storage, Locator!(Object, string) locator, string id) {
59     auto fact = new GenericFactoryImpl!Type(locator);
60     auto configurable = new ConfigurationContextFactory!Type();
61     configurable.storage = storage;
62     configurable.locator = locator;
63     configurable.identity = id;
64     configurable.decorated = fact;
65     configurable.wrapper = new WrappingFactory!(Factory!Type)(fact);
66     
67     storage.set(configurable.wrapper, id);
68     
69     return configurable;
70 }
71 
72 /**
73 ditto
74 **/
75 auto register(Type)(ConfigurableContainer storage, string id) {
76     return register!Type(storage, storage, id);
77 }
78 
79 /**
80 Register a new factory for type Type object into storage/DI container by it's fully qualified name.
81 
82 Params:
83     Type = the type of object registered in storage
84 	storage = the storage where factory will be stored.
85 	locator = the locator that will be used by GenericFactory implementation to fetch required objects.
86 	
87 Returns:
88 	GenericFactory implementation for further configuration.
89 **/
90 auto register(Type)(Storage!(ObjectFactory, string) storage, Locator!(Object, string) locator) {
91     return storage.register!(Type)(locator, name!Type);
92 }
93 
94 /**
95 ditto
96 **/
97 auto register(Type)(ConfigurableContainer storage) {
98     return register!Type(storage, storage);
99 }
100 
101 /**
102 Register a new factory for type T object into storage/DI container by Interface fully qualified name.
103 
104 Params:
105     Type = the type of object registered in storage
106     Interface = interface implemented by object registered in storage
107 	storage = the storage where factory will be stored.
108 	locator = the locator that will be used by GenericFactory implementation to fetch required objects.
109 	
110 Returns:
111 	GenericFactory implementation for further configuration.
112 **/
113 auto register(Interface, Type)(Storage!(ObjectFactory, string) storage, Locator!(Object, string) locator)
114 	if (is(Type : Interface) && isReferenceType!Type) {
115     
116     return storage.register!Type(locator, name!Interface);
117 }
118 
119 /**
120 ditto
121 **/
122 auto register(Interface, Type)(ConfigurableContainer storage) {
123     return register!(Interface, Type)(storage, storage);
124 }
125 
126 /**
127 Register an object into a storage by storageId located in storageLocator.
128 
129 Params:
130     Type = the type of object registered in storage
131     storageLocator = locator containing the storage where to store object.
132     locator = locator used to fetch dependencies for registered object
133     id = the id of object registered in storage
134     storageId = the id of storage where object is stored.
135     
136 Throws:
137     NotFoundException when storage with storageId is not found.
138     
139 Returns:
140     storageLocator for further configuration
141 **/
142 auto register(Type, R : Locator!())(R storageLocator, Locator!() locator, string id, string storageId = "singleton") 
143     if (!is(R : Storage!(ObjectFactory, string))) {
144     import std.algorithm;
145 
146     return storageLocator
147         .locate!(Storage!(ObjectFactory, string))(storageId)
148         .register!Type(locator, id);
149 }
150     
151 /**
152 ditto
153 **/
154 auto registerInto(Type, R : Locator!())(R storageLocator, Locator!() locator, string storageId = "singleton") 
155     if (!is(R : Storage!(ObjectFactory, string))) {
156     
157     return storageLocator.register!Type(locator, name!Type, storageId);
158 }
159 
160 /**
161 ditto
162 **/
163 auto register(Type, R : Locator!())(R locator, string id, string storageId = "singleton") 
164     if (!is(R : Storage!(ObjectFactory, string))) {
165     
166     return locator.register!Type(locator, id, storageId);
167 }
168     
169 /**
170 ditto
171 **/
172 auto registerInto(Type, R : Locator!())(R locator, string storageId = "singleton") 
173     if (!is(R : Storage!(ObjectFactory, string))) {
174     
175     return locator.registerInto!Type(locator, storageId);
176 }
177 
178 /**
179 Register an object into a storage by storageId located in storageLocator with id being FQN of an Interface that object implements.
180 
181 Params:
182     Interface = interface that object implements
183     Type = the type of object registered in storage
184     storageLocator = locator containing the storage where to store object.
185     locator = locator used to fetch dependencies for registered object
186     storageId = the id of storage where object is stored.
187     
188 Throws:
189     NotFoundException when storage with storageId is not found.
190     
191 Returns:
192     storageLocator for further configuration
193 **/
194 auto register(Interface, Type, R : Locator!())(R storageLocator, Locator!() locator, string storageId = "singleton") 
195     if (!is(R : Storage!(ObjectFactory, string))) {
196         
197     return storageLocator.register!Type(locator, name!Interface, storageId);
198 }
199 
200 /**
201 ditto
202 **/
203 auto register(Interface, Type, R : Locator!())(R locator, string storageId = "singleton") 
204     if (!is(R : Storage!(ObjectFactory, string))) {
205         
206     return locator.register!Type(locator, name!Interface, storageId);
207 }
208 
209 /**
210 Register data into an object storage.
211 
212 Wraps up any already instantiated data that is not reference type into an object, and saves it into storage.
213 Any data that is of reference type is just saved in storage
214 
215 Params:
216     Type = the type of object registered in storage
217     storage = the storage were data is saved
218     data = actual data to be saved
219     id = the identity of data that is to be saved.
220     
221 Returns:
222     the storage were data was saved.
223 **/
224 auto register(Type)(Storage!(Object, string) storage, Type data, string id) {
225     import aermicioi.aedi.storage.wrapper : WrapperImpl;
226     
227     static if (is(Type : Object)) {
228         
229         storage.set(data, id);
230     } else {
231 
232         auto wrapper = new WrapperImpl!Type(data);
233         storage.set(wrapper, id);
234     }
235     
236     return storage;
237 }
238 
239 /**
240 Register data inta a object storage identified by it's type.
241 
242 Wraps up any copy-by-value data into an object, and saves it into storage by it's type.
243 
244 Params:
245     Type = the type of object registered in storage
246     storage = the storage were data is saved
247     data = actual data to be saved
248 
249 Returns:
250     the storage were data was saved.
251 **/
252 auto register(Type)(Storage!(Object, string) storage, Type data) {
253     return storage.register!Type(data, name!Type);
254 }
255 
256 /**
257 Register data into an object storage identified by implemented interface.
258 
259 Wraps up any copy-by-value data into an object, and saves it into storage by it's type.
260 
261 Params:
262     Interface = interface that object implements
263     Type = the type of object registered in storage
264     storage = the storage were data is saved
265     data = actual data to be saved
266 
267 Returns:
268     the storage were data was saved.
269 **/
270 auto register(Interface, Type)(Storage!(Object, string) storage, Type data)
271     if (is(Type : Interface) && !is(Type == Interface)) {
272     
273     return storage.register!Type(data, name!Interface);
274 }
275 
276 /**
277 Register data into an object storage located in locator by storageId.
278 
279 Params:
280     Type = the type of object registered in storage
281     locator = locator containing object storage were data is saved.
282     data = the actual data saved in storage
283     id = the id by which data will be identified
284     storageId = identity of storage in locator
285 **/
286 auto register(Type, R : Locator!())(R locator, Type data, string id, string storageId = "parameters")
287     if (!is(R : Storage!(Object, string))) {
288     import aermicioi.aedi.storage.wrapper : Wrapper;
289 
290     locator
291         .locate!(Storage!(Object, string))(storageId)
292         .register!Type(data, id);
293 
294     return locator;
295 }
296 
297 /**
298 ditto
299 **/
300 auto registerInto(Type, R : Locator!())(R locator, Type data, string storageId = "parameters")
301     if (!is(R : Storage!(Object, string))) {
302     
303     return locator.register!Type(data, name!Type, storageId);
304 }
305 
306 /**
307 ditto
308 **/
309 auto register(Interface, Type, R : Locator!())(R storage, Type object, string storageId = "parameters") 
310     if (is(Type : Interface) && !is(R : Storage!(Object, string)) && !is(Type == Interface)) {
311     return storage.register!Type(object, name!Interface, storageId);
312 }