import ceylon.language.meta.model { ClassModel } import ceylon.language.meta.declaration { ValueDeclaration } """A contract for identifying instances, specifying their classes, attributes, elements and values, and ultimately reconstructing those instances. Instances are identified using the [[Id]]'s semantics for equality. The methods of this interface can be called in any order; the id serves to associate each method invocation with the instance(s) to pertains to. The only constraint is that [[reconstruct]] will throw if the context lacks enough information to fully initialize the requested instance _or any instance reachable from it_. Reference cycles are supported. For example, given serializable class Person(name, employer) { shared String name; shared Company employer; } serializable class Company(name) { shared String name; shared late Person owner; } And an instance graph corresponding to: value wonkaInc = Company("Wonka Inc."); value willy = Person("Willy Wonka", wonkaInc); value umpaLumpa = Person("Umpa lumpa", wonkaInc); wonkaInc.owner = willy; Then we could reconstruct that instance graph like so: value dc = deserialization<String>(); dc.attribute("ww", `value Person.name`, "wwn"); dc.attribute("ww", `value Person.employer`, "wi"); dc.attribute("ul", `value Person.name`, "uln"); dc.attribute("ul", `value Person.employer`, "wi"); dc.attribute("wi", `value Company.name`, "win"); dc.attribute("wi", `value Company.owner`, "ww"); dc.instanceValue("win", "Wonka Inc."); dc.instanceValue("wwn", "Willy Wonka"); dc.instanceValue("uln", "Umpa lumpa"); dc.instance("wi", `Company`); dc.instance("ww", `Person`); dc.instance("ul", `Person`); value wonkaInc2 = dc.reconstruct<Company>("wi"); value willy2 = dc.reconstruct<Person>("ww"); value umpaLumpa2 = dc.reconstruct<Person>("ul"); assert(wonkaInc2.owner === willy2); assert(willy2.employer === wonkaInc2); assert(umpaLumpa2.employer === wonkaInc2); The calls to [[attribute]], [[instanceValue]] and [[instance]] could be in any order. """ shared sealed interface DeserializationContext<Id> { """The given [[instanceId]] refers to an instance of the given class.""" throws(`class DeserializationException`, "the given instance was specified by [[instanceValue]] or has already been reconstructed.") shared formal void instance(Id instanceId, ClassModel<> clazz); """The given [[instanceId]] is a member of the instance with the given [[containerId]]. This is used for member class instances.""" throws(`class DeserializationException`, "the given instance was specified by [[instanceValue]] or has already been reconstructed.") shared formal void memberInstance(Id containerId, Id instanceId); """The value of the given [[attribute]] of the instance with the given [[instanceId]] has given [[attributeValueId]].""" throws(`class DeserializationException`, "the given instance was specified by [[instanceValue]] or has already been reconstructed.") shared formal void attribute(Id instanceId, ValueDeclaration attribute, Id attributeValueId); """The value at the given [[index]] of the [[Array]] instance with the given [[instanceId]] has given [[elementValueId]].""" throws(`class DeserializationException`, "the given instance was specified by [[instanceValue]] or has already been reconstructed.") shared formal void element(Id instanceId, Integer index, Id elementValueId); """The instance with the given [[instanceId]] has the given value. This can used to register non-serializable instances with the context, for example object declarations.""" shared formal void instanceValue(Id instanceId, Anything instanceValue); """Get the instance with the given [[instanceId]] reconstructing it if necessary.""" throws(`class DeserializationException`, "the instance, or an instance reachable from it, could not be reconstructed") shared formal Instance reconstruct<Instance>(Id instanceId); /*shared formal void factory(Id instanceId, Type type); shared formal void factory2(Id instanceId, Callable f); shared formal void argument(Id instanceId, Id argumentId); shared formal void argumentValue(Id instanceId, Anything argumentValue);*/ }