private static IEnumerable <PropertyTypeNode> ParseContainersSchema(
            IDictionary <string, object> d, Dictionary <string, PropertyTypeNode.TypeTag> injectBuiltinTypes)
        {
            var definitions = new List <PropertyTypeNode>();

            if (!IsCompatibleVersion(d))
            {
                throw new Exception($"Incompatible schema versions CurrentVersion : {CurrentVersion}");
            }

            var referenceAssemblyNames = new List <string>();

            if (d.ContainsKey(Keys.RequiredAssembliesKey))
            {
                var assemblyNames = d[Keys.RequiredAssembliesKey] as IEnumerable;
                if (assemblyNames != null)
                {
                    referenceAssemblyNames.AddRange(assemblyNames.OfType <string>().ToList());
                }
            }

            if (d.ContainsKey(Keys.TypesKey))
            {
                var types = d[Keys.TypesKey] as IEnumerable;
                if (types == null)
                {
                    return(definitions);
                }

                // 1. Do a first pass to collect the list of symbols

                var builtinSymbols = new Dictionary <string, PropertyTypeNode.TypeTag>();

                if (injectBuiltinTypes != null)
                {
                    builtinSymbols = builtinSymbols.Union(injectBuiltinTypes)
                                     .ToDictionary(k => k.Key, v => v.Value);
                }

                CollectTypesFromTypeTree(types, builtinSymbols);

                // 2. Actual parsing

                var resolver = new TypeResolver(referenceAssemblyNames, builtinSymbols);
                definitions.AddRange(
                    types.OfType <IDictionary <string, object> >().Select(
                        e => PropertyTypeNodeJsonSerializer.FromJson(e, resolver)
                        )
                    );
            }

            // Post fix
            if (d.ContainsKey(Keys.NamespaceKey) && !string.IsNullOrEmpty(d[Keys.NamespaceKey] as string))
            {
                var globalNamespace = d[Keys.NamespaceKey] as string;

                definitions = definitions.Select(definition =>
                {
                    if (string.IsNullOrEmpty(definition.TypePath.Namespace))
                    {
                        definition.TypePath.Namespace = globalNamespace;
                    }

                    return(definition);
                }).ToList();
            }

            return(definitions);
        }