/// <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 AddTypeFields(EffectiveType entityType, XmlSchemaGroupBase memberGroup) { // Example: // <xs:element minOccurs="0" maxOccurs="1" ref="firstName" /> // Define fields applicable to type // This is defining that a given field can appear under a resource of a particular type var fields = from type in _schemaManager.GetAncestors(entityType.Type) from field in _schemaManager.GetDeclaredFields(type) select field; foreach (Entity field in fields) { if (field.Alias == null) { continue; } var fieldElem = new XmlSchemaElement(); fieldElem.RefName = NameUsed(field.Alias.ToQualifiedName()); fieldElem.MaxOccurs = 1; bool required = (_schemaManager.GetBoolFieldValue(field, Aliases2.IsRequired) && _schemaManager.GetStringFieldValue(field, Aliases2.DefaultValue) == null ) || field.Alias == Aliases.Alias; // special case: alias is required in config, but not at runtime fieldElem.MinOccurs = required ? 1 : 0; memberGroup.Items.Add(fieldElem); } }
private bool TryParseToPredicateType(string s, out object value) { value = null; if (ValueIsNull(s)) { return(!IsNullable); } if (EffectiveType.Is <string>()) { value = s; return(true); } else if (DataType == PredicateDataType.Number) { var r = TryParseNumber(s, typeof(decimal), out value); value = NumericTypeHelper.NarrowNumber(value); return(r); } else if (DataType == PredicateDataType.Boolean) { var r = TryParseBool(s, out var b); value = b; return(r); } else if (DataType == PredicateDataType.DateTime) { var r = TryParseDateTime(s, out var d); value = d; return(r); } else if (DataType == PredicateDataType.TimeSpan) { var r = TryParseTimeSpan(s, out var t); value = t; return(r); } return(false); }
/// <summary> /// Declares the element type for this entity. Refers to the the complex type that describes the members. /// Is referred to by the 'is a' groups. /// </summary> /// <param name="entityType">The type entity.</param> private void AddTypeElement(EffectiveType entityType, XmlSchema xsd) { // Example: //<xs:element name="person" type="type_person" /> var typeElement = new XmlSchemaElement(); typeElement.Name = NameDeclared(entityType.Alias.Value, entityType.Alias.Namespace); typeElement.SchemaTypeName = entityType.Alias.ToQualifiedName(prefix: "type_"); xsd.Items.Add(typeElement); }
/// <summary> /// Creates a group that contains all of the types that inherit from a given type, /// as well as the type itself. Reference this group when any inherited type is suitable. /// </summary> private void AddTypeDescendents(EffectiveType entityType, XmlSchema xsd) { // Example of inheritance declaration //<xs:group name="is_person"> // <xs:choice> // <xs:element ref="person" /> // <xs:element ref="employee" /> // <xs:element ref="manager" /> // </xs:choice> //</xs:group> // Create a group, named "is_%typename%" var isType = new XmlSchemaGroup(); isType.Name = NameDeclared("is_" + entityType.Alias.Value, entityType.Alias.Namespace); isType.Particle = new XmlSchemaChoice(); // Determine valid descendents IEnumerable <Entity> descendents; bool isSealed = _schemaManager.GetBoolFieldValue(entityType.Type, Aliases2.IsSealed); if (isSealed) { descendents = new List <Entity> { entityType.Type } } ; else { descendents = _schemaManager.GetDecendants(entityType.Type); } // Render each type foreach (EffectiveType desc in EffectiveTypes(descendents)) { bool isAbstract = _schemaManager.GetBoolFieldValue(desc.Type, Aliases2.IsAbstract); if (isAbstract) { continue; } var derivedType = new XmlSchemaElement(); derivedType.RefName = NameUsed(desc.Alias.ToQualifiedName()); isType.Particle.Items.Add(derivedType); } xsd.Items.Add(isType); }
/// <summary> /// Given a stream of types, returns a stream of types where any 'relationship' types 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 <EffectiveType> EffectiveTypes(IEnumerable <Entity> types) { foreach (var type in types) { bool isRelationship = _schemaManager.IsInstance(type, A(Aliases.Relationship)); if (isRelationship) { continue; } var et = new EffectiveType() { Type = type, Alias = type.Alias }; yield return(et); } }
/// <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> private void AddTypeMembers(EffectiveType entityType, XmlSchema xsd) { // Example of member declaration // This contains both fields and relationships (and reverse relationships) //<xs:complexType name="type_person"> // <xs:all> // <!-- fields --> // <xs:element minOccurs="0" maxOccurs="1" ref="name" /> // <xs:element minOccurs="0" maxOccurs="1" ref="description" /> // <xs:element minOccurs="0" maxOccurs="1" ref="alias" /> // <xs:element minOccurs="0" maxOccurs="1" ref="firstName" /> // <xs:element minOccurs="0" maxOccurs="1" ref="lastName" /> // <!-- relationships --> // <xs:element minOccurs="0" maxOccurs="1" ref="worksFor" /> // </xs:all> //</xs:complexType> // Create a complex type, named "type_%typename%" var typeMembers = new XmlSchemaComplexType(); typeMembers.Name = NameDeclared("type_" + entityType.Alias.Value, entityType.Alias.Namespace); // Create a group to hold the members var memberGroup = new XmlSchemaAll(); typeMembers.Particle = memberGroup; // Add members AddTypeFields(entityType, memberGroup); AddTypeRelationships(entityType, memberGroup); // Add 'source' attribute for file types Entity file = _aliasResolver[Aliases2.File]; if (_schemaManager.IsSameOrDerivedType(entityType.Type, file)) { XmlSchemaAttribute sourceAttrib = new XmlSchemaAttribute(); sourceAttrib.Name = "source"; sourceAttrib.SchemaTypeName = XmlSchemaSimpleType.GetBuiltInSimpleType(XmlTypeCode.String).QualifiedName; typeMembers.Attributes.Add(sourceAttrib); } xsd.Items.Add(typeMembers); }
/// <summary> /// Declares 'relationship' members for a type. /// That is, all forward or reverse relationships that can connect to this type at one end or the other. /// </summary> /// <param name="entityType">The type entity.</param> /// <param name="memberGroup">The XSD container that will hold the members.</param> private void AddTypeRelationships(EffectiveType entityType, XmlSchemaGroupBase memberGroup) { // Define relationships applicable to type // This is defining that a given relationship container can appear under a resource of a particular type // e.g. <xs:element ref="worksFor" minOccurs="0" maxOccurs="1"/> // Note: maxOccurs refers to the relationship container, not the cardinality of the relationship itself. var relationships = from type in _schemaManager.GetAncestors(entityType.Type) from relationshipDefn in _schemaManager.GetRelationshipsToEntity(type, A(Aliases.FromType)) select new { Relationship = relationshipDefn, Alias = relationshipDefn.Alias }; var relationshipsRev = from type in _schemaManager.GetAncestors(entityType.Type) from relationshipDefn in _schemaManager.GetRelationshipsToEntity(type, A(Aliases.ToType)) select new { Relationship = relationshipDefn, Alias = relationshipDefn.ReverseAlias }; HashSet <XmlQualifiedName> hash = new HashSet <XmlQualifiedName>(); foreach (var rel in relationships.Concat(relationshipsRev)) { if (rel.Alias == null || string.IsNullOrEmpty(rel.Alias.Value)) { continue; } var fieldElem = new XmlSchemaElement(); fieldElem.MaxOccurs = 1; // the relationship container, not the relationships themselves fieldElem.MinOccurs = 0; fieldElem.RefName = NameUsed(rel.Alias.ToQualifiedName()); if (hash.Contains(fieldElem.RefName)) { throw new Exception("Already used: " + fieldElem.RefName.ToString()); // note: this can also get triggered if an inline-relationship defines a fromType node. } hash.Add(fieldElem.RefName); memberGroup.Items.Add(fieldElem); } }