1 module hunt.entity.EntityDeserializer; 2 3 4 import hunt.entity.eql.Common; 5 6 import hunt.entity; 7 import hunt.entity.EntityMetaInfo; 8 import hunt.entity.DefaultEntityManagerFactory; 9 import hunt.entity.dialect; 10 11 import hunt.logging; 12 import hunt.util.Traits; 13 14 import std.conv; 15 import std.string; 16 import std.traits; 17 import std.variant; 18 19 string makeDeserializer(T)() { 20 string str; 21 22 str ~= "\n" ~ indent(4) ~ "/// T=" ~ T.stringof; 23 str ~= ` 24 T deSerialize(P, bool canInit = true)(Row[] rows, ref long count, int startIndex = 0,` ~ 25 ` P owner = null, bool isFromManyToOne = false) { 26 version(HUNT_ENTITY_DEBUG_MORE) { 27 infof("Target: %s, Rows: %d, count: %s, startIndex: %d, tableName: %s ", 28 T.stringof, rows.length, count, startIndex, _tableName); 29 } 30 31 import std.variant; 32 33 T _data = new T(); 34 bool isObjectDeserialized = false; 35 bool isMemberDeserialized = false; 36 bool isDeserializationNeed = true; 37 // T actualOwner = null; 38 39 _data.setManager(_manager); 40 Row row = rows[startIndex]; 41 string columnAsName; 42 string columnName; 43 version(HUNT_ENTITY_DEBUG_MORE) logDebugf("rows[%d]: %s", startIndex, row); 44 if (row is null || row.size() == 0) 45 return null; 46 47 columnAsName = getCountAsName(); 48 Variant columnValue = row.getValue(columnAsName); 49 if (columnValue.hasValue()) { 50 version(HUNT_ENTITY_DEBUG) tracef("count: %s", columnValue.toString()); 51 count = columnValue.coerce!(long); 52 return null; 53 } 54 `; 55 56 // static if(is(T == P)) { 57 // str ~= indent(8) ~ "T actualOwner = _data;\n"; 58 // } else { 59 // str ~= indent(8) ~ "T actualOwner = null;\n"; 60 // } 61 62 str ~= indent(8) ~ "T actualOwner = _data;\n"; 63 64 static foreach (string memberName; FieldNameTuple!T) {{ 65 alias currentMember = __traits(getMember, T, memberName); 66 alias memType = typeof(currentMember); 67 68 static if (__traits(getProtection, currentMember) != "public") { 69 enum isEntityMember = false; 70 } else static if(hasUDA!(currentMember, Transient)) { 71 enum isEntityMember = false; 72 } else { 73 enum isEntityMember = true; 74 } 75 76 static if (isEntityMember) { 77 string mappedBy; 78 static if(hasUDA!(currentMember, ManyToMany)) { 79 mappedBy = "\""~getUDAs!(currentMember, ManyToMany)[0].mappedBy~"\""; 80 } 81 82 str ~= "\n\n"; 83 str ~= indent(8) ~ "// Handle membmer: " ~ memberName ~ ", type: " ~ memType.stringof ~ "\n"; 84 85 // string or basic type 86 static if (isBasicType!memType || isSomeString!memType) { 87 str ~= indent(8) ~ `isMemberDeserialized = false; 88 auto `~memberName~`Field = cast(EntityFieldNormal!`~memType.stringof~`)(this.`~memberName~`); 89 90 columnAsName = `~memberName~`Field.getColumnAsName(); 91 columnName = `~memberName~`Field.getColumnName(); 92 columnValue = row.getValue(columnAsName); 93 94 if(!columnValue.hasValue()) { 95 version(HUNT_ENTITY_DEBUG) { 96 warningf("No value found for column [%s]. Try [%s] now.", columnAsName, columnName); 97 } 98 columnValue = row.getValue(columnName); 99 } 100 101 if(!columnValue.hasValue()) { 102 version(HUNT_ENTITY_DEBUG) { 103 warningf("No value found for column: %s, asName: %s", columnName, columnAsName); 104 } 105 } else { 106 version(HUNT_ENTITY_DEBUG) { 107 tracef("A column: %s = %s; The AsName: %s", columnName, columnValue, columnAsName); 108 } 109 110 if(typeid(` ~ memType.stringof ~ `) == columnValue.type) { 111 _data.` ~ memberName ~ ` = columnValue.get!(` ~ memType.stringof ~ `); 112 if(isMemberDeserialized) isObjectDeserialized = true; 113 } else if(columnValue.type == typeid(null)) { 114 version(HUNT_ENTITY_DEBUG) { 115 warningf("The value of column [%s] is null. So use its default.", "` 116 ~ memberName ~ `"); 117 } 118 } else { 119 string cvalue = columnValue.toString(); 120 version(HUNT_ENTITY_DEBUG_MORE) { 121 tracef("field: name=%s, type=%s; column: name=%s, type=%s; value: %s", "` 122 ~ memberName ~ `", "` ~ memType.stringof 123 ~ `", columnAsName, columnValue.type,` 124 ~ ` cvalue.empty() ? "(empty)" : cvalue); 125 } 126 _data.` ~ memberName ~ ` = ` ~ memberName ~ `Field.deSerialize!(` 127 ~ memType.stringof ~ `)(cvalue, isMemberDeserialized); 128 129 if(isMemberDeserialized) isObjectDeserialized = true; 130 } 131 }`; 132 133 } else static if(isByteArray!(memType)) { 134 str ~= indent(8) ~ `isMemberDeserialized = false; 135 auto `~memberName~`Field = cast(EntityFieldNormal!(`~memType.stringof~`))(this.`~memberName~`); 136 137 columnAsName = `~memberName~`Field.getColumnAsName(); 138 columnName = `~memberName~`Field.getColumnName(); 139 columnValue = row.getValue(columnAsName); 140 141 if(!columnValue.hasValue()) { 142 version(HUNT_ENTITY_DEBUG) { 143 warningf("No value found for column [%s]. Try [%s] now.", columnAsName, columnName); 144 } 145 columnValue = row.getValue(columnName); 146 } 147 148 if(!columnValue.hasValue()) { 149 version(HUNT_ENTITY_DEBUG) { 150 warningf("No value found for column: %s, asName: %s", columnName, columnAsName); 151 } 152 } else { 153 version(HUNT_ENTITY_DEBUG) { 154 tracef("A column: %s = %s; The AsName: %s", columnName, columnValue, columnAsName); 155 } 156 157 if(typeid(` ~ memType.stringof ~ `) == columnValue.type) { 158 _data.` ~ memberName ~ ` = columnValue.get!(` ~ memType.stringof ~ `); 159 if(isMemberDeserialized) isObjectDeserialized = true; 160 } else if(columnValue.type == typeid(null)) { 161 version(HUNT_ENTITY_DEBUG) { 162 warningf("The value of column [%s] is null. So use its default.", "` 163 ~ memberName ~ `"); 164 } 165 } else { 166 version(HUNT_ENTITY_DEBUG_MORE) { 167 tracef("field: name=%s, type=%s; column: name=%s, type=%s", "` 168 ~ memberName ~ `", "` ~ memType.stringof 169 ~ `", columnAsName, columnValue.type); 170 } 171 _data.` ~ memberName ~ ` = cast(` ~ memType.stringof ~ `)columnValue.get!(byte[]); 172 173 if(isMemberDeserialized) isObjectDeserialized = true; 174 } 175 }`; 176 177 } else { // Object 178 str ~= indent(8) ~ "isDeserializationNeed = true;\n"; 179 180 str ~=` 181 static if(is(P == ` ~ memType.stringof ~ `)) { 182 if(owner is null) { 183 version(HUNT_ENTITY_DEBUG) { 184 warningf("The owner [%s] of [%s] is null.", P.stringof, T.stringof); 185 } 186 } else { 187 version(HUNT_ENTITY_DEBUG) { 188 warningf("set [` ~ memberName ~ 189 `] to the owner {Type: %s, isNull: false}", P.stringof); 190 } 191 isDeserializationNeed = false; 192 _data.` ~ memberName ~ ` = owner; 193 } 194 } else { 195 // version(HUNT_ENTITY_DEBUG) { 196 // warningf("Type mismatched: P=%s, memType=` ~ memType.stringof ~ `", P.stringof); 197 // } 198 }` ~ "\n\n"; 199 200 str ~= indent(8) ~ "if(isDeserializationNeed) {\n"; 201 str ~= indent(12) ~ "version(HUNT_ENTITY_DEBUG) info(\"Deserializing member: " 202 ~ memberName ~ " \");\n"; 203 str ~= indent(12) ~ "EntityFieldInfo fieldInfo = this.opDispatch!(\"" ~ memberName ~ "\")();\n"; 204 205 static if (isArray!memType && hasUDA!(currentMember, OneToMany)) { 206 str ~=` 207 auto fieldObject = (cast(EntityFieldOneToMany!(`~memType.stringof.replace("[]","")~`,T))(fieldInfo)); 208 if(fieldObject is null) { 209 warningf("The field is not a EntityFieldManyToOne. It's a %s", typeid(fieldInfo)); 210 } else { 211 _data.addLazyData("`~memberName~`", fieldObject.getLazyData(rows[startIndex])); 212 _data.`~memberName~` = fieldObject.deSerialize(rows, startIndex, isFromManyToOne, actualOwner); 213 isMemberDeserialized = true; 214 }`; 215 216 } else static if (hasUDA!(currentMember, ManyToOne)) { 217 str ~=` 218 auto fieldObject = (cast(EntityFieldManyToOne!(`~memType.stringof~`))(fieldInfo)); 219 if(fieldObject is null) { 220 warningf("The field is not a EntityFieldManyToOne. It's a %s", typeid(fieldInfo)); 221 } else { 222 _data.addLazyData("`~memberName~`", fieldObject.getLazyData(rows[startIndex])); 223 _data.`~memberName~` = fieldObject.deSerialize(rows[startIndex]); 224 isMemberDeserialized = true; 225 }`; 226 227 } else static if (hasUDA!(currentMember, OneToOne)) { 228 str ~= ` 229 auto fieldObject = (cast(EntityFieldOneToOne!(`~memType.stringof~`, T))(fieldInfo)); 230 if(fieldObject is null) { 231 warningf("The field is not a EntityFieldOneToOne. It's a %s", typeid(fieldInfo)); 232 } else { 233 _data.addLazyData("`~memberName~`", fieldObject.getLazyData(rows[startIndex])); 234 _data.`~memberName~` = fieldObject.deSerialize(rows[startIndex], actualOwner); 235 isMemberDeserialized = true; 236 }`; 237 } else static if (is(memType : U[], U) && hasUDA!(currentMember, ManyToMany)) { 238 239 str ~= ` 240 static if(is(P == ` ~ U.stringof ~`)) { 241 auto ` ~ memberName ~ `Field = (cast(EntityFieldManyToManyOwner!(` ~ U.stringof ~ `, P ,` ~ mappedBy ~ `))(fieldInfo)); 242 _data.addLazyData("` ~ memberName ~ `",` ~ memberName ~ `Field.getLazyData(rows[startIndex])); 243 _data.` ~ memberName ~ ` = ` ~ memberName ~ `Field.deSerialize(rows, startIndex, isFromManyToOne); 244 } else { 245 auto ` ~ memberName ~ `Field = (cast(EntityFieldManyToMany!(` ~ U.stringof ~ `, T,` ~ mappedBy~ `))(fieldInfo)); 246 _data.addLazyData("` ~ memberName ~`",` ~ memberName ~ `Field.getLazyData(rows[startIndex])); 247 _data.` ~ memberName ~ ` = ` ~ memberName ~ `Field.deSerialize(rows, startIndex, isFromManyToOne); 248 } 249 `; 250 251 // str ~= ` 252 // static if(is(P == ` ~ U.stringof ~`)) { 253 // auto ` ~ memberName ~ `Field = (cast(EntityFieldManyToManyOwner!(` ~ U.stringof ~ `, P ,` ~ mappedBy ~ `))(fieldInfo)); 254 // _data.addLazyData("` ~ memberName ~ `",` ~ memberName ~ `Field.getLazyData(rows[startIndex])); 255 // _data.` ~ memberName ~ ` = ` ~ memberName ~ `Field.deSerialize!(T)(rows, startIndex, isFromManyToOne); 256 // } else { 257 // auto ` ~ memberName ~ ` = (cast(EntityFieldManyToMany!(` ~ U.stringof ~ `, T,` ~ mappedBy~ `))(fieldInfo)); 258 // _data.addLazyData("` ~ memberName ~`",` ~ memberName ~ `Field.getLazyData(rows[startIndex])); 259 // _data.` ~ memberName ~ ` = ` ~ memberName ~ `Field.deSerialize!(T)(rows, startIndex, isFromManyToOne); 260 // } 261 // `; 262 // static if ( memType.stringof.replace("[]","") == P.stringof) { 263 // str ~=` 264 // auto `~memberName~`Field = (cast(EntityFieldManyToManyOwner!(`~memType.stringof.replace("[]","")~`,P,`~mappedBy~`))(fieldInfo)); 265 // _data.addLazyData("`~memberName~`",`~memberName~`Field.getLazyData(rows[startIndex])); 266 // _data.`~memberName~` = `~memberName~`Field.deSerialize!(T)(rows, startIndex, isFromManyToOne);`; 267 // } else { 268 // str ~=` 269 // auto `~memberName~` = (cast(EntityFieldManyToMany!(`~memType.stringof.replace("[]","")~`,T,`~mappedBy~`))(fieldInfo)); 270 // _data.addLazyData("`~memberName~`",`~memberName~`Field.getLazyData(rows[startIndex])); 271 // _data.`~memberName~` = `~memberName~`Field.deSerialize!(T)(rows, startIndex, isFromManyToOne);`; 272 // } 273 // static if ( memType.stringof.replace("[]","") == P.stringof) { 274 // str ~=` 275 // auto `~memberName~`Field = (cast(EntityFieldManyToManyOwner!(`~memType.stringof.replace("[]","")~`,P,`~mappedBy~`))(fieldInfo)); 276 // _data.addLazyData("`~memberName~`",`~memberName~`Field.getLazyData(rows[startIndex])); 277 // _data.`~memberName~` = `~memberName~`Field.deSerialize!(T)(rows, startIndex, isFromManyToOne);`; 278 // } else { 279 // str ~=` 280 // auto `~memberName~` = (cast(EntityFieldManyToMany!(`~memType.stringof.replace("[]","")~`,T,`~mappedBy~`))(fieldInfo)); 281 // _data.addLazyData("`~memberName~`",`~memberName~`Field.getLazyData(rows[startIndex])); 282 // _data.`~memberName~` = `~memberName~`Field.deSerialize!(T)(rows, startIndex, isFromManyToOne);`; 283 // } 284 285 } 286 287 str ~= "\n" ~ indent(12) ~ "if(isMemberDeserialized) isObjectDeserialized = true;"; 288 str ~= ` 289 version(HUNT_ENTITY_DEBUG) { 290 warningf("member: `~memberName~`, isDeserialized: %s, result: %s null", ` ~ 291 `isMemberDeserialized, _data.` ~ memberName ~ ` is null ? "is" : "is not"); 292 }`; 293 294 str ~= "\n" ~ indent(8) ~ "}\n"; 295 } 296 } 297 }} 298 299 300 301 // FIXME: Needing refactor or cleanup -@zhangxueping at 2020-08-25T15:22:46+08:00 302 // More tests needed 303 str ~= ` 304 version(HUNT_ENTITY_DEBUG) { 305 infof("Object: ` ~ T.stringof ~`, isDeserialized: %s", isObjectDeserialized); 306 } 307 308 scope(exit) { 309 _data.onInitialized(); 310 } 311 312 if(isObjectDeserialized) { 313 _data.loadLazyMembers(); 314 return _data; 315 } else { 316 static if(canInit) { 317 return _data; 318 } else { 319 return T.init; 320 } 321 } 322 }`; 323 324 return str; 325 }