/// <summary> /// Given a stream of relationships, returns a stream where applicable relationships are duplicated so that their /// reverse alias also appears in the output stream. /// Caution: remember to invert the from/to types, and the cardinality, as applicable. /// </summary> /// <param name="types"></param> /// <returns></returns> IEnumerable <EffectiveRelationship> EffectiveRelationships(IEnumerable <Entity> relationships) { foreach (var type in relationships) { bool isSingleEnum = false; var card = _schemaManager.GetCardinality(type); if (card == Aliases.ManyToOne) { var relToType = _schemaManager.GetRelationshipToType(type); var entType = _schemaManager.GetEntityType(relToType).Alias; isSingleEnum = entType == Aliases.EnumType; } var et = new EffectiveRelationship() { Type = type, Alias = type.Alias, IsSingleEnum = isSingleEnum }; yield return(et); if (type.ReverseAlias != null) { var rev = new EffectiveRelationship() { Type = type, Alias = type.ReverseAlias, IsReverseAlias = true, IsSingleEnum = false }; yield return(rev); } } }
/// <summary> /// Declares 'field' members for a type. /// That is, all fields that apply to this type, either directly or through inheritance. /// </summary> /// <param name="entityType">The type entity.</param> /// <param name="memberGroup">The XSD container that will hold the members.</param> private void AddRelationshipInstanceMember(EffectiveRelationship entityType, XmlSchemaGroupBase memberGroup, string elementName, Entity targetType, bool required) { // <xs:element name="fields"> // <xs:complexType mixed="true"> // <xs:group minOccurs="0" maxOccurs="unbounded" ref="is_field" /> // </xs:complexType> // </xs:element> XmlSchemaElement elem = new XmlSchemaElement(); elem.MinOccurs = required ? 1 : 0; elem.MaxOccurs = 1; elem.Name = elementName; elem.SchemaType = new XmlSchemaComplexType() { IsMixed = true, Particle = new XmlSchemaGroupRef() { MinOccurs = 0, // zero, since we might refer by alias text MaxOccurs = 1, RefName = targetType.Alias.ToQualifiedName(prefix: "is_") } }; memberGroup.Items.Add(elem); }
/// <summary> /// Declares the ability to have specific relationship instances that connect a 'from' to a 'to'. /// </summary> /// <param name="entityType">The type entity.</param> private void AddRelationshipInstanceElement(EffectiveRelationship entityType, XmlSchema xsd) { // Example: //<xs:element name="worksFor.instance" type="ri_worksFor" /> var typeElement = new XmlSchemaElement(); typeElement.Name = NameDeclared(entityType.Alias.Value + XmlParser.RelationshipInstanceSuffix, entityType.Alias.Namespace); typeElement.SchemaTypeName = entityType.Alias.ToQualifiedName(prefix: "ri_"); xsd.Items.Add(typeElement); // Example of member declaration // This contains both fields and relationships (and reverse relationships) //<xs:complexType name="ri_worksFor"> // <xs:all> // <!-- explicit relationships --> // <xs:element minOccurs="1" maxOccurs="1" name="from" type="is_fromType" /> // <xs:element minOccurs="1" maxOccurs="1" name="to" type="is_toType" /> // </xs:all> //</xs:complexType> // Create a complex type, named "ri_%typename%" var typeMembers = new XmlSchemaComplexType(); typeMembers.Name = NameDeclared("ri_" + entityType.Alias.Value, entityType.Alias.Namespace); // Create a group to hold the members var memberGroup = new XmlSchemaAll(); typeMembers.Particle = memberGroup; // Add from/to if (entityType.IsReverseAlias) { AddRelationshipInstanceMember(entityType, memberGroup, "to", _schemaManager.GetRelationshipFromType(entityType.Type), required: true); AddRelationshipInstanceMember(entityType, memberGroup, "from", _schemaManager.GetRelationshipToType(entityType.Type), required: true); } else { AddRelationshipInstanceMember(entityType, memberGroup, "from", _schemaManager.GetRelationshipFromType(entityType.Type), required: true); AddRelationshipInstanceMember(entityType, memberGroup, "to", _schemaManager.GetRelationshipToType(entityType.Type), required: true); } xsd.Items.Add(typeMembers); }
/// <summary> /// Generate valid values for an enum. /// </summary> private void AddEnumValues(EffectiveRelationship relationship) { var enumType = _schemaManager.GetRelationshipToType(relationship.Type); var instances = _schemaManager.GetInstancesOfType(enumType); var restriction = new XmlSchemaSimpleTypeRestriction(); restriction.BaseTypeName = XmlSchemaType.GetBuiltInSimpleType(XmlTypeCode.String).QualifiedName; foreach (Entity instance in instances) { XmlSchemaEnumerationFacet facet = new XmlSchemaEnumerationFacet(); if (instance.Alias.Namespace == "core") { facet.Value = instance.Alias.Value; } else { facet.Value = instance.Alias.Namespace + ":" + instance.Alias.Value; } restriction.Facets.Add(facet); } var simpleType = new XmlSchemaSimpleType(); simpleType.Content = restriction; var relElement = new XmlSchemaElement(); relElement.Name = NameDeclared(relationship.Alias.Value, relationship.Alias.Namespace); relElement.SchemaType = simpleType; // Add to schema XmlSchema xsd = GetSchema(relationship.Alias.Namespace); xsd.Items.Add(relElement); }