protected override Maybe<String> GetBaseMolecule(MoleculeSyntax molecule)
        {
            var aggregate = (AggregateSyntax)molecule.Parent;

            var id = aggregate.GetIdTypeName(SymbolTable);

            return base.GetBaseMolecule(molecule)
                .Or(String.Format("AggregateEvent<{0}>", id));
        }
        protected override void WriteModuleClassAttributes(MoleculeSyntax molecule)
        {
            var version = molecule.Annotations.TrySingle(x => x.Name == "Event")
                .SelectMaybe(x => x.Pairs.TryFirst(y => y.Name == "Version"))
                .Select(x => x.Value)
                .TrySelect<string, int>(int.TryParse)
                .Where(x => x > 0)
                .ValueOrDefault(1);

            WriteLine("[AggregateEventVersion({0})]", version);
        }
        protected override IEnumerable<AtomInfo> GetBaseAtomInfo(MoleculeSyntax molecule)
        {
            var aggregate = (AggregateSyntax)molecule.Parent;

            var id = aggregate.GetIdTypeName(SymbolTable);

            return base.GetBaseAtomInfo(molecule)
                .Concat(new[]
                {
                    new AtomInfo(Syntax.IdentifierName("id"), new TypeReferenceSyntax(id, new TypeCardinalitySyntax(1, 1)), true), 
                    new AtomInfo(Syntax.IdentifierName("version"), new TypeReferenceSyntax(Syntax.IdentifierName("Int32"), new TypeCardinalitySyntax(1, 1)), true), 
                });
        }
        protected override void Visit(MoleculeSyntax molecule)
        {
            if (molecule.IsAbstract) return;

            var atoms = molecule.Atoms.Select(GetAtomInfo).Concat(GetBaseAtomInfo(molecule));

            Write($"protected void Apply{molecule.Name}(");
            Delimit(atoms, "parameter", ", ");
            WriteLine(")");
            using (WithBlock())
            {
                WriteLine($"if (Version <= 0) throw new InvalidOperationException(\"This overload of Apply{molecule.Name} can only be called after the first event is applied. Please call the overload which requires the Aggregate's ID to be provided.\");");
                WriteLine();

                Write($"ApplyEvent(new {molecule.Name}(");
                Delimit(atoms, "argument", ", ");
                WriteLine($"{(atoms.Any() ? ", " : "")}Id, Version + 1));");
            }

            var aggregate = (AggregateSyntax)molecule.Parent;

            var id = aggregate.GetIdTypeName(SymbolTable);
            var idAtom = new AtomInfo(Syntax.IdentifierName("id"), new TypeReferenceSyntax(id, new TypeCardinalitySyntax(1, 1)), true);

            atoms = atoms.Concat(new[] { idAtom });

            Write($"protected void Apply{molecule.Name}(");
            Delimit(atoms, "parameter", ", ");
            WriteLine(")");
            using (WithBlock())
            {
                Write($"ApplyEvent(new {molecule.Name}(");
                Delimit(atoms, "argument", ", ");
                WriteLine($", Version + 1));");

            }
        }
 protected override void WriteModuleClassAttributes(MoleculeSyntax molecule)
 {
     WriteLine("[ValueObject]");
 }
 protected override bool ShouldImplementEssencePattern(MoleculeSyntax molecule)
 {
     return false;
 }
 protected override bool ShouldBeEquatable(MoleculeSyntax molecule)
 {
     return false;
 }