--- /dev/null
+package org.simantics.databoard.serialization;\r
+\r
+import java.util.HashMap;\r
+import java.util.Map;\r
+\r
+import org.simantics.databoard.binding.Binding;\r
+\r
+/**\r
+ *\r
+ * \r
+ * @author Toni Kalajainen\r
+ */\r
+public abstract class SerializerFactory implements SerializerScheme {\r
+\r
+ /**\r
+ * Map of failed constructions. \r
+ */\r
+ protected Map<Binding, SerializerConstructionException> failures = new HashMap<Binding, SerializerConstructionException>();\r
+ \r
+ /**\r
+ * Repository where serializers are placed. \r
+ */\r
+ Map<Binding, Serializer> repository; \r
+ \r
+ /**\r
+ * Map that contains in incomplete constructions.\r
+ */\r
+ Map<Binding, Serializer> inprogress = new HashMap<Binding, Serializer>();\r
+ \r
+ /**\r
+ * Construct a new serializer.\r
+ */\r
+ public SerializerFactory() {\r
+ this.repository = new HashMap<Binding, Serializer>();\r
+ }\r
+ \r
+ /**\r
+ * Construct a new serializer factory that places constructed serializers\r
+ * into user given repository.\r
+ * \r
+ * @param repository\r
+ */\r
+ public SerializerFactory(Map<Binding, Serializer> repository) {\r
+ this.repository = repository;\r
+ }\r
+ \r
+ public Map<Binding, Serializer> getRepository() {\r
+ return repository;\r
+ }\r
+ \r
+ /**\r
+ * Constructs a serilizer for a binding. Implement this.\r
+ * It should use the inprogress -map for construction of \r
+ * serializers that have component types.\r
+ * \r
+ * e.g. \r
+ * inprogress.put(binding, notCompletelyConstructedSerializer);\r
+ * Serializer componentSerializer = construct( componentBinding );\r
+ * notCompletelyConstructedSerializer.setComponent( componentSerializer );\r
+ * inprogress.remove(binding);\r
+ * \r
+ * try-finally is not needed.\r
+ * \r
+ * @param request\r
+ * @return\r
+ * @throws SerializerConstructionException\r
+ */\r
+ protected abstract Serializer doConstruct(Binding request) throws SerializerConstructionException;\r
+ \r
+ public Serializer construct(Binding request) throws SerializerConstructionException\r
+ {\r
+ // Optimization: if binding provides a cached serializer, just return it.\r
+ { Serializer ser = request.cachedSerializer(); if (ser != null) return ser; } \r
+ { Serializer ser = repository.get(request); if(ser != null) return ser; }\r
+ { Serializer ser = inprogress.get(request); if(ser != null) return ser; }\r
+ { SerializerConstructionException e = failures.get(request); if(e != null) throw e; }\r
+ \r
+ // Start construction\r
+ try { \r
+ Serializer binding = doConstruct(request);\r
+ repository.put(request, binding);\r
+ request.cacheSerializer(binding);\r
+ return binding;\r
+ } catch (SerializerConstructionException e) {\r
+ inprogress.remove( request );\r
+ failures.put(request, e);\r
+ throw e;\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public Serializer getSerializer(Binding binding)\r
+ throws SerializerConstructionException { \r
+ return construct(binding);\r
+ }\r
+ \r
+ public Serializer getSerializerUnchecked(Binding binding)\r
+ throws RuntimeSerializerConstructionException {\r
+ try {\r
+ return construct(binding);\r
+ } catch (SerializerConstructionException e) {\r
+ throw new RuntimeSerializerConstructionException(e);\r
+ }\r
+ } \r
+ \r
+ \r
+}\r