44import lombok .AccessLevel ;
55import lombok .Getter ;
66import me .zort .sqllib .SQLDatabaseConnectionImpl ;
7+ import me .zort .sqllib .api .DefsVals ;
8+ import me .zort .sqllib .api .ISQLDatabaseOptions ;
79import me .zort .sqllib .api .ObjectMapper ;
810import me .zort .sqllib .api .data .Row ;
911import me .zort .sqllib .internal .annotation .JsonField ;
12+ import me .zort .sqllib .util .Validator ;
1013import org .jetbrains .annotations .NotNull ;
1114import org .jetbrains .annotations .Nullable ;
1215
1316import java .lang .reflect .*;
17+ import java .util .HashMap ;
1418import java .util .List ;
19+ import java .util .Map ;
20+ import java .util .Objects ;
21+ import java .util .concurrent .ConcurrentHashMap ;
1522import java .util .concurrent .CopyOnWriteArrayList ;
23+ import java .util .concurrent .atomic .AtomicReference ;
1624
1725public class DefaultObjectMapper implements ObjectMapper {
1826
1927 // Resolvers used after no value is found for the field
2028 // in mapped object as backup.
2129 @ Getter (AccessLevel .PROTECTED )
2230 private final List <ObjectMapper .FieldValueResolver > backupValueResolvers ;
31+ private final Map <Class <?>, ObjectMapper .TypeAdapter <?>> typeAdapters ;
2332 private final SQLDatabaseConnectionImpl connectionWrapper ;
2433
2534 public DefaultObjectMapper (SQLDatabaseConnectionImpl connectionWrapper ) {
2635 this .backupValueResolvers = new CopyOnWriteArrayList <>();
36+ this .typeAdapters = new ConcurrentHashMap <>();
2737 this .connectionWrapper = connectionWrapper ;
2838 }
2939
@@ -32,8 +42,13 @@ public void registerBackupValueResolver(@NotNull FieldValueResolver resolver) {
3242 this .backupValueResolvers .add (resolver );
3343 }
3444
45+ @ Override
46+ public void registerAdapter (@ NotNull Class <?> typeClass , @ NotNull TypeAdapter <?> adapter ) {
47+ this .typeAdapters .put (typeClass , adapter );
48+ }
49+
3550 @ Nullable
36- public <T > T assignValues (Row row , Class <T > typeClass ) {
51+ public <T > T deserializeValues (Row row , Class <T > typeClass ) {
3752 T instance = null ;
3853 try {
3954 try {
@@ -113,6 +128,11 @@ private Object buildElementValue(AnnotatedElement element, Row row) {
113128 debug (String .format ("Cannot find column for class %s target %s (%s)" , declaringClass .getName (), name , converted ));
114129 return null ;
115130 }
131+ } else {
132+ TypeAdapter <?> typeAdapter = typeAdapters .get (type .getClass ());
133+ if (typeAdapter != null ) {
134+ return typeAdapter .deserialize (element , row , obj );
135+ }
116136 }
117137 if (element .isAnnotationPresent (JsonField .class ) && obj instanceof String ) {
118138 String jsonString = (String ) obj ;
@@ -123,6 +143,51 @@ private Object buildElementValue(AnnotatedElement element, Row row) {
123143 }
124144 }
125145
146+ @ Override
147+ public DefsVals serializeValues (Object obj ) {
148+ Objects .requireNonNull (obj );
149+
150+ Class <?> aClass = obj .getClass ();
151+
152+ Map <String , Object > fields = new HashMap <>();
153+ for (Field field : aClass .getDeclaredFields ()) {
154+
155+ if (Modifier .isTransient (field .getModifiers ())) {
156+ // Transient fields are ignored.
157+ continue ;
158+ }
159+
160+ ISQLDatabaseOptions options = connectionWrapper .getOptions ();
161+
162+ try {
163+ field .setAccessible (true );
164+ Object o = field .get (obj );
165+ if (typeAdapters .containsKey (field .getType ())) {
166+ o = typeAdapters .get (field .getType ()).serialize (field , o );
167+ } else if (field .isAnnotationPresent (JsonField .class )) {
168+ o = options .getGson ().toJson (o );
169+ } else if (Validator .validateAutoIncrement (field ) && field .get (obj ) == null ) {
170+ // If field is PrimaryKey and autoIncrement true and is null,
171+ // We will skip this to use auto increment strategy on SQL server.
172+ continue ;
173+ }
174+ fields .put (options .getNamingStrategy ().fieldNameToColumn (field .getName ()), o );
175+ } catch (IllegalAccessException e ) {
176+ e .printStackTrace ();
177+ return null ;
178+ }
179+ }
180+ // I make entry array for indexing safety.
181+ Map .Entry <String , Object >[] entryArray = fields .entrySet ().toArray (new Map .Entry [0 ]);
182+ String [] defs = new String [entryArray .length ];
183+ AtomicReference <Object >[] vals = new AtomicReference [entryArray .length ];
184+ for (int i = 0 ; i < entryArray .length ; i ++) {
185+ defs [i ] = entryArray [i ].getKey ();
186+ vals [i ] = new AtomicReference <>(entryArray [i ].getValue ());
187+ }
188+ return new DefsVals (defs , vals );
189+ }
190+
126191 private void debug (String message ) {
127192 connectionWrapper .debug (message );
128193 }
0 commit comments