Meta Data - STARIONGROUP/COMET-SDK-Community-Edition GitHub Wiki

Introduction

The CDP4-COMET-SDK provides different means to use and inspect the structure of the CDP4-COMET Data Model. This can be useful for serialization and deserialization purposes, but also for the construction of the full object graph based on the POCO classes. Two mechanisms are provided for this purpuse. The UmlInformationAttribute C# attribute and the MetaInfo classes.

ContainerAttribute

The ContainerAttribute is used to decorate classes that take part in a containment relationship. The attribute has 2 properties:

  • ClassType: The Type that is the container of the decorated class.
  • PropertyName: The name of the property of the container Type that is used to contain the decorated class.

The following code snippet demonstrates the use of the attribute on the EmailAddress class which has a composite aggregation relationship with the Person class.

[Container(typeof(Person), "EmailAddress")]
public sealed partial class EmailAddress : Thing
{

}

The ContainerAttribute can be used in combination with reflection to determine what the containment hierarchy is of class.

UmlInformationAttribute

The UmlInformationAttribute is used to decorate properties of CDP4-COMET Data Model classes with information derived from the UML model. The UmlInformationAttribute has the following properties:

  • Aggregation: Specification of the AggregationKind which has as possible values None, Shared, and Composite
  • IsOrdered: A value that indicates whether the property is ordered. Ordered properties are encapsulated by the OrderedItem class that makes use of a key/value pair to maintain the order.
  • IsDerived: A value that indicates whether the property is derived. Derived properties are included on the DTO classes for completeness but will throw an InvalidOperation exception when called. The POCO classes also contain the derived properties, where the getter is hand-coded in a partial class.
  • IsNullable: A value that indicates whether the property is nullable
  • IsPersistent: A value that indicates whether the property is persistent. Persistent properties are stored by a server implementation, non-persistent properties are not stored by a server implementation and are only used client-side.

The UmlInformationAttribute can be used with reflection to extract all attributes that are decorated with this attribute. In combination with LINQ developers can query specific attributes and operate on them. It also provide a self-documenting mechanism for the DTO and POCO classes. For Example: the fact that a property is persisted by the server or not is now also apparent from the code in the COMET-SDK.

CDP Version

The CDP4-COMET Data Model is in essence an extension of ECSS-E-TM-10-25A. It includes extra classes and properties on existing classes that extend the data model based on experience gained in the last 10+ years with CDP3. The properties and classes in the data model that are extensions of ECSS-E-TM-10-25A are decorated with the CDPVersionAttribute.

The CDPVersion attribute has one property called Version, this denotes the version of the data-model that the extension (a class or a property) is a member of.

The CDP4-COMET Web Services make use of this attribute to return valid data to a client that makes use of the REST API. In case a client does not specify what version of the CDP4-COMET Data Model it supports, the response will be pure ECSS-E-TM-10-25A Annex C.2. In case the CDPVersion is specified, including the actual version number, those classes and properties that are a member of that version will be returned. This mechanimsm ensures that multiple implementations of the CDP4-COMET Data Model can be used in combination in one Concurrent Design environment.

MetaInfo Classes

All the classes that are part of the CDP4-COMET Data Model are implemented as a DTOs and a POCOs. Next to the DTOs and the POCOs, the COMET-SDK also provides for each of these classes a MetaInfo Class. The MetaInfo classes provide helper methods that would otherwise require a lot of reflection which would make any implementation slow. These helper methods are used by the CDP4JsonSerializer for optimised (de)serialization and by the CDP4-COMET Web Services to determine how the database needs to be queried in an optimal way without relying on (slow-er) reflection.

Each CDP4-COMET Data Model class is represented by an Interface that adheres to the following naming convention:

<Class-Name>MetaInfo

These MetaInfo classess implement the IMetaInfo interface which is defined as follows:

namespace CDP4Common.MetaInfo
{
    public interface IMetaInfo
    {
        /// <summary>
        /// Gets the base type name of this class.
        /// </summary>
        string BaseType { get; }

        /// <summary>
        /// Gets the CDP class version.
        /// </summary>
        string ClassVersion { get; }

        /// <summary>
        /// Get the data model version of the supplied property.
        /// </summary>
        /// <param name="propertyName">
        /// Name of the property for which to check if it is scalar.
        /// </param>
        /// <returns>
        /// The version number as specified property otherwise the default data model version.
        /// </returns>
        string GetPropertyVersion(string propertyName);

        /// <summary>
        /// Returns the <see cref="Thing"/> containment property info from the supplied property name.
        /// </summary>
        /// <param name="propertyName">
        /// The containment property name.
        /// </param>
        /// <returns>
        /// The type info of the containment property.
        /// </returns>
        /// <exception cref="ArgumentException">
        /// If the property name is not supported for the <see cref="Thing"/>.
        /// </exception>
        PropertyMetaInfo GetContainmentType(string propertyName);

        /// <summary>
        /// Check if the supplied property name is scalar.
        /// </summary>
        /// <param name="propertyName">
        /// Name of the property for which to check if it is scalar.
        /// </param>
        /// <returns>
        /// True if the supplied property name is a scalar property.
        /// </returns>
        bool IsScalar(string propertyName);

        /// <summary>
        /// Gets a value indicating whether this type should be deprecated upon Delete.
        /// </summary>
        bool IsDeprecatableThing { get; }

        /// <summary>
        /// Gets a value indicating whether this type is a top container.
        /// </summary>
        bool IsTopContainer { get; }

        /// <summary>
        /// Gets the <see cref="PropertyMetaInfo"/>s for the represented <see cref="Thing"/>
        /// </summary>
        IEnumerable<PropertyMetaInfo> Properties { get; }

        /// <summary>
        /// Returns the <see cref="PropertyMetaInfo"/> for the property of a <see cref="Thing"/>
        /// </summary>
        /// <param name="propertyName">
        /// The property name.
        /// </param>
        /// <returns>
        /// The type info of the property.
        /// </returns>
        /// <exception cref="ArgumentException">
        /// If the property name is not supported for the <see cref="CDP4Common.DTO.Thing"/>.
        /// </exception>
        PropertyMetaInfo GetPropertyMetaInfo(string propertyName);

        /// <summary>
        /// Returns the container property for the supplied type name is a possible container for <see cref="Thing"/>.
        /// </summary>
        /// <param name="typeName">
        /// Name of the type for which to check if it is a container of <see cref="Thing"/>.
        /// </param>
        /// <param name="containerProperty">
        /// Supplied container property info instance that will be set if the supplied type name is a container of <see cref="Thing"/>.
        /// </param>
        /// <returns>
        /// True if the supplied typeName is a container for <see cref="Thing"/> and sets the container property name.
        /// </returns>
        bool TryGetContainerProperty(string typeName, out PropertyMetaInfo containerProperty);

        /// <summary>
        /// Returns a deserialized object from the supplied value string for the property name.
        /// </summary>
        /// <param name="propertyName">
        /// The property name.
        /// </param>
        /// <param name="value">
        /// The value to deserialize from its current string form.
        /// </param>
        /// <returns>
        /// A deserialized object from the supplied value.
        /// </returns>
        /// <exception cref="ArgumentException">
        /// If the property name is not supported for the <see cref="CDP4Common.DTO.Thing"/>.
        /// </exception>
        object DeserializeCollectionValue(string propertyName, object value);

        /// <summary>
        /// Apply the value update to the supplied property name of the updatable <see cref="Thing"/> instance.
        /// </summary>
        /// <param name="updatableThing">
        /// The <see cref="Thing"/> instance to which to apply the property value update.
        /// </param>
        /// <param name="propertyName">
        /// The property name of the <see cref="Thing"/> to which to apply the value update.
        /// </param>
        /// <param name="value">
        /// The updated value to apply.
        /// </param>
        /// <returns>
        /// True if the value update was successfully applied.
        /// </returns>
        bool ApplyPropertyUpdate(Thing updatableThing, string propertyName, object value);

        /// <summary>
        /// Returns the value of the property of a Thing
        /// </summary>
        /// <param name="propertyName">
        /// The property name.
        /// </param>
        /// <param name="thing">
        /// The Thing object
        /// </param>
        /// <returns>
        /// The value of the property of a Thing
        /// </returns>
        /// <exception cref="ArgumentException">
        /// If the property name is not supported for the <see cref="CDP4Common.DTO.Thing"/>.
        /// </exception>
        object GetValue(string propertyName, Thing thing);

        /// <summary>
        /// Gets the collection of property names for a <see cref="Thing"/>
        /// </summary>
        IEnumerable<string> GetPropertyNameCollection();

        /// <summary>
        /// Validates the supplied <see cref="Thing"/> by running the business validation rules as per its meta info definition class.
        /// </summary>
        /// <param name="thing">
        /// The <see cref="Thing"/> for which to run the validation rules.
        /// </param>
        /// <exception cref="Cdp4ModelValidationException">
        /// If any validation rule failed.
        /// </exception>
        void Validate(Thing thing);

        /// <summary>
        /// Validates the supplied <see cref="Thing"/> by running the business validation rules as per its meta info definition class.
        /// </summary>
        /// <param name="thing">
        /// The <see cref="Thing"/> for which to run the validation rules.
        /// </param>
        /// <param name="validateProperty">
        /// The validate Property.
        /// </param>
        /// <exception cref="Cdp4ModelValidationException">
        /// If any validation rule failed.
        /// </exception>
        void Validate(Thing thing, Func<string, bool> validateProperty);

        /// <summary>
        /// Validates the supplied <see cref="Thing"/> by running the business validation rules as per its meta info definition class.
        /// </summary>
        /// <param name="thing">
        /// The <see cref="Thing"/> for which to run the validation rules.
        /// </param>
        /// <returns>
        /// True if all validation rules have passed or if none are defined.
        /// </returns>
        bool TryValidate(Thing thing);

        /// <summary>
        /// Validates the supplied <see cref="Thing"/> by running the business validation rules as per its meta info definition class.
        /// </summary>
        /// <param name="thing">
        /// The <see cref="Thing"/> for which to run the validation rules.
        /// </param>
        /// <param name="validateProperty">
        /// The validate Property.
        /// </param>
        /// <returns>
        /// True if all validation rules have passed or if none are defined.
        /// </returns>
        bool TryValidate(Thing thing, Func<string, bool> validateProperty);

        /// <summary>
        /// Returns the containment property value for the supplied <see cref="Thing"/>.
        /// </summary>
        /// <param name="thing">
        /// The <see cref="Thing"/> for which to return the containment property value.
        /// </param>
        /// <param name="propertyName">
        /// Name of the containment property for which to return the value.
        /// </param>
        /// <returns>
        /// A collection of containment <see cref="Guid"/>.
        /// </returns>
        /// <exception cref="ArgumentException">
        /// If the property name is not supported for the <see cref="Thing"/>.
        /// </exception>
        IEnumerable<Guid> GetContainmentIds(Thing thing, string propertyName);

        /// <summary>
        /// Returns the ordered containment property value for the supplied <see cref="Thing"/>.
        /// </summary>
        /// <param name="thing">
        /// The <see cref="Thing"/> for which to return the containment property value.
        /// </param>
        /// <param name="propertyName">
        /// Name of the containment property for which to return the value.
        /// </param>
        /// <returns>
        /// A collection of ordered containment <see cref="OrderedItem"/>.
        /// </returns>
        /// <exception cref="ArgumentException">
        /// If the property name is not supported for the <see cref="Thing"/>.
        /// </exception>
        IEnumerable<OrderedItem> GetOrderedContainmentIds(Thing thing, string propertyName);

        /// <summary>
        /// Instantiates a <see cref="Dto.Thing"/>
        /// </summary>
        /// <returns>
        /// The instantiated <see cref="Dto.Thing"/>
        /// </returns>
        DTO.Thing InstantiateDto(Guid guid, int revisionNumber);
    }
}

These MetaInfo classes can be accessed by means of the MetaDataProvider or the StaticMetadataProvider. The MetaDataProvider implements the IMetaDataProvider interface and should be used in combination with a Dependency Injection Framework such as Autofac or ninject. The StaticMetadataProvider exposes the same functionality as static class and should be used when a Dependency Injection Framework is not available.


« CDP4Common-CE Types  —  Documentation overview  —  CDP4Common-CE Permissions »

⚠️ **GitHub.com Fallback** ⚠️