1 /**
2     AutoMapper API.
3 
4     This module is the entry point for building an AutoMapper configuration.
5 */
6 module automapper.api;
7 
8 import automapper.meta;
9 import automapper.naming;
10 public import automapper.config;
11 
12 
13 /// Entry point for building an object mapper configuration in a fluent way
14 class CreateMap(TSource, TDest, Configs...) : ObjectMapperConfig!(TSource, TDest, 
15         findOrDefault!(isSourceNamingConventionConfig,
16             SourceNamingConventionConfig!CamelCaseNamingConvention, Configs)
17                 .Convention,
18         findOrDefault!(isDestNamingConventionConfig,
19             DestNamingConventionConfig!CamelCaseNamingConvention, Configs)
20                 .Convention, 
21         onlyOneExists!(isReverseMapConfig, Configs), 
22         Filter!(isObjectMemberMappingConfig, Configs))
23     if (isClassOrStruct!TSource && isClassOrStruct!TDest)
24 {
25     /// Tell to reverse the mapper automatically
26     template ReverseMap()
27     {
28         alias ReverseMap = CreateMap!(TSource, TDest, AliasSeq!(Configs, ReverseMapConfig));
29     }
30 
31     /// Precise a member mapping
32     template ForMember(string DestMember, string SrcMember)
33     {
34         alias ForMember = CreateMap!(TSource, TDest, AliasSeq!(Configs,
35             ForMemberConfig!(DestMember, SrcMember)));
36     }
37 
38     /// Customize member mapping with a delegate
39     template ForMember(string DestMember, alias Delegate)
40     {
41         alias ForMember = CreateMap!(TSource, TDest, AliasSeq!(Configs,
42             ForMemberConfig!(DestMember, Delegate)));
43     }
44 
45     /// Ignore a member
46     template Ignore(string DestMember)
47     {
48         alias Ignore = CreateMap!(TSource, TDest, AliasSeq!(Configs, IgnoreConfig!DestMember));
49     }
50 
51     /// Set source naming convention
52     template SourceMemberNaming(TConv) if (isNamingConvention!TConv)
53     {
54         alias SourceMemberNaming = CreateMap!(TSource, TDest, AliasSeq!(Configs, SourceNamingConventionConfig!TConv));
55     }
56 
57     /// Set dest. naming convention
58     template DestMemberNaming(TConv) if (isNamingConvention!TConv)
59     {
60         alias DestMemberNaming = CreateMap!(TSource, TDest, AliasSeq!(Configs, DestNamingConventionConfig!TConv));
61     }
62 }
63 
64 ///
65 unittest
66 {
67     import automapper : MapperConfiguration, CreateMap;
68 
69     static class A {
70         string foo;
71         int bar;
72     }
73 
74     static class B {
75         string qux;
76         int baz;
77     }
78 
79     MapperConfiguration!(
80         CreateMap!(A, B)
81             .ForMember!("qux", "foo")
82             .ForMember!("baz", "foo"))
83                 .createMapper();
84 }
85 
86 ///
87 
88 
89 
90 
91 /// entry point for bulding a type converter configuration
92 class CreateMap(A, B) if (!isClassOrStruct!A || !isClassOrStruct!B)
93 {
94     import automapper.type.converter : DelegateTypeConverter, isTypeConverter;
95 
96     ///
97     static class ConvertUsing(alias Delegate) : DelegateTypeConverter!(A, B, Delegate) if (isCallable!Delegate)
98     {
99         static assert(is(ReturnType!Delegate == B), "must return a " ~ B.stringof);
100         static assert((Parameters!Delegate.length == 1) && is(Parameters!Delegate[0] == A), 
101             "must take one argument of type " ~ A.stringof);
102     }
103 
104     ///
105     template ConvertUsing(Type) if (isTypeConverter!Type)
106     {
107         alias ConvertUsing = Type;
108     }
109 }
110 
111 
112 ///
113 unittest
114 {
115     import automapper;
116     import std.datetime : SysTime;
117 
118     static class A {
119         long timestamp;
120     }
121 
122     static class B {
123         SysTime timestamp;
124     }
125 
126     MapperConfiguration!(
127         CreateMap!(long, SysTime)
128             .ConvertUsing!((long ts) => SysTime(ts)),
129         CreateMap!(A, B))
130             .createMapper();
131 }