X-Git-Url: https://mograsim.net/gitweb/?a=blobdiff_plain;f=net.mograsim.logic.model%2Fsrc%2Fnet%2Fmograsim%2Flogic%2Fmodel%2Fserializing%2FIndirectGUIComponentCreator.java;h=f346d02908d62a24e228d414653820b81147a578;hb=8e8d5776ccc95a08885789834abd55cc50e18a24;hp=1c6a4846d981ea061d0bf4b75929c9b2b8ead440;hpb=47ea68ed5c444dd14864412639f6a6fd60ab8a0f;p=Mograsim.git diff --git a/net.mograsim.logic.model/src/net/mograsim/logic/model/serializing/IndirectGUIComponentCreator.java b/net.mograsim.logic.model/src/net/mograsim/logic/model/serializing/IndirectGUIComponentCreator.java index 1c6a4846..f346d029 100644 --- a/net.mograsim.logic.model/src/net/mograsim/logic/model/serializing/IndirectGUIComponentCreator.java +++ b/net.mograsim.logic.model/src/net/mograsim/logic/model/serializing/IndirectGUIComponentCreator.java @@ -2,26 +2,40 @@ package net.mograsim.logic.model.serializing; import java.io.IOException; import java.io.InputStream; -import java.util.Collection; +import java.io.UncheckedIOException; +import java.lang.reflect.InvocationTargetException; +import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.Objects; +import java.util.function.Supplier; import com.google.gson.JsonElement; import com.google.gson.JsonNull; +import com.google.gson.JsonObject; import net.mograsim.logic.model.model.ViewModelModifiable; import net.mograsim.logic.model.model.components.GUIComponent; +import net.mograsim.logic.model.model.components.submodels.SubmodelComponent; +import net.mograsim.logic.model.snippets.CodeSnippetSupplier; import net.mograsim.logic.model.util.JsonHandler; public class IndirectGUIComponentCreator { private static final Map standardComponentIDs = new HashMap<>(); + private static final Map standardComponentIDsUnmodifiable = Collections.unmodifiableMap(standardComponentIDs); private static final Map componentSuppliers = new HashMap<>(); + private static final Map resourceLoaders = new HashMap<>(); static { - try (InputStream s = IndirectGUIComponentCreator.class.getResourceAsStream("./standardComponentIDMapping.json")) + loadStandardComponentIDs(IndirectGUIComponentCreator.class.getResourceAsStream("standardComponentIDMapping.json")); + } + + public static void loadStandardComponentIDs(InputStream standardComponentIdMappingStream) + { + try (InputStream s = standardComponentIdMappingStream) { if (s == null) throw new IOException("Resource not found"); @@ -47,14 +61,14 @@ public class IndirectGUIComponentCreator public static void addStandardComponentID(String standardComponentID, String associatedComponentID) { - if (!associatedComponentID.startsWith("file:") && !associatedComponentID.startsWith("class:")) + if (!associatedComponentID.matches("(file|class|resource):.+")) throw new IllegalArgumentException("Unrecognized component ID format: " + associatedComponentID); standardComponentIDs.put(standardComponentID, associatedComponentID); } - public static Collection getStandardComponentIDs() + public static Map getStandardComponentIDs() { - return standardComponentIDs.keySet(); + return standardComponentIDsUnmodifiable; } public static void setComponentSupplier(String className, ComponentSupplier componentSupplier) @@ -81,26 +95,105 @@ public class IndirectGUIComponentCreator { if (id != null) { - String resolvedID; - if (id.startsWith("class:") || id.startsWith("file:")) - resolvedID = id; - else - resolvedID = standardComponentIDs.get(id); - if (resolvedID.startsWith("class:")) + String resolvedID = resolveID(id); + if (resolvedID != null) { - String className = resolvedID.substring(6); - tryLoadComponentClass(className); - ComponentSupplier componentSupplier = componentSuppliers.get(className); - if (componentSupplier != null) - return componentSupplier.create(model, params, name); - } else - // we know id has to start with "file:" here - // because standardComponentIDs only contains strings starting with "class:" or "file:" - return SubmodelComponentDeserializer.create(model, resolvedID.substring(5), name); + if (resolvedID.startsWith("class:")) + { + String className = resolvedID.substring(6); + tryLoadComponentClass(className); + ComponentSupplier componentSupplier = componentSuppliers.get(className); + if (componentSupplier != null) + return componentSupplier.create(model, params, name); + throw new IllegalArgumentException("Component supplier not found for ID " + id + " (resolved: " + resolvedID + ")"); + } else if (params != null && !JsonNull.INSTANCE.equals(params)) + throw new IllegalArgumentException("Can't give params to a component deserialized from a JSON file"); + if (resolvedID.startsWith("resource:")) + { + String[] parts = resolvedID.split(":"); + if (parts.length != 3) + throw new IllegalArgumentException("invaild resource id: " + resolvedID); + String rLoadID = parts[1]; + String resID = parts[2]; + try + { + ResourceLoader loader; + if (!resourceLoaders.containsKey(rLoadID)) + { + Class c = Class.forName(rLoadID); + if (ResourceLoader.class.isAssignableFrom(c)) + loader = (ResourceLoader) c.getConstructor().newInstance(); + else + loader = (ResourceLoader) Objects.requireNonNull(c.getMethod("resourceLoader").invoke(null)); + resourceLoaders.put(rLoadID, loader); + } else + { + loader = Objects.requireNonNull(resourceLoaders.get(parts[1])); + } + JsonObject jsonContents = JsonHandler.readJson(loader.loadResource(resID), JsonObject.class); + return loadComponentFromJsonObject(model, id, name, jsonContents); + } + catch (IOException e) + { + throw new UncheckedIOException(e); + } + catch (ClassCastException | ReflectiveOperationException e) + { + throw new IllegalArgumentException("invaild resource loader specified:" + parts[1], e); + } + } else if (resolvedID.startsWith("file:")) + { + try + { + String filename = resolvedID.substring(5); + JsonObject jsonContents = JsonHandler.readJson(filename, JsonObject.class); + return loadComponentFromJsonObject(model, id, name, jsonContents); + } + catch (IOException e) + { + throw new UncheckedIOException(e); + } + } else + { + throw new IllegalArgumentException("unable to resolve/interpret id" + resolvedID); + } + } } throw new RuntimeException("Could not get component supplier for ID " + id); } + public static String resolveID(String id) + { + if (id.matches("(file|class|resource):.+")) + return id; + return standardComponentIDs.get(id); + } + + private static SubmodelComponent loadComponentFromJsonObject(ViewModelModifiable model, String id, String name, JsonObject jsonContents) + { + SerializablePojo jsonContentsAsSerializablePojo = JsonHandler.parser.fromJson(jsonContents, SerializablePojo.class); + if (jsonContentsAsSerializablePojo.version == null) + return LegacySubmodelComponentSerializer.deserialize(model, + JsonHandler.parser.fromJson(jsonContents, LegacySubmodelComponentParams.class), name, id, null); + return SubmodelComponentSerializer.deserialize(model, JsonHandler.parser.fromJson(jsonContents, SubmodelComponentParams.class), + name, id, null); + } + + public static void registerResourceLoader(ResourceLoader resourceLoader) + { + registerResourceLoader(resourceLoader, resourceLoader.getClass()); + } + + public static void registerResourceLoader(ResourceLoader resourceLoader, Class reference) + { + resourceLoaders.put(reference.getName(), Objects.requireNonNull(resourceLoader)); + } + + public static void registerResourceLoader(ResourceLoader resourceLoader, String reference) + { + resourceLoaders.put(reference, Objects.requireNonNull(resourceLoader)); + } + private static void tryLoadComponentClass(String componentClassName) { CodeSnippetSupplier.tryInvokeStaticInitializer(componentClassName, "Error loading component class %s: %s\n");