Skip to content

Commit 335d199

Browse files
improved adapters and factories
1 parent a480cfb commit 335d199

10 files changed

+108
-63
lines changed

src/main/java/codes/laivy/serializable/AbstractTypeSerializer.java

+31
Original file line numberDiff line numberDiff line change
@@ -536,10 +536,41 @@ public AbstractTypeSerializer() {
536536
return list;
537537
}
538538

539+
@Override
540+
public <E> @Nullable E deserialize(@NotNull Class<E> reference, @NotNull Context context, @NotNull Config config) throws IncompatibleReferenceException {
541+
@Nullable Object object = deserializeUnsafe(reference, context, config);
542+
543+
if (object != null && !Allocator.isAssignableFromIncludingPrimitive(reference, object.getClass())) {
544+
throw new ClassCastException("the returned object from deserialization is '" + object + "' and cannot be cast to '" + reference.getName() + "'");
545+
}
546+
547+
//noinspection unchecked
548+
return (E) object;
549+
}
550+
@Override
551+
public <E> @Nullable E deserialize(@NotNull Class<E> reference, @Nullable T element, @NotNull Config config) throws IncompatibleReferenceException {
552+
@Nullable Object object = deserializeUnsafe(reference, element, config);
553+
554+
if (object != null && !Allocator.isAssignableFromIncludingPrimitive(reference, object.getClass())) {
555+
throw new ClassCastException("the returned object from deserialization is '" + object + "' and cannot be cast to '" + reference.getName() + "'");
556+
}
557+
558+
//noinspection unchecked
559+
return (E) object;
560+
}
561+
539562
@Override
540563
public <E> @Nullable E deserialize(@NotNull Class<E> reference, @NotNull Context context) throws IncompatibleReferenceException {
541564
return deserialize(reference, context, Config.create(this, reference));
542565
}
566+
@Override
567+
public @Nullable Object deserializeUnsafe(@NotNull Class<?> reference, @NotNull Context context) throws IncompatibleReferenceException {
568+
return deserializeUnsafe(reference, context, Config.create(this, reference));
569+
}
570+
@Override
571+
public @Nullable Object deserializeUnsafe(@NotNull Class<?> reference, @Nullable T element) throws IncompatibleReferenceException {
572+
return deserializeUnsafe(reference, element, Config.create(this, reference));
573+
}
543574

544575
@Override
545576
public @NotNull Context toContext(@Nullable Object object) {

src/main/java/codes/laivy/serializable/Serializer.java

+3
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,9 @@ public interface Serializer {
169169
<E> @Nullable E deserialize(@NotNull Class<E> reference, @NotNull Context context) throws IncompatibleReferenceException;
170170
<E> @Nullable E deserialize(@NotNull Class<E> reference, @NotNull Context context, @NotNull Config config) throws IncompatibleReferenceException;
171171

172+
@Nullable Object deserializeUnsafe(@NotNull Class<?> reference, @NotNull Context context) throws IncompatibleReferenceException;
173+
@Nullable Object deserializeUnsafe(@NotNull Class<?> reference, @NotNull Context context, @NotNull Config config) throws IncompatibleReferenceException;
174+
172175
@NotNull Context toContext(@Nullable Object object);
173176
@NotNull Context toContext(@Nullable Object object, @NotNull Config config);
174177

src/main/java/codes/laivy/serializable/TypeSerializer.java

+3
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,9 @@ public interface TypeSerializer<T> extends Serializer {
203203
<E> @NotNull Iterable<@Nullable E> deserialize(@NotNull Class<E> reference, @NotNull Iterable<@Nullable T> iterable) throws IncompatibleReferenceException;
204204
<E> @NotNull Iterable<@Nullable E> deserialize(@NotNull Class<E> reference, @NotNull Iterable<@Nullable T> iterable, @NotNull Config config) throws IncompatibleReferenceException;
205205

206+
@Nullable Object deserializeUnsafe(@NotNull Class<?> reference, @Nullable T element) throws IncompatibleReferenceException;
207+
@Nullable Object deserializeUnsafe(@NotNull Class<?> reference, @Nullable T element, @NotNull Config config) throws IncompatibleReferenceException;
208+
206209
// Context
207210

208211
@Nullable T serialize(@NotNull Context context);
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,8 @@
11
package codes.laivy.serializable.adapter;
22

3-
import codes.laivy.serializable.Serializer;
4-
import codes.laivy.serializable.config.Config;
5-
import codes.laivy.serializable.context.Context;
3+
import codes.laivy.serializable.factory.context.ContextFactory;
64
import org.jetbrains.annotations.NotNull;
75

8-
import java.io.EOFException;
9-
10-
public interface Adapter {
11-
6+
public interface Adapter extends ContextFactory {
127
@NotNull Class<?> @NotNull [] getReferences();
13-
14-
@NotNull Context write(@NotNull Object object, @NotNull Serializer serializer, @NotNull Config config);
15-
@NotNull Object read(@NotNull Class<?> reference, @NotNull Serializer serializer, @NotNull Context context, @NotNull Config config) throws EOFException;
16-
178
}

src/main/java/codes/laivy/serializable/adapter/provided/CharacterArrayAdapter.java

+6-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
import java.util.Arrays;
1515
import java.util.Objects;
1616

17-
public class CharacterArrayAdapter implements Adapter {
17+
public final class CharacterArrayAdapter implements Adapter {
1818

1919
@Override
2020
public @NotNull Class<?> @NotNull [] getReferences() {
@@ -25,7 +25,11 @@ public class CharacterArrayAdapter implements Adapter {
2525
}
2626

2727
@Override
28-
public @NotNull Context write(@NotNull Object object, @NotNull Serializer serializer, @NotNull Config config) {
28+
public @Nullable Context write(@NotNull Class<?> reference, @Nullable Object object, @NotNull Serializer serializer, @NotNull Config config) {
29+
if (object == null) {
30+
return null;
31+
}
32+
2933
if (object instanceof Character[]) {
3034
@Nullable Character[] instance = (Character[]) object;
3135

src/main/java/codes/laivy/serializable/adapter/provided/CollectionAdapter.java

+7-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import codes.laivy.serializable.config.Config;
66
import codes.laivy.serializable.context.ArrayContext;
77
import codes.laivy.serializable.context.Context;
8+
import codes.laivy.serializable.context.NullContext;
89
import codes.laivy.serializable.exception.IncompatibleReferenceException;
910
import org.jetbrains.annotations.NotNull;
1011
import org.jetbrains.annotations.Nullable;
@@ -18,7 +19,7 @@
1819
import java.util.concurrent.CopyOnWriteArraySet;
1920
import java.util.function.Consumer;
2021

21-
public class CollectionAdapter implements Adapter {
22+
public final class CollectionAdapter implements Adapter {
2223

2324
public static final @NotNull Class<?> ARRAYS_ARRAYLIST;
2425

@@ -50,7 +51,11 @@ public class CollectionAdapter implements Adapter {
5051
}
5152

5253
@Override
53-
public @NotNull Context write(@NotNull Object object, @NotNull Serializer serializer, @NotNull Config config) {
54+
public @NotNull Context write(@NotNull Class<?> reference, @Nullable Object object, @NotNull Serializer serializer, @NotNull Config config) {
55+
if (object == null) {
56+
return NullContext.create();
57+
}
58+
5459
if (object instanceof Collection<?>) {
5560
// Start
5661
@NotNull Collection<?> collection = (Collection<?>) object;

src/main/java/codes/laivy/serializable/adapter/provided/GsonAdapter.java

+10-3
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66
import codes.laivy.serializable.context.*;
77
import com.google.gson.*;
88
import org.jetbrains.annotations.NotNull;
9+
import org.jetbrains.annotations.Nullable;
910

1011
import java.io.EOFException;
12+
import java.util.Objects;
1113
import java.util.function.Function;
1214

1315
public final class GsonAdapter implements Adapter {
@@ -23,13 +25,18 @@ public final class GsonAdapter implements Adapter {
2325
}
2426

2527
@Override
26-
public @NotNull Context write(@NotNull Object element, @NotNull Serializer serializer, @NotNull Config config) {
28+
public @NotNull Context write(@NotNull Class<?> reference, @Nullable Object element, @NotNull Serializer serializer, @NotNull Config config) {
29+
if (element == null) {
30+
return NullContext.create();
31+
}
32+
2733
if (element instanceof JsonObject) {
2834
@NotNull MapContext context = MapContext.create(serializer);
2935
@NotNull JsonObject object = (JsonObject) element;
3036

3137
for (@NotNull String key : object.keySet()) {
32-
context.setContext(key, write(object.get(key), serializer, Config.create()));
38+
@NotNull JsonElement value = object.get(key);
39+
context.setContext(key, (Context) Objects.requireNonNull(write(value.getClass(), value, serializer, Config.create())));
3340
}
3441

3542
return context;
@@ -38,7 +45,7 @@ public final class GsonAdapter implements Adapter {
3845
@NotNull JsonArray array = (JsonArray) element;
3946

4047
for (@NotNull JsonElement target : array) {
41-
context.write(write(target, serializer, Config.create()));
48+
context.write((Context) Objects.requireNonNull(write(target.getClass(), target, serializer, Config.create())));
4249
}
4350

4451
return context;

src/main/java/codes/laivy/serializable/adapter/provided/TemporalAdapter.java

+10-6
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,13 @@
66
import codes.laivy.serializable.context.Context;
77
import codes.laivy.serializable.context.PrimitiveContext;
88
import org.jetbrains.annotations.NotNull;
9+
import org.jetbrains.annotations.Nullable;
910

1011
import java.io.EOFException;
1112
import java.time.*;
1213
import java.util.Date;
1314

14-
public class TemporalAdapter implements Adapter {
15+
public final class TemporalAdapter implements Adapter {
1516

1617
@Override
1718
public @NotNull Class<?> @NotNull [] getReferences() {
@@ -33,14 +34,17 @@ public class TemporalAdapter implements Adapter {
3334
}
3435

3536
@Override
36-
public @NotNull Context write(@NotNull Object object, @NotNull Serializer serializer, @NotNull Config config) {
37-
if (object.getClass() == Date.class) {
38-
return PrimitiveContext.create(((Date) object).getTime());
37+
public @Nullable Object write(@NotNull Class<?> reference, @Nullable Object object, @NotNull Serializer serializer, @NotNull Config config) {
38+
if (object == null) {
39+
return null;
40+
}
41+
42+
if (object instanceof Date) {
43+
return ((Date) object).getTime();
3944
} else {
40-
return PrimitiveContext.create(object.toString());
45+
return object.toString();
4146
}
4247
}
43-
4448
@Override
4549
public @NotNull Object read(@NotNull Class<?> reference, @NotNull Serializer serializer, @NotNull Context context, @NotNull Config config) throws EOFException {
4650
@NotNull PrimitiveContext object = context.getAsPrimitive();

src/main/java/codes/laivy/serializable/adapter/provided/UUIDAdapter.java

+8-4
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,26 @@
44
import codes.laivy.serializable.adapter.Adapter;
55
import codes.laivy.serializable.config.Config;
66
import codes.laivy.serializable.context.Context;
7-
import codes.laivy.serializable.context.PrimitiveContext;
87
import org.jetbrains.annotations.NotNull;
8+
import org.jetbrains.annotations.Nullable;
99

1010
import java.io.EOFException;
1111
import java.util.UUID;
1212

13-
public class UUIDAdapter implements Adapter {
13+
public final class UUIDAdapter implements Adapter {
1414

1515
@Override
1616
public @NotNull Class<?> @NotNull [] getReferences() {
1717
return new Class[] { UUID.class };
1818
}
1919

2020
@Override
21-
public @NotNull Context write(@NotNull Object object, @NotNull Serializer serializer, @NotNull Config config) {
22-
return PrimitiveContext.create(object.toString());
21+
public @Nullable Object write(@NotNull Class<?> reference, @Nullable Object object, @NotNull Serializer serializer, @NotNull Config config) {
22+
if (object == null) {
23+
return null;
24+
}
25+
26+
return object.toString();
2327
}
2428
@Override
2529
public @NotNull Object read(@NotNull Class<?> reference, @NotNull Serializer serializer, @NotNull Context context, @NotNull Config config) throws EOFException {

src/main/java/codes/laivy/serializable/json/JsonSerializer.java

+28-35
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@
55
import codes.laivy.serializable.adapter.Adapter;
66
import codes.laivy.serializable.config.Config;
77
import codes.laivy.serializable.context.*;
8+
import codes.laivy.serializable.exception.IncompatibleReferenceException;
89
import codes.laivy.serializable.factory.context.ContextFactory;
910
import codes.laivy.serializable.utilities.Classes;
1011
import com.google.gson.*;
1112
import org.jetbrains.annotations.NotNull;
1213
import org.jetbrains.annotations.Nullable;
1314

14-
import java.io.EOFException;
1515
import java.io.IOException;
1616
import java.lang.reflect.Array;
1717

@@ -30,8 +30,6 @@ public final class JsonSerializer extends AbstractTypeSerializer<JsonElement> {
3030

3131
@Override
3232
public @NotNull JsonElement serialize(@Nullable Object object, @NotNull Config config) {
33-
@NotNull ContextFactory contextFactory = config.getContextFactory();
34-
3533
// Check nullability
3634
if (object == null) {
3735
return JsonNull.INSTANCE;
@@ -42,9 +40,10 @@ public final class JsonSerializer extends AbstractTypeSerializer<JsonElement> {
4240
// Adapters
4341
@NotNull Class<?> reference = object.getClass();
4442
@Nullable Adapter adapter = config.getAdapter();
43+
@NotNull ContextFactory contextFactory = config.getContextFactory();
4544

4645
if (adapter != null) {
47-
return serialize(adapter.write(object, this, config));
46+
contextFactory = adapter;
4847
}
4948

5049
// Serialize
@@ -60,48 +59,39 @@ public final class JsonSerializer extends AbstractTypeSerializer<JsonElement> {
6059

6160
// Deserialization
6261

63-
@SuppressWarnings("unchecked")
6462
@Override
65-
public <E> @Nullable E deserialize(@NotNull Class<E> reference, @NotNull Context context, @NotNull Config config) {
63+
public @Nullable Object deserializeUnsafe(@NotNull Class<?> reference, @NotNull Context context, @NotNull Config config) throws IncompatibleReferenceException {
6664
// Start deserialization with compatible reference
6765
if (!Classes.isConcrete(reference)) {
6866
throw new IllegalArgumentException("the references should be all concretes: '" + reference.getName() + "'");
6967
}
7068

71-
// Adapters
72-
@Nullable Adapter adapter = config.getAdapter();
73-
74-
if (adapter != null) try {
75-
return (E) adapter.read(reference, this, context, config);
76-
} catch (@NotNull EOFException e) {
77-
// todo: exception message
78-
throw new RuntimeException(e);
79-
}
80-
81-
if (context.isNull()) {
82-
return null;
83-
}
69+
// Adapters and factory
70+
@NotNull ContextFactory factory;
8471

85-
// Factory
86-
@NotNull ContextFactory factory = config.getContextFactory();
72+
if (config.getAdapter() != null) factory = config.getAdapter();
73+
else factory = config.getContextFactory();
8774

8875
// Deserialize with factory
8976
try {
90-
@Nullable Object deserialized = factory.read(reference, this, context, config);
91-
92-
// todo: check type
93-
return (E) deserialized;
77+
return factory.read(reference, this, context, config);
9478
} catch (@NotNull IOException e) {
9579
throw new RuntimeException(e);
9680
} catch (@NotNull InstantiationException e) {
9781
throw new RuntimeException("cannot instantiate '" + reference.getName() + "'", e);
9882
}
9983
}
84+
10085
@Override
10186
public <E> @Nullable E deserialize(@NotNull Class<E> reference, @Nullable JsonElement element, @NotNull Config config) {
10287
return deserialize(reference, toContext(element), config);
10388
}
10489

90+
@Override
91+
public @Nullable Object deserializeUnsafe(@NotNull Class<?> reference, @Nullable JsonElement element, @NotNull Config config) throws IncompatibleReferenceException {
92+
return deserializeUnsafe(reference, toContext(element), config);
93+
}
94+
10595
// Context
10696

10797
@Override
@@ -110,9 +100,10 @@ public final class JsonSerializer extends AbstractTypeSerializer<JsonElement> {
110100
return NullContext.create();
111101
} else {
112102
@NotNull Class<?> reference = object.getClass();
103+
@NotNull ContextFactory contextFactory;
113104

114105
if (adapters.map.containsKey(reference)) {
115-
return adapters.map.get(reference).write(object, this, config);
106+
contextFactory = adapters.map.get(reference);
116107
} else if (object instanceof Context) {
117108
throw new IllegalArgumentException("you cannot convert a context into a context");
118109
} else if (object instanceof Enum<?>) {
@@ -146,15 +137,17 @@ public final class JsonSerializer extends AbstractTypeSerializer<JsonElement> {
146137

147138
return context;
148139
} else {
149-
@Nullable ContextFactory factory = config.getContextFactory();
150-
@Nullable Object instance = factory.write(reference, object, this, config);
151-
152-
if (instance instanceof Context) {
153-
return (Context) instance;
154-
} else {
155-
// Repeat recursively the serialization
156-
return toContext(instance);
157-
}
140+
contextFactory = config.getContextFactory();
141+
}
142+
143+
// Generate using context factory
144+
@Nullable Object instance = contextFactory.write(reference, object, this, config);
145+
146+
if (instance instanceof Context) {
147+
return (Context) instance;
148+
} else {
149+
// Repeat recursively the serialization
150+
return toContext(instance);
158151
}
159152
}
160153
}

0 commit comments

Comments
 (0)