public override CodeTypeDeclaration Generate()
        {
            var classDeclaration = base.Generate();

            GenerateSerializableAttribute(classDeclaration);
            GenerateTypeAttribute(classDeclaration);

            classDeclaration.IsClass = true;
            classDeclaration.IsPartial = true;

            if (EnableDataBinding)
            {
                classDeclaration.Members.Add(new CodeMemberEvent()
                {
                    Name = "PropertyChanged",
                    Type = new CodeTypeReference("PropertyChangedEventHandler"),
                    Attributes = MemberAttributes.Public,
                });

                var onPropChangedMethod = new CodeMemberMethod
                {
                    Name = "OnPropertyChanged",
                    Attributes = MemberAttributes.Family,
                };
                var param = new CodeParameterDeclarationExpression(typeof(string), "propertyName");
                onPropChangedMethod.Parameters.Add(param);
                onPropChangedMethod.Statements.Add(
                    new CodeConditionStatement(
                        new CodeBinaryOperatorExpression(
                            new CodeEventReferenceExpression(null, "PropertyChanged"),
                            CodeBinaryOperatorType.IdentityInequality,
                            new CodePrimitiveExpression(null)),
                        new CodeExpressionStatement(new CodeDelegateInvokeExpression(
                            new CodeEventReferenceExpression(null, "PropertyChanged"),
                            new CodeThisReferenceExpression(),
                            new CodeObjectCreateExpression(
                                "PropertyChangedEventArgs",
                                new CodeArgumentReferenceExpression("propertyName"))
                            ))));
                classDeclaration.Members.Add(onPropChangedMethod);
            }

            if (BaseClass != null)
            {
                if (BaseClass is ClassModel)
                    classDeclaration.BaseTypes.Add(BaseClass.GetReferenceFor(Namespace, false));
                else
                {
                    var typeReference = BaseClass.GetReferenceFor(Namespace, false);

                    var member = new CodeMemberField(typeReference, "Value")
                    {
                        Attributes = MemberAttributes.Public,
                    };

                    if (EnableDataBinding)
                    {
                        var backingFieldMember = new CodeMemberField(typeReference, member.Name.ToBackingField())
                        {
                            Attributes = MemberAttributes.Private
                        };
                        member.Name += PropertyModel.GetAccessors(member.Name, backingFieldMember.Name, BaseClass.GetPropertyValueTypeCode(), false);
                        classDeclaration.Members.Add(backingFieldMember);
                    }
                    else
                    {
                        // hack to generate automatic property
                        member.Name += " { get; set; }";
                    }

                    var docs = new[] { new DocumentationModel { Language = "en", Text = "Gets or sets the text value." },
                        new DocumentationModel { Language = "de", Text = "Ruft den Text ab oder legt diesen fest." } };
                    member.Comments.AddRange(DocumentationModel.GetComments(docs).ToArray());

                    var attribute = new CodeAttributeDeclaration(new CodeTypeReference(typeof(XmlTextAttribute)));
                    var simpleModel = BaseClass as SimpleModel;
                    if (simpleModel != null && (simpleModel.XmlSchemaType.IsDataTypeAttributeAllowed(Configuration) ?? simpleModel.UseDataTypeAttribute))
                    {
                        var name = BaseClass.GetQualifiedName();
                        if (name.Namespace == XmlSchema.Namespace)
                        {
                            var dataType = new CodeAttributeArgument("DataType", new CodePrimitiveExpression(name.Name));
                            attribute.Arguments.Add(dataType);
                        }
                    }

                    member.CustomAttributes.Add(attribute);
                    classDeclaration.Members.Add(member);
                }
            }

            if (EnableDataBinding)
                classDeclaration.BaseTypes.Add(new CodeTypeReference("INotifyPropertyChanged"));

            if (Configuration.EntityFramework && (BaseClass == null || !(BaseClass is ClassModel)))
            {
                // generate key
                var keyProperty = Properties.FirstOrDefault(p => p.Name.ToLowerInvariant() == "id")
                    ?? Properties.FirstOrDefault(p => p.Name.ToLowerInvariant() == (Name.ToLowerInvariant() + "id"));

                if (keyProperty == null)
                {
                    keyProperty = new PropertyModel(Configuration)
                    {
                        Name = "Id",
                        Type = new SimpleModel(Configuration) { ValueType = typeof(long) },
                        OwningType = this,
                        Documentation = { new DocumentationModel {  Language = "en", Text = "Gets or sets a value uniquely identifying this entity." },
                            new DocumentationModel { Language = "de", Text = "Ruft einen Wert ab, der diese Entität eindeutig identifiziert, oder legt diesen fest." } }
                    };
                    Properties.Insert(0, keyProperty);
                }

                keyProperty.IsKey = true;
            }

            foreach (var property in Properties)
                property.AddMembersTo(classDeclaration, EnableDataBinding);

            if (IsMixed && (BaseClass == null || BaseClass is ClassModel))
            {
                var text = new CodeMemberField(typeof(string), "Text");
                // hack to generate automatic property
                text.Name += " { get; set; }";
                text.Attributes = MemberAttributes.Public;
                var xmlTextAttribute = new CodeAttributeDeclaration(new CodeTypeReference(typeof(XmlTextAttribute)));
                text.CustomAttributes.Add(xmlTextAttribute);
                classDeclaration.Members.Add(text);
            }

            classDeclaration.CustomAttributes.Add(
                new CodeAttributeDeclaration(new CodeTypeReference(typeof(DebuggerStepThroughAttribute))));
            if (Configuration.GenerateDesignerCategoryAttribute)
            {
                classDeclaration.CustomAttributes.Add(
                    new CodeAttributeDeclaration(new CodeTypeReference(typeof (DesignerCategoryAttribute)),
                        new CodeAttributeArgument(new CodePrimitiveExpression("code"))));
            }

            if (RootElementName != null)
            {
                var rootAttribute = new CodeAttributeDeclaration(new CodeTypeReference(typeof(XmlRootAttribute)),
                    new CodeAttributeArgument(new CodePrimitiveExpression(RootElementName.Name)),
                    new CodeAttributeArgument("Namespace", new CodePrimitiveExpression(RootElementName.Namespace)));
                classDeclaration.CustomAttributes.Add(rootAttribute);
            }

            var derivedTypes = GetAllDerivedTypes();
            foreach (var derivedType in derivedTypes.OrderBy(t => t.Name))
            {
                var includeAttribute = new CodeAttributeDeclaration(new CodeTypeReference(typeof(XmlIncludeAttribute)),
                    new CodeAttributeArgument(new CodeTypeOfExpression(derivedType.GetReferenceFor(Namespace, false))));
                classDeclaration.CustomAttributes.Add(includeAttribute);
            }

            classDeclaration.BaseTypes.AddRange(Interfaces.Select(i => i.GetReferenceFor(Namespace, false)).ToArray());

            return classDeclaration;
        }
        public static string GetUniqueFieldName(this TypeModel typeModel, PropertyModel propertyModel)
        {
            var propBackingFieldName = propertyModel.Name.ToBackingField();
            var classModel = typeModel as ClassModel;
            if (classModel == null)
                return propBackingFieldName;
            
            var i = 0;
            foreach (var prop in classModel.Properties)
            {
                if (!classModel.EnableDataBinding && !(prop.Type is SimpleModel))
                    continue;

                if (propertyModel == prop)
                {
                    i += 1;
                    break;
                }

                var backingFieldName = prop.Name.ToBackingField();
                if (backingFieldName == propBackingFieldName)
                    i += 1;
            }

            if (i <= 1)
                return propBackingFieldName;

            return string.Format("{0}{1}", propBackingFieldName, i);
        }
        private IEnumerable<PropertyModel> CreatePropertiesForAttributes(Uri source, TypeModel typeModel, IEnumerable<XmlSchemaObject> items)
        {
            var properties = new List<PropertyModel>();

            foreach (var item in items)
            {
                var attribute = item as XmlSchemaAttribute;
                if (attribute != null)
                {
                    if (attribute.Use != XmlSchemaUse.Prohibited)
                    {
                        var attributeQualifiedName = attribute.AttributeSchemaType.QualifiedName;

                        if (attributeQualifiedName.IsEmpty)
                        {
                            attributeQualifiedName = attribute.QualifiedName;

                            if (attributeQualifiedName.IsEmpty || attributeQualifiedName.Namespace == "")
                            {
                                // inner type, have to generate a type name
                                var typeName = ToTitleCase(typeModel.Name) + ToTitleCase(attribute.QualifiedName.Name);
                                attributeQualifiedName = new XmlQualifiedName(typeName, typeModel.XmlSchemaName.Namespace);
                                // try to avoid name clashes
                                if (NameExists(attributeQualifiedName))
                                    attributeQualifiedName = new[] { "Item", "Property", "Element" }
                                        .Select(s => new XmlQualifiedName(attributeQualifiedName.Name + s, attributeQualifiedName.Namespace))
                                        .First(n => !NameExists(n));
                            }
                        }

                        var attributeName = ToTitleCase(attribute.QualifiedName.Name);
                        if (attributeName == typeModel.Name) attributeName += "Property"; // member names cannot be the same as their enclosing type

                        var property = new PropertyModel(_configuration)
                        {
                            OwningType = typeModel,
                            Name = attributeName,
                            XmlSchemaName = attribute.QualifiedName,
                            Type = CreateTypeModel(source, attribute.AttributeSchemaType, attributeQualifiedName),
                            IsAttribute = true,
                            IsNullable = attribute.Use != XmlSchemaUse.Required,
                            DefaultValue = attribute.DefaultValue,
                            Form = attribute.Form == XmlSchemaForm.None ? attribute.GetSchema().AttributeFormDefault : attribute.Form,
                            XmlNamespace = attribute.QualifiedName.Namespace != "" && attribute.QualifiedName.Namespace != typeModel.XmlSchemaName.Namespace ? attribute.QualifiedName.Namespace : null,
                        };

                        var attributeDocs = GetDocumentation(attribute);
                        property.Documentation.AddRange(attributeDocs);

                        properties.Add(property);
                    }
                }
                else
                {
                    var attributeGroupRef = item as XmlSchemaAttributeGroupRef;
                    if (attributeGroupRef != null)
                    {
                        if (GenerateInterfaces)
                            CreateTypeModel(new Uri(attributeGroupRef.SourceUri), AttributeGroups[attributeGroupRef.RefName], attributeGroupRef.RefName);

                        var groupItems = AttributeGroups[attributeGroupRef.RefName].Attributes;
                        var groupProperties = CreatePropertiesForAttributes(source, typeModel, groupItems.Cast<XmlSchemaObject>());
                        properties.AddRange(groupProperties);
                    }
                }
            }

            return properties;
        }
        private IEnumerable<PropertyModel> CreatePropertiesForElements(Uri source, TypeModel typeModel, XmlSchemaParticle particle,  IEnumerable<Particle> items)
        {
            var properties = new List<PropertyModel>();
            var order = 0;
            foreach (var item in items)
            {
                PropertyModel property = null;

                var element = item.XmlParticle as XmlSchemaElement;
                // ElementSchemaType must be non-null. This is not the case when maxOccurs="0".
                if (element != null && element.ElementSchemaType != null)
                {
                    var elementQualifiedName = element.ElementSchemaType.QualifiedName;

                    if (elementQualifiedName.IsEmpty)
                    {
                        elementQualifiedName = element.RefName;

                        if (elementQualifiedName.IsEmpty)
                        {
                            // inner type, have to generate a type name
                            var typeName = ToTitleCase(typeModel.Name) + ToTitleCase(element.QualifiedName.Name);
                            elementQualifiedName = new XmlQualifiedName(typeName, typeModel.XmlSchemaName.Namespace);
                            // try to avoid name clashes
                            if (NameExists(elementQualifiedName))
                                elementQualifiedName = new[] { "Item", "Property", "Element" }
                                    .Select(s => new XmlQualifiedName(elementQualifiedName.Name + s, elementQualifiedName.Namespace))
                                    .First(n => !NameExists(n));
                        }
                    }

                    var propertyName = ToTitleCase(element.QualifiedName.Name);
                    if (propertyName == typeModel.Name) propertyName += "Property"; // member names cannot be the same as their enclosing type

                    property = new PropertyModel(_configuration)
                    {
                        OwningType = typeModel,
                        XmlSchemaName = element.QualifiedName,
                        Name = propertyName,
                        Type = CreateTypeModel(source, element.ElementSchemaType, elementQualifiedName),
                        IsNillable = element.IsNillable,
                        IsNullable = item.MinOccurs < 1.0m,
                        IsCollection = item.MaxOccurs > 1.0m || particle.MaxOccurs > 1.0m, // http://msdn.microsoft.com/en-us/library/vstudio/d3hx2s7e(v=vs.100).aspx
                        DefaultValue = element.DefaultValue,
                        Form = element.Form == XmlSchemaForm.None ? element.GetSchema().ElementFormDefault : element.Form,
                        XmlNamespace = element.QualifiedName.Namespace != "" && element.QualifiedName.Namespace != typeModel.XmlSchemaName.Namespace ? element.QualifiedName.Namespace : null,
                    };
                }
                else
                {
                    var any = item.XmlParticle as XmlSchemaAny;
                    if (any != null)
                    {
                        property = new PropertyModel(_configuration)
                        {
                            OwningType = typeModel,
                            Name = "Any",
                            Type = new SimpleModel(_configuration) { ValueType = (UseXElementForAny ? typeof(XElement) : typeof(XmlElement)), UseDataTypeAttribute = false },
                            IsNullable = item.MinOccurs < 1.0m,
                            IsCollection = item.MaxOccurs > 1.0m || particle.MaxOccurs > 1.0m, // http://msdn.microsoft.com/en-us/library/vstudio/d3hx2s7e(v=vs.100).aspx
                            IsAny = true,
                        };
                    }
                    else
                    {
                        var groupRef = item.XmlParticle as XmlSchemaGroupRef;
                        if (groupRef != null)
                        {
                            if (GenerateInterfaces)
                                CreateTypeModel(new Uri(groupRef.SourceUri), Groups[groupRef.RefName], groupRef.RefName);

                            var groupItems = GetElements(groupRef.Particle);
                            var groupProperties = CreatePropertiesForElements(source, typeModel, item.XmlParticle, groupItems);
                            properties.AddRange(groupProperties);
                        }
                    }
                }

                // Discard duplicate property names. This is most likely due to:
                // - Choice or
                // - Element and attribute with the same name
                if (property != null && !properties.Any(p => p.Name == property.Name))
                {
                    var itemDocs = GetDocumentation(item.XmlParticle);
                    property.Documentation.AddRange(itemDocs);

                    if (EmitOrder)
                        property.Order = order++;
                    property.IsDeprecated = itemDocs.Any(d => d.Text.StartsWith("DEPRECATED"));

                    properties.Add(property);
                }
            }

            return properties;
        }
        // ReSharper disable once FunctionComplexityOverflow
        private TypeModel CreateTypeModel(Uri source, XmlSchemaAnnotated type, XmlQualifiedName qualifiedName)
        {
            TypeModel typeModel;
            if (!qualifiedName.IsEmpty && Types.TryGetValue(qualifiedName, out typeModel)) return typeModel;

            if (source == null)
                throw new ArgumentNullException("source");
            var namespaceModel = CreateNamespaceModel(source, qualifiedName);

            var docs = GetDocumentation(type);

            var group = type as XmlSchemaGroup;
            if (group != null)
            {
                var name = "I" + ToTitleCase(qualifiedName.Name);
                if (namespaceModel != null) name = namespaceModel.GetUniqueTypeName(name);

                var interfaceModel = new InterfaceModel(_configuration)
                {
                    Name = name,
                    Namespace = namespaceModel,
                    XmlSchemaName = qualifiedName
                };

                interfaceModel.Documentation.AddRange(docs);

                if (namespaceModel != null) namespaceModel.Types[name] = interfaceModel;
                if (!qualifiedName.IsEmpty) Types[qualifiedName] = interfaceModel;

                var particle = group.Particle;
                var items = GetElements(particle);
                var properties = CreatePropertiesForElements(source, interfaceModel, particle, items.Where(i => !(i.XmlParticle is XmlSchemaGroupRef)));
                interfaceModel.Properties.AddRange(properties);
                var interfaces = items.Select(i => i.XmlParticle).OfType<XmlSchemaGroupRef>()
                    .Select(i => (InterfaceModel)CreateTypeModel(new Uri(i.SourceUri), Groups[i.RefName], i.RefName));
                interfaceModel.Interfaces.AddRange(interfaces);

                return interfaceModel;
            }

            var attributeGroup = type as XmlSchemaAttributeGroup;
            if (attributeGroup != null)
            {
                var name = "I" + ToTitleCase(qualifiedName.Name);
                if (namespaceModel != null) name = namespaceModel.GetUniqueTypeName(name);

                var interfaceModel = new InterfaceModel(_configuration)
                {
                    Name = name,
                    Namespace = namespaceModel,
                    XmlSchemaName = qualifiedName
                };

                interfaceModel.Documentation.AddRange(docs);

                if (namespaceModel != null) namespaceModel.Types[name] = interfaceModel;
                if (!qualifiedName.IsEmpty) Types[qualifiedName] = interfaceModel;

                var items = attributeGroup.Attributes;
                var properties = CreatePropertiesForAttributes(source, interfaceModel, items.OfType<XmlSchemaAttribute>());
                interfaceModel.Properties.AddRange(properties);
                var interfaces = items.OfType<XmlSchemaAttributeGroupRef>()
                    .Select(a => (InterfaceModel)CreateTypeModel(new Uri(a.SourceUri), AttributeGroups[a.RefName], a.RefName));
                interfaceModel.Interfaces.AddRange(interfaces);

                return interfaceModel;
            }

            var complexType = type as XmlSchemaComplexType;
            if (complexType != null)
            {
                var name = ToTitleCase(qualifiedName.Name);
                if (namespaceModel != null) name = namespaceModel.GetUniqueTypeName(name);

                var classModel = new ClassModel(_configuration)
                {
                    Name = name,
                    Namespace = namespaceModel,
                    XmlSchemaName = qualifiedName,
                    XmlSchemaType = complexType,
                    IsAbstract = complexType.IsAbstract,
                    IsAnonymous = complexType.QualifiedName.Name == "",
                    IsMixed = complexType.IsMixed,
                    IsSubstitution = complexType.Parent is XmlSchemaElement && !((XmlSchemaElement)complexType.Parent).SubstitutionGroup.IsEmpty,
                    EnableDataBinding = EnableDataBinding,
                };

                classModel.Documentation.AddRange(docs);

                if (namespaceModel != null)
                {
                    namespaceModel.Types[classModel.Name] = classModel;
                }

                if (!qualifiedName.IsEmpty) Types[qualifiedName] = classModel;

                if (complexType.BaseXmlSchemaType != null && complexType.BaseXmlSchemaType.QualifiedName != AnyType)
                {
                    var baseModel = CreateTypeModel(source, complexType.BaseXmlSchemaType, complexType.BaseXmlSchemaType.QualifiedName);
                    classModel.BaseClass = baseModel;
                    if (baseModel is ClassModel) ((ClassModel)classModel.BaseClass).DerivedTypes.Add(classModel);
                }

                XmlSchemaParticle particle = null;
                if (classModel.BaseClass != null)
                {
                    if (complexType.ContentModel.Content is XmlSchemaComplexContentExtension)
                        particle = ((XmlSchemaComplexContentExtension)complexType.ContentModel.Content).Particle;

                    // If it's a restriction, do not duplicate elements on the derived class, they're already in the base class.
                    // See https://msdn.microsoft.com/en-us/library/f3z3wh0y.aspx
                    //else if (complexType.ContentModel.Content is XmlSchemaComplexContentRestriction)
                    //    particle = ((XmlSchemaComplexContentRestriction)complexType.ContentModel.Content).Particle;
                }
                else particle = complexType.ContentTypeParticle;

                var items = GetElements(particle);
                var properties = CreatePropertiesForElements(source, classModel, particle, items);
                classModel.Properties.AddRange(properties);

                if (GenerateInterfaces)
                {
                    var interfaces = items.Select(i => i.XmlParticle).OfType<XmlSchemaGroupRef>()
                        .Select(i => (InterfaceModel)CreateTypeModel(new Uri(i.SourceUri), Groups[i.RefName], i.RefName));
                    classModel.Interfaces.AddRange(interfaces);
                }

                XmlSchemaObjectCollection attributes = null;
                if (classModel.BaseClass != null)
                {
                    if (complexType.ContentModel.Content is XmlSchemaComplexContentExtension)
                        attributes = ((XmlSchemaComplexContentExtension)complexType.ContentModel.Content).Attributes;
                    else if (complexType.ContentModel.Content is XmlSchemaSimpleContentExtension)
                        attributes = ((XmlSchemaSimpleContentExtension)complexType.ContentModel.Content).Attributes;

                    // If it's a restriction, do not duplicate attributes on the derived class, they're already in the base class.
                    // See https://msdn.microsoft.com/en-us/library/f3z3wh0y.aspx
                    //else if (complexType.ContentModel.Content is XmlSchemaComplexContentRestriction)
                    //    attributes = ((XmlSchemaComplexContentRestriction)complexType.ContentModel.Content).Attributes;
                    //else if (complexType.ContentModel.Content is XmlSchemaSimpleContentRestriction)
                    //    attributes = ((XmlSchemaSimpleContentRestriction)complexType.ContentModel.Content).Attributes;
                }
                else attributes = complexType.Attributes;

                if (attributes != null)
                {
                    var attributeProperties = CreatePropertiesForAttributes(source, classModel, attributes.Cast<XmlSchemaObject>());
                    classModel.Properties.AddRange(attributeProperties);

                    if (GenerateInterfaces)
                    {
                        var attributeInterfaces = attributes.OfType<XmlSchemaAttributeGroupRef>()
                            .Select(i => (InterfaceModel)CreateTypeModel(new Uri(i.SourceUri), AttributeGroups[i.RefName], i.RefName));
                        classModel.Interfaces.AddRange(attributeInterfaces);
                    }
                }

                if (complexType.AnyAttribute != null)
                {
                    var property = new PropertyModel(_configuration)
                    {
                        OwningType = classModel,
                        Name = "AnyAttribute",
                        Type = new SimpleModel(_configuration) { ValueType = typeof(XmlAttribute), UseDataTypeAttribute = false },
                        IsAttribute = true,
                        IsCollection = true,
                        IsAny = true
                    };

                    var attributeDocs = GetDocumentation(complexType.AnyAttribute);
                    property.Documentation.AddRange(attributeDocs);

                    classModel.Properties.Add(property);
                }

                return classModel;
            }

            var simpleType = type as XmlSchemaSimpleType;
            if (simpleType != null)
            {
                var restrictions = new List<RestrictionModel>();

                var typeRestriction = simpleType.Content as XmlSchemaSimpleTypeRestriction;
                if (typeRestriction != null)
                {
                    var enumFacets = typeRestriction.Facets.OfType<XmlSchemaEnumerationFacet>().ToList();
                    var isEnum = (enumFacets.Count == typeRestriction.Facets.Count && enumFacets.Count != 0)
                                    || (EnumTypes.Contains(typeRestriction.BaseTypeName.Name) && enumFacets.Any());
                    if (isEnum)
                    {
                        // we got an enum
                        var name = ToTitleCase(qualifiedName.Name);
                        if (namespaceModel != null) name = namespaceModel.GetUniqueTypeName(name);

                        var enumModel = new EnumModel(_configuration)
                        {
                            Name = name,
                            Namespace = namespaceModel,
                            XmlSchemaName = qualifiedName,
                            XmlSchemaType = simpleType,
                        };

                        enumModel.Documentation.AddRange(docs);

                        foreach (var facet in enumFacets.DistinctBy(f => f.Value))
                        {
                            var value = new EnumValueModel
                            {
                                Name = ToTitleCase(facet.Value).ToNormalizedEnumName(),
                                Value = facet.Value
                            };

                            var valueDocs = GetDocumentation(facet);
                            value.Documentation.AddRange(valueDocs);

                            var deprecated = facet.Annotation != null && facet.Annotation.Items.OfType<XmlSchemaAppInfo>()
                                .Any(a => a.Markup.Any(m => m.Name == "annox:annotate" && m.HasChildNodes && m.FirstChild.Name == "jl:Deprecated"));
                            value.IsDeprecated = deprecated;

                            enumModel.Values.Add(value);
                        }

                        if (namespaceModel != null)
                        {
                            namespaceModel.Types[enumModel.Name] = enumModel;
                        }

                        if (!qualifiedName.IsEmpty) Types[qualifiedName] = enumModel;

                        return enumModel;
                    }

                    restrictions = GetRestrictions(typeRestriction.Facets.Cast<XmlSchemaFacet>(), simpleType).Where(r => r != null).Sanitize().ToList();
                }

                var simpleModelName = ToTitleCase(qualifiedName.Name);
                if (namespaceModel != null) simpleModelName = namespaceModel.GetUniqueTypeName(simpleModelName);

                var simpleModel = new SimpleModel(_configuration)
                {
                    Name = simpleModelName,
                    Namespace = namespaceModel,
                    XmlSchemaName = qualifiedName,
                    XmlSchemaType = simpleType,
                    ValueType = simpleType.Datatype.GetEffectiveType(_configuration),
                };

                simpleModel.Documentation.AddRange(docs);
                simpleModel.Restrictions.AddRange(restrictions);

                if (namespaceModel != null)
                {
                    namespaceModel.Types[simpleModel.Name] = simpleModel;
                }

                if (!qualifiedName.IsEmpty) Types[qualifiedName] = simpleModel;

                return simpleModel;
            }

            throw new Exception(string.Format("Cannot build declaration for {0}", qualifiedName));
        }