-
Notifications
You must be signed in to change notification settings - Fork 0
/
CompositeFactory.ts
105 lines (92 loc) · 3.28 KB
/
CompositeFactory.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
/** @module build */
/** @hidden */
let _ = require('lodash');
import { IFactory } from './IFactory';
import { CreateException } from './CreateException';
/**
* Aggregates multiple factories into a single factory component.
* When a new component is requested, it iterates through
* factories to locate the one able to create the requested component.
*
* This component is used to conveniently keep all supported factories in a single place.
*
* ### Example ###
*
* let factory = new CompositeFactory();
* factory.add(new DefaultLoggerFactory());
* factory.add(new DefaultCountersFactory());
*
* let loggerLocator = new Descriptor("*", "logger", "*", "*", "1.0");
* factory.canCreate(loggerLocator); // Result: Descriptor("pip-service", "logger", "null", "default", "1.0")
* factory.create(loggerLocator); // Result: created NullLogger
*/
export class CompositeFactory implements IFactory {
private _factories: IFactory[] = [];
/**
* Creates a new instance of the factory.
*
* @param factories a list of factories to embed into this factory.
*/
public constructor(...factories: IFactory[]) {
if (factories != null)
this._factories = this._factories.concat(factories);
}
/**
* Adds a factory into the list of embedded factories.
*
* @param factory a factory to be added.
*/
public add(factory: IFactory): void {
if (factory == null)
throw new Error("Factory cannot be null");
this._factories.push(factory);
}
/**
* Removes a factory from the list of embedded factories.
*
* @param factory the factory to remove.
*/
public remove(factory: IFactory): void {
this._factories = _.remove(this._factories, f => f == factory);
}
/**
* Checks if this factory is able to create component by given locator.
*
* This method searches for all registered components and returns
* a locator for component it is able to create that matches the given locator.
* If the factory is not able to create a requested component is returns null.
*
* @param locator a locator to identify component to be created.
* @returns a locator for a component that the factory is able to create.
*/
public canCreate(locator: any): any {
if (locator == null)
throw new Error("Locator cannot be null");
// Iterate from the latest factories
for (let index = this._factories.length - 1; index >= 0; index--) {
let thisLocator = this._factories[index].canCreate(locator);
if (thisLocator != null)
return thisLocator;
}
return null;
}
/**
* Creates a component identified by given locator.
*
* @param locator a locator to identify component to be created.
* @returns the created component.
*
* @throws a CreateException if the factory is not able to create the component.
*/
public create(locator: any): any {
if (locator == null)
throw new Error("Locator cannot be null");
// Iterate from the latest factories
for (let index = this._factories.length - 1; index >= 0; index--) {
let factory = this._factories[index];
if (factory.canCreate(locator) != null)
return factory.create(locator);
}
throw new CreateException(null, locator);
}
}