package org.fenixedu.bennu.core.json; import java.util.Collection; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Stream; import org.fenixedu.commons.stream.StreamUtils; import com.google.gson.JsonArray; import com.google.gson.JsonElement; @SuppressWarnings({ "rawtypes", "unchecked" }) public class JsonBuilder { private final Map<Class<?>, Object> adapters = new ConcurrentHashMap<>(); private final TableRegistry<JsonCreator> creators = new TableRegistry<>(adapters); private final TableRegistry<JsonUpdater> updaters = new TableRegistry<>(adapters); private final TableRegistry<JsonViewer> viewers = new TableRegistry<>(adapters); public void setDefault(Class<?> objectClass, Class<?> registeeClass) { if (JsonCreator.class.isAssignableFrom(registeeClass)) { creators.setDefault(objectClass, (Class<? extends JsonCreator>) registeeClass); } if (JsonViewer.class.isAssignableFrom(registeeClass)) { viewers.setDefault(objectClass, (Class<? extends JsonViewer>) registeeClass); } if (JsonUpdater.class.isAssignableFrom(registeeClass)) { updaters.setDefault(objectClass, (Class<? extends JsonUpdater>) registeeClass); } } public JsonElement view(Object obj) { return view(obj, null); } public JsonElement view(Object obj, Class<? extends JsonViewer> jsonViewerClass) { return view(obj, obj == null ? null : obj.getClass(), jsonViewerClass); } public JsonElement view(Object obj, Class<?> objectClass, Class<? extends JsonViewer> jsonViewerClass) { if (objectClass == null) { return null; } if (Collection.class.isAssignableFrom(objectClass) && obj != null) { return views((Collection) obj, jsonViewerClass); } if (Stream.class.isAssignableFrom(objectClass) && obj != null) { return viewStream((Stream) obj, jsonViewerClass); } return viewers.get(objectClass, jsonViewerClass).view(obj, this); } private JsonArray viewStream(Stream<?> stream, Class<? extends JsonViewer> jsonViewerClass) { return stream.map(obj -> view(obj, jsonViewerClass)).collect(StreamUtils.toJsonArray()); } private JsonArray views(Collection coll, Class<? extends JsonViewer> jsonViewerClass) { JsonArray json = new JsonArray(); for (final Object el : coll) { json.add(view(el, jsonViewerClass)); } return json; } public <T> T create(JsonElement json, Class<T> clazz) { return create(json, clazz, null); } public <T> T create(JsonElement json, Class<T> clazz, Class<? extends JsonCreator> jsonCreatorClass) { final JsonCreator jsonCreator = creators.get(clazz, jsonCreatorClass); return (T) jsonCreator.create(json, this); } public <T> T update(JsonElement json, T object) { return update(json, object, null); } public <T> T update(JsonElement json, T object, Class<? extends JsonUpdater> jsonUpdaterClass) { final JsonUpdater jsonUpdater = updaters.get(object.getClass(), jsonUpdaterClass); return (T) jsonUpdater.update(json, object, this); } }