    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);*/
    }