1 
2 module witchcraft.aggregates;
3 
4 import witchcraft;
5 
6 import std.algorithm;
7 import std.array;
8 import std.range;
9 
10 abstract class Aggregate : Type
11 {
12     /++
13      + Looks up and returns a constructor with a parameter list that exactly
14      + matches the given array of types.
15      +
16      + Params:
17      +   parameterTypes = A parameter list the constructor must exactly match.
18      +
19      + Returns:
20      +   The constructor object, or null if no such constructor exists.
21      ++/
22     final const(Constructor) getConstructor(Type[] parameterTypes...) const
23     {
24         // Iterate up the inheritance tree.
25         return getConstructors.retro
26             .filter!(c => c.getParameterTypes == parameterTypes)
27             .takeOne
28             .chain(null.only)
29             .front;
30     }
31 
32     /++
33      + Looks up and returns a constructor with a parameter list that exactly
34      + matches the given array of types.
35      +
36      + Params:
37      +   parameterTypeInfos = A parameter list the constructor must exactly match.
38      +
39      + Returns:
40      +   The constructor object, or null if no such constructor exists.
41      ++/
42     final const(Constructor) getConstructor(TypeInfo[] parameterTypeInfos) const
43     {
44         // Iterate up the inheritance tree.
45         return getConstructors.retro
46             .filter!(c => c.getParameterTypeInfos == parameterTypeInfos)
47             .takeOne
48             .chain(null.only)
49             .front;
50     }
51 
52     /++
53      + Ditto, but accepts types given by variadic template arguments.
54      +
55      + Params:
56      +   TList = A list of types the constructor must exactly match.
57      +
58      + Returns:
59      +   The constructor object, or null if no such constructor exists.
60      ++/
61     final const(Constructor) getConstructor(TList...)() const
62     {
63         auto types = new TypeInfo[TList.length];
64 
65         foreach(index, type; TList)
66         {
67             types[index] = typeid(type);
68         }
69 
70         return this.getConstructor(types);
71     }
72 
73     /++
74      + Returns an array of all constructors defined by this type.
75      + This does not include the default constructor.
76      +
77      + If a type declares no constructors, this method will return an empty
78      + array.
79      +
80      + Returns:
81      +   And array of all constructors on the aggregate type.
82      ++/
83     abstract const(Constructor)[] getConstructors() const;
84 
85     @property
86     final override bool isAggregate() const
87     {
88         return true;
89     }
90 }