1 /* 2 * Entity - Entity is an object-relational mapping tool for the D programming language. Referring to the design idea of JPA. 3 * 4 * Copyright (C) 2015-2018 Shanghai Putao Technology Co., Ltd 5 * 6 * Developer: HuntLabs.cn 7 * 8 * Licensed under the Apache-2.0 License. 9 * 10 */ 11 12 module hunt.entity.EntityInfo; 13 14 import hunt.entity.eql.Common; 15 16 import hunt.entity; 17 import hunt.entity.EntityDeserializer; 18 import hunt.entity.EntityMetaInfo; 19 import hunt.entity.DefaultEntityManagerFactory; 20 import hunt.entity.dialect; 21 import hunt.entity.EntityInfoMaker; 22 23 import hunt.logging; 24 25 import std.conv; 26 import std.string; 27 import std.traits; 28 import std.variant; 29 30 class EntityInfo(T : Object, F : Object = T) { 31 32 private EntityFieldInfo[string] _fields; 33 private string _factoryName = defaultEntityManagerFactoryName(); 34 private string _tableName; 35 private string _tableNameInLower; // for PostgreSQL, the column's name will be converted to lowercase. 36 private string _entityClassName; 37 private string _autoIncrementKey; 38 private string _primaryKey; 39 private EntityManager _manager; 40 private Dialect _dialect; 41 private T _data; 42 private F _owner; 43 private string _tablePrefix; 44 45 private EntityMetaInfo _metaInfo; 46 47 // private string[string] _fieldColumnMaps; 48 49 //auto mixin function 50 // public T deSerialize(Row row) {} 51 // public void setIncreaseKey(ref T entity, int value) {} 52 // public R getPrimaryValue() {} 53 // public void setPrimaryValue(ref T entity, int value) {} 54 55 // pragma(msg, "T = "~T.stringof~ " F = "~F.stringof); 56 // pragma(msg,makeImport!(T)()); 57 // pragma(msg,makeInitEntityData!(T,F)()); 58 // pragma(msg,makeDeserializer!(T)); 59 // pragma(msg,makeSetIncreaseKey!(T)); 60 // pragma(msg,makeGetPrimaryValue!(T)); 61 // pragma(msg,makeSetPrimaryValue!(T)()); 62 63 64 mixin(makeImport!(T)()); 65 mixin(makeInitEntityData!(T,F)()); 66 67 mixin(makeDeserializer!(T)()); 68 mixin(makeSetIncreaseKey!(T)()); 69 mixin(makeGetPrimaryValue!(T)()); 70 mixin(makeSetPrimaryValue!(T)()); 71 72 this(EntityManager manager = null, T t = null, F owner = null) 73 { 74 version(HUNT_ENTITY_DEBUG) { 75 warningf("T: %s, F: %s", T.stringof, F.stringof); 76 } 77 78 if (t is null) { 79 _data = new T(); 80 } 81 else { 82 _data = t; 83 } 84 85 static if (is(T == F)){ 86 _owner = _data; 87 } 88 else{ 89 _owner = owner; 90 } 91 _manager = manager; 92 if (_manager) { 93 if(_data !is null) 94 _data.setManager(_manager); 95 _tablePrefix = _manager.getPrefix(); 96 } 97 98 initializeEntityInfo(); 99 } 100 101 private void initializeEntityInfo() { 102 // _metaInfo = extractEntityInfo!(T)(); 103 _metaInfo = T.metaInfo; // extractEntityInfo!(T)(); 104 105 _entityClassName = _metaInfo.simpleName; 106 _tableName = _tablePrefix ~ _metaInfo.tableName; 107 _tableNameInLower = _tableName.toLower(); 108 109 initEntityData(); 110 } 111 112 private string toColumnName(string fieldName) { 113 return _metaInfo.columnName(fieldName); 114 } 115 116 public EntityFieldInfo getPrimaryField() { 117 if (_primaryKey.length > 0) 118 return _fields[_primaryKey]; 119 return null; 120 } 121 122 public Variant[string] getInsertString() { 123 Variant[string] str; 124 125 foreach(string fieldName, EntityFieldInfo info; _fields) { 126 string columnName = info.getColumnName(); 127 Variant currentValue = info.getColumnFieldData(); 128 129 TypeInfo typeInfo = info.typeInfo(); 130 if(typeInfo is null) { 131 typeInfo = currentValue.type; 132 } 133 134 version(HUNT_DB_DEBUG_MORE) { 135 tracef("fieldName: %s, columnName: %s, type: %s, value: %s", 136 fieldName, columnName, typeInfo, currentValue.toString()); 137 } 138 139 // Skip the autoIncrementKey 140 if (columnName == _autoIncrementKey) 141 continue; 142 143 // version(HUNT_DB_DEBUG) trace(currentValue.type); 144 145 // skip Object member 146 if(typeid(typeInfo) == typeid(TypeInfo_Class) || 147 typeid(typeInfo) == typeid(TypeInfo_Struct) ) { 148 version(HUNT_DB_DEBUG) warningf("Object member skipped: %s", fieldName); 149 continue; 150 } 151 152 if (columnName.empty()) { 153 version(HUNT_DEBUG) warningf("The name of column for the field [%s] is empty.", fieldName); 154 continue; 155 } 156 157 if(!_manager.getDbOption().isPgsql()) { 158 columnName = info.getFullColumn(); 159 } 160 161 if(columnName in str) { 162 version(HUNT_DEBUG) { 163 warningf("skip a existed column [%s] with value [%s].", columnName, currentValue.toString()); 164 } 165 } else { 166 str[columnName] = currentValue; 167 } 168 } 169 return str; 170 } 171 172 EntityFieldInfo opDispatch(string name)() 173 { 174 version(HUNT_ENTITY_DEBUG) { 175 infof("getting field info for: %s", name); 176 } 177 178 EntityFieldInfo fieldInfo = _fields.get(name,null); 179 if (fieldInfo is null) { 180 throw new EntityException("Cannot find entityfieldinfo by name : " ~ name); 181 } else { 182 version(HUNT_ENTITY_DEBUG_MORE) { 183 tracef("The field info is %s", typeid(fieldInfo)); 184 } 185 } 186 return fieldInfo; 187 } 188 189 public string getFactoryName() { return _factoryName; } 190 public string getEntityClassName() { return _entityClassName; } 191 public string getTableName() { return _tableName; } 192 public string getAutoIncrementKey() { return _autoIncrementKey; } 193 public EntityFieldInfo[string] getFields() { return _fields; } 194 public string getPrimaryKeyString() { return _primaryKey; } 195 public EntityFieldInfo getSingleField(string name) { return _fields.get(name,null); } 196 197 private string getCountAsName() { 198 if(_manager.getDbOption().isPgsql()) { 199 return EntityExpression.getCountAsName(_tableNameInLower); 200 } else { 201 return EntityExpression.getCountAsName(_tableName); 202 } 203 } 204 } 205 206 string makeSetPrimaryValue(T)() { 207 string R; 208 string name; 209 foreach(memberName; __traits(derivedMembers, T)) { 210 static if (__traits(getProtection, __traits(getMember, T, memberName)) == "public") { 211 alias memType = typeof(__traits(getMember, T ,memberName)); 212 static if (!isFunction!(memType) && hasUDA!(__traits(getMember, T ,memberName), PrimaryKey)) { 213 R = typeof(__traits(getMember, T ,memberName)).stringof; 214 name = memberName; 215 } 216 } 217 } 218 return ` 219 public void setPrimaryValue(string value) { 220 _data.`~name~` = value.to!`~R~`; 221 }`; 222 } 223 224 225 string makeGetPrimaryValue(T)() { 226 string R; 227 string name; 228 foreach(memberName; __traits(derivedMembers, T)) { 229 static if (__traits(getProtection, __traits(getMember, T, memberName)) == "public") { 230 alias memType = typeof(__traits(getMember, T ,memberName)); 231 static if (!isFunction!(memType) && hasUDA!(__traits(getMember, T ,memberName), PrimaryKey)) { 232 R = typeof(__traits(getMember, T ,memberName)).stringof; 233 name = memberName; 234 } 235 } 236 } 237 return ` 238 public `~R~` getPrimaryValue() { 239 return _data.`~name~`; 240 }`; 241 } 242 243 string makeSetIncreaseKey(T)() { 244 string name; 245 foreach(memberName; __traits(derivedMembers, T)) { 246 static if (__traits(getProtection, __traits(getMember, T, memberName)) == "public") { 247 alias memType = typeof(__traits(getMember, T ,memberName)); 248 static if (!isFunction!(memType) && (hasUDA!(__traits(getMember, T ,memberName), AutoIncrement) || 249 hasUDA!(__traits(getMember, T ,memberName), Auto))) { 250 name = memberName; 251 } 252 } 253 } 254 if (name == "") 255 return ` 256 public void setIncreaseKey(ref T entity, int value) { 257 }`; 258 else 259 return ` 260 public void setIncreaseKey(ref T entity, int value) { 261 entity.`~name~` = value; 262 }`; 263 }