1 module hunt.entity.EntityMetaInfo;
2 
3 import hunt.entity.eql.Common;
4 
5 import hunt.entity;
6 import hunt.entity.DefaultEntityManagerFactory;
7 import hunt.entity.dialect;
8 
9 import hunt.logging;
10 
11 import std.conv;
12 import std.string;
13 import std.traits;
14 
15 /**
16  * 
17  */
18 struct EntityMetaInfo {
19 
20     string tablePrfix;
21     string tableName;
22     string simpleName;
23 
24     // fully qualified name
25     string fullName;
26 
27     string primaryKey;
28     string autoIncrementKey;
29 
30     private EntityField[] _fields;
31 
32     EntityField[] fields() {
33         return _fields;
34     }
35 
36     bool hasField(string name) {
37         foreach(ref EntityField f; _fields) {
38             if(name == f.name) {
39                 return true;
40             }
41         }
42 
43         return false;
44     }
45 
46     EntityField field(string name) {
47         foreach(ref EntityField f; _fields) {
48             if(name == f.name) {
49                 return f;
50             }
51         }
52         warningf("Can't find the field for %s", name);
53         return EntityField.init;
54     }
55 
56     string columnName(string name) {
57         if(hasField(name)) {
58             EntityField f = field(name);
59             string r = f.columnName;
60             if(r.empty)
61                 return name;
62             else
63                 return r;
64         } else {
65             return name;
66         }
67     }
68 
69     string fullColumnName(string name) {
70         string column = columnName(name);
71         return tablePrfix ~ tableName ~ "." ~ column;
72     }
73 }
74 
75 struct EntityField {
76     string name;
77 
78     // fully qualified name
79     string fullName;
80 
81     string columnName;
82 
83     bool isPrimary = false;
84 
85     bool isAutoIncrement = false;
86 
87     bool isAvaliable = true; 
88 }
89 
90 /**
91  * 
92  */
93 EntityMetaInfo extractEntityInfo(T)() {
94     EntityMetaInfo metaInfo;
95 
96     metaInfo.fullName = fullyQualifiedName!T;
97     metaInfo.simpleName = T.stringof;
98 
99     static if (hasUDA!(T, Table)) {
100         enum tableUda = getUDAs!(T, Table)[0];
101         metaInfo.tableName = tableUda.name;
102         metaInfo.tablePrfix = tableUda.prefix;
103     } else {
104         metaInfo.tableName = T.stringof;
105     }
106 
107     static foreach (string memberName; FieldNameTuple!T) {{
108         alias currentMember = __traits(getMember, T, memberName);
109         alias memberType = typeof(currentMember);
110 
111         static if (__traits(getProtection, currentMember) == "public") {
112 
113             // The field and column mapping
114             EntityField currentField;
115             currentField.name = memberName;
116             currentField.fullName = fullyQualifiedName!memberType;
117 
118             // Column
119             static if (hasUDA!(currentMember, Column)) {
120                 enum columnName = getUDAs!(currentMember, Column)[0].name;
121                 currentField.columnName = columnName;
122             } else {
123                 currentField.columnName = memberName;
124             }
125 
126             // The autoIncrementKey
127             static if (hasUDA!(currentMember, AutoIncrement) || hasUDA!(currentMember, Auto)) {
128                 currentField.isAutoIncrement = true;
129                 metaInfo.autoIncrementKey = memberName;
130             }
131 
132             // PrimaryKey
133             static if (hasUDA!(currentMember, PrimaryKey)) {
134                 currentField.isPrimary = true;
135                 metaInfo.primaryKey = memberName;
136             }
137 
138             // Transient
139             static if (hasUDA!(currentMember, Transient)) {
140                 currentField.isAvaliable = false;
141             }
142 
143             metaInfo._fields ~= currentField;
144         }
145     }}  
146 
147     return metaInfo;  
148 }