// 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)); }
private void BuildModel() { var objectModel = new SimpleModel(_configuration) { Name = "AnyType", Namespace = CreateNamespaceModel(new Uri(XmlSchema.Namespace), AnyType), XmlSchemaName = AnyType, XmlSchemaType = null, ValueType = typeof(object), UseDataTypeAttribute = false }; Types[AnyType] = objectModel; AttributeGroups = Set.Schemas().Cast<XmlSchema>().SelectMany(s => s.AttributeGroups.Values.Cast<XmlSchemaAttributeGroup>()).ToDictionary(g => g.QualifiedName); Groups = Set.Schemas().Cast<XmlSchema>().SelectMany(s => s.Groups.Values.Cast<XmlSchemaGroup>()).ToDictionary(g => g.QualifiedName); foreach (var rootElement in Set.GlobalElements.Values.Cast<XmlSchemaElement>()) { var source = new Uri(rootElement.GetSchema().SourceUri); var qualifiedName = rootElement.ElementSchemaType.QualifiedName; if (qualifiedName.IsEmpty) qualifiedName = rootElement.QualifiedName; var type = CreateTypeModel(source, rootElement.ElementSchemaType, qualifiedName); if (type.RootElementName != null) { if (type is ClassModel) { // There is already another global element with this type. // Need to create an empty derived class. var derivedClassModel = new ClassModel(_configuration) { Name = ToTitleCase(rootElement.QualifiedName.Name), Namespace = CreateNamespaceModel(source, rootElement.QualifiedName) }; derivedClassModel.Documentation.AddRange(GetDocumentation(rootElement)); if (derivedClassModel.Namespace != null) { derivedClassModel.Name = derivedClassModel.Namespace.GetUniqueTypeName(derivedClassModel.Name); derivedClassModel.Namespace.Types[derivedClassModel.Name] = derivedClassModel; } Types[rootElement.QualifiedName] = derivedClassModel; derivedClassModel.BaseClass = (ClassModel)type; ((ClassModel)derivedClassModel.BaseClass).DerivedTypes.Add(derivedClassModel); derivedClassModel.RootElementName = rootElement.QualifiedName; } else { Types[rootElement.QualifiedName] = type; } } else { var classModel = type as ClassModel; if (classModel != null) { classModel.Documentation.AddRange(GetDocumentation(rootElement)); } type.RootElementName = rootElement.QualifiedName; } } foreach (var globalType in Set.GlobalTypes.Values.Cast<XmlSchemaType>()) { var schema = globalType.GetSchema(); var source = (schema == null ? null : new Uri(schema.SourceUri)); var type = CreateTypeModel(source, globalType, globalType.QualifiedName); } }