diff --git a/dotnet/gen/ParserGenerator/MaterialClassValidator.cs b/dotnet/gen/ParserGenerator/MaterialClassValidator.cs index fb29ca73..ff87d96d 100644 --- a/dotnet/gen/ParserGenerator/MaterialClassValidator.cs +++ b/dotnet/gen/ParserGenerator/MaterialClassValidator.cs @@ -242,7 +242,7 @@ private static void AddValidationChecks(int dtdlVersion, CsClass obverseClass, C if (instanceConditionDigest.Pattern != null) { - AddPatternCheck(dtdlVersion, obverseClass, scope, instanceConditionDigest.Pattern, $"{eltVar}.GetString()", $"{level}Value", termination, conformanceText); + AddPatternCheck(dtdlVersion, obverseClass, scope, instanceConditionDigest.Pattern, $"{eltVar}.{(instanceConditionDigest.JsonType == "string" ? "GetString" : "GetRawText")}()", $"{level}Value", termination, conformanceText); } if (instanceConditionDigest.NamePattern != null) @@ -283,14 +283,16 @@ private static void AddJsonTypeCheck(CsScope scope, string jsonType, string eltV private static void AddDatatypeCheck(CsScope scope, string datatype, string eltVar, string termination, string conformanceText) { + if (TryGetIntegralType(datatype, out string csType)) + { + scope.If($"!{csType}.TryParse({eltVar}.GetRawText(), out {csType} _)") + .Line($"violations.Add($\"{{{eltVar}.GetRawText()}} does not conform to {conformanceText}\");") + .Line($"{termination};"); + return; + } + switch (datatype) { - case "int": - case "long": - scope.If($"!{datatype}.TryParse({eltVar}.GetRawText(), out {datatype} _)") - .Line($"violations.Add($\"{{{eltVar}.GetRawText()}} does not conform to {conformanceText}\");") - .Line($"{termination};"); - break; case "float": case "double": scope.If($"!{datatype}.TryParse({eltVar}.GetRawText(), out {datatype} val) || {datatype}.IsInfinity(val)") @@ -307,6 +309,40 @@ private static void AddDatatypeCheck(CsScope scope, string datatype, string eltV } } + private static bool TryGetIntegralType(string datatype, out string csType) + { + switch (datatype) + { + case "byte": + csType = "sbyte"; + return true; + case "int": + csType = "int"; + return true; + case "long": + csType = "long"; + return true; + case "short": + csType = "short"; + return true; + case "unsignedByte": + csType = "byte"; + return true; + case "unsignedInt": + csType = "uint"; + return true; + case "unsignedLong": + csType = "ulong"; + return true; + case "unsignedShort": + csType = "ushort"; + return true; + default: + csType = string.Empty; + return false; + } + } + private static void AddInstancePropertyCheck(int dtdlVersion, CsScope scope, string instanceProperty, Dictionary propertyDigests, Dictionary classInstanceValidationDigests, string eltVar, string nameVar, string termination) { string propertyName = NameFormatter.FormatNameAsProperty(instanceProperty); diff --git a/dotnet/src/DTDLParser/LiteralValidator.cs b/dotnet/src/DTDLParser/LiteralValidator.cs index 6419c0ea..ae93c8f7 100644 --- a/dotnet/src/DTDLParser/LiteralValidator.cs +++ b/dotnet/src/DTDLParser/LiteralValidator.cs @@ -21,6 +21,14 @@ internal static bool HasValue(JsonElement elt, object value) { return elt.ValueKind == JsonValueKind.String && (string)value == elt.GetString(); } + else if (valueType == typeof(sbyte)) + { + return elt.ValueKind == JsonValueKind.Number && (sbyte)value == elt.GetSByte(); + } + else if (valueType == typeof(short)) + { + return elt.ValueKind == JsonValueKind.Number && (short)value == elt.GetInt16(); + } else if (valueType == typeof(int)) { return elt.ValueKind == JsonValueKind.Number && (int)value == elt.GetInt32(); @@ -29,6 +37,22 @@ internal static bool HasValue(JsonElement elt, object value) { return elt.ValueKind == JsonValueKind.Number && (long)value == elt.GetInt64(); } + else if (valueType == typeof(byte)) + { + return elt.ValueKind == JsonValueKind.Number && (byte)value == elt.GetByte(); + } + else if (valueType == typeof(ushort)) + { + return elt.ValueKind == JsonValueKind.Number && (ushort)value == elt.GetUInt16(); + } + else if (valueType == typeof(uint)) + { + return elt.ValueKind == JsonValueKind.Number && (uint)value == elt.GetUInt32(); + } + else if (valueType == typeof(ulong)) + { + return elt.ValueKind == JsonValueKind.Number && (ulong)value == elt.GetUInt64(); + } else if (valueType == typeof(float)) { return elt.ValueKind == JsonValueKind.Number && (float)value == elt.GetSingle(); diff --git a/dotnet/src/DTDLParser/generated/ContextCollection.g.cs b/dotnet/src/DTDLParser/generated/ContextCollection.g.cs index 6179631d..ade7c8ab 100644 --- a/dotnet/src/DTDLParser/generated/ContextCollection.g.cs +++ b/dotnet/src/DTDLParser/generated/ContextCollection.g.cs @@ -1422,6 +1422,8 @@ private static ContextHistory GetDtdlContextHistory() context4_0.AddTermDefinition("asynchronous", new Dtmi("dtmi:dtdl:instance:CommandType:asynchronous;4"), isMergeableType: false); context4_0.AddTermDefinition("boolean", new Dtmi("dtmi:dtdl:instance:Schema:boolean;4"), isMergeableType: false); context4_0.AddTermDefinition("Boolean", new Dtmi("dtmi:dtdl:class:Boolean;4"), isMergeableType: false); + context4_0.AddTermDefinition("byte", new Dtmi("dtmi:dtdl:instance:Schema:byte;4"), isMergeableType: false); + context4_0.AddTermDefinition("Byte", new Dtmi("dtmi:dtdl:class:Byte;4"), isMergeableType: false); context4_0.AddTermDefinition("bytes", new Dtmi("dtmi:dtdl:instance:Schema:bytes;4"), isMergeableType: false); context4_0.AddTermDefinition("Bytes", new Dtmi("dtmi:dtdl:class:Bytes;4"), isMergeableType: false); context4_0.AddTermDefinition("Command", new Dtmi("dtmi:dtdl:class:Command;4"), isMergeableType: false); @@ -1498,6 +1500,8 @@ private static ContextHistory GetDtdlContextHistory() context4_0.AddTermDefinition("schemas", new Dtmi("dtmi:dtdl:property:schemas;4"), isMergeableType: false); context4_0.AddTermDefinition("SemanticType", new Dtmi("dtmi:dtdl:class:SemanticType;4"), isMergeableType: false); context4_0.AddTermDefinition("SemanticUnit", new Dtmi("dtmi:dtdl:class:SemanticUnit;4"), isMergeableType: false); + context4_0.AddTermDefinition("short", new Dtmi("dtmi:dtdl:instance:Schema:short;4"), isMergeableType: false); + context4_0.AddTermDefinition("Short", new Dtmi("dtmi:dtdl:class:Short;4"), isMergeableType: false); context4_0.AddTermDefinition("string", new Dtmi("dtmi:dtdl:instance:Schema:string;4"), isMergeableType: false); context4_0.AddTermDefinition("String", new Dtmi("dtmi:dtdl:class:String;4"), isMergeableType: false); context4_0.AddTermDefinition("symbol", new Dtmi("dtmi:dtdl:property:symbol;4"), isMergeableType: false); @@ -1509,6 +1513,14 @@ private static ContextHistory GetDtdlContextHistory() context4_0.AddTermDefinition("Time", new Dtmi("dtmi:dtdl:class:Time;4"), isMergeableType: false); context4_0.AddTermDefinition("Unit", new Dtmi("dtmi:dtdl:class:Unit;4"), isMergeableType: false); context4_0.AddTermDefinition("UnitAttribute", new Dtmi("dtmi:dtdl:class:UnitAttribute;4"), isMergeableType: false); + context4_0.AddTermDefinition("unsignedByte", new Dtmi("dtmi:dtdl:instance:Schema:unsignedByte;4"), isMergeableType: false); + context4_0.AddTermDefinition("UnsignedByte", new Dtmi("dtmi:dtdl:class:UnsignedByte;4"), isMergeableType: false); + context4_0.AddTermDefinition("unsignedInteger", new Dtmi("dtmi:dtdl:instance:Schema:unsignedInteger;4"), isMergeableType: false); + context4_0.AddTermDefinition("UnsignedInteger", new Dtmi("dtmi:dtdl:class:UnsignedInteger;4"), isMergeableType: false); + context4_0.AddTermDefinition("unsignedLong", new Dtmi("dtmi:dtdl:instance:Schema:unsignedLong;4"), isMergeableType: false); + context4_0.AddTermDefinition("UnsignedLong", new Dtmi("dtmi:dtdl:class:UnsignedLong;4"), isMergeableType: false); + context4_0.AddTermDefinition("unsignedShort", new Dtmi("dtmi:dtdl:instance:Schema:unsignedShort;4"), isMergeableType: false); + context4_0.AddTermDefinition("UnsignedShort", new Dtmi("dtmi:dtdl:class:UnsignedShort;4"), isMergeableType: false); context4_0.AddTermDefinition("uuid", new Dtmi("dtmi:dtdl:instance:Schema:uuid;4"), isMergeableType: false); context4_0.AddTermDefinition("Uuid", new Dtmi("dtmi:dtdl:class:Uuid;4"), isMergeableType: false); context4_0.AddTermDefinition("valueSchema", new Dtmi("dtmi:dtdl:property:valueSchema;4"), isMergeableType: false); diff --git a/dotnet/src/DTDLParser/generated/DTByteInfo.g.cs b/dotnet/src/DTDLParser/generated/DTByteInfo.g.cs new file mode 100644 index 00000000..3d878fd3 --- /dev/null +++ b/dotnet/src/DTDLParser/generated/DTByteInfo.g.cs @@ -0,0 +1,1887 @@ +/* This is an auto-generated file. Do not modify. */ + +namespace DTDLParser.Models +{ + using System; + using System.Collections.Generic; + using System.ComponentModel; + using System.Globalization; + using System.IO; + using System.Linq; + using System.Text; + using System.Text.Json; + using System.Text.RegularExpressions; + using System.Threading; + using System.Threading.Tasks; + using DTDLParser; + + /// + /// Class DTByteInfo corresponds to an element of type Byte in a DTDL model. + /// + public class DTByteInfo : DTNumericSchemaInfo, ITypeChecker, IConstrainer, IEquatable + { + private static readonly Dictionary> ConcreteKinds = new Dictionary>(); + + private static readonly Dictionary BadTypeActionFormat = new Dictionary(); + + private static readonly Dictionary BadTypeCauseFormat = new Dictionary(); + + private static readonly Dictionary BadTypeLocatedCauseFormat = new Dictionary(); + + private static readonly HashSet PropertyNames = new HashSet(); + + private static readonly HashSet VersionlessTypes = new HashSet(); + + private bool checkedForDescendantSchemaArray = false; + + private bool checkedForDescendantSchemaOrContentsComponentNarrow = false; + + private Dictionary supplementalPropertySources = new Dictionary(); + + private Dictionary eltsOfDescendantSchemaArray = null; + + private Dictionary eltsOfDescendantSchemaOrContentsComponentNarrow = null; + + private Dictionary supplementalProperties; + + private Dictionary descriptionPropertyLayer = null; + + private Dictionary displayNamePropertyLayer = null; + + private Dictionary supplementalSingularPropertyLayers = new Dictionary(); + + private Dtmi idOfDescendantSchemaArray = null; + + private Dtmi idOfDescendantSchemaOrContentsComponentNarrow = null; + + private HashSet supplementalTypeIds; + + private int countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowValue = 0; + + private int countOfExtendsNarrowValue = 0; + + private List supplementalTypes; + + private List commentValueConstraints = null; + + private List descriptionValueConstraints = null; + + private List displayNameValueConstraints = null; + + private string commentPropertyLayer = null; + + private TraversalStatus countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowStatus = TraversalStatus.NotStarted; + + private TraversalStatus countOfExtendsNarrowStatus = TraversalStatus.NotStarted; + + private Type checkedDescendantEnumValueDatatype = null; + + static DTByteInfo() + { + VersionlessTypes.Add("dtmi:dtdl:class:Byte"); + VersionlessTypes.Add("dtmi:dtdl:class:Entity"); + VersionlessTypes.Add("dtmi:dtdl:class:NumericSchema"); + VersionlessTypes.Add("dtmi:dtdl:class:PrimitiveSchema"); + VersionlessTypes.Add("dtmi:dtdl:class:Schema"); + + PropertyNames.Add("comment"); + PropertyNames.Add("description"); + PropertyNames.Add("displayName"); + PropertyNames.Add("languageMajorVersion"); + + ConcreteKinds[4] = new HashSet(); + ConcreteKinds[4].Add(DTEntityKind.Byte); + + BadTypeActionFormat[4] = "Use this standard value for property '{property}'{line1}: byte."; + + BadTypeCauseFormat[4] = "{layer}{primaryId:p} property '{property}' has value{secondaryId:e} that is not a standard value for this property."; + + BadTypeLocatedCauseFormat[4] = "In {sourceName1}, property '{property}'{line1} has value{secondaryId:e}{line2} that is not a standard value for this property."; + } + + /// + /// Initializes a new instance of the class. + /// + /// Version of DTDL used to define the Byte. + /// Identifier for the Byte. + /// Identifier of the parent element in which this Byte is defined. + /// Name of the property by which the parent DTDL element refers to this Byte. + /// Identifier of the partition in which this Byte is defined. + internal DTByteInfo(int dtdlVersion, Dtmi id, Dtmi childOf, string myPropertyName, Dtmi definedIn) + : base(dtdlVersion, id, childOf, myPropertyName, definedIn, DTEntityKind.Byte) + { + this.supplementalTypeIds = new HashSet(); + this.supplementalProperties = new Dictionary(); + this.supplementalTypes = new List(); + + this.IsPartition = false; + + this.MaybePartial = false; + } + + /// + /// Initializes a new instance of the class. + /// + /// Version of DTDL used to define the Byte. + /// Identifier for the Byte. + /// Identifier of the parent element in which this Byte is defined. + /// Name of the property by which the parent DTDL element refers to this Byte. + /// Identifier of the partition in which this Byte is defined. + /// The kind of Entity, which may be other than Byte if this constructor is called from a derived class. + internal DTByteInfo(int dtdlVersion, Dtmi id, Dtmi childOf, string myPropertyName, Dtmi definedIn, DTEntityKind entityKind) + : base(dtdlVersion, id, childOf, myPropertyName, definedIn, entityKind) + { + this.supplementalTypeIds = new HashSet(); + this.supplementalProperties = new Dictionary(); + this.supplementalTypes = new List(); + + this.IsPartition = false; + + this.MaybePartial = false; + } + + /// + /// Get the DTMI that identifies type Byte in the version of DTDL used to define this element. + /// + /// The DTMI for the DTDL type Byte. + public override Dtmi ClassId + { + get + { + return new Dtmi($"dtmi:dtdl:class:Byte;{this.LanguageMajorVersion}"); + } + } + + /// + /// Gets the supplemantal properties of the DTDL element that corresponds to this object. + /// + /// A dictionary that maps each string-valued property name to an object that holds the value of the property with the given name. + /// + /// If the property is a literal in the DTDL model, the object holds a literal value. + /// If the property is another DTDL element in the model, the object is the C# object that corresponds to this element. + /// + public override IDictionary SupplementalProperties + { + get + { + return this.supplementalProperties; + } + } + + /// + /// Gets a collection of identifiers, each of which is a Dtmi that indicates a supplemental type that applies to the DTDL element that corresponds to this object. + /// + /// A collection of DTMIs indicating the supplemental types that apply to the DTDL element. + public override IReadOnlyCollection SupplementalTypes + { + get + { + return this.supplementalTypeIds; + } + } + + /// + /// Gets a value indicating whether this class is a partition point for the object model. + /// + internal override bool IsPartition { get; } + + /// + /// Gets material properties allowed by the type of DTDL element. + /// + internal override HashSet MaterialProperties + { + get + { + return PropertyNames; + } + } + + /// + /// Determines whether two DTByteInfo objects are not equal. + /// + /// One DTByteInfo object to compare. + /// Another DTByteInfo object to compare to the first. + /// True if not equal. + public static bool operator !=(DTByteInfo x, DTByteInfo y) + { + if (ReferenceEquals(null, x)) + { + return !ReferenceEquals(null, y); + } + + return !x.Equals(y); + } + + /// + /// Determines whether two DTByteInfo objects are equal. + /// + /// One DTByteInfo object to compare. + /// Another DTByteInfo object to compare to the first. + /// True if equal. + public static bool operator ==(DTByteInfo x, DTByteInfo y) + { + if (ReferenceEquals(null, x)) + { + return ReferenceEquals(null, y); + } + + return x.Equals(y); + } + + /// + /// Compares to another DTByteInfo object, recursing through the entire subtree of object properties. + /// + /// The other DTByteInfo object to compare to. + /// True if equal. + public virtual bool DeepEquals(DTByteInfo other) + { + return base.DeepEquals(other) + && Helpers.AreDictionariesDeepOrLiteralEqual(this.supplementalProperties, other.supplementalProperties) + && this.supplementalTypeIds.SetEquals(other.supplementalTypeIds) + ; + } + + /// + public override bool DeepEquals(DTNumericSchemaInfo other) + { + return this.EntityKind == other?.EntityKind && this.DeepEquals((DTByteInfo)other); + } + + /// + public override bool DeepEquals(DTPrimitiveSchemaInfo other) + { + return this.EntityKind == other?.EntityKind && this.DeepEquals((DTByteInfo)other); + } + + /// + public override bool DeepEquals(DTSchemaInfo other) + { + return this.EntityKind == other?.EntityKind && this.DeepEquals((DTByteInfo)other); + } + + /// + public override bool DeepEquals(DTEntityInfo other) + { + return this.EntityKind == other?.EntityKind && this.DeepEquals((DTByteInfo)other); + } + + /// + /// Compares to another DTByteInfo object. + /// + /// The other DTByteInfo object to compare to. + /// True if equal. + public virtual bool Equals(DTByteInfo other) + { + return base.Equals(other) + && Helpers.AreDictionariesIdOrLiteralEqual(this.supplementalProperties, other.supplementalProperties) + && this.supplementalTypeIds.SetEquals(other.supplementalTypeIds) + ; + } + + /// + public override bool Equals(DTNumericSchemaInfo other) + { + return this.EntityKind == other?.EntityKind && this.Equals((DTByteInfo)other); + } + + /// + public override bool Equals(DTPrimitiveSchemaInfo other) + { + return this.EntityKind == other?.EntityKind && this.Equals((DTByteInfo)other); + } + + /// + public override bool Equals(DTSchemaInfo other) + { + return this.EntityKind == other?.EntityKind && this.Equals((DTByteInfo)other); + } + + /// + public override bool Equals(DTEntityInfo other) + { + return this.EntityKind == other?.EntityKind && this.Equals((DTByteInfo)other); + } + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object otherObj) + { + return otherObj is DTByteInfo other && this.Equals(other); + } + + /// + bool ITypeChecker.DoesHaveType(Dtmi typeId) + { + return VersionlessTypes.Contains(typeId.Versionless) + || this.supplementalTypes.Any(ps => ((ITypeChecker)ps).DoesHaveType(typeId)) + ; + } + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() + { + int hashCode = base.GetHashCode(); + + unchecked + { + hashCode = (hashCode * 131) + Helpers.GetDictionaryIdOrLiteralHashCode(this.supplementalProperties); + hashCode = (hashCode * 131) + Helpers.GetSetLiteralHashCode(this.supplementalTypeIds); + } + + return hashCode; + } + + /// + /// Validate a JsonElement to determine whether it is a numeric value that conforms to the XSD definition of 'byte'. + /// + /// The JsonElement to validate. + /// A list of strings that each indicate a validation failure; the list is empty if the JsonElement conforms. + public override IReadOnlyCollection ValidateInstance(JsonElement instanceElt) + { + List violations = new List(); + this.ValidateInstance(instanceElt, null, violations); + return violations; + } + + /// + void IConstrainer.AddPropertyValueConstraint(string propertyName, ValueConstraint valueConstraint) + { + switch (propertyName) + { + case "comment": + if (this.commentValueConstraints == null) + { + this.commentValueConstraints = new List(); + } + + this.commentValueConstraints.Add(valueConstraint); + break; + case "description": + if (this.descriptionValueConstraints == null) + { + this.descriptionValueConstraints = new List(); + } + + this.descriptionValueConstraints.Add(valueConstraint); + break; + case "displayName": + if (this.displayNameValueConstraints == null) + { + this.displayNameValueConstraints = new List(); + } + + this.displayNameValueConstraints.Add(valueConstraint); + break; + } + } + + /// + void IConstrainer.AddSiblingConstraint(SiblingConstraint siblingConstraint) + { + if (this.SiblingConstraints == null) + { + this.SiblingConstraints = new List(); + } + + this.SiblingConstraints.Add(siblingConstraint); + } + + /// + /// Parse an element encoded in a into an object that is a subclass of type DTByteInfo. + /// + /// The model to add the element to. + /// A list of ParsedObjectPropertyInfo to add any object properties, which will be assigned after all parsing has completed. + /// List of ElementPropertyConstraint to be checked after object property assignment. + /// List of to be added to . + /// An AggregateContext object representing information retrieved from JSON-LD context blocks. + /// A ParsingErrorCollection to which any parsing errors are added. + /// The to parse. + /// Name of the layer currently being parsed. + /// The identifier of the parent of the element. + /// Identifier of the partition or top-level element under which this element is defined. + /// The name of the property by which the parent refers to this element, used for auto ID generation. + /// The representing the source of the property by which the parent refers to this element. + /// A DTMI segment identifier, used for auto ID generation. + /// A property used for the key if the parent exposes a collection of these elements as a dictionary. + /// A boolean value indicating whether an @id must be present. + /// A boolean value indicating whether a @type must be present. + /// Treat all nested definitions as though defined globally. + /// Allow elements to define IDs that have reserved prefixes. + /// Tolerate specific minor invalidities to support backward compatibility. + /// A set of allowed versions for the element. + /// The type name to infer if no @type specified on element. + /// True if the parses correctly as an appropriate element. + internal static new bool TryParseElement(Model model, List objectPropertyInfoList, List elementPropertyConstraints, List valueConstraints, AggregateContext aggregateContext, ParsingErrorCollection parsingErrorCollection, JsonLdElement elt, string layer, Dtmi parentId, Dtmi definedIn, string propName, JsonLdProperty propProp, string dtmiSeg, string keyProp, bool idRequired, bool typeRequired, bool globalize, bool allowReservedIds, bool tolerateSolecisms, HashSet allowedVersions, string inferredType) + { + AggregateContext childAggregateContext = aggregateContext.GetChildContext(elt, parsingErrorCollection); + + bool allowIdReferenceSyntax = tolerateSolecisms && aggregateContext.DtdlVersion < 3; + + if (elt.PropertyCount == 1 && elt.Id != null) + { + if (allowIdReferenceSyntax) + { + if (TryParseIdString(objectPropertyInfoList, elementPropertyConstraints, valueConstraints, childAggregateContext, parsingErrorCollection, elt.Id, layer, parentId, propName, propProp, keyProp, allowedVersions)) + { + return true; + } + else + { + parsingErrorCollection.Notify( + "idRefBadDtmiOrTerm", + elementId: parentId, + propertyName: propName, + propertyValue: elt.Id, + element: elt, + version: aggregateContext.DtdlVersion.ToString(), + layer: layer); + return false; + } + } + else + { + parsingErrorCollection.Notify( + "idReference", + elementId: parentId, + propertyName: propName, + identifier: elt.Id, + element: elt, + layer: layer); + return false; + } + } + + if (elt.Graph != null) + { + parsingErrorCollection.Notify( + "graphDisallowed", + elementId: parentId, + propertyName: propName, + element: elt); + } + + if (childAggregateContext.RestrictKeywords) + { + if (elt.Language != null) + { + parsingErrorCollection.Notify( + "keywordDisallowed", + elementId: parentId, + propertyName: propName, + keyword: "@language", + element: elt); + } + + if (elt.Value != null) + { + parsingErrorCollection.Notify( + "keywordDisallowed", + elementId: parentId, + propertyName: propName, + keyword: "@value", + element: elt); + } + + foreach (string keyword in elt.Keywords) + { + parsingErrorCollection.Notify( + "keywordDisallowed", + elementId: parentId, + propertyName: propName, + keyword: keyword, + element: elt); + } + } + + if (allowedVersions != null && !allowedVersions.Contains(childAggregateContext.DtdlVersion)) + { + parsingErrorCollection.Notify( + "disallowedVersionDefinition", + elementId: parentId, + propertyName: propName, + version: childAggregateContext.DtdlVersion.ToString(), + versionRestriction: string.Join(" ,", allowedVersions), + contextComponent: childAggregateContext.DtdlContextComponent, + layer: layer); + } + + bool tolerateReservedIds = tolerateSolecisms && aggregateContext.DtdlVersion < 3; + + Dtmi elementId = IdValidator.ParseIdProperty(childAggregateContext, elt, childAggregateContext.MergeDefinitions ? layer : null, parentId, propName, dtmiSeg, idRequired, allowReservedIds || tolerateReservedIds, parsingErrorCollection); + + Dtmi baseElementId = childAggregateContext.MergeDefinitions || elementId.Tail == string.Empty ? elementId.Fragmentless : elementId; + string elementLayer = childAggregateContext.MergeDefinitions ? elementId.Tail : string.Empty; + + bool ignoreElementsWithAutoIDsAndDuplicateNames = tolerateSolecisms && aggregateContext.DtdlVersion < 3; + + if (model.Dict.TryGetValue(baseElementId, out DTEntityInfo baseElement)) + { + if (baseElement.JsonLdElements.TryGetValue(elementLayer, out JsonLdElement duplicateElt)) + { + if (!baseElementId.IsReserved) + { + parsingErrorCollection.Notify( + "duplicateDefinition", + elementId: baseElementId, + element: elt, + extantElement: duplicateElt, + layer: layer); + } + else if (!ignoreElementsWithAutoIDsAndDuplicateNames && dtmiSeg != null) + { + JsonLdProperty dtmiSegProp = elt.Properties.First(p => p.Name == dtmiSeg || (Dtmi.TryCreateDtmi(p.Name, out Dtmi d) && ContextCollection.GetTermOrUri(d) == dtmiSeg)); + JsonLdProperty dupSegProp = duplicateElt.Properties.First(p => p.Name == dtmiSeg || (Dtmi.TryCreateDtmi(p.Name, out Dtmi d) && ContextCollection.GetTermOrUri(d) == dtmiSeg)); + parsingErrorCollection.Notify( + "nonUniquePropertyValue", + elementId: parentId, + propertyName: propName, + nestedName: dtmiSeg, + nestedValue: dtmiSegProp.Values.Values.First().StringValue, + incidentProperty: dupSegProp, + extantProperty: dtmiSegProp); + } + + return false; + } + + if (baseElement.DtdlVersion != childAggregateContext.DtdlVersion) + { + parsingErrorCollection.Notify( + "inconsistentContext", + elementId: baseElementId, + version: childAggregateContext.DtdlVersion.ToString(), + versionRestriction: baseElement.DtdlVersion.ToString(), + layer: elementLayer); + return false; + } + } + + if (typeRequired && elt.Types == null) + { + string sourceName1 = null; + int sourceLine1 = 0; + if (propProp != null && propProp.TryGetSourceLocation(out sourceName1, out sourceLine1) && elt.TryGetSourceLocation(out string sourceName2, out int startLine2, out int endLine2)) + { + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeLocatedCauseFormat[childAggregateContext.DtdlVersion], + BadTypeActionFormat[childAggregateContext.DtdlVersion], + primaryId: parentId, + property: propName, + secondaryId: baseElementId, + layer: layer, + sourceName1: sourceName1, + startLine1: sourceLine1, + sourceName2: sourceName2, + startLine2: startLine2, + endLine2: endLine2); + } + else + { + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeCauseFormat[childAggregateContext.DtdlVersion], + BadTypeActionFormat[childAggregateContext.DtdlVersion], + primaryId: parentId, + property: propName, + secondaryId: baseElementId, + layer: layer); + } + + return false; + } + + DTByteInfo elementInfo = (DTByteInfo)baseElement; + HashSet immediateSupplementalTypeIds; + List immediateUndefinedTypes; + bool typeArrayParsed; + if (elt.Types == null) + { + typeArrayParsed = TryParseTypeStrings(new List() { inferredType }, baseElementId, elementLayer, elt, parentId, definedIn, propName, propProp, ref elementInfo, childAggregateContext, out immediateSupplementalTypeIds, out immediateUndefinedTypes, parsingErrorCollection); + } + else + { + typeArrayParsed = TryParseTypeStrings(elt.Types, baseElementId, elementLayer, elt, parentId, definedIn, propName, propProp, ref elementInfo, childAggregateContext, out immediateSupplementalTypeIds, out immediateUndefinedTypes, parsingErrorCollection); + } + + if (!typeArrayParsed || ReferenceEquals(null, elementInfo)) + { + return false; + } + + switch (childAggregateContext.DtdlVersion) + { + case 4: + elementInfo.ParsePropertiesV4(model, objectPropertyInfoList, elementPropertyConstraints, childAggregateContext, immediateSupplementalTypeIds, immediateUndefinedTypes, parsingErrorCollection, elt, elementLayer, definedIn, globalize, allowReservedIds, tolerateSolecisms); + break; + } + + elementInfo.LimitSpecifier = aggregateContext.LimitSpecifier; + + elementInfo.RecordSourceAsAppropriate(elementLayer, elt, childAggregateContext, parsingErrorCollection, atRoot: parentId == null, globalized: globalize); + + model.Dict[baseElementId] = elementInfo; + + if (parentId != null) + { + objectPropertyInfoList.Add(new ParsedObjectPropertyInfo() { ElementId = parentId, PropertyName = propName, Layer = layer, JsonLdProperty = propProp, ReferencedElementId = baseElementId, KeyProperty = keyProp, ExpectedKinds = null, AllowedVersions = null, ChildOf = null, BadTypeCauseFormat = null, BadTypeLocatedCauseFormat = null, BadTypeActionFormat = null }); + + if (valueConstraints != null && elementPropertyConstraints != null) + { + foreach (ValueConstraint valueConstraint in valueConstraints) + { + elementPropertyConstraints.Add(new ElementPropertyConstraint() { ParentId = parentId, PropertyName = propName, ElementId = baseElementId, ValueConstraint = valueConstraint }); + } + } + } + + return true; + } + + /// + /// Parse a string property value as an identifier for type DTByteInfo. + /// + /// A list of ParsedObjectPropertyInfo to add any object properties, which will be assigned after all parsing has completed. + /// List of ElementPropertyConstraint to be checked after object property assignment. + /// List of to be added to . + /// An AggregateContext object representing information retrieved from JSON-LD context blocks. + /// A ParsingErrorCollection to which any parsing errors are added. + /// The identifier string to parse. + /// Name of the layer currently being parsed. + /// The identifier of the parent of the element. + /// The name of the property by which the parent refers to this element, used for auto ID generation. + /// The representing the source of the property by which the parent refers to this element. + /// A property used for the key if the parent exposes a collection of these elements as a dictionary. + /// A set of allowed versions for the element. + /// True if the string parses correctly as an identifier. + internal static new bool TryParseIdString(List objectPropertyInfoList, List elementPropertyConstraints, List valueConstraints, AggregateContext aggregateContext, ParsingErrorCollection parsingErrorCollection, string idString, string layer, Dtmi parentId, string propName, JsonLdProperty propProp, string keyProp, HashSet allowedVersions) + { + if (!aggregateContext.TryCreateDtmi(idString, out Dtmi elementId)) + { + return false; + } + + objectPropertyInfoList.Add(new ParsedObjectPropertyInfo() { ElementId = parentId, PropertyName = propName, Layer = layer, JsonLdProperty = propProp, ReferencedIdString = idString, ReferencedElementId = elementId, KeyProperty = keyProp, ExpectedKinds = ConcreteKinds[aggregateContext.DtdlVersion], AllowedVersions = allowedVersions, ChildOf = null, BadTypeCauseFormat = BadTypeCauseFormat[aggregateContext.DtdlVersion], BadTypeLocatedCauseFormat = BadTypeLocatedCauseFormat[aggregateContext.DtdlVersion], BadTypeActionFormat = BadTypeActionFormat[aggregateContext.DtdlVersion] }); + + if (valueConstraints != null && elementPropertyConstraints != null) + { + foreach (ValueConstraint valueConstraint in valueConstraints) + { + elementPropertyConstraints.Add(new ElementPropertyConstraint() { ParentId = parentId, PropertyName = propName, ElementId = elementId, ValueConstraint = valueConstraint }); + } + } + + return true; + } + + /// + /// Parse a list of @type values containing material or supplemental types. + /// + /// The list of strings to parse. + /// The identifier of the element of this type to create. + /// Name of the layer currently being parsed. + /// The currently being parsed. + /// The identifier of the parent of the element. + /// Identifier of the partition or top-level element under which this element is defined. + /// The name of the property by which the parent refers to this element, used for auto ID generation. + /// The representing the source of the property by which the parent refers to this element. + /// The created. + /// An AggregateContext object representing information retrieved from JSON-LD context blocks. + /// A set of supplemental type IDs from the type array. + /// A list of undefind type strings from the type array. + /// A ParsingErrorCollection to which any parsing errors are added. + /// True if no errors detected in type array. + internal static bool TryParseTypeStrings(List typeStrings, Dtmi elementId, string layer, JsonLdElement elt, Dtmi parentId, Dtmi definedIn, string propName, JsonLdProperty propProp, ref DTByteInfo elementInfo, AggregateContext aggregateContext, out HashSet immediateSupplementalTypeIds, out List immediateUndefinedTypes, ParsingErrorCollection parsingErrorCollection) + { + immediateSupplementalTypeIds = new HashSet(); + immediateUndefinedTypes = new List(); + + HashSet materialKinds = new HashSet(); + + bool anyFailures = false; + foreach (string typeString in typeStrings) + { + switch (aggregateContext.DtdlVersion) + { + case 4: + if (!TryParseTypeStringV4(typeString, elementId, layer, elt, parentId, definedIn, propName, propProp, materialKinds, immediateSupplementalTypeIds, ref elementInfo, ref immediateUndefinedTypes, aggregateContext, parsingErrorCollection)) + { + anyFailures = true; + } + + break; + } + } + + if (anyFailures) + { + return false; + } + + if (ReferenceEquals(null, elementInfo)) + { + string sourceName1 = null; + int sourceLine1 = 0; + if (propProp != null && propProp.TryGetSourceLocation(out sourceName1, out sourceLine1) && elt.TryGetSourceLocation(out string sourceName2, out int startLine2, out int endLine2)) + { + elt.TryGetSourceLocationForType(out _, out int sourceLine3); + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeLocatedCauseFormat[aggregateContext.DtdlVersion], + BadTypeActionFormat[aggregateContext.DtdlVersion], + primaryId: parentId, + property: propName, + secondaryId: elementId, + layer: layer, + sourceName1: sourceName1, + startLine1: sourceLine1, + sourceName2: sourceName2, + startLine2: startLine2, + endLine2: endLine2, + startLine3: sourceLine3); + } + else + { + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeCauseFormat[aggregateContext.DtdlVersion], + BadTypeActionFormat[aggregateContext.DtdlVersion], + primaryId: parentId, + property: propName, + secondaryId: elementId, + layer: layer); + } + + return false; + } + + if (!materialKinds.Any()) + { + parsingErrorCollection.Notify( + "layerMissingMaterialType", + elementId: elementId, + elementType: elementInfo.EntityKind.ToString(), + element: elt, + layer: layer); + return false; + } + + materialKinds.Add(elementInfo.EntityKind); + if (materialKinds.Count() > 1) + { + parsingErrorCollection.Notify( + "multipleMaterialTypes", + elementId: elementId, + valueConjunction: string.Join(" and ", materialKinds), + element: elt, + layer: layer); + return false; + } + + elementInfo.UndefinedTypeStrings.UnionWith(immediateUndefinedTypes); + + bool requiresMergeability = layer != string.Empty && !elementId.IsReserved; + bool isMergeable = false; + foreach (Dtmi supplementalTypeId in immediateSupplementalTypeIds) + { + if (aggregateContext.SupplementalTypeCollection.TryGetSupplementalTypeInfo(supplementalTypeId, out DTSupplementalTypeInfo supplementalTypeInfo)) + { + if (!supplementalTypeInfo.AllowedCotypeKinds.Contains(elementInfo.EntityKind)) + { + parsingErrorCollection.Notify( + "invalidCotype", + elementId: elementId, + cotype: ContextCollection.GetTermOrUri(supplementalTypeId), + typeRestriction: string.Join(" or ", supplementalTypeInfo.AllowedCotypeKinds), + element: elt, + layer: layer); + } + else if (!supplementalTypeInfo.AllowedCotypeVersions.Contains(elementInfo.DtdlVersion)) + { + parsingErrorCollection.Notify( + "invalidCotypeVersion", + elementId: elementId, + cotype: ContextCollection.GetTermOrUri(supplementalTypeId), + versionRestriction: string.Join(" or ", supplementalTypeInfo.AllowedCotypeVersions), + element: elt, + layer: layer); + } + else + { + elementInfo.AddType(supplementalTypeId, supplementalTypeInfo, parsingErrorCollection); + foreach (Dtmi requiredCocotype in supplementalTypeInfo.RequiredCocotypes) + { + if (!immediateSupplementalTypeIds.Contains(requiredCocotype)) + { + string requiredCocotypeTerm = ContextCollection.GetTermOrUri(requiredCocotype); + parsingErrorCollection.Notify( + "missingCocotype", + elementId: elementId, + elementType: ContextCollection.GetTermOrUri(supplementalTypeId), + cotype: requiredCocotypeTerm, + element: elt); + } + } + } + + isMergeable = isMergeable || supplementalTypeInfo.IsMergeable; + } + } + + if (requiresMergeability && !isMergeable) + { + parsingErrorCollection.Notify( + "disallowedIdFragment", + elementId: elementId, + element: elt, + layer: layer); + } + + return true; + } + + /// + /// Parse a string @type value, whether material or supplemental. + /// + /// The string value to parse. + /// The identifier of the element of this type to create. + /// Name of the layer currently being parsed. + /// The currently being parsed. + /// The identifier of the parent of the element. + /// Identifier of the partition or top-level element under which this element is defined. + /// The name of the property by which the parent refers to this element. + /// The representing the source of the property by which the parent refers to this element. + /// A set of material kinds to update with the material kind of the type, if any. + /// A set of supplemental type IDs to update with the supplemental type, if any. + /// The element created if the type is material. + /// A list of string values of any undefined supplemental types. + /// An AggregateContext object representing information retrieved from JSON-LD context blocks. + /// A ParsingErrorCollection to which any parsing errors are added. + /// True if the parse is sucessful. + internal static bool TryParseTypeStringV4(string typeString, Dtmi elementId, string layer, JsonLdElement elt, Dtmi parentId, Dtmi definedIn, string propName, JsonLdProperty propProp, HashSet materialKinds, HashSet supplementalTypeIds, ref DTByteInfo elementInfo, ref List undefinedTypes, AggregateContext aggregateContext, ParsingErrorCollection parsingErrorCollection) + { + if (MaterialTypeNameCollection.IsMaterialType(typeString)) + { + string sourceName1 = null; + int sourceLine1 = 0; + if (propProp != null && propProp.TryGetSourceLocation(out sourceName1, out sourceLine1) && elt.TryGetSourceLocation(out string sourceName2, out int startLine2, out int endLine2)) + { + elt.TryGetSourceLocationForType(out _, out int sourceLine3); + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeLocatedCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer, + sourceName1: sourceName1, + startLine1: sourceLine1, + sourceName2: sourceName2, + startLine2: startLine2, + endLine2: endLine2, + startLine3: sourceLine3); + } + else + { + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer); + } + + return false; + } + + if (!aggregateContext.TryCreateDtmi(typeString, out Dtmi supplementalTypeId)) + { + if (typeString.StartsWith("dtmi:")) + { + parsingErrorCollection.Notify( + "typeInvalidDtmi", + elementId: elementId, + cotype: typeString, + element: elt, + layer: layer); + return false; + } + else if (typeString.Contains(":")) + { + parsingErrorCollection.Notify( + "typeNotDtmiNorTerm", + elementId: elementId, + cotype: typeString, + element: elt, + layer: layer); + return false; + } + else + { + if (aggregateContext.IsComplete) + { + parsingErrorCollection.Notify( + "typeUndefinedTerm", + elementId: elementId, + cotype: typeString, + element: elt, + version: aggregateContext.DtdlVersion.ToString(), + layer: layer); + return false; + } + } + + undefinedTypes.Add(typeString); + return true; + } + + if (!aggregateContext.SupplementalTypeCollection.TryGetSupplementalTypeInfo(supplementalTypeId, out DTSupplementalTypeInfo supplementalTypeInfo)) + { + if (aggregateContext.IsComplete) + { + parsingErrorCollection.Notify( + "typeIrrelevantDtmiOrTerm", + elementId: elementId, + cotype: typeString, + element: elt, + version: aggregateContext.DtdlVersion.ToString(), + layer: layer); + return false; + } + + undefinedTypes.Add(typeString); + return true; + } + + if (supplementalTypeInfo.IsAbstract) + { + parsingErrorCollection.Notify( + "abstractSupplementalType", + elementId: elementId, + cotype: ContextCollection.GetTermOrUri(supplementalTypeId), + element: elt, + layer: layer); + return false; + } + + switch (supplementalTypeInfo.ExtensionKind) + { + case DTExtensionKind.LatentType: + { + string sourceName1 = null; + int sourceLine1 = 0; + if (propProp != null && propProp.TryGetSourceLocation(out sourceName1, out sourceLine1) && elt.TryGetSourceLocation(out string sourceName2, out int startLine2, out int endLine2)) + { + elt.TryGetSourceLocationForType(out _, out int sourceLine3); + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeLocatedCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer, + sourceName1: sourceName1, + startLine1: sourceLine1, + sourceName2: sourceName2, + startLine2: startLine2, + endLine2: endLine2, + startLine3: sourceLine3); + } + else + { + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer); + } + } + + return false; + case DTExtensionKind.NamedLatentType: + { + string sourceName1 = null; + int sourceLine1 = 0; + if (propProp != null && propProp.TryGetSourceLocation(out sourceName1, out sourceLine1) && elt.TryGetSourceLocation(out string sourceName2, out int startLine2, out int endLine2)) + { + elt.TryGetSourceLocationForType(out _, out int sourceLine3); + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeLocatedCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer, + sourceName1: sourceName1, + startLine1: sourceLine1, + sourceName2: sourceName2, + startLine2: startLine2, + endLine2: endLine2, + startLine3: sourceLine3); + } + else + { + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer); + } + } + + return false; + case DTExtensionKind.Unit: + { + string sourceName1 = null; + int sourceLine1 = 0; + if (propProp != null && propProp.TryGetSourceLocation(out sourceName1, out sourceLine1) && elt.TryGetSourceLocation(out string sourceName2, out int startLine2, out int endLine2)) + { + elt.TryGetSourceLocationForType(out _, out int sourceLine3); + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeLocatedCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer, + sourceName1: sourceName1, + startLine1: sourceLine1, + sourceName2: sourceName2, + startLine2: startLine2, + endLine2: endLine2, + startLine3: sourceLine3); + } + else + { + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer); + } + } + + return false; + case DTExtensionKind.UnitAttribute: + { + string sourceName1 = null; + int sourceLine1 = 0; + if (propProp != null && propProp.TryGetSourceLocation(out sourceName1, out sourceLine1) && elt.TryGetSourceLocation(out string sourceName2, out int startLine2, out int endLine2)) + { + elt.TryGetSourceLocationForType(out _, out int sourceLine3); + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeLocatedCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer, + sourceName1: sourceName1, + startLine1: sourceLine1, + sourceName2: sourceName2, + startLine2: startLine2, + endLine2: endLine2, + startLine3: sourceLine3); + } + else + { + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer); + } + } + + return false; + } + + supplementalTypeIds.Add(supplementalTypeId); + + return true; + } + + /// + /// Parse elements encoded in a into objects of subclasses of type DTByteInfo. + /// + /// The model to add the element to. + /// A list of ParsedObjectPropertyInfo to add any object properties, which will be assigned after all parsing has completed. + /// List of ElementPropertyConstraint to be checked after object property assignment. + /// List of to be added to . + /// An AggregateContext object representing information retrieved from JSON-LD context blocks. + /// A ParsingErrorCollection to which any parsing errors are added. + /// The holding the to parse. + /// Name of the layer currently being parsed. + /// The identifier of the parent of the element. + /// Identifier of the partition or top-level element under which this element is defined. + /// The name of the property by which the parent refers to this element, used for auto ID generation. + /// A DTMI segment identifier, used for auto ID generation. + /// A property used for the key if the parent exposes a collection of these elements as a dictionary. + /// The minimum count of element values required. + /// A boolean value indicating whether the property allows multiple values. + /// A boolean value indicating whether an @id must be present. + /// A boolean value indicating whether a @type must be present. + /// Treat all nested definitions as though defined globally. + /// Allow elements to define IDs that have reserved prefixes. + /// Tolerate specific minor invalidities to support backward compatibility. + /// A set of allowed versions for the element. + internal static new void ParseValueCollection(Model model, List objectPropertyInfoList, List elementPropertyConstraints, List valueConstraints, AggregateContext aggregateContext, ParsingErrorCollection parsingErrorCollection, JsonLdProperty valueCollectionProp, string layer, Dtmi parentId, Dtmi definedIn, string propName, string dtmiSeg, string keyProp, int minCount, bool isPlural, bool idRequired, bool typeRequired, bool globalize, bool allowReservedIds, bool tolerateSolecisms, HashSet allowedVersions) + { + int valueCount = 0; + + foreach (JsonLdValue value in valueCollectionProp.Values.Values) + { + if (!isPlural && valueCount > 0) + { + parsingErrorCollection.Notify( + "objectMultipleValues", + elementId: parentId, + propertyName: propName, + incidentValues: valueCollectionProp.Values, + layer: layer); + return; + } + + switch (value.ValueType) + { + case JsonLdValueType.String: + if (parentId != null) + { + if (TryParseIdString(objectPropertyInfoList, elementPropertyConstraints, valueConstraints, aggregateContext, parsingErrorCollection, value.StringValue, layer, parentId, propName, valueCollectionProp, keyProp, allowedVersions)) + { + ++valueCount; + } + else + { + parsingErrorCollection.Notify( + "badDtmiOrTerm", + elementId: parentId, + propertyName: propName, + propertyValue: value.StringValue, + incidentProperty: valueCollectionProp, + incidentValue: value, + version: aggregateContext.DtdlVersion.ToString(), + layer: layer); + } + } + + break; + case JsonLdValueType.Element: + if (TryParseElement(model, objectPropertyInfoList, elementPropertyConstraints, valueConstraints, aggregateContext, parsingErrorCollection, value.ElementValue, layer, parentId, definedIn, propName, valueCollectionProp, dtmiSeg, keyProp, idRequired, typeRequired, globalize, allowReservedIds, tolerateSolecisms, allowedVersions, "Byte")) + { + ++valueCount; + } + + break; + default: + parsingErrorCollection.Notify( + "refNotStringOrObject", + elementId: parentId, + propertyName: propName, + incidentProperty: valueCollectionProp, + incidentValue: value, + layer: layer); + break; + } + } + + if (valueCount < minCount) + { + parsingErrorCollection.Notify( + "objectCountBelowMin", + elementId: parentId, + propertyName: propName, + observedCount: valueCount, + expectedCount: minCount, + incidentProperty: valueCollectionProp, + layer: layer); + } + } + + /// + internal override bool CheckDepthOfElementSchemaOrSchema(int depth, int depthLimit, bool allowSelf, List tooDeepElementIds, out Dictionary tooDeepElts, ParsingErrorCollection parsingErrorCollection) + { + tooDeepElts = null; + return true; + } + + /// + /// Determine whether a JsonElement matches this DTDL element. + /// + /// The JsonElement to match. + /// If the instance is a property in a JSON object, the name corresponding to ; otherwise, null. + /// True if the JsonElement matches; false otherwise. + internal override bool DoesInstanceMatch(JsonElement instanceElt, string instanceName) + { + switch (this.DtdlVersion) + { + case 4: + return this.DoesInstanceMatchV4(instanceElt, instanceName); + } + + return false; + } + + /// + /// Indicate whether the property with a given is a dictionary that holds a given . + /// + /// The name of the property to check. + /// The key for the dictionary property. + /// True if the property is present, is a dictionary, and holds the given key. + internal override bool DoesPropertyDictContainKey(string propertyName, string key) + { + if (base.DoesPropertyDictContainKey(propertyName, key)) + { + return true; + } + + switch (propertyName) + { + default: + return false; + } + } + + /// + internal override bool TryGetChild(string childrenPropertyName, string keyPropertyName, string keyPropertyValue, out DTEntityInfo child) + { + switch (childrenPropertyName) + { + default: + break; + } + + child = null; + return false; + } + + /// + internal override bool TryGetDescendantSchemaArray(out Dtmi elementId, out Dictionary excludedElts) + { + if (this.checkedForDescendantSchemaArray) + { + elementId = this.idOfDescendantSchemaArray; + excludedElts = this.eltsOfDescendantSchemaArray; + return this.idOfDescendantSchemaArray != null; + } + + this.checkedForDescendantSchemaArray = true; + + elementId = null; + excludedElts = null; + return false; + } + + /// + internal override bool TryGetDescendantSchemaOrContentsComponentNarrow(out Dtmi elementId, out Dictionary excludedElts) + { + if (this.checkedForDescendantSchemaOrContentsComponentNarrow) + { + elementId = this.idOfDescendantSchemaOrContentsComponentNarrow; + excludedElts = this.eltsOfDescendantSchemaOrContentsComponentNarrow; + return this.idOfDescendantSchemaOrContentsComponentNarrow != null; + } + + this.checkedForDescendantSchemaOrContentsComponentNarrow = true; + + elementId = null; + excludedElts = null; + return false; + } + + /// + /// Try to set an object property with a given . + /// + /// The name of the property whose element value to set if the property is recognized. + /// The key property for dictionary properties. + /// The representing the source of the property by which the parent refers to this element. + /// The reference element to set. + /// The key property for dictionary properties. + /// The key value for dictionary properties. + /// A ParsingErrorCollection to which any parsing errors are added. + /// True if the property name is recognized. + internal override bool TrySetObjectProperty(string propertyName, string layer, JsonLdProperty propProp, DTEntityInfo element, string keyProp, string keyValue, ParsingErrorCollection parsingErrorCollection) + { + if (base.TrySetObjectProperty(propertyName, layer, propProp, element, keyProp, keyValue, parsingErrorCollection)) + { + return true; + } + + switch (propertyName) + { + default: + break; + } + + foreach (DTSupplementalTypeInfo supplementalType in this.supplementalTypes) + { + if (supplementalType.TrySetObjectProperty(this.Id, propertyName, element, keyValue, layer, propProp, ref this.supplementalProperties, this.supplementalSingularPropertyLayers, this.JsonLdElements, parsingErrorCollection)) + { + return true; + } + } + + return false; + } + + /// + /// Validate a JsonElement to determine whether it is a numeric value that conforms to the XSD definition of 'byte'. + /// + /// The JsonElement to validate. + /// If the instance is a property in a JSON object, the name corresponding to ; otherwise, null. + /// A list of strings to which to add any validation failures. + internal override bool ValidateInstance(JsonElement instanceElt, string instanceName, List violations) + { + switch (this.DtdlVersion) + { + case 4: + return this.ValidateInstanceV4(instanceElt, instanceName, violations); + } + + return true; + } + + /// + internal override HashSet GetTransitiveExtendsNarrow(int depth, int depthLimit, bool allowSelf, List tooDeepElementIds, out Dictionary tooDeepElts, ParsingErrorCollection parsingErrorCollection) + { + HashSet closure = new HashSet(); + + tooDeepElts = null; + return closure; + } + + /// + internal override IEnumerable GetChildren(string childrenPropertyName) + { + switch (childrenPropertyName) + { + default: + return new List(); + } + } + + /// + internal override int GetCountOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrow(bool allowSelf, ParsingErrorCollection parsingErrorCollection) + { + if (this.countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowStatus == TraversalStatus.Complete) + { + return this.countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowValue; + } + + if (this.countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowStatus == TraversalStatus.InProgress) + { + if (allowSelf) + { + this.countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowStatus = TraversalStatus.Complete; + } + else + { + parsingErrorCollection.Notify( + "recursiveStructureNarrow", + elementId: this.Id, + propertyDisjunction: "'contents' or 'fields' or 'enumValues' or 'request' or 'response' or 'properties' or 'schema' or 'elementSchema' or 'mapValue'", + element: this.JsonLdElements.First().Value); + } + + return 0; + } + + this.countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowStatus = TraversalStatus.InProgress; + this.countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowStatus = TraversalStatus.Complete; + return this.countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowValue; + } + + /// + internal override int GetCountOfExtendsNarrow(bool allowSelf, ParsingErrorCollection parsingErrorCollection) + { + if (this.countOfExtendsNarrowStatus == TraversalStatus.Complete) + { + return this.countOfExtendsNarrowValue; + } + + if (this.countOfExtendsNarrowStatus == TraversalStatus.InProgress) + { + if (allowSelf) + { + this.countOfExtendsNarrowStatus = TraversalStatus.Complete; + } + else + { + parsingErrorCollection.Notify( + "recursiveStructureNarrow", + elementId: this.Id, + propertyDisjunction: "'extends'", + element: this.JsonLdElements.First().Value); + } + + return 0; + } + + this.countOfExtendsNarrowStatus = TraversalStatus.InProgress; + this.countOfExtendsNarrowStatus = TraversalStatus.Complete; + return this.countOfExtendsNarrowValue; + } + + /// + /// Add a supplemental type. + /// + /// Identifier for the supplemental type to add. + /// DTSupplementalTypeInfo for the supplemental type. + /// A ParsingErrorCollection to which any parsing errors are added. + internal override void AddType(Dtmi id, DTSupplementalTypeInfo supplementalType, ParsingErrorCollection parsingErrorCollection) + { + if (this.supplementalTypeIds.Add(id)) + { + this.supplementalTypes.Add(supplementalType); + } + } + + /// + internal override void ApplyTransformations(Model model, ParsingErrorCollection parsingErrorCollection) + { + switch (this.DtdlVersion) + { + case 4: + this.ApplyTransformationsV4(model, parsingErrorCollection); + break; + } + } + + /// + internal override void CheckDescendantEnumValueDatatype(Dtmi ancestorId, Dictionary ancestorElts, Type datatype, ParsingErrorCollection parsingErrorCollection) + { + if (this.checkedDescendantEnumValueDatatype != datatype) + { + this.checkedDescendantEnumValueDatatype = datatype; + } + } + + /// + internal override void CheckRestrictions(ParsingErrorCollection parsingErrorCollection) + { + this.CheckForDisallowedCocotypes(this.supplementalTypeIds, this.supplementalTypes, parsingErrorCollection); + + foreach (DTSupplementalTypeInfo supplementalType in this.supplementalTypes) + { + supplementalType.CheckRestrictions(this.supplementalProperties, parsingErrorCollection, this.Id, this.JsonLdElements); + } + + switch (this.DtdlVersion) + { + case 4: + this.CheckRestrictionsV4(parsingErrorCollection); + break; + } + } + + /// + /// Parse the properties in a JSON Byte object. + /// + /// Model to which to add object properties. + /// List of object info structs for deferred assignments. + /// List of ElementPropertyConstraint to be checked after object property assignment. + /// An AggregateContext object representing information retrieved from JSON-LD context blocks. + /// A set of supplemental type IDs. + /// A list of undefind type strings. + /// A ParsingErrorCollection to which any parsing errors are added. + /// The to parse. + /// Name of the layer currently being parsed. + /// Identifier of the partition or top-level element under which this element is defined. + /// Treat all nested definitions as though defined globally. + /// Allow elements to define IDs that have reserved prefixes. + /// Tolerate specific minor invalidities to support backward compatibility. + internal override void ParsePropertiesV4(Model model, List objectPropertyInfoList, List elementPropertyConstraints, AggregateContext aggregateContext, HashSet immediateSupplementalTypeIds, List immediateUndefinedTypes, ParsingErrorCollection parsingErrorCollection, JsonLdElement elt, string layer, Dtmi definedIn, bool globalize, bool allowReservedIds, bool tolerateSolecisms) + { + this.LanguageMajorVersion = 4; + + JsonLdProperty commentProperty = null; + JsonLdProperty descriptionProperty = null; + JsonLdProperty displayNameProperty = null; + Dictionary supplementalJsonLdProperties = new Dictionary(); + + foreach (JsonLdProperty prop in elt.Properties) + { + switch (prop.Name) + { + case "comment": + case "dtmi:dtdl:property:comment;4": + if (commentProperty != null) + { + parsingErrorCollection.Notify( + "duplicatePropertyName", + elementId: this.Id, + propertyName: "comment", + incidentProperty: prop, + extantProperty: commentProperty, + layer: layer); + } + else + { + commentProperty = prop; + int? maxLength = aggregateContext.LimitSpecifier switch + { + "" => 512, + "onvif_1" => 515, + _ => null, + }; + + string newComment = ValueParser.ParseSingularStringValueCollection(aggregateContext, this.Id, "comment", prop.Values, maxLength, null, layer, parsingErrorCollection, isOptional: true); + if (this.commentPropertyLayer != null) + { + if (this.Comment != newComment) + { + JsonLdProperty extantProp = this.JsonLdElements[this.commentPropertyLayer].Properties.FirstOrDefault(p => p.Name == "comment"); + parsingErrorCollection.Notify( + "inconsistentStringValues", + elementId: this.Id, + propertyName: "comment", + propertyValue: newComment.ToString(), + valueRestriction: this.Comment.ToString(), + incidentProperty: prop, + extantProperty: extantProp, + layer: layer); + } + } + else + { + this.Comment = newComment; + this.commentPropertyLayer = layer; + + if (this.commentValueConstraints != null) + { + foreach (ValueConstraint valueConstraint in this.commentValueConstraints) + { + if (valueConstraint.RequiredLiteral != null && !valueConstraint.RequiredLiteral.Equals(newComment)) + { + parsingErrorCollection.Notify( + "notRequiredStringValue", + elementId: this.Id, + propertyName: "comment", + propertyValue: newComment.ToString(), + valueRestriction: valueConstraint.RequiredLiteral.ToString(), + incidentProperty: prop, + layer: layer); + } + } + } + + ((Dictionary)this.StringProperties)["comment"] = newComment; + } + } + + continue; + case "description": + case "dtmi:dtdl:property:description;4": + if (descriptionProperty != null) + { + parsingErrorCollection.Notify( + "duplicatePropertyName", + elementId: this.Id, + propertyName: "description", + incidentProperty: prop, + extantProperty: descriptionProperty, + layer: layer); + } + else + { + descriptionProperty = prop; + int? maxLength = aggregateContext.LimitSpecifier switch + { + "" => 512, + "onvif_1" => 514, + _ => null, + }; + + Dictionary newDescription = ValueParser.ParseLangStringValueCollection(aggregateContext, this.Id, "description", prop.Values, "en", maxLength, null, layer, parsingErrorCollection); + List descriptionCodes = Helpers.GetKeysWithDifferingLiteralValues(this.Description, newDescription); + if (descriptionCodes.Any()) + { + JsonLdProperty extantProp = Helpers.TryGetSingleUniqueValue(descriptionCodes.Select(c => this.descriptionPropertyLayer[c]), out string uniqueCodeLayer) && this.JsonLdElements[uniqueCodeLayer].Properties.Any(p => p.Name == "description") ? this.JsonLdElements[uniqueCodeLayer].Properties.First(p => p.Name == "description") : null; + parsingErrorCollection.Notify( + "inconsistentLangStringValues", + elementId: this.Id, + propertyName: "description", + langCode: string.Join(" and ", descriptionCodes.Select(c => $"'{c}'")), + observedCount: descriptionCodes.Count, + incidentProperty: prop, + extantProperty: extantProp, + layer: layer); + } + else if (this.Description.Any()) + { + foreach (KeyValuePair kvp in newDescription) + { + ((Dictionary)this.Description)[kvp.Key] = kvp.Value; + this.descriptionPropertyLayer[kvp.Key] = layer; + } + } + else + { + this.Description = newDescription; + this.descriptionPropertyLayer = newDescription.ToDictionary(e => e.Key, e => layer); + } + } + + continue; + case "displayName": + case "dtmi:dtdl:property:displayName;4": + if (displayNameProperty != null) + { + parsingErrorCollection.Notify( + "duplicatePropertyName", + elementId: this.Id, + propertyName: "displayName", + incidentProperty: prop, + extantProperty: displayNameProperty, + layer: layer); + } + else + { + displayNameProperty = prop; + int? maxLength = aggregateContext.LimitSpecifier switch + { + "" => 512, + "onvif_1" => 513, + _ => null, + }; + + Dictionary newDisplayName = ValueParser.ParseLangStringValueCollection(aggregateContext, this.Id, "displayName", prop.Values, "en", maxLength, null, layer, parsingErrorCollection); + List displayNameCodes = Helpers.GetKeysWithDifferingLiteralValues(this.DisplayName, newDisplayName); + if (displayNameCodes.Any()) + { + JsonLdProperty extantProp = Helpers.TryGetSingleUniqueValue(displayNameCodes.Select(c => this.displayNamePropertyLayer[c]), out string uniqueCodeLayer) && this.JsonLdElements[uniqueCodeLayer].Properties.Any(p => p.Name == "displayName") ? this.JsonLdElements[uniqueCodeLayer].Properties.First(p => p.Name == "displayName") : null; + parsingErrorCollection.Notify( + "inconsistentLangStringValues", + elementId: this.Id, + propertyName: "displayName", + langCode: string.Join(" and ", displayNameCodes.Select(c => $"'{c}'")), + observedCount: displayNameCodes.Count, + incidentProperty: prop, + extantProperty: extantProp, + layer: layer); + } + else if (this.DisplayName.Any()) + { + foreach (KeyValuePair kvp in newDisplayName) + { + ((Dictionary)this.DisplayName)[kvp.Key] = kvp.Value; + this.displayNamePropertyLayer[kvp.Key] = layer; + } + } + else + { + this.DisplayName = newDisplayName; + this.displayNamePropertyLayer = newDisplayName.ToDictionary(e => e.Key, e => layer); + } + } + + continue; + } + + if (this.TryParseSupplementalProperty(model, immediateSupplementalTypeIds, objectPropertyInfoList, elementPropertyConstraints, aggregateContext, layer, definedIn, parsingErrorCollection, prop.Name, globalize, allowReservedIds, tolerateSolecisms, prop, supplementalJsonLdProperties)) + { + continue; + } + + if (aggregateContext.TryCreateDtmi(prop.Name, out Dtmi _)) + { + if (aggregateContext.IsComplete) + { + parsingErrorCollection.Notify( + "propertyIrrelevantDtmiOrTerm", + elementId: this.Id, + propertyName: prop.Name, + incidentProperty: prop, + element: elt, + layer: layer); + continue; + } + } + else if (prop.Name.StartsWith("dtmi:")) + { + parsingErrorCollection.Notify( + "propertyInvalidDtmi", + elementId: this.Id, + propertyName: prop.Name, + incidentProperty: prop, + element: elt, + layer: layer); + continue; + } + else if (prop.Name.Contains(":")) + { + parsingErrorCollection.Notify( + "propertyNotDtmiNorTerm", + elementId: this.Id, + propertyName: prop.Name, + incidentProperty: prop, + element: elt, + layer: layer); + continue; + } + else + { + if (aggregateContext.IsComplete) + { + parsingErrorCollection.Notify( + "propertyUndefinedTerm", + elementId: this.Id, + propertyName: prop.Name, + incidentProperty: prop, + element: elt, + version: aggregateContext.DtdlVersion.ToString(), + layer: layer); + continue; + } + } + + if (!immediateUndefinedTypes.Any()) + { + if (elt.Types != null) + { + parsingErrorCollection.Notify( + "noTypeThatAllows", + elementId: this.Id, + propertyName: prop.Name, + incidentProperty: prop, + element: elt, + layer: layer); + } + else + { + parsingErrorCollection.Notify( + "inferredTypeDoesNotAllow", + elementId: this.Id, + referenceType: "Byte", + propertyName: prop.Name, + incidentProperty: prop, + element: elt, + layer: layer); + } + + continue; + } + + using (JsonDocument propDoc = JsonDocument.Parse(prop.Values.GetJsonText())) + { + this.UndefinedPropertyDictionary[prop.Name] = propDoc.RootElement.Clone(); + } + } + + foreach (Dtmi supplementalTypeId in immediateSupplementalTypeIds) + { + if (aggregateContext.SupplementalTypeCollection.TryGetSupplementalTypeInfo(supplementalTypeId, out DTSupplementalTypeInfo supplementalTypeInfo)) + { + supplementalTypeInfo.CheckForRequiredProperties(parsingErrorCollection, this.Id, elt, supplementalJsonLdProperties); + } + } + } + + /// + /// Record JSON-LD source as appropriate and check length of text against limit. + /// + /// The name of the layer whose source to record. + /// A JsonLdElement containing the JSON-LD source of the element. + /// An AggregateContext object representing information retrieved from JSON-LD context blocks. + /// A ParsingErrorCollection to which any parsing errors are added. + /// True if the element is at the document root. + /// True if the element has been globalized. + internal override void RecordSourceAsAppropriate(string layer, JsonLdElement elt, AggregateContext aggregateContext, ParsingErrorCollection parsingErrorCollection, bool atRoot, bool globalized) + { + } + + /// + /// Write a JSON representation of the DTDL element represented by an object of this class. + /// + /// A Utf8JsonWriter object with which to write the JSON representation. + /// True if the mothed should add a ClassId property to the JSON object. + internal override void WriteToJson(Utf8JsonWriter jsonWriter, bool includeClassId) + { + base.WriteToJson(jsonWriter, includeClassId: false); + + if (includeClassId) + { + jsonWriter.WriteString("ClassId", $"dtmi:dtdl:class:Byte;{this.LanguageMajorVersion}"); + } + } + + private bool DoesInstanceMatchV4(JsonElement instanceElt, string instanceName) + { + return true; + } + + private bool TryParseSupplementalProperty(Model model, HashSet immediateSupplementalTypeIds, List objectPropertyInfoList, List elementPropertyConstraints, AggregateContext aggregateContext, string layer, Dtmi definedIn, ParsingErrorCollection parsingErrorCollection, string propName, bool globalize, bool allowReservedIds, bool tolerateSolecisms, JsonLdProperty valueCollectionProp, Dictionary supplementalJsonLdProperties) + { + if (!aggregateContext.TryCreateDtmi(propName, out Dtmi propDtmi)) + { + return false; + } + + foreach (Dtmi supplementalTypeId in immediateSupplementalTypeIds) + { + if (aggregateContext.SupplementalTypeCollection.TryGetSupplementalTypeInfo(supplementalTypeId, out DTSupplementalTypeInfo supplementalTypeInfo) && supplementalTypeInfo.TryParseProperty(model, objectPropertyInfoList, elementPropertyConstraints, aggregateContext, parsingErrorCollection, layer, this.Id, definedIn, propDtmi.ToString(), globalize, allowReservedIds, tolerateSolecisms, valueCollectionProp, ref this.supplementalProperties, supplementalJsonLdProperties, this.supplementalSingularPropertyLayers, this.JsonLdElements)) + { + return true; + } + } + + return false; + } + + private bool ValidateInstanceV4(JsonElement instanceElt, string instanceName, List violations) + { + if (instanceElt.ValueKind != JsonValueKind.Number) + { + violations.Add($">>{instanceElt.GetRawText()}<< is not a numeric value"); + return false; + } + + if (!sbyte.TryParse(instanceElt.GetRawText(), out sbyte _)) + { + violations.Add($"{instanceElt.GetRawText()} does not conform to the XSD definition of 'byte'"); + return false; + } + + return true; + } + + private void ApplyTransformationsV4(Model model, ParsingErrorCollection parsingErrorCollection) + { + } + + /// + private void CheckRestrictionsV4(ParsingErrorCollection parsingErrorCollection) + { + } + } +} diff --git a/dotnet/src/DTDLParser/generated/DTEntityInfo.g.cs b/dotnet/src/DTDLParser/generated/DTEntityInfo.g.cs index bc81537c..a31d8101 100644 --- a/dotnet/src/DTDLParser/generated/DTEntityInfo.g.cs +++ b/dotnet/src/DTDLParser/generated/DTEntityInfo.g.cs @@ -110,6 +110,7 @@ static DTEntityInfo() ConcreteKinds[4] = new HashSet(); ConcreteKinds[4].Add(DTEntityKind.Array); ConcreteKinds[4].Add(DTEntityKind.Boolean); + ConcreteKinds[4].Add(DTEntityKind.Byte); ConcreteKinds[4].Add(DTEntityKind.Bytes); ConcreteKinds[4].Add(DTEntityKind.Command); ConcreteKinds[4].Add(DTEntityKind.CommandRequest); @@ -133,9 +134,14 @@ static DTEntityInfo() ConcreteKinds[4].Add(DTEntityKind.Object); ConcreteKinds[4].Add(DTEntityKind.Property); ConcreteKinds[4].Add(DTEntityKind.Relationship); + ConcreteKinds[4].Add(DTEntityKind.Short); ConcreteKinds[4].Add(DTEntityKind.String); ConcreteKinds[4].Add(DTEntityKind.Telemetry); ConcreteKinds[4].Add(DTEntityKind.Time); + ConcreteKinds[4].Add(DTEntityKind.UnsignedByte); + ConcreteKinds[4].Add(DTEntityKind.UnsignedInteger); + ConcreteKinds[4].Add(DTEntityKind.UnsignedLong); + ConcreteKinds[4].Add(DTEntityKind.UnsignedShort); ConcreteKinds[4].Add(DTEntityKind.Uuid); BadTypeActionFormat[2] = "Provide a @type{line3} in the set of allowable types."; @@ -1913,6 +1919,16 @@ internal static bool TryParseTypeStringV4(string typeString, Dtmi elementId, str elementInfo.JsonLdElements[string.Empty] = elt; materialKinds.Add(DTEntityKind.Boolean); return true; + case "Byte": + case "dtmi:dtdl:class:Byte;4": + if (elementInfo == null) + { + elementInfo = new DTByteInfo(4, elementId, parentId, propName, definedIn); + } + + elementInfo.JsonLdElements[string.Empty] = elt; + materialKinds.Add(DTEntityKind.Byte); + return true; case "Bytes": case "dtmi:dtdl:class:Bytes;4": if (elementInfo == null) @@ -2160,6 +2176,16 @@ internal static bool TryParseTypeStringV4(string typeString, Dtmi elementId, str elementInfo.JsonLdElements[string.Empty] = elt; materialKinds.Add(DTEntityKind.Relationship); return true; + case "Short": + case "dtmi:dtdl:class:Short;4": + if (elementInfo == null) + { + elementInfo = new DTShortInfo(4, elementId, parentId, propName, definedIn); + } + + elementInfo.JsonLdElements[string.Empty] = elt; + materialKinds.Add(DTEntityKind.Short); + return true; case "String": case "dtmi:dtdl:class:String;4": if (elementInfo == null) @@ -2190,6 +2216,46 @@ internal static bool TryParseTypeStringV4(string typeString, Dtmi elementId, str elementInfo.JsonLdElements[string.Empty] = elt; materialKinds.Add(DTEntityKind.Time); return true; + case "UnsignedByte": + case "dtmi:dtdl:class:UnsignedByte;4": + if (elementInfo == null) + { + elementInfo = new DTUnsignedByteInfo(4, elementId, parentId, propName, definedIn); + } + + elementInfo.JsonLdElements[string.Empty] = elt; + materialKinds.Add(DTEntityKind.UnsignedByte); + return true; + case "UnsignedInteger": + case "dtmi:dtdl:class:UnsignedInteger;4": + if (elementInfo == null) + { + elementInfo = new DTUnsignedIntegerInfo(4, elementId, parentId, propName, definedIn); + } + + elementInfo.JsonLdElements[string.Empty] = elt; + materialKinds.Add(DTEntityKind.UnsignedInteger); + return true; + case "UnsignedLong": + case "dtmi:dtdl:class:UnsignedLong;4": + if (elementInfo == null) + { + elementInfo = new DTUnsignedLongInfo(4, elementId, parentId, propName, definedIn); + } + + elementInfo.JsonLdElements[string.Empty] = elt; + materialKinds.Add(DTEntityKind.UnsignedLong); + return true; + case "UnsignedShort": + case "dtmi:dtdl:class:UnsignedShort;4": + if (elementInfo == null) + { + elementInfo = new DTUnsignedShortInfo(4, elementId, parentId, propName, definedIn); + } + + elementInfo.JsonLdElements[string.Empty] = elt; + materialKinds.Add(DTEntityKind.UnsignedShort); + return true; case "Uuid": case "dtmi:dtdl:class:Uuid;4": if (elementInfo == null) diff --git a/dotnet/src/DTDLParser/generated/DTEntityKind.g.cs b/dotnet/src/DTDLParser/generated/DTEntityKind.g.cs index b4b160cd..1c32b0d6 100644 --- a/dotnet/src/DTDLParser/generated/DTEntityKind.g.cs +++ b/dotnet/src/DTDLParser/generated/DTEntityKind.g.cs @@ -26,6 +26,9 @@ public enum DTEntityKind /// The kind of the Entity is Boolean. Boolean, + /// The kind of the Entity is Byte. + Byte, + /// The kind of the Entity is Bytes. Bytes, @@ -107,6 +110,9 @@ public enum DTEntityKind /// The kind of the Entity is Relationship. Relationship, + /// The kind of the Entity is Short. + Short, + /// The kind of the Entity is String. String, @@ -122,6 +128,18 @@ public enum DTEntityKind /// The kind of the Entity is UnitAttribute. UnitAttribute, + /// The kind of the Entity is UnsignedByte. + UnsignedByte, + + /// The kind of the Entity is UnsignedInteger. + UnsignedInteger, + + /// The kind of the Entity is UnsignedLong. + UnsignedLong, + + /// The kind of the Entity is UnsignedShort. + UnsignedShort, + /// The kind of the Entity is Uuid. Uuid, } diff --git a/dotnet/src/DTDLParser/generated/DTNumericSchemaInfo.g.cs b/dotnet/src/DTDLParser/generated/DTNumericSchemaInfo.g.cs index cb900d49..135f9335 100644 --- a/dotnet/src/DTDLParser/generated/DTNumericSchemaInfo.g.cs +++ b/dotnet/src/DTDLParser/generated/DTNumericSchemaInfo.g.cs @@ -63,14 +63,20 @@ static DTNumericSchemaInfo() ConcreteKinds[3].Add(DTEntityKind.Long); ConcreteKinds[4] = new HashSet(); + ConcreteKinds[4].Add(DTEntityKind.Byte); ConcreteKinds[4].Add(DTEntityKind.Double); ConcreteKinds[4].Add(DTEntityKind.Float); ConcreteKinds[4].Add(DTEntityKind.Integer); ConcreteKinds[4].Add(DTEntityKind.Long); + ConcreteKinds[4].Add(DTEntityKind.Short); + ConcreteKinds[4].Add(DTEntityKind.UnsignedByte); + ConcreteKinds[4].Add(DTEntityKind.UnsignedInteger); + ConcreteKinds[4].Add(DTEntityKind.UnsignedLong); + ConcreteKinds[4].Add(DTEntityKind.UnsignedShort); BadTypeActionFormat[2] = "Use one of these standard values for property '{property}'{line1}: double, float, integer, long."; BadTypeActionFormat[3] = "Use one of these standard values for property '{property}'{line1}: double, float, integer, long."; - BadTypeActionFormat[4] = "Use one of these standard values for property '{property}'{line1}: double, float, integer, long."; + BadTypeActionFormat[4] = "Use one of these standard values for property '{property}'{line1}: byte, double, float, integer, long, short, unsignedByte, unsignedInteger, unsignedLong, unsignedShort."; BadTypeCauseFormat[2] = "{layer}{primaryId:p} property '{property}' has value{secondaryId:e} that is not a standard value for this property."; BadTypeCauseFormat[3] = "{layer}{primaryId:p} property '{property}' has value{secondaryId:e} that is not a standard value for this property."; diff --git a/dotnet/src/DTDLParser/generated/DTPrimitiveSchemaInfo.g.cs b/dotnet/src/DTDLParser/generated/DTPrimitiveSchemaInfo.g.cs index 1a69f1cb..5f230f61 100644 --- a/dotnet/src/DTDLParser/generated/DTPrimitiveSchemaInfo.g.cs +++ b/dotnet/src/DTDLParser/generated/DTPrimitiveSchemaInfo.g.cs @@ -75,6 +75,7 @@ static DTPrimitiveSchemaInfo() ConcreteKinds[4] = new HashSet(); ConcreteKinds[4].Add(DTEntityKind.Boolean); + ConcreteKinds[4].Add(DTEntityKind.Byte); ConcreteKinds[4].Add(DTEntityKind.Bytes); ConcreteKinds[4].Add(DTEntityKind.Date); ConcreteKinds[4].Add(DTEntityKind.DateTime); @@ -83,13 +84,18 @@ static DTPrimitiveSchemaInfo() ConcreteKinds[4].Add(DTEntityKind.Float); ConcreteKinds[4].Add(DTEntityKind.Integer); ConcreteKinds[4].Add(DTEntityKind.Long); + ConcreteKinds[4].Add(DTEntityKind.Short); ConcreteKinds[4].Add(DTEntityKind.String); ConcreteKinds[4].Add(DTEntityKind.Time); + ConcreteKinds[4].Add(DTEntityKind.UnsignedByte); + ConcreteKinds[4].Add(DTEntityKind.UnsignedInteger); + ConcreteKinds[4].Add(DTEntityKind.UnsignedLong); + ConcreteKinds[4].Add(DTEntityKind.UnsignedShort); ConcreteKinds[4].Add(DTEntityKind.Uuid); BadTypeActionFormat[2] = "Use one of these standard values for property '{property}'{line1}: boolean, date, dateTime, double, duration, float, integer, long, string, time."; BadTypeActionFormat[3] = "Use one of these standard values for property '{property}'{line1}: boolean, date, dateTime, double, duration, float, integer, long, string, time."; - BadTypeActionFormat[4] = "Use one of these standard values for property '{property}'{line1}: boolean, bytes, date, dateTime, double, duration, float, integer, long, string, time, uuid."; + BadTypeActionFormat[4] = "Use one of these standard values for property '{property}'{line1}: boolean, byte, bytes, date, dateTime, double, duration, float, integer, long, short, string, time, unsignedByte, unsignedInteger, unsignedLong, unsignedShort, uuid."; BadTypeCauseFormat[2] = "{layer}{primaryId:p} property '{property}' has value{secondaryId:e} that is not a standard value for this property."; BadTypeCauseFormat[3] = "{layer}{primaryId:p} property '{property}' has value{secondaryId:e} that is not a standard value for this property."; diff --git a/dotnet/src/DTDLParser/generated/DTSchemaInfo.g.cs b/dotnet/src/DTDLParser/generated/DTSchemaInfo.g.cs index 34e4a631..0f15d115 100644 --- a/dotnet/src/DTDLParser/generated/DTSchemaInfo.g.cs +++ b/dotnet/src/DTDLParser/generated/DTSchemaInfo.g.cs @@ -83,6 +83,7 @@ static DTSchemaInfo() ConcreteKinds[4] = new HashSet(); ConcreteKinds[4].Add(DTEntityKind.Array); ConcreteKinds[4].Add(DTEntityKind.Boolean); + ConcreteKinds[4].Add(DTEntityKind.Byte); ConcreteKinds[4].Add(DTEntityKind.Bytes); ConcreteKinds[4].Add(DTEntityKind.Date); ConcreteKinds[4].Add(DTEntityKind.DateTime); @@ -94,13 +95,18 @@ static DTSchemaInfo() ConcreteKinds[4].Add(DTEntityKind.Long); ConcreteKinds[4].Add(DTEntityKind.Map); ConcreteKinds[4].Add(DTEntityKind.Object); + ConcreteKinds[4].Add(DTEntityKind.Short); ConcreteKinds[4].Add(DTEntityKind.String); ConcreteKinds[4].Add(DTEntityKind.Time); + ConcreteKinds[4].Add(DTEntityKind.UnsignedByte); + ConcreteKinds[4].Add(DTEntityKind.UnsignedInteger); + ConcreteKinds[4].Add(DTEntityKind.UnsignedLong); + ConcreteKinds[4].Add(DTEntityKind.UnsignedShort); ConcreteKinds[4].Add(DTEntityKind.Uuid); BadTypeActionFormat[2] = "Provide a @type{line3} in the set of allowable types, or provide a value for property '{property}'{line1} with @type in the set of allowable types, or use one of these standard values for property '{property}'{line1}: boolean, date, dateTime, double, duration, float, integer, long, string, time."; BadTypeActionFormat[3] = "Provide a @type{line3} in the set of allowable types, or provide a value for property '{property}'{line1} with @type in the set of allowable types, or use one of these standard values for property '{property}'{line1}: boolean, date, dateTime, double, duration, float, integer, long, string, time."; - BadTypeActionFormat[4] = "Provide a @type{line3} in the set of allowable types, or provide a value for property '{property}'{line1} with @type in the set of allowable types, or use one of these standard values for property '{property}'{line1}: boolean, bytes, date, dateTime, double, duration, float, integer, long, string, time, uuid."; + BadTypeActionFormat[4] = "Provide a @type{line3} in the set of allowable types, or provide a value for property '{property}'{line1} with @type in the set of allowable types, or use one of these standard values for property '{property}'{line1}: boolean, byte, bytes, date, dateTime, double, duration, float, integer, long, short, string, time, unsignedByte, unsignedInteger, unsignedLong, unsignedShort, uuid."; BadTypeCauseFormat[2] = "{layer}{primaryId:p} property '{property}' has value{secondaryId:e} that does not have @type of Array, Enum, Map, or Object, and it is not a standard value for this property."; BadTypeCauseFormat[3] = "{layer}{primaryId:p} property '{property}' has value{secondaryId:e} that does not have @type of Array, Enum, Map, or Object, and it is not a standard value for this property."; diff --git a/dotnet/src/DTDLParser/generated/DTShortInfo.g.cs b/dotnet/src/DTDLParser/generated/DTShortInfo.g.cs new file mode 100644 index 00000000..9fd8f276 --- /dev/null +++ b/dotnet/src/DTDLParser/generated/DTShortInfo.g.cs @@ -0,0 +1,1887 @@ +/* This is an auto-generated file. Do not modify. */ + +namespace DTDLParser.Models +{ + using System; + using System.Collections.Generic; + using System.ComponentModel; + using System.Globalization; + using System.IO; + using System.Linq; + using System.Text; + using System.Text.Json; + using System.Text.RegularExpressions; + using System.Threading; + using System.Threading.Tasks; + using DTDLParser; + + /// + /// Class DTShortInfo corresponds to an element of type Short in a DTDL model. + /// + public class DTShortInfo : DTNumericSchemaInfo, ITypeChecker, IConstrainer, IEquatable + { + private static readonly Dictionary> ConcreteKinds = new Dictionary>(); + + private static readonly Dictionary BadTypeActionFormat = new Dictionary(); + + private static readonly Dictionary BadTypeCauseFormat = new Dictionary(); + + private static readonly Dictionary BadTypeLocatedCauseFormat = new Dictionary(); + + private static readonly HashSet PropertyNames = new HashSet(); + + private static readonly HashSet VersionlessTypes = new HashSet(); + + private bool checkedForDescendantSchemaArray = false; + + private bool checkedForDescendantSchemaOrContentsComponentNarrow = false; + + private Dictionary supplementalPropertySources = new Dictionary(); + + private Dictionary eltsOfDescendantSchemaArray = null; + + private Dictionary eltsOfDescendantSchemaOrContentsComponentNarrow = null; + + private Dictionary supplementalProperties; + + private Dictionary descriptionPropertyLayer = null; + + private Dictionary displayNamePropertyLayer = null; + + private Dictionary supplementalSingularPropertyLayers = new Dictionary(); + + private Dtmi idOfDescendantSchemaArray = null; + + private Dtmi idOfDescendantSchemaOrContentsComponentNarrow = null; + + private HashSet supplementalTypeIds; + + private int countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowValue = 0; + + private int countOfExtendsNarrowValue = 0; + + private List supplementalTypes; + + private List commentValueConstraints = null; + + private List descriptionValueConstraints = null; + + private List displayNameValueConstraints = null; + + private string commentPropertyLayer = null; + + private TraversalStatus countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowStatus = TraversalStatus.NotStarted; + + private TraversalStatus countOfExtendsNarrowStatus = TraversalStatus.NotStarted; + + private Type checkedDescendantEnumValueDatatype = null; + + static DTShortInfo() + { + VersionlessTypes.Add("dtmi:dtdl:class:Entity"); + VersionlessTypes.Add("dtmi:dtdl:class:NumericSchema"); + VersionlessTypes.Add("dtmi:dtdl:class:PrimitiveSchema"); + VersionlessTypes.Add("dtmi:dtdl:class:Schema"); + VersionlessTypes.Add("dtmi:dtdl:class:Short"); + + PropertyNames.Add("comment"); + PropertyNames.Add("description"); + PropertyNames.Add("displayName"); + PropertyNames.Add("languageMajorVersion"); + + ConcreteKinds[4] = new HashSet(); + ConcreteKinds[4].Add(DTEntityKind.Short); + + BadTypeActionFormat[4] = "Use this standard value for property '{property}'{line1}: short."; + + BadTypeCauseFormat[4] = "{layer}{primaryId:p} property '{property}' has value{secondaryId:e} that is not a standard value for this property."; + + BadTypeLocatedCauseFormat[4] = "In {sourceName1}, property '{property}'{line1} has value{secondaryId:e}{line2} that is not a standard value for this property."; + } + + /// + /// Initializes a new instance of the class. + /// + /// Version of DTDL used to define the Short. + /// Identifier for the Short. + /// Identifier of the parent element in which this Short is defined. + /// Name of the property by which the parent DTDL element refers to this Short. + /// Identifier of the partition in which this Short is defined. + internal DTShortInfo(int dtdlVersion, Dtmi id, Dtmi childOf, string myPropertyName, Dtmi definedIn) + : base(dtdlVersion, id, childOf, myPropertyName, definedIn, DTEntityKind.Short) + { + this.supplementalTypeIds = new HashSet(); + this.supplementalProperties = new Dictionary(); + this.supplementalTypes = new List(); + + this.IsPartition = false; + + this.MaybePartial = false; + } + + /// + /// Initializes a new instance of the class. + /// + /// Version of DTDL used to define the Short. + /// Identifier for the Short. + /// Identifier of the parent element in which this Short is defined. + /// Name of the property by which the parent DTDL element refers to this Short. + /// Identifier of the partition in which this Short is defined. + /// The kind of Entity, which may be other than Short if this constructor is called from a derived class. + internal DTShortInfo(int dtdlVersion, Dtmi id, Dtmi childOf, string myPropertyName, Dtmi definedIn, DTEntityKind entityKind) + : base(dtdlVersion, id, childOf, myPropertyName, definedIn, entityKind) + { + this.supplementalTypeIds = new HashSet(); + this.supplementalProperties = new Dictionary(); + this.supplementalTypes = new List(); + + this.IsPartition = false; + + this.MaybePartial = false; + } + + /// + /// Get the DTMI that identifies type Short in the version of DTDL used to define this element. + /// + /// The DTMI for the DTDL type Short. + public override Dtmi ClassId + { + get + { + return new Dtmi($"dtmi:dtdl:class:Short;{this.LanguageMajorVersion}"); + } + } + + /// + /// Gets the supplemantal properties of the DTDL element that corresponds to this object. + /// + /// A dictionary that maps each string-valued property name to an object that holds the value of the property with the given name. + /// + /// If the property is a literal in the DTDL model, the object holds a literal value. + /// If the property is another DTDL element in the model, the object is the C# object that corresponds to this element. + /// + public override IDictionary SupplementalProperties + { + get + { + return this.supplementalProperties; + } + } + + /// + /// Gets a collection of identifiers, each of which is a Dtmi that indicates a supplemental type that applies to the DTDL element that corresponds to this object. + /// + /// A collection of DTMIs indicating the supplemental types that apply to the DTDL element. + public override IReadOnlyCollection SupplementalTypes + { + get + { + return this.supplementalTypeIds; + } + } + + /// + /// Gets a value indicating whether this class is a partition point for the object model. + /// + internal override bool IsPartition { get; } + + /// + /// Gets material properties allowed by the type of DTDL element. + /// + internal override HashSet MaterialProperties + { + get + { + return PropertyNames; + } + } + + /// + /// Determines whether two DTShortInfo objects are not equal. + /// + /// One DTShortInfo object to compare. + /// Another DTShortInfo object to compare to the first. + /// True if not equal. + public static bool operator !=(DTShortInfo x, DTShortInfo y) + { + if (ReferenceEquals(null, x)) + { + return !ReferenceEquals(null, y); + } + + return !x.Equals(y); + } + + /// + /// Determines whether two DTShortInfo objects are equal. + /// + /// One DTShortInfo object to compare. + /// Another DTShortInfo object to compare to the first. + /// True if equal. + public static bool operator ==(DTShortInfo x, DTShortInfo y) + { + if (ReferenceEquals(null, x)) + { + return ReferenceEquals(null, y); + } + + return x.Equals(y); + } + + /// + /// Compares to another DTShortInfo object, recursing through the entire subtree of object properties. + /// + /// The other DTShortInfo object to compare to. + /// True if equal. + public virtual bool DeepEquals(DTShortInfo other) + { + return base.DeepEquals(other) + && Helpers.AreDictionariesDeepOrLiteralEqual(this.supplementalProperties, other.supplementalProperties) + && this.supplementalTypeIds.SetEquals(other.supplementalTypeIds) + ; + } + + /// + public override bool DeepEquals(DTNumericSchemaInfo other) + { + return this.EntityKind == other?.EntityKind && this.DeepEquals((DTShortInfo)other); + } + + /// + public override bool DeepEquals(DTPrimitiveSchemaInfo other) + { + return this.EntityKind == other?.EntityKind && this.DeepEquals((DTShortInfo)other); + } + + /// + public override bool DeepEquals(DTSchemaInfo other) + { + return this.EntityKind == other?.EntityKind && this.DeepEquals((DTShortInfo)other); + } + + /// + public override bool DeepEquals(DTEntityInfo other) + { + return this.EntityKind == other?.EntityKind && this.DeepEquals((DTShortInfo)other); + } + + /// + /// Compares to another DTShortInfo object. + /// + /// The other DTShortInfo object to compare to. + /// True if equal. + public virtual bool Equals(DTShortInfo other) + { + return base.Equals(other) + && Helpers.AreDictionariesIdOrLiteralEqual(this.supplementalProperties, other.supplementalProperties) + && this.supplementalTypeIds.SetEquals(other.supplementalTypeIds) + ; + } + + /// + public override bool Equals(DTNumericSchemaInfo other) + { + return this.EntityKind == other?.EntityKind && this.Equals((DTShortInfo)other); + } + + /// + public override bool Equals(DTPrimitiveSchemaInfo other) + { + return this.EntityKind == other?.EntityKind && this.Equals((DTShortInfo)other); + } + + /// + public override bool Equals(DTSchemaInfo other) + { + return this.EntityKind == other?.EntityKind && this.Equals((DTShortInfo)other); + } + + /// + public override bool Equals(DTEntityInfo other) + { + return this.EntityKind == other?.EntityKind && this.Equals((DTShortInfo)other); + } + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object otherObj) + { + return otherObj is DTShortInfo other && this.Equals(other); + } + + /// + bool ITypeChecker.DoesHaveType(Dtmi typeId) + { + return VersionlessTypes.Contains(typeId.Versionless) + || this.supplementalTypes.Any(ps => ((ITypeChecker)ps).DoesHaveType(typeId)) + ; + } + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() + { + int hashCode = base.GetHashCode(); + + unchecked + { + hashCode = (hashCode * 131) + Helpers.GetDictionaryIdOrLiteralHashCode(this.supplementalProperties); + hashCode = (hashCode * 131) + Helpers.GetSetLiteralHashCode(this.supplementalTypeIds); + } + + return hashCode; + } + + /// + /// Validate a JsonElement to determine whether it is a numeric value that conforms to the XSD definition of 'short'. + /// + /// The JsonElement to validate. + /// A list of strings that each indicate a validation failure; the list is empty if the JsonElement conforms. + public override IReadOnlyCollection ValidateInstance(JsonElement instanceElt) + { + List violations = new List(); + this.ValidateInstance(instanceElt, null, violations); + return violations; + } + + /// + void IConstrainer.AddPropertyValueConstraint(string propertyName, ValueConstraint valueConstraint) + { + switch (propertyName) + { + case "comment": + if (this.commentValueConstraints == null) + { + this.commentValueConstraints = new List(); + } + + this.commentValueConstraints.Add(valueConstraint); + break; + case "description": + if (this.descriptionValueConstraints == null) + { + this.descriptionValueConstraints = new List(); + } + + this.descriptionValueConstraints.Add(valueConstraint); + break; + case "displayName": + if (this.displayNameValueConstraints == null) + { + this.displayNameValueConstraints = new List(); + } + + this.displayNameValueConstraints.Add(valueConstraint); + break; + } + } + + /// + void IConstrainer.AddSiblingConstraint(SiblingConstraint siblingConstraint) + { + if (this.SiblingConstraints == null) + { + this.SiblingConstraints = new List(); + } + + this.SiblingConstraints.Add(siblingConstraint); + } + + /// + /// Parse an element encoded in a into an object that is a subclass of type DTShortInfo. + /// + /// The model to add the element to. + /// A list of ParsedObjectPropertyInfo to add any object properties, which will be assigned after all parsing has completed. + /// List of ElementPropertyConstraint to be checked after object property assignment. + /// List of to be added to . + /// An AggregateContext object representing information retrieved from JSON-LD context blocks. + /// A ParsingErrorCollection to which any parsing errors are added. + /// The to parse. + /// Name of the layer currently being parsed. + /// The identifier of the parent of the element. + /// Identifier of the partition or top-level element under which this element is defined. + /// The name of the property by which the parent refers to this element, used for auto ID generation. + /// The representing the source of the property by which the parent refers to this element. + /// A DTMI segment identifier, used for auto ID generation. + /// A property used for the key if the parent exposes a collection of these elements as a dictionary. + /// A boolean value indicating whether an @id must be present. + /// A boolean value indicating whether a @type must be present. + /// Treat all nested definitions as though defined globally. + /// Allow elements to define IDs that have reserved prefixes. + /// Tolerate specific minor invalidities to support backward compatibility. + /// A set of allowed versions for the element. + /// The type name to infer if no @type specified on element. + /// True if the parses correctly as an appropriate element. + internal static new bool TryParseElement(Model model, List objectPropertyInfoList, List elementPropertyConstraints, List valueConstraints, AggregateContext aggregateContext, ParsingErrorCollection parsingErrorCollection, JsonLdElement elt, string layer, Dtmi parentId, Dtmi definedIn, string propName, JsonLdProperty propProp, string dtmiSeg, string keyProp, bool idRequired, bool typeRequired, bool globalize, bool allowReservedIds, bool tolerateSolecisms, HashSet allowedVersions, string inferredType) + { + AggregateContext childAggregateContext = aggregateContext.GetChildContext(elt, parsingErrorCollection); + + bool allowIdReferenceSyntax = tolerateSolecisms && aggregateContext.DtdlVersion < 3; + + if (elt.PropertyCount == 1 && elt.Id != null) + { + if (allowIdReferenceSyntax) + { + if (TryParseIdString(objectPropertyInfoList, elementPropertyConstraints, valueConstraints, childAggregateContext, parsingErrorCollection, elt.Id, layer, parentId, propName, propProp, keyProp, allowedVersions)) + { + return true; + } + else + { + parsingErrorCollection.Notify( + "idRefBadDtmiOrTerm", + elementId: parentId, + propertyName: propName, + propertyValue: elt.Id, + element: elt, + version: aggregateContext.DtdlVersion.ToString(), + layer: layer); + return false; + } + } + else + { + parsingErrorCollection.Notify( + "idReference", + elementId: parentId, + propertyName: propName, + identifier: elt.Id, + element: elt, + layer: layer); + return false; + } + } + + if (elt.Graph != null) + { + parsingErrorCollection.Notify( + "graphDisallowed", + elementId: parentId, + propertyName: propName, + element: elt); + } + + if (childAggregateContext.RestrictKeywords) + { + if (elt.Language != null) + { + parsingErrorCollection.Notify( + "keywordDisallowed", + elementId: parentId, + propertyName: propName, + keyword: "@language", + element: elt); + } + + if (elt.Value != null) + { + parsingErrorCollection.Notify( + "keywordDisallowed", + elementId: parentId, + propertyName: propName, + keyword: "@value", + element: elt); + } + + foreach (string keyword in elt.Keywords) + { + parsingErrorCollection.Notify( + "keywordDisallowed", + elementId: parentId, + propertyName: propName, + keyword: keyword, + element: elt); + } + } + + if (allowedVersions != null && !allowedVersions.Contains(childAggregateContext.DtdlVersion)) + { + parsingErrorCollection.Notify( + "disallowedVersionDefinition", + elementId: parentId, + propertyName: propName, + version: childAggregateContext.DtdlVersion.ToString(), + versionRestriction: string.Join(" ,", allowedVersions), + contextComponent: childAggregateContext.DtdlContextComponent, + layer: layer); + } + + bool tolerateReservedIds = tolerateSolecisms && aggregateContext.DtdlVersion < 3; + + Dtmi elementId = IdValidator.ParseIdProperty(childAggregateContext, elt, childAggregateContext.MergeDefinitions ? layer : null, parentId, propName, dtmiSeg, idRequired, allowReservedIds || tolerateReservedIds, parsingErrorCollection); + + Dtmi baseElementId = childAggregateContext.MergeDefinitions || elementId.Tail == string.Empty ? elementId.Fragmentless : elementId; + string elementLayer = childAggregateContext.MergeDefinitions ? elementId.Tail : string.Empty; + + bool ignoreElementsWithAutoIDsAndDuplicateNames = tolerateSolecisms && aggregateContext.DtdlVersion < 3; + + if (model.Dict.TryGetValue(baseElementId, out DTEntityInfo baseElement)) + { + if (baseElement.JsonLdElements.TryGetValue(elementLayer, out JsonLdElement duplicateElt)) + { + if (!baseElementId.IsReserved) + { + parsingErrorCollection.Notify( + "duplicateDefinition", + elementId: baseElementId, + element: elt, + extantElement: duplicateElt, + layer: layer); + } + else if (!ignoreElementsWithAutoIDsAndDuplicateNames && dtmiSeg != null) + { + JsonLdProperty dtmiSegProp = elt.Properties.First(p => p.Name == dtmiSeg || (Dtmi.TryCreateDtmi(p.Name, out Dtmi d) && ContextCollection.GetTermOrUri(d) == dtmiSeg)); + JsonLdProperty dupSegProp = duplicateElt.Properties.First(p => p.Name == dtmiSeg || (Dtmi.TryCreateDtmi(p.Name, out Dtmi d) && ContextCollection.GetTermOrUri(d) == dtmiSeg)); + parsingErrorCollection.Notify( + "nonUniquePropertyValue", + elementId: parentId, + propertyName: propName, + nestedName: dtmiSeg, + nestedValue: dtmiSegProp.Values.Values.First().StringValue, + incidentProperty: dupSegProp, + extantProperty: dtmiSegProp); + } + + return false; + } + + if (baseElement.DtdlVersion != childAggregateContext.DtdlVersion) + { + parsingErrorCollection.Notify( + "inconsistentContext", + elementId: baseElementId, + version: childAggregateContext.DtdlVersion.ToString(), + versionRestriction: baseElement.DtdlVersion.ToString(), + layer: elementLayer); + return false; + } + } + + if (typeRequired && elt.Types == null) + { + string sourceName1 = null; + int sourceLine1 = 0; + if (propProp != null && propProp.TryGetSourceLocation(out sourceName1, out sourceLine1) && elt.TryGetSourceLocation(out string sourceName2, out int startLine2, out int endLine2)) + { + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeLocatedCauseFormat[childAggregateContext.DtdlVersion], + BadTypeActionFormat[childAggregateContext.DtdlVersion], + primaryId: parentId, + property: propName, + secondaryId: baseElementId, + layer: layer, + sourceName1: sourceName1, + startLine1: sourceLine1, + sourceName2: sourceName2, + startLine2: startLine2, + endLine2: endLine2); + } + else + { + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeCauseFormat[childAggregateContext.DtdlVersion], + BadTypeActionFormat[childAggregateContext.DtdlVersion], + primaryId: parentId, + property: propName, + secondaryId: baseElementId, + layer: layer); + } + + return false; + } + + DTShortInfo elementInfo = (DTShortInfo)baseElement; + HashSet immediateSupplementalTypeIds; + List immediateUndefinedTypes; + bool typeArrayParsed; + if (elt.Types == null) + { + typeArrayParsed = TryParseTypeStrings(new List() { inferredType }, baseElementId, elementLayer, elt, parentId, definedIn, propName, propProp, ref elementInfo, childAggregateContext, out immediateSupplementalTypeIds, out immediateUndefinedTypes, parsingErrorCollection); + } + else + { + typeArrayParsed = TryParseTypeStrings(elt.Types, baseElementId, elementLayer, elt, parentId, definedIn, propName, propProp, ref elementInfo, childAggregateContext, out immediateSupplementalTypeIds, out immediateUndefinedTypes, parsingErrorCollection); + } + + if (!typeArrayParsed || ReferenceEquals(null, elementInfo)) + { + return false; + } + + switch (childAggregateContext.DtdlVersion) + { + case 4: + elementInfo.ParsePropertiesV4(model, objectPropertyInfoList, elementPropertyConstraints, childAggregateContext, immediateSupplementalTypeIds, immediateUndefinedTypes, parsingErrorCollection, elt, elementLayer, definedIn, globalize, allowReservedIds, tolerateSolecisms); + break; + } + + elementInfo.LimitSpecifier = aggregateContext.LimitSpecifier; + + elementInfo.RecordSourceAsAppropriate(elementLayer, elt, childAggregateContext, parsingErrorCollection, atRoot: parentId == null, globalized: globalize); + + model.Dict[baseElementId] = elementInfo; + + if (parentId != null) + { + objectPropertyInfoList.Add(new ParsedObjectPropertyInfo() { ElementId = parentId, PropertyName = propName, Layer = layer, JsonLdProperty = propProp, ReferencedElementId = baseElementId, KeyProperty = keyProp, ExpectedKinds = null, AllowedVersions = null, ChildOf = null, BadTypeCauseFormat = null, BadTypeLocatedCauseFormat = null, BadTypeActionFormat = null }); + + if (valueConstraints != null && elementPropertyConstraints != null) + { + foreach (ValueConstraint valueConstraint in valueConstraints) + { + elementPropertyConstraints.Add(new ElementPropertyConstraint() { ParentId = parentId, PropertyName = propName, ElementId = baseElementId, ValueConstraint = valueConstraint }); + } + } + } + + return true; + } + + /// + /// Parse a string property value as an identifier for type DTShortInfo. + /// + /// A list of ParsedObjectPropertyInfo to add any object properties, which will be assigned after all parsing has completed. + /// List of ElementPropertyConstraint to be checked after object property assignment. + /// List of to be added to . + /// An AggregateContext object representing information retrieved from JSON-LD context blocks. + /// A ParsingErrorCollection to which any parsing errors are added. + /// The identifier string to parse. + /// Name of the layer currently being parsed. + /// The identifier of the parent of the element. + /// The name of the property by which the parent refers to this element, used for auto ID generation. + /// The representing the source of the property by which the parent refers to this element. + /// A property used for the key if the parent exposes a collection of these elements as a dictionary. + /// A set of allowed versions for the element. + /// True if the string parses correctly as an identifier. + internal static new bool TryParseIdString(List objectPropertyInfoList, List elementPropertyConstraints, List valueConstraints, AggregateContext aggregateContext, ParsingErrorCollection parsingErrorCollection, string idString, string layer, Dtmi parentId, string propName, JsonLdProperty propProp, string keyProp, HashSet allowedVersions) + { + if (!aggregateContext.TryCreateDtmi(idString, out Dtmi elementId)) + { + return false; + } + + objectPropertyInfoList.Add(new ParsedObjectPropertyInfo() { ElementId = parentId, PropertyName = propName, Layer = layer, JsonLdProperty = propProp, ReferencedIdString = idString, ReferencedElementId = elementId, KeyProperty = keyProp, ExpectedKinds = ConcreteKinds[aggregateContext.DtdlVersion], AllowedVersions = allowedVersions, ChildOf = null, BadTypeCauseFormat = BadTypeCauseFormat[aggregateContext.DtdlVersion], BadTypeLocatedCauseFormat = BadTypeLocatedCauseFormat[aggregateContext.DtdlVersion], BadTypeActionFormat = BadTypeActionFormat[aggregateContext.DtdlVersion] }); + + if (valueConstraints != null && elementPropertyConstraints != null) + { + foreach (ValueConstraint valueConstraint in valueConstraints) + { + elementPropertyConstraints.Add(new ElementPropertyConstraint() { ParentId = parentId, PropertyName = propName, ElementId = elementId, ValueConstraint = valueConstraint }); + } + } + + return true; + } + + /// + /// Parse a list of @type values containing material or supplemental types. + /// + /// The list of strings to parse. + /// The identifier of the element of this type to create. + /// Name of the layer currently being parsed. + /// The currently being parsed. + /// The identifier of the parent of the element. + /// Identifier of the partition or top-level element under which this element is defined. + /// The name of the property by which the parent refers to this element, used for auto ID generation. + /// The representing the source of the property by which the parent refers to this element. + /// The created. + /// An AggregateContext object representing information retrieved from JSON-LD context blocks. + /// A set of supplemental type IDs from the type array. + /// A list of undefind type strings from the type array. + /// A ParsingErrorCollection to which any parsing errors are added. + /// True if no errors detected in type array. + internal static bool TryParseTypeStrings(List typeStrings, Dtmi elementId, string layer, JsonLdElement elt, Dtmi parentId, Dtmi definedIn, string propName, JsonLdProperty propProp, ref DTShortInfo elementInfo, AggregateContext aggregateContext, out HashSet immediateSupplementalTypeIds, out List immediateUndefinedTypes, ParsingErrorCollection parsingErrorCollection) + { + immediateSupplementalTypeIds = new HashSet(); + immediateUndefinedTypes = new List(); + + HashSet materialKinds = new HashSet(); + + bool anyFailures = false; + foreach (string typeString in typeStrings) + { + switch (aggregateContext.DtdlVersion) + { + case 4: + if (!TryParseTypeStringV4(typeString, elementId, layer, elt, parentId, definedIn, propName, propProp, materialKinds, immediateSupplementalTypeIds, ref elementInfo, ref immediateUndefinedTypes, aggregateContext, parsingErrorCollection)) + { + anyFailures = true; + } + + break; + } + } + + if (anyFailures) + { + return false; + } + + if (ReferenceEquals(null, elementInfo)) + { + string sourceName1 = null; + int sourceLine1 = 0; + if (propProp != null && propProp.TryGetSourceLocation(out sourceName1, out sourceLine1) && elt.TryGetSourceLocation(out string sourceName2, out int startLine2, out int endLine2)) + { + elt.TryGetSourceLocationForType(out _, out int sourceLine3); + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeLocatedCauseFormat[aggregateContext.DtdlVersion], + BadTypeActionFormat[aggregateContext.DtdlVersion], + primaryId: parentId, + property: propName, + secondaryId: elementId, + layer: layer, + sourceName1: sourceName1, + startLine1: sourceLine1, + sourceName2: sourceName2, + startLine2: startLine2, + endLine2: endLine2, + startLine3: sourceLine3); + } + else + { + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeCauseFormat[aggregateContext.DtdlVersion], + BadTypeActionFormat[aggregateContext.DtdlVersion], + primaryId: parentId, + property: propName, + secondaryId: elementId, + layer: layer); + } + + return false; + } + + if (!materialKinds.Any()) + { + parsingErrorCollection.Notify( + "layerMissingMaterialType", + elementId: elementId, + elementType: elementInfo.EntityKind.ToString(), + element: elt, + layer: layer); + return false; + } + + materialKinds.Add(elementInfo.EntityKind); + if (materialKinds.Count() > 1) + { + parsingErrorCollection.Notify( + "multipleMaterialTypes", + elementId: elementId, + valueConjunction: string.Join(" and ", materialKinds), + element: elt, + layer: layer); + return false; + } + + elementInfo.UndefinedTypeStrings.UnionWith(immediateUndefinedTypes); + + bool requiresMergeability = layer != string.Empty && !elementId.IsReserved; + bool isMergeable = false; + foreach (Dtmi supplementalTypeId in immediateSupplementalTypeIds) + { + if (aggregateContext.SupplementalTypeCollection.TryGetSupplementalTypeInfo(supplementalTypeId, out DTSupplementalTypeInfo supplementalTypeInfo)) + { + if (!supplementalTypeInfo.AllowedCotypeKinds.Contains(elementInfo.EntityKind)) + { + parsingErrorCollection.Notify( + "invalidCotype", + elementId: elementId, + cotype: ContextCollection.GetTermOrUri(supplementalTypeId), + typeRestriction: string.Join(" or ", supplementalTypeInfo.AllowedCotypeKinds), + element: elt, + layer: layer); + } + else if (!supplementalTypeInfo.AllowedCotypeVersions.Contains(elementInfo.DtdlVersion)) + { + parsingErrorCollection.Notify( + "invalidCotypeVersion", + elementId: elementId, + cotype: ContextCollection.GetTermOrUri(supplementalTypeId), + versionRestriction: string.Join(" or ", supplementalTypeInfo.AllowedCotypeVersions), + element: elt, + layer: layer); + } + else + { + elementInfo.AddType(supplementalTypeId, supplementalTypeInfo, parsingErrorCollection); + foreach (Dtmi requiredCocotype in supplementalTypeInfo.RequiredCocotypes) + { + if (!immediateSupplementalTypeIds.Contains(requiredCocotype)) + { + string requiredCocotypeTerm = ContextCollection.GetTermOrUri(requiredCocotype); + parsingErrorCollection.Notify( + "missingCocotype", + elementId: elementId, + elementType: ContextCollection.GetTermOrUri(supplementalTypeId), + cotype: requiredCocotypeTerm, + element: elt); + } + } + } + + isMergeable = isMergeable || supplementalTypeInfo.IsMergeable; + } + } + + if (requiresMergeability && !isMergeable) + { + parsingErrorCollection.Notify( + "disallowedIdFragment", + elementId: elementId, + element: elt, + layer: layer); + } + + return true; + } + + /// + /// Parse a string @type value, whether material or supplemental. + /// + /// The string value to parse. + /// The identifier of the element of this type to create. + /// Name of the layer currently being parsed. + /// The currently being parsed. + /// The identifier of the parent of the element. + /// Identifier of the partition or top-level element under which this element is defined. + /// The name of the property by which the parent refers to this element. + /// The representing the source of the property by which the parent refers to this element. + /// A set of material kinds to update with the material kind of the type, if any. + /// A set of supplemental type IDs to update with the supplemental type, if any. + /// The element created if the type is material. + /// A list of string values of any undefined supplemental types. + /// An AggregateContext object representing information retrieved from JSON-LD context blocks. + /// A ParsingErrorCollection to which any parsing errors are added. + /// True if the parse is sucessful. + internal static bool TryParseTypeStringV4(string typeString, Dtmi elementId, string layer, JsonLdElement elt, Dtmi parentId, Dtmi definedIn, string propName, JsonLdProperty propProp, HashSet materialKinds, HashSet supplementalTypeIds, ref DTShortInfo elementInfo, ref List undefinedTypes, AggregateContext aggregateContext, ParsingErrorCollection parsingErrorCollection) + { + if (MaterialTypeNameCollection.IsMaterialType(typeString)) + { + string sourceName1 = null; + int sourceLine1 = 0; + if (propProp != null && propProp.TryGetSourceLocation(out sourceName1, out sourceLine1) && elt.TryGetSourceLocation(out string sourceName2, out int startLine2, out int endLine2)) + { + elt.TryGetSourceLocationForType(out _, out int sourceLine3); + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeLocatedCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer, + sourceName1: sourceName1, + startLine1: sourceLine1, + sourceName2: sourceName2, + startLine2: startLine2, + endLine2: endLine2, + startLine3: sourceLine3); + } + else + { + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer); + } + + return false; + } + + if (!aggregateContext.TryCreateDtmi(typeString, out Dtmi supplementalTypeId)) + { + if (typeString.StartsWith("dtmi:")) + { + parsingErrorCollection.Notify( + "typeInvalidDtmi", + elementId: elementId, + cotype: typeString, + element: elt, + layer: layer); + return false; + } + else if (typeString.Contains(":")) + { + parsingErrorCollection.Notify( + "typeNotDtmiNorTerm", + elementId: elementId, + cotype: typeString, + element: elt, + layer: layer); + return false; + } + else + { + if (aggregateContext.IsComplete) + { + parsingErrorCollection.Notify( + "typeUndefinedTerm", + elementId: elementId, + cotype: typeString, + element: elt, + version: aggregateContext.DtdlVersion.ToString(), + layer: layer); + return false; + } + } + + undefinedTypes.Add(typeString); + return true; + } + + if (!aggregateContext.SupplementalTypeCollection.TryGetSupplementalTypeInfo(supplementalTypeId, out DTSupplementalTypeInfo supplementalTypeInfo)) + { + if (aggregateContext.IsComplete) + { + parsingErrorCollection.Notify( + "typeIrrelevantDtmiOrTerm", + elementId: elementId, + cotype: typeString, + element: elt, + version: aggregateContext.DtdlVersion.ToString(), + layer: layer); + return false; + } + + undefinedTypes.Add(typeString); + return true; + } + + if (supplementalTypeInfo.IsAbstract) + { + parsingErrorCollection.Notify( + "abstractSupplementalType", + elementId: elementId, + cotype: ContextCollection.GetTermOrUri(supplementalTypeId), + element: elt, + layer: layer); + return false; + } + + switch (supplementalTypeInfo.ExtensionKind) + { + case DTExtensionKind.LatentType: + { + string sourceName1 = null; + int sourceLine1 = 0; + if (propProp != null && propProp.TryGetSourceLocation(out sourceName1, out sourceLine1) && elt.TryGetSourceLocation(out string sourceName2, out int startLine2, out int endLine2)) + { + elt.TryGetSourceLocationForType(out _, out int sourceLine3); + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeLocatedCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer, + sourceName1: sourceName1, + startLine1: sourceLine1, + sourceName2: sourceName2, + startLine2: startLine2, + endLine2: endLine2, + startLine3: sourceLine3); + } + else + { + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer); + } + } + + return false; + case DTExtensionKind.NamedLatentType: + { + string sourceName1 = null; + int sourceLine1 = 0; + if (propProp != null && propProp.TryGetSourceLocation(out sourceName1, out sourceLine1) && elt.TryGetSourceLocation(out string sourceName2, out int startLine2, out int endLine2)) + { + elt.TryGetSourceLocationForType(out _, out int sourceLine3); + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeLocatedCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer, + sourceName1: sourceName1, + startLine1: sourceLine1, + sourceName2: sourceName2, + startLine2: startLine2, + endLine2: endLine2, + startLine3: sourceLine3); + } + else + { + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer); + } + } + + return false; + case DTExtensionKind.Unit: + { + string sourceName1 = null; + int sourceLine1 = 0; + if (propProp != null && propProp.TryGetSourceLocation(out sourceName1, out sourceLine1) && elt.TryGetSourceLocation(out string sourceName2, out int startLine2, out int endLine2)) + { + elt.TryGetSourceLocationForType(out _, out int sourceLine3); + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeLocatedCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer, + sourceName1: sourceName1, + startLine1: sourceLine1, + sourceName2: sourceName2, + startLine2: startLine2, + endLine2: endLine2, + startLine3: sourceLine3); + } + else + { + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer); + } + } + + return false; + case DTExtensionKind.UnitAttribute: + { + string sourceName1 = null; + int sourceLine1 = 0; + if (propProp != null && propProp.TryGetSourceLocation(out sourceName1, out sourceLine1) && elt.TryGetSourceLocation(out string sourceName2, out int startLine2, out int endLine2)) + { + elt.TryGetSourceLocationForType(out _, out int sourceLine3); + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeLocatedCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer, + sourceName1: sourceName1, + startLine1: sourceLine1, + sourceName2: sourceName2, + startLine2: startLine2, + endLine2: endLine2, + startLine3: sourceLine3); + } + else + { + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer); + } + } + + return false; + } + + supplementalTypeIds.Add(supplementalTypeId); + + return true; + } + + /// + /// Parse elements encoded in a into objects of subclasses of type DTShortInfo. + /// + /// The model to add the element to. + /// A list of ParsedObjectPropertyInfo to add any object properties, which will be assigned after all parsing has completed. + /// List of ElementPropertyConstraint to be checked after object property assignment. + /// List of to be added to . + /// An AggregateContext object representing information retrieved from JSON-LD context blocks. + /// A ParsingErrorCollection to which any parsing errors are added. + /// The holding the to parse. + /// Name of the layer currently being parsed. + /// The identifier of the parent of the element. + /// Identifier of the partition or top-level element under which this element is defined. + /// The name of the property by which the parent refers to this element, used for auto ID generation. + /// A DTMI segment identifier, used for auto ID generation. + /// A property used for the key if the parent exposes a collection of these elements as a dictionary. + /// The minimum count of element values required. + /// A boolean value indicating whether the property allows multiple values. + /// A boolean value indicating whether an @id must be present. + /// A boolean value indicating whether a @type must be present. + /// Treat all nested definitions as though defined globally. + /// Allow elements to define IDs that have reserved prefixes. + /// Tolerate specific minor invalidities to support backward compatibility. + /// A set of allowed versions for the element. + internal static new void ParseValueCollection(Model model, List objectPropertyInfoList, List elementPropertyConstraints, List valueConstraints, AggregateContext aggregateContext, ParsingErrorCollection parsingErrorCollection, JsonLdProperty valueCollectionProp, string layer, Dtmi parentId, Dtmi definedIn, string propName, string dtmiSeg, string keyProp, int minCount, bool isPlural, bool idRequired, bool typeRequired, bool globalize, bool allowReservedIds, bool tolerateSolecisms, HashSet allowedVersions) + { + int valueCount = 0; + + foreach (JsonLdValue value in valueCollectionProp.Values.Values) + { + if (!isPlural && valueCount > 0) + { + parsingErrorCollection.Notify( + "objectMultipleValues", + elementId: parentId, + propertyName: propName, + incidentValues: valueCollectionProp.Values, + layer: layer); + return; + } + + switch (value.ValueType) + { + case JsonLdValueType.String: + if (parentId != null) + { + if (TryParseIdString(objectPropertyInfoList, elementPropertyConstraints, valueConstraints, aggregateContext, parsingErrorCollection, value.StringValue, layer, parentId, propName, valueCollectionProp, keyProp, allowedVersions)) + { + ++valueCount; + } + else + { + parsingErrorCollection.Notify( + "badDtmiOrTerm", + elementId: parentId, + propertyName: propName, + propertyValue: value.StringValue, + incidentProperty: valueCollectionProp, + incidentValue: value, + version: aggregateContext.DtdlVersion.ToString(), + layer: layer); + } + } + + break; + case JsonLdValueType.Element: + if (TryParseElement(model, objectPropertyInfoList, elementPropertyConstraints, valueConstraints, aggregateContext, parsingErrorCollection, value.ElementValue, layer, parentId, definedIn, propName, valueCollectionProp, dtmiSeg, keyProp, idRequired, typeRequired, globalize, allowReservedIds, tolerateSolecisms, allowedVersions, "Short")) + { + ++valueCount; + } + + break; + default: + parsingErrorCollection.Notify( + "refNotStringOrObject", + elementId: parentId, + propertyName: propName, + incidentProperty: valueCollectionProp, + incidentValue: value, + layer: layer); + break; + } + } + + if (valueCount < minCount) + { + parsingErrorCollection.Notify( + "objectCountBelowMin", + elementId: parentId, + propertyName: propName, + observedCount: valueCount, + expectedCount: minCount, + incidentProperty: valueCollectionProp, + layer: layer); + } + } + + /// + internal override bool CheckDepthOfElementSchemaOrSchema(int depth, int depthLimit, bool allowSelf, List tooDeepElementIds, out Dictionary tooDeepElts, ParsingErrorCollection parsingErrorCollection) + { + tooDeepElts = null; + return true; + } + + /// + /// Determine whether a JsonElement matches this DTDL element. + /// + /// The JsonElement to match. + /// If the instance is a property in a JSON object, the name corresponding to ; otherwise, null. + /// True if the JsonElement matches; false otherwise. + internal override bool DoesInstanceMatch(JsonElement instanceElt, string instanceName) + { + switch (this.DtdlVersion) + { + case 4: + return this.DoesInstanceMatchV4(instanceElt, instanceName); + } + + return false; + } + + /// + /// Indicate whether the property with a given is a dictionary that holds a given . + /// + /// The name of the property to check. + /// The key for the dictionary property. + /// True if the property is present, is a dictionary, and holds the given key. + internal override bool DoesPropertyDictContainKey(string propertyName, string key) + { + if (base.DoesPropertyDictContainKey(propertyName, key)) + { + return true; + } + + switch (propertyName) + { + default: + return false; + } + } + + /// + internal override bool TryGetChild(string childrenPropertyName, string keyPropertyName, string keyPropertyValue, out DTEntityInfo child) + { + switch (childrenPropertyName) + { + default: + break; + } + + child = null; + return false; + } + + /// + internal override bool TryGetDescendantSchemaArray(out Dtmi elementId, out Dictionary excludedElts) + { + if (this.checkedForDescendantSchemaArray) + { + elementId = this.idOfDescendantSchemaArray; + excludedElts = this.eltsOfDescendantSchemaArray; + return this.idOfDescendantSchemaArray != null; + } + + this.checkedForDescendantSchemaArray = true; + + elementId = null; + excludedElts = null; + return false; + } + + /// + internal override bool TryGetDescendantSchemaOrContentsComponentNarrow(out Dtmi elementId, out Dictionary excludedElts) + { + if (this.checkedForDescendantSchemaOrContentsComponentNarrow) + { + elementId = this.idOfDescendantSchemaOrContentsComponentNarrow; + excludedElts = this.eltsOfDescendantSchemaOrContentsComponentNarrow; + return this.idOfDescendantSchemaOrContentsComponentNarrow != null; + } + + this.checkedForDescendantSchemaOrContentsComponentNarrow = true; + + elementId = null; + excludedElts = null; + return false; + } + + /// + /// Try to set an object property with a given . + /// + /// The name of the property whose element value to set if the property is recognized. + /// The key property for dictionary properties. + /// The representing the source of the property by which the parent refers to this element. + /// The reference element to set. + /// The key property for dictionary properties. + /// The key value for dictionary properties. + /// A ParsingErrorCollection to which any parsing errors are added. + /// True if the property name is recognized. + internal override bool TrySetObjectProperty(string propertyName, string layer, JsonLdProperty propProp, DTEntityInfo element, string keyProp, string keyValue, ParsingErrorCollection parsingErrorCollection) + { + if (base.TrySetObjectProperty(propertyName, layer, propProp, element, keyProp, keyValue, parsingErrorCollection)) + { + return true; + } + + switch (propertyName) + { + default: + break; + } + + foreach (DTSupplementalTypeInfo supplementalType in this.supplementalTypes) + { + if (supplementalType.TrySetObjectProperty(this.Id, propertyName, element, keyValue, layer, propProp, ref this.supplementalProperties, this.supplementalSingularPropertyLayers, this.JsonLdElements, parsingErrorCollection)) + { + return true; + } + } + + return false; + } + + /// + /// Validate a JsonElement to determine whether it is a numeric value that conforms to the XSD definition of 'short'. + /// + /// The JsonElement to validate. + /// If the instance is a property in a JSON object, the name corresponding to ; otherwise, null. + /// A list of strings to which to add any validation failures. + internal override bool ValidateInstance(JsonElement instanceElt, string instanceName, List violations) + { + switch (this.DtdlVersion) + { + case 4: + return this.ValidateInstanceV4(instanceElt, instanceName, violations); + } + + return true; + } + + /// + internal override HashSet GetTransitiveExtendsNarrow(int depth, int depthLimit, bool allowSelf, List tooDeepElementIds, out Dictionary tooDeepElts, ParsingErrorCollection parsingErrorCollection) + { + HashSet closure = new HashSet(); + + tooDeepElts = null; + return closure; + } + + /// + internal override IEnumerable GetChildren(string childrenPropertyName) + { + switch (childrenPropertyName) + { + default: + return new List(); + } + } + + /// + internal override int GetCountOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrow(bool allowSelf, ParsingErrorCollection parsingErrorCollection) + { + if (this.countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowStatus == TraversalStatus.Complete) + { + return this.countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowValue; + } + + if (this.countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowStatus == TraversalStatus.InProgress) + { + if (allowSelf) + { + this.countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowStatus = TraversalStatus.Complete; + } + else + { + parsingErrorCollection.Notify( + "recursiveStructureNarrow", + elementId: this.Id, + propertyDisjunction: "'contents' or 'fields' or 'enumValues' or 'request' or 'response' or 'properties' or 'schema' or 'elementSchema' or 'mapValue'", + element: this.JsonLdElements.First().Value); + } + + return 0; + } + + this.countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowStatus = TraversalStatus.InProgress; + this.countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowStatus = TraversalStatus.Complete; + return this.countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowValue; + } + + /// + internal override int GetCountOfExtendsNarrow(bool allowSelf, ParsingErrorCollection parsingErrorCollection) + { + if (this.countOfExtendsNarrowStatus == TraversalStatus.Complete) + { + return this.countOfExtendsNarrowValue; + } + + if (this.countOfExtendsNarrowStatus == TraversalStatus.InProgress) + { + if (allowSelf) + { + this.countOfExtendsNarrowStatus = TraversalStatus.Complete; + } + else + { + parsingErrorCollection.Notify( + "recursiveStructureNarrow", + elementId: this.Id, + propertyDisjunction: "'extends'", + element: this.JsonLdElements.First().Value); + } + + return 0; + } + + this.countOfExtendsNarrowStatus = TraversalStatus.InProgress; + this.countOfExtendsNarrowStatus = TraversalStatus.Complete; + return this.countOfExtendsNarrowValue; + } + + /// + /// Add a supplemental type. + /// + /// Identifier for the supplemental type to add. + /// DTSupplementalTypeInfo for the supplemental type. + /// A ParsingErrorCollection to which any parsing errors are added. + internal override void AddType(Dtmi id, DTSupplementalTypeInfo supplementalType, ParsingErrorCollection parsingErrorCollection) + { + if (this.supplementalTypeIds.Add(id)) + { + this.supplementalTypes.Add(supplementalType); + } + } + + /// + internal override void ApplyTransformations(Model model, ParsingErrorCollection parsingErrorCollection) + { + switch (this.DtdlVersion) + { + case 4: + this.ApplyTransformationsV4(model, parsingErrorCollection); + break; + } + } + + /// + internal override void CheckDescendantEnumValueDatatype(Dtmi ancestorId, Dictionary ancestorElts, Type datatype, ParsingErrorCollection parsingErrorCollection) + { + if (this.checkedDescendantEnumValueDatatype != datatype) + { + this.checkedDescendantEnumValueDatatype = datatype; + } + } + + /// + internal override void CheckRestrictions(ParsingErrorCollection parsingErrorCollection) + { + this.CheckForDisallowedCocotypes(this.supplementalTypeIds, this.supplementalTypes, parsingErrorCollection); + + foreach (DTSupplementalTypeInfo supplementalType in this.supplementalTypes) + { + supplementalType.CheckRestrictions(this.supplementalProperties, parsingErrorCollection, this.Id, this.JsonLdElements); + } + + switch (this.DtdlVersion) + { + case 4: + this.CheckRestrictionsV4(parsingErrorCollection); + break; + } + } + + /// + /// Parse the properties in a JSON Short object. + /// + /// Model to which to add object properties. + /// List of object info structs for deferred assignments. + /// List of ElementPropertyConstraint to be checked after object property assignment. + /// An AggregateContext object representing information retrieved from JSON-LD context blocks. + /// A set of supplemental type IDs. + /// A list of undefind type strings. + /// A ParsingErrorCollection to which any parsing errors are added. + /// The to parse. + /// Name of the layer currently being parsed. + /// Identifier of the partition or top-level element under which this element is defined. + /// Treat all nested definitions as though defined globally. + /// Allow elements to define IDs that have reserved prefixes. + /// Tolerate specific minor invalidities to support backward compatibility. + internal override void ParsePropertiesV4(Model model, List objectPropertyInfoList, List elementPropertyConstraints, AggregateContext aggregateContext, HashSet immediateSupplementalTypeIds, List immediateUndefinedTypes, ParsingErrorCollection parsingErrorCollection, JsonLdElement elt, string layer, Dtmi definedIn, bool globalize, bool allowReservedIds, bool tolerateSolecisms) + { + this.LanguageMajorVersion = 4; + + JsonLdProperty commentProperty = null; + JsonLdProperty descriptionProperty = null; + JsonLdProperty displayNameProperty = null; + Dictionary supplementalJsonLdProperties = new Dictionary(); + + foreach (JsonLdProperty prop in elt.Properties) + { + switch (prop.Name) + { + case "comment": + case "dtmi:dtdl:property:comment;4": + if (commentProperty != null) + { + parsingErrorCollection.Notify( + "duplicatePropertyName", + elementId: this.Id, + propertyName: "comment", + incidentProperty: prop, + extantProperty: commentProperty, + layer: layer); + } + else + { + commentProperty = prop; + int? maxLength = aggregateContext.LimitSpecifier switch + { + "" => 512, + "onvif_1" => 515, + _ => null, + }; + + string newComment = ValueParser.ParseSingularStringValueCollection(aggregateContext, this.Id, "comment", prop.Values, maxLength, null, layer, parsingErrorCollection, isOptional: true); + if (this.commentPropertyLayer != null) + { + if (this.Comment != newComment) + { + JsonLdProperty extantProp = this.JsonLdElements[this.commentPropertyLayer].Properties.FirstOrDefault(p => p.Name == "comment"); + parsingErrorCollection.Notify( + "inconsistentStringValues", + elementId: this.Id, + propertyName: "comment", + propertyValue: newComment.ToString(), + valueRestriction: this.Comment.ToString(), + incidentProperty: prop, + extantProperty: extantProp, + layer: layer); + } + } + else + { + this.Comment = newComment; + this.commentPropertyLayer = layer; + + if (this.commentValueConstraints != null) + { + foreach (ValueConstraint valueConstraint in this.commentValueConstraints) + { + if (valueConstraint.RequiredLiteral != null && !valueConstraint.RequiredLiteral.Equals(newComment)) + { + parsingErrorCollection.Notify( + "notRequiredStringValue", + elementId: this.Id, + propertyName: "comment", + propertyValue: newComment.ToString(), + valueRestriction: valueConstraint.RequiredLiteral.ToString(), + incidentProperty: prop, + layer: layer); + } + } + } + + ((Dictionary)this.StringProperties)["comment"] = newComment; + } + } + + continue; + case "description": + case "dtmi:dtdl:property:description;4": + if (descriptionProperty != null) + { + parsingErrorCollection.Notify( + "duplicatePropertyName", + elementId: this.Id, + propertyName: "description", + incidentProperty: prop, + extantProperty: descriptionProperty, + layer: layer); + } + else + { + descriptionProperty = prop; + int? maxLength = aggregateContext.LimitSpecifier switch + { + "" => 512, + "onvif_1" => 514, + _ => null, + }; + + Dictionary newDescription = ValueParser.ParseLangStringValueCollection(aggregateContext, this.Id, "description", prop.Values, "en", maxLength, null, layer, parsingErrorCollection); + List descriptionCodes = Helpers.GetKeysWithDifferingLiteralValues(this.Description, newDescription); + if (descriptionCodes.Any()) + { + JsonLdProperty extantProp = Helpers.TryGetSingleUniqueValue(descriptionCodes.Select(c => this.descriptionPropertyLayer[c]), out string uniqueCodeLayer) && this.JsonLdElements[uniqueCodeLayer].Properties.Any(p => p.Name == "description") ? this.JsonLdElements[uniqueCodeLayer].Properties.First(p => p.Name == "description") : null; + parsingErrorCollection.Notify( + "inconsistentLangStringValues", + elementId: this.Id, + propertyName: "description", + langCode: string.Join(" and ", descriptionCodes.Select(c => $"'{c}'")), + observedCount: descriptionCodes.Count, + incidentProperty: prop, + extantProperty: extantProp, + layer: layer); + } + else if (this.Description.Any()) + { + foreach (KeyValuePair kvp in newDescription) + { + ((Dictionary)this.Description)[kvp.Key] = kvp.Value; + this.descriptionPropertyLayer[kvp.Key] = layer; + } + } + else + { + this.Description = newDescription; + this.descriptionPropertyLayer = newDescription.ToDictionary(e => e.Key, e => layer); + } + } + + continue; + case "displayName": + case "dtmi:dtdl:property:displayName;4": + if (displayNameProperty != null) + { + parsingErrorCollection.Notify( + "duplicatePropertyName", + elementId: this.Id, + propertyName: "displayName", + incidentProperty: prop, + extantProperty: displayNameProperty, + layer: layer); + } + else + { + displayNameProperty = prop; + int? maxLength = aggregateContext.LimitSpecifier switch + { + "" => 512, + "onvif_1" => 513, + _ => null, + }; + + Dictionary newDisplayName = ValueParser.ParseLangStringValueCollection(aggregateContext, this.Id, "displayName", prop.Values, "en", maxLength, null, layer, parsingErrorCollection); + List displayNameCodes = Helpers.GetKeysWithDifferingLiteralValues(this.DisplayName, newDisplayName); + if (displayNameCodes.Any()) + { + JsonLdProperty extantProp = Helpers.TryGetSingleUniqueValue(displayNameCodes.Select(c => this.displayNamePropertyLayer[c]), out string uniqueCodeLayer) && this.JsonLdElements[uniqueCodeLayer].Properties.Any(p => p.Name == "displayName") ? this.JsonLdElements[uniqueCodeLayer].Properties.First(p => p.Name == "displayName") : null; + parsingErrorCollection.Notify( + "inconsistentLangStringValues", + elementId: this.Id, + propertyName: "displayName", + langCode: string.Join(" and ", displayNameCodes.Select(c => $"'{c}'")), + observedCount: displayNameCodes.Count, + incidentProperty: prop, + extantProperty: extantProp, + layer: layer); + } + else if (this.DisplayName.Any()) + { + foreach (KeyValuePair kvp in newDisplayName) + { + ((Dictionary)this.DisplayName)[kvp.Key] = kvp.Value; + this.displayNamePropertyLayer[kvp.Key] = layer; + } + } + else + { + this.DisplayName = newDisplayName; + this.displayNamePropertyLayer = newDisplayName.ToDictionary(e => e.Key, e => layer); + } + } + + continue; + } + + if (this.TryParseSupplementalProperty(model, immediateSupplementalTypeIds, objectPropertyInfoList, elementPropertyConstraints, aggregateContext, layer, definedIn, parsingErrorCollection, prop.Name, globalize, allowReservedIds, tolerateSolecisms, prop, supplementalJsonLdProperties)) + { + continue; + } + + if (aggregateContext.TryCreateDtmi(prop.Name, out Dtmi _)) + { + if (aggregateContext.IsComplete) + { + parsingErrorCollection.Notify( + "propertyIrrelevantDtmiOrTerm", + elementId: this.Id, + propertyName: prop.Name, + incidentProperty: prop, + element: elt, + layer: layer); + continue; + } + } + else if (prop.Name.StartsWith("dtmi:")) + { + parsingErrorCollection.Notify( + "propertyInvalidDtmi", + elementId: this.Id, + propertyName: prop.Name, + incidentProperty: prop, + element: elt, + layer: layer); + continue; + } + else if (prop.Name.Contains(":")) + { + parsingErrorCollection.Notify( + "propertyNotDtmiNorTerm", + elementId: this.Id, + propertyName: prop.Name, + incidentProperty: prop, + element: elt, + layer: layer); + continue; + } + else + { + if (aggregateContext.IsComplete) + { + parsingErrorCollection.Notify( + "propertyUndefinedTerm", + elementId: this.Id, + propertyName: prop.Name, + incidentProperty: prop, + element: elt, + version: aggregateContext.DtdlVersion.ToString(), + layer: layer); + continue; + } + } + + if (!immediateUndefinedTypes.Any()) + { + if (elt.Types != null) + { + parsingErrorCollection.Notify( + "noTypeThatAllows", + elementId: this.Id, + propertyName: prop.Name, + incidentProperty: prop, + element: elt, + layer: layer); + } + else + { + parsingErrorCollection.Notify( + "inferredTypeDoesNotAllow", + elementId: this.Id, + referenceType: "Short", + propertyName: prop.Name, + incidentProperty: prop, + element: elt, + layer: layer); + } + + continue; + } + + using (JsonDocument propDoc = JsonDocument.Parse(prop.Values.GetJsonText())) + { + this.UndefinedPropertyDictionary[prop.Name] = propDoc.RootElement.Clone(); + } + } + + foreach (Dtmi supplementalTypeId in immediateSupplementalTypeIds) + { + if (aggregateContext.SupplementalTypeCollection.TryGetSupplementalTypeInfo(supplementalTypeId, out DTSupplementalTypeInfo supplementalTypeInfo)) + { + supplementalTypeInfo.CheckForRequiredProperties(parsingErrorCollection, this.Id, elt, supplementalJsonLdProperties); + } + } + } + + /// + /// Record JSON-LD source as appropriate and check length of text against limit. + /// + /// The name of the layer whose source to record. + /// A JsonLdElement containing the JSON-LD source of the element. + /// An AggregateContext object representing information retrieved from JSON-LD context blocks. + /// A ParsingErrorCollection to which any parsing errors are added. + /// True if the element is at the document root. + /// True if the element has been globalized. + internal override void RecordSourceAsAppropriate(string layer, JsonLdElement elt, AggregateContext aggregateContext, ParsingErrorCollection parsingErrorCollection, bool atRoot, bool globalized) + { + } + + /// + /// Write a JSON representation of the DTDL element represented by an object of this class. + /// + /// A Utf8JsonWriter object with which to write the JSON representation. + /// True if the mothed should add a ClassId property to the JSON object. + internal override void WriteToJson(Utf8JsonWriter jsonWriter, bool includeClassId) + { + base.WriteToJson(jsonWriter, includeClassId: false); + + if (includeClassId) + { + jsonWriter.WriteString("ClassId", $"dtmi:dtdl:class:Short;{this.LanguageMajorVersion}"); + } + } + + private bool DoesInstanceMatchV4(JsonElement instanceElt, string instanceName) + { + return true; + } + + private bool TryParseSupplementalProperty(Model model, HashSet immediateSupplementalTypeIds, List objectPropertyInfoList, List elementPropertyConstraints, AggregateContext aggregateContext, string layer, Dtmi definedIn, ParsingErrorCollection parsingErrorCollection, string propName, bool globalize, bool allowReservedIds, bool tolerateSolecisms, JsonLdProperty valueCollectionProp, Dictionary supplementalJsonLdProperties) + { + if (!aggregateContext.TryCreateDtmi(propName, out Dtmi propDtmi)) + { + return false; + } + + foreach (Dtmi supplementalTypeId in immediateSupplementalTypeIds) + { + if (aggregateContext.SupplementalTypeCollection.TryGetSupplementalTypeInfo(supplementalTypeId, out DTSupplementalTypeInfo supplementalTypeInfo) && supplementalTypeInfo.TryParseProperty(model, objectPropertyInfoList, elementPropertyConstraints, aggregateContext, parsingErrorCollection, layer, this.Id, definedIn, propDtmi.ToString(), globalize, allowReservedIds, tolerateSolecisms, valueCollectionProp, ref this.supplementalProperties, supplementalJsonLdProperties, this.supplementalSingularPropertyLayers, this.JsonLdElements)) + { + return true; + } + } + + return false; + } + + private bool ValidateInstanceV4(JsonElement instanceElt, string instanceName, List violations) + { + if (instanceElt.ValueKind != JsonValueKind.Number) + { + violations.Add($">>{instanceElt.GetRawText()}<< is not a numeric value"); + return false; + } + + if (!short.TryParse(instanceElt.GetRawText(), out short _)) + { + violations.Add($"{instanceElt.GetRawText()} does not conform to the XSD definition of 'short'"); + return false; + } + + return true; + } + + private void ApplyTransformationsV4(Model model, ParsingErrorCollection parsingErrorCollection) + { + } + + /// + private void CheckRestrictionsV4(ParsingErrorCollection parsingErrorCollection) + { + } + } +} diff --git a/dotnet/src/DTDLParser/generated/DTUnsignedByteInfo.g.cs b/dotnet/src/DTDLParser/generated/DTUnsignedByteInfo.g.cs new file mode 100644 index 00000000..59775419 --- /dev/null +++ b/dotnet/src/DTDLParser/generated/DTUnsignedByteInfo.g.cs @@ -0,0 +1,1895 @@ +/* This is an auto-generated file. Do not modify. */ + +namespace DTDLParser.Models +{ + using System; + using System.Collections.Generic; + using System.ComponentModel; + using System.Globalization; + using System.IO; + using System.Linq; + using System.Text; + using System.Text.Json; + using System.Text.RegularExpressions; + using System.Threading; + using System.Threading.Tasks; + using DTDLParser; + + /// + /// Class DTUnsignedByteInfo corresponds to an element of type UnsignedByte in a DTDL model. + /// + public class DTUnsignedByteInfo : DTNumericSchemaInfo, ITypeChecker, IConstrainer, IEquatable + { + private static readonly Dictionary> ConcreteKinds = new Dictionary>(); + + private static readonly Dictionary BadTypeActionFormat = new Dictionary(); + + private static readonly Dictionary BadTypeCauseFormat = new Dictionary(); + + private static readonly Dictionary BadTypeLocatedCauseFormat = new Dictionary(); + + private static readonly HashSet PropertyNames = new HashSet(); + + private static readonly HashSet VersionlessTypes = new HashSet(); + + private static readonly Regex ElementValueInstanceRegexPatternV4 = new Regex(@"^[0-9]+$", RegexOptions.Compiled); + + private bool checkedForDescendantSchemaArray = false; + + private bool checkedForDescendantSchemaOrContentsComponentNarrow = false; + + private Dictionary supplementalPropertySources = new Dictionary(); + + private Dictionary eltsOfDescendantSchemaArray = null; + + private Dictionary eltsOfDescendantSchemaOrContentsComponentNarrow = null; + + private Dictionary supplementalProperties; + + private Dictionary descriptionPropertyLayer = null; + + private Dictionary displayNamePropertyLayer = null; + + private Dictionary supplementalSingularPropertyLayers = new Dictionary(); + + private Dtmi idOfDescendantSchemaArray = null; + + private Dtmi idOfDescendantSchemaOrContentsComponentNarrow = null; + + private HashSet supplementalTypeIds; + + private int countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowValue = 0; + + private int countOfExtendsNarrowValue = 0; + + private List supplementalTypes; + + private List commentValueConstraints = null; + + private List descriptionValueConstraints = null; + + private List displayNameValueConstraints = null; + + private string commentPropertyLayer = null; + + private TraversalStatus countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowStatus = TraversalStatus.NotStarted; + + private TraversalStatus countOfExtendsNarrowStatus = TraversalStatus.NotStarted; + + private Type checkedDescendantEnumValueDatatype = null; + + static DTUnsignedByteInfo() + { + VersionlessTypes.Add("dtmi:dtdl:class:Entity"); + VersionlessTypes.Add("dtmi:dtdl:class:NumericSchema"); + VersionlessTypes.Add("dtmi:dtdl:class:PrimitiveSchema"); + VersionlessTypes.Add("dtmi:dtdl:class:Schema"); + VersionlessTypes.Add("dtmi:dtdl:class:UnsignedByte"); + + PropertyNames.Add("comment"); + PropertyNames.Add("description"); + PropertyNames.Add("displayName"); + PropertyNames.Add("languageMajorVersion"); + + ConcreteKinds[4] = new HashSet(); + ConcreteKinds[4].Add(DTEntityKind.UnsignedByte); + + BadTypeActionFormat[4] = "Use this standard value for property '{property}'{line1}: unsignedByte."; + + BadTypeCauseFormat[4] = "{layer}{primaryId:p} property '{property}' has value{secondaryId:e} that is not a standard value for this property."; + + BadTypeLocatedCauseFormat[4] = "In {sourceName1}, property '{property}'{line1} has value{secondaryId:e}{line2} that is not a standard value for this property."; + } + + /// + /// Initializes a new instance of the class. + /// + /// Version of DTDL used to define the UnsignedByte. + /// Identifier for the UnsignedByte. + /// Identifier of the parent element in which this UnsignedByte is defined. + /// Name of the property by which the parent DTDL element refers to this UnsignedByte. + /// Identifier of the partition in which this UnsignedByte is defined. + internal DTUnsignedByteInfo(int dtdlVersion, Dtmi id, Dtmi childOf, string myPropertyName, Dtmi definedIn) + : base(dtdlVersion, id, childOf, myPropertyName, definedIn, DTEntityKind.UnsignedByte) + { + this.supplementalTypeIds = new HashSet(); + this.supplementalProperties = new Dictionary(); + this.supplementalTypes = new List(); + + this.IsPartition = false; + + this.MaybePartial = false; + } + + /// + /// Initializes a new instance of the class. + /// + /// Version of DTDL used to define the UnsignedByte. + /// Identifier for the UnsignedByte. + /// Identifier of the parent element in which this UnsignedByte is defined. + /// Name of the property by which the parent DTDL element refers to this UnsignedByte. + /// Identifier of the partition in which this UnsignedByte is defined. + /// The kind of Entity, which may be other than UnsignedByte if this constructor is called from a derived class. + internal DTUnsignedByteInfo(int dtdlVersion, Dtmi id, Dtmi childOf, string myPropertyName, Dtmi definedIn, DTEntityKind entityKind) + : base(dtdlVersion, id, childOf, myPropertyName, definedIn, entityKind) + { + this.supplementalTypeIds = new HashSet(); + this.supplementalProperties = new Dictionary(); + this.supplementalTypes = new List(); + + this.IsPartition = false; + + this.MaybePartial = false; + } + + /// + /// Get the DTMI that identifies type UnsignedByte in the version of DTDL used to define this element. + /// + /// The DTMI for the DTDL type UnsignedByte. + public override Dtmi ClassId + { + get + { + return new Dtmi($"dtmi:dtdl:class:UnsignedByte;{this.LanguageMajorVersion}"); + } + } + + /// + /// Gets the supplemantal properties of the DTDL element that corresponds to this object. + /// + /// A dictionary that maps each string-valued property name to an object that holds the value of the property with the given name. + /// + /// If the property is a literal in the DTDL model, the object holds a literal value. + /// If the property is another DTDL element in the model, the object is the C# object that corresponds to this element. + /// + public override IDictionary SupplementalProperties + { + get + { + return this.supplementalProperties; + } + } + + /// + /// Gets a collection of identifiers, each of which is a Dtmi that indicates a supplemental type that applies to the DTDL element that corresponds to this object. + /// + /// A collection of DTMIs indicating the supplemental types that apply to the DTDL element. + public override IReadOnlyCollection SupplementalTypes + { + get + { + return this.supplementalTypeIds; + } + } + + /// + /// Gets a value indicating whether this class is a partition point for the object model. + /// + internal override bool IsPartition { get; } + + /// + /// Gets material properties allowed by the type of DTDL element. + /// + internal override HashSet MaterialProperties + { + get + { + return PropertyNames; + } + } + + /// + /// Determines whether two DTUnsignedByteInfo objects are not equal. + /// + /// One DTUnsignedByteInfo object to compare. + /// Another DTUnsignedByteInfo object to compare to the first. + /// True if not equal. + public static bool operator !=(DTUnsignedByteInfo x, DTUnsignedByteInfo y) + { + if (ReferenceEquals(null, x)) + { + return !ReferenceEquals(null, y); + } + + return !x.Equals(y); + } + + /// + /// Determines whether two DTUnsignedByteInfo objects are equal. + /// + /// One DTUnsignedByteInfo object to compare. + /// Another DTUnsignedByteInfo object to compare to the first. + /// True if equal. + public static bool operator ==(DTUnsignedByteInfo x, DTUnsignedByteInfo y) + { + if (ReferenceEquals(null, x)) + { + return ReferenceEquals(null, y); + } + + return x.Equals(y); + } + + /// + /// Compares to another DTUnsignedByteInfo object, recursing through the entire subtree of object properties. + /// + /// The other DTUnsignedByteInfo object to compare to. + /// True if equal. + public virtual bool DeepEquals(DTUnsignedByteInfo other) + { + return base.DeepEquals(other) + && Helpers.AreDictionariesDeepOrLiteralEqual(this.supplementalProperties, other.supplementalProperties) + && this.supplementalTypeIds.SetEquals(other.supplementalTypeIds) + ; + } + + /// + public override bool DeepEquals(DTNumericSchemaInfo other) + { + return this.EntityKind == other?.EntityKind && this.DeepEquals((DTUnsignedByteInfo)other); + } + + /// + public override bool DeepEquals(DTPrimitiveSchemaInfo other) + { + return this.EntityKind == other?.EntityKind && this.DeepEquals((DTUnsignedByteInfo)other); + } + + /// + public override bool DeepEquals(DTSchemaInfo other) + { + return this.EntityKind == other?.EntityKind && this.DeepEquals((DTUnsignedByteInfo)other); + } + + /// + public override bool DeepEquals(DTEntityInfo other) + { + return this.EntityKind == other?.EntityKind && this.DeepEquals((DTUnsignedByteInfo)other); + } + + /// + /// Compares to another DTUnsignedByteInfo object. + /// + /// The other DTUnsignedByteInfo object to compare to. + /// True if equal. + public virtual bool Equals(DTUnsignedByteInfo other) + { + return base.Equals(other) + && Helpers.AreDictionariesIdOrLiteralEqual(this.supplementalProperties, other.supplementalProperties) + && this.supplementalTypeIds.SetEquals(other.supplementalTypeIds) + ; + } + + /// + public override bool Equals(DTNumericSchemaInfo other) + { + return this.EntityKind == other?.EntityKind && this.Equals((DTUnsignedByteInfo)other); + } + + /// + public override bool Equals(DTPrimitiveSchemaInfo other) + { + return this.EntityKind == other?.EntityKind && this.Equals((DTUnsignedByteInfo)other); + } + + /// + public override bool Equals(DTSchemaInfo other) + { + return this.EntityKind == other?.EntityKind && this.Equals((DTUnsignedByteInfo)other); + } + + /// + public override bool Equals(DTEntityInfo other) + { + return this.EntityKind == other?.EntityKind && this.Equals((DTUnsignedByteInfo)other); + } + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object otherObj) + { + return otherObj is DTUnsignedByteInfo other && this.Equals(other); + } + + /// + bool ITypeChecker.DoesHaveType(Dtmi typeId) + { + return VersionlessTypes.Contains(typeId.Versionless) + || this.supplementalTypes.Any(ps => ((ITypeChecker)ps).DoesHaveType(typeId)) + ; + } + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() + { + int hashCode = base.GetHashCode(); + + unchecked + { + hashCode = (hashCode * 131) + Helpers.GetDictionaryIdOrLiteralHashCode(this.supplementalProperties); + hashCode = (hashCode * 131) + Helpers.GetSetLiteralHashCode(this.supplementalTypeIds); + } + + return hashCode; + } + + /// + /// Validate a JsonElement to determine whether it is a numeric value that conforms to the XSD definition of 'unsignedByte'. + /// + /// The JsonElement to validate. + /// A list of strings that each indicate a validation failure; the list is empty if the JsonElement conforms. + public override IReadOnlyCollection ValidateInstance(JsonElement instanceElt) + { + List violations = new List(); + this.ValidateInstance(instanceElt, null, violations); + return violations; + } + + /// + void IConstrainer.AddPropertyValueConstraint(string propertyName, ValueConstraint valueConstraint) + { + switch (propertyName) + { + case "comment": + if (this.commentValueConstraints == null) + { + this.commentValueConstraints = new List(); + } + + this.commentValueConstraints.Add(valueConstraint); + break; + case "description": + if (this.descriptionValueConstraints == null) + { + this.descriptionValueConstraints = new List(); + } + + this.descriptionValueConstraints.Add(valueConstraint); + break; + case "displayName": + if (this.displayNameValueConstraints == null) + { + this.displayNameValueConstraints = new List(); + } + + this.displayNameValueConstraints.Add(valueConstraint); + break; + } + } + + /// + void IConstrainer.AddSiblingConstraint(SiblingConstraint siblingConstraint) + { + if (this.SiblingConstraints == null) + { + this.SiblingConstraints = new List(); + } + + this.SiblingConstraints.Add(siblingConstraint); + } + + /// + /// Parse an element encoded in a into an object that is a subclass of type DTUnsignedByteInfo. + /// + /// The model to add the element to. + /// A list of ParsedObjectPropertyInfo to add any object properties, which will be assigned after all parsing has completed. + /// List of ElementPropertyConstraint to be checked after object property assignment. + /// List of to be added to . + /// An AggregateContext object representing information retrieved from JSON-LD context blocks. + /// A ParsingErrorCollection to which any parsing errors are added. + /// The to parse. + /// Name of the layer currently being parsed. + /// The identifier of the parent of the element. + /// Identifier of the partition or top-level element under which this element is defined. + /// The name of the property by which the parent refers to this element, used for auto ID generation. + /// The representing the source of the property by which the parent refers to this element. + /// A DTMI segment identifier, used for auto ID generation. + /// A property used for the key if the parent exposes a collection of these elements as a dictionary. + /// A boolean value indicating whether an @id must be present. + /// A boolean value indicating whether a @type must be present. + /// Treat all nested definitions as though defined globally. + /// Allow elements to define IDs that have reserved prefixes. + /// Tolerate specific minor invalidities to support backward compatibility. + /// A set of allowed versions for the element. + /// The type name to infer if no @type specified on element. + /// True if the parses correctly as an appropriate element. + internal static new bool TryParseElement(Model model, List objectPropertyInfoList, List elementPropertyConstraints, List valueConstraints, AggregateContext aggregateContext, ParsingErrorCollection parsingErrorCollection, JsonLdElement elt, string layer, Dtmi parentId, Dtmi definedIn, string propName, JsonLdProperty propProp, string dtmiSeg, string keyProp, bool idRequired, bool typeRequired, bool globalize, bool allowReservedIds, bool tolerateSolecisms, HashSet allowedVersions, string inferredType) + { + AggregateContext childAggregateContext = aggregateContext.GetChildContext(elt, parsingErrorCollection); + + bool allowIdReferenceSyntax = tolerateSolecisms && aggregateContext.DtdlVersion < 3; + + if (elt.PropertyCount == 1 && elt.Id != null) + { + if (allowIdReferenceSyntax) + { + if (TryParseIdString(objectPropertyInfoList, elementPropertyConstraints, valueConstraints, childAggregateContext, parsingErrorCollection, elt.Id, layer, parentId, propName, propProp, keyProp, allowedVersions)) + { + return true; + } + else + { + parsingErrorCollection.Notify( + "idRefBadDtmiOrTerm", + elementId: parentId, + propertyName: propName, + propertyValue: elt.Id, + element: elt, + version: aggregateContext.DtdlVersion.ToString(), + layer: layer); + return false; + } + } + else + { + parsingErrorCollection.Notify( + "idReference", + elementId: parentId, + propertyName: propName, + identifier: elt.Id, + element: elt, + layer: layer); + return false; + } + } + + if (elt.Graph != null) + { + parsingErrorCollection.Notify( + "graphDisallowed", + elementId: parentId, + propertyName: propName, + element: elt); + } + + if (childAggregateContext.RestrictKeywords) + { + if (elt.Language != null) + { + parsingErrorCollection.Notify( + "keywordDisallowed", + elementId: parentId, + propertyName: propName, + keyword: "@language", + element: elt); + } + + if (elt.Value != null) + { + parsingErrorCollection.Notify( + "keywordDisallowed", + elementId: parentId, + propertyName: propName, + keyword: "@value", + element: elt); + } + + foreach (string keyword in elt.Keywords) + { + parsingErrorCollection.Notify( + "keywordDisallowed", + elementId: parentId, + propertyName: propName, + keyword: keyword, + element: elt); + } + } + + if (allowedVersions != null && !allowedVersions.Contains(childAggregateContext.DtdlVersion)) + { + parsingErrorCollection.Notify( + "disallowedVersionDefinition", + elementId: parentId, + propertyName: propName, + version: childAggregateContext.DtdlVersion.ToString(), + versionRestriction: string.Join(" ,", allowedVersions), + contextComponent: childAggregateContext.DtdlContextComponent, + layer: layer); + } + + bool tolerateReservedIds = tolerateSolecisms && aggregateContext.DtdlVersion < 3; + + Dtmi elementId = IdValidator.ParseIdProperty(childAggregateContext, elt, childAggregateContext.MergeDefinitions ? layer : null, parentId, propName, dtmiSeg, idRequired, allowReservedIds || tolerateReservedIds, parsingErrorCollection); + + Dtmi baseElementId = childAggregateContext.MergeDefinitions || elementId.Tail == string.Empty ? elementId.Fragmentless : elementId; + string elementLayer = childAggregateContext.MergeDefinitions ? elementId.Tail : string.Empty; + + bool ignoreElementsWithAutoIDsAndDuplicateNames = tolerateSolecisms && aggregateContext.DtdlVersion < 3; + + if (model.Dict.TryGetValue(baseElementId, out DTEntityInfo baseElement)) + { + if (baseElement.JsonLdElements.TryGetValue(elementLayer, out JsonLdElement duplicateElt)) + { + if (!baseElementId.IsReserved) + { + parsingErrorCollection.Notify( + "duplicateDefinition", + elementId: baseElementId, + element: elt, + extantElement: duplicateElt, + layer: layer); + } + else if (!ignoreElementsWithAutoIDsAndDuplicateNames && dtmiSeg != null) + { + JsonLdProperty dtmiSegProp = elt.Properties.First(p => p.Name == dtmiSeg || (Dtmi.TryCreateDtmi(p.Name, out Dtmi d) && ContextCollection.GetTermOrUri(d) == dtmiSeg)); + JsonLdProperty dupSegProp = duplicateElt.Properties.First(p => p.Name == dtmiSeg || (Dtmi.TryCreateDtmi(p.Name, out Dtmi d) && ContextCollection.GetTermOrUri(d) == dtmiSeg)); + parsingErrorCollection.Notify( + "nonUniquePropertyValue", + elementId: parentId, + propertyName: propName, + nestedName: dtmiSeg, + nestedValue: dtmiSegProp.Values.Values.First().StringValue, + incidentProperty: dupSegProp, + extantProperty: dtmiSegProp); + } + + return false; + } + + if (baseElement.DtdlVersion != childAggregateContext.DtdlVersion) + { + parsingErrorCollection.Notify( + "inconsistentContext", + elementId: baseElementId, + version: childAggregateContext.DtdlVersion.ToString(), + versionRestriction: baseElement.DtdlVersion.ToString(), + layer: elementLayer); + return false; + } + } + + if (typeRequired && elt.Types == null) + { + string sourceName1 = null; + int sourceLine1 = 0; + if (propProp != null && propProp.TryGetSourceLocation(out sourceName1, out sourceLine1) && elt.TryGetSourceLocation(out string sourceName2, out int startLine2, out int endLine2)) + { + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeLocatedCauseFormat[childAggregateContext.DtdlVersion], + BadTypeActionFormat[childAggregateContext.DtdlVersion], + primaryId: parentId, + property: propName, + secondaryId: baseElementId, + layer: layer, + sourceName1: sourceName1, + startLine1: sourceLine1, + sourceName2: sourceName2, + startLine2: startLine2, + endLine2: endLine2); + } + else + { + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeCauseFormat[childAggregateContext.DtdlVersion], + BadTypeActionFormat[childAggregateContext.DtdlVersion], + primaryId: parentId, + property: propName, + secondaryId: baseElementId, + layer: layer); + } + + return false; + } + + DTUnsignedByteInfo elementInfo = (DTUnsignedByteInfo)baseElement; + HashSet immediateSupplementalTypeIds; + List immediateUndefinedTypes; + bool typeArrayParsed; + if (elt.Types == null) + { + typeArrayParsed = TryParseTypeStrings(new List() { inferredType }, baseElementId, elementLayer, elt, parentId, definedIn, propName, propProp, ref elementInfo, childAggregateContext, out immediateSupplementalTypeIds, out immediateUndefinedTypes, parsingErrorCollection); + } + else + { + typeArrayParsed = TryParseTypeStrings(elt.Types, baseElementId, elementLayer, elt, parentId, definedIn, propName, propProp, ref elementInfo, childAggregateContext, out immediateSupplementalTypeIds, out immediateUndefinedTypes, parsingErrorCollection); + } + + if (!typeArrayParsed || ReferenceEquals(null, elementInfo)) + { + return false; + } + + switch (childAggregateContext.DtdlVersion) + { + case 4: + elementInfo.ParsePropertiesV4(model, objectPropertyInfoList, elementPropertyConstraints, childAggregateContext, immediateSupplementalTypeIds, immediateUndefinedTypes, parsingErrorCollection, elt, elementLayer, definedIn, globalize, allowReservedIds, tolerateSolecisms); + break; + } + + elementInfo.LimitSpecifier = aggregateContext.LimitSpecifier; + + elementInfo.RecordSourceAsAppropriate(elementLayer, elt, childAggregateContext, parsingErrorCollection, atRoot: parentId == null, globalized: globalize); + + model.Dict[baseElementId] = elementInfo; + + if (parentId != null) + { + objectPropertyInfoList.Add(new ParsedObjectPropertyInfo() { ElementId = parentId, PropertyName = propName, Layer = layer, JsonLdProperty = propProp, ReferencedElementId = baseElementId, KeyProperty = keyProp, ExpectedKinds = null, AllowedVersions = null, ChildOf = null, BadTypeCauseFormat = null, BadTypeLocatedCauseFormat = null, BadTypeActionFormat = null }); + + if (valueConstraints != null && elementPropertyConstraints != null) + { + foreach (ValueConstraint valueConstraint in valueConstraints) + { + elementPropertyConstraints.Add(new ElementPropertyConstraint() { ParentId = parentId, PropertyName = propName, ElementId = baseElementId, ValueConstraint = valueConstraint }); + } + } + } + + return true; + } + + /// + /// Parse a string property value as an identifier for type DTUnsignedByteInfo. + /// + /// A list of ParsedObjectPropertyInfo to add any object properties, which will be assigned after all parsing has completed. + /// List of ElementPropertyConstraint to be checked after object property assignment. + /// List of to be added to . + /// An AggregateContext object representing information retrieved from JSON-LD context blocks. + /// A ParsingErrorCollection to which any parsing errors are added. + /// The identifier string to parse. + /// Name of the layer currently being parsed. + /// The identifier of the parent of the element. + /// The name of the property by which the parent refers to this element, used for auto ID generation. + /// The representing the source of the property by which the parent refers to this element. + /// A property used for the key if the parent exposes a collection of these elements as a dictionary. + /// A set of allowed versions for the element. + /// True if the string parses correctly as an identifier. + internal static new bool TryParseIdString(List objectPropertyInfoList, List elementPropertyConstraints, List valueConstraints, AggregateContext aggregateContext, ParsingErrorCollection parsingErrorCollection, string idString, string layer, Dtmi parentId, string propName, JsonLdProperty propProp, string keyProp, HashSet allowedVersions) + { + if (!aggregateContext.TryCreateDtmi(idString, out Dtmi elementId)) + { + return false; + } + + objectPropertyInfoList.Add(new ParsedObjectPropertyInfo() { ElementId = parentId, PropertyName = propName, Layer = layer, JsonLdProperty = propProp, ReferencedIdString = idString, ReferencedElementId = elementId, KeyProperty = keyProp, ExpectedKinds = ConcreteKinds[aggregateContext.DtdlVersion], AllowedVersions = allowedVersions, ChildOf = null, BadTypeCauseFormat = BadTypeCauseFormat[aggregateContext.DtdlVersion], BadTypeLocatedCauseFormat = BadTypeLocatedCauseFormat[aggregateContext.DtdlVersion], BadTypeActionFormat = BadTypeActionFormat[aggregateContext.DtdlVersion] }); + + if (valueConstraints != null && elementPropertyConstraints != null) + { + foreach (ValueConstraint valueConstraint in valueConstraints) + { + elementPropertyConstraints.Add(new ElementPropertyConstraint() { ParentId = parentId, PropertyName = propName, ElementId = elementId, ValueConstraint = valueConstraint }); + } + } + + return true; + } + + /// + /// Parse a list of @type values containing material or supplemental types. + /// + /// The list of strings to parse. + /// The identifier of the element of this type to create. + /// Name of the layer currently being parsed. + /// The currently being parsed. + /// The identifier of the parent of the element. + /// Identifier of the partition or top-level element under which this element is defined. + /// The name of the property by which the parent refers to this element, used for auto ID generation. + /// The representing the source of the property by which the parent refers to this element. + /// The created. + /// An AggregateContext object representing information retrieved from JSON-LD context blocks. + /// A set of supplemental type IDs from the type array. + /// A list of undefind type strings from the type array. + /// A ParsingErrorCollection to which any parsing errors are added. + /// True if no errors detected in type array. + internal static bool TryParseTypeStrings(List typeStrings, Dtmi elementId, string layer, JsonLdElement elt, Dtmi parentId, Dtmi definedIn, string propName, JsonLdProperty propProp, ref DTUnsignedByteInfo elementInfo, AggregateContext aggregateContext, out HashSet immediateSupplementalTypeIds, out List immediateUndefinedTypes, ParsingErrorCollection parsingErrorCollection) + { + immediateSupplementalTypeIds = new HashSet(); + immediateUndefinedTypes = new List(); + + HashSet materialKinds = new HashSet(); + + bool anyFailures = false; + foreach (string typeString in typeStrings) + { + switch (aggregateContext.DtdlVersion) + { + case 4: + if (!TryParseTypeStringV4(typeString, elementId, layer, elt, parentId, definedIn, propName, propProp, materialKinds, immediateSupplementalTypeIds, ref elementInfo, ref immediateUndefinedTypes, aggregateContext, parsingErrorCollection)) + { + anyFailures = true; + } + + break; + } + } + + if (anyFailures) + { + return false; + } + + if (ReferenceEquals(null, elementInfo)) + { + string sourceName1 = null; + int sourceLine1 = 0; + if (propProp != null && propProp.TryGetSourceLocation(out sourceName1, out sourceLine1) && elt.TryGetSourceLocation(out string sourceName2, out int startLine2, out int endLine2)) + { + elt.TryGetSourceLocationForType(out _, out int sourceLine3); + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeLocatedCauseFormat[aggregateContext.DtdlVersion], + BadTypeActionFormat[aggregateContext.DtdlVersion], + primaryId: parentId, + property: propName, + secondaryId: elementId, + layer: layer, + sourceName1: sourceName1, + startLine1: sourceLine1, + sourceName2: sourceName2, + startLine2: startLine2, + endLine2: endLine2, + startLine3: sourceLine3); + } + else + { + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeCauseFormat[aggregateContext.DtdlVersion], + BadTypeActionFormat[aggregateContext.DtdlVersion], + primaryId: parentId, + property: propName, + secondaryId: elementId, + layer: layer); + } + + return false; + } + + if (!materialKinds.Any()) + { + parsingErrorCollection.Notify( + "layerMissingMaterialType", + elementId: elementId, + elementType: elementInfo.EntityKind.ToString(), + element: elt, + layer: layer); + return false; + } + + materialKinds.Add(elementInfo.EntityKind); + if (materialKinds.Count() > 1) + { + parsingErrorCollection.Notify( + "multipleMaterialTypes", + elementId: elementId, + valueConjunction: string.Join(" and ", materialKinds), + element: elt, + layer: layer); + return false; + } + + elementInfo.UndefinedTypeStrings.UnionWith(immediateUndefinedTypes); + + bool requiresMergeability = layer != string.Empty && !elementId.IsReserved; + bool isMergeable = false; + foreach (Dtmi supplementalTypeId in immediateSupplementalTypeIds) + { + if (aggregateContext.SupplementalTypeCollection.TryGetSupplementalTypeInfo(supplementalTypeId, out DTSupplementalTypeInfo supplementalTypeInfo)) + { + if (!supplementalTypeInfo.AllowedCotypeKinds.Contains(elementInfo.EntityKind)) + { + parsingErrorCollection.Notify( + "invalidCotype", + elementId: elementId, + cotype: ContextCollection.GetTermOrUri(supplementalTypeId), + typeRestriction: string.Join(" or ", supplementalTypeInfo.AllowedCotypeKinds), + element: elt, + layer: layer); + } + else if (!supplementalTypeInfo.AllowedCotypeVersions.Contains(elementInfo.DtdlVersion)) + { + parsingErrorCollection.Notify( + "invalidCotypeVersion", + elementId: elementId, + cotype: ContextCollection.GetTermOrUri(supplementalTypeId), + versionRestriction: string.Join(" or ", supplementalTypeInfo.AllowedCotypeVersions), + element: elt, + layer: layer); + } + else + { + elementInfo.AddType(supplementalTypeId, supplementalTypeInfo, parsingErrorCollection); + foreach (Dtmi requiredCocotype in supplementalTypeInfo.RequiredCocotypes) + { + if (!immediateSupplementalTypeIds.Contains(requiredCocotype)) + { + string requiredCocotypeTerm = ContextCollection.GetTermOrUri(requiredCocotype); + parsingErrorCollection.Notify( + "missingCocotype", + elementId: elementId, + elementType: ContextCollection.GetTermOrUri(supplementalTypeId), + cotype: requiredCocotypeTerm, + element: elt); + } + } + } + + isMergeable = isMergeable || supplementalTypeInfo.IsMergeable; + } + } + + if (requiresMergeability && !isMergeable) + { + parsingErrorCollection.Notify( + "disallowedIdFragment", + elementId: elementId, + element: elt, + layer: layer); + } + + return true; + } + + /// + /// Parse a string @type value, whether material or supplemental. + /// + /// The string value to parse. + /// The identifier of the element of this type to create. + /// Name of the layer currently being parsed. + /// The currently being parsed. + /// The identifier of the parent of the element. + /// Identifier of the partition or top-level element under which this element is defined. + /// The name of the property by which the parent refers to this element. + /// The representing the source of the property by which the parent refers to this element. + /// A set of material kinds to update with the material kind of the type, if any. + /// A set of supplemental type IDs to update with the supplemental type, if any. + /// The element created if the type is material. + /// A list of string values of any undefined supplemental types. + /// An AggregateContext object representing information retrieved from JSON-LD context blocks. + /// A ParsingErrorCollection to which any parsing errors are added. + /// True if the parse is sucessful. + internal static bool TryParseTypeStringV4(string typeString, Dtmi elementId, string layer, JsonLdElement elt, Dtmi parentId, Dtmi definedIn, string propName, JsonLdProperty propProp, HashSet materialKinds, HashSet supplementalTypeIds, ref DTUnsignedByteInfo elementInfo, ref List undefinedTypes, AggregateContext aggregateContext, ParsingErrorCollection parsingErrorCollection) + { + if (MaterialTypeNameCollection.IsMaterialType(typeString)) + { + string sourceName1 = null; + int sourceLine1 = 0; + if (propProp != null && propProp.TryGetSourceLocation(out sourceName1, out sourceLine1) && elt.TryGetSourceLocation(out string sourceName2, out int startLine2, out int endLine2)) + { + elt.TryGetSourceLocationForType(out _, out int sourceLine3); + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeLocatedCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer, + sourceName1: sourceName1, + startLine1: sourceLine1, + sourceName2: sourceName2, + startLine2: startLine2, + endLine2: endLine2, + startLine3: sourceLine3); + } + else + { + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer); + } + + return false; + } + + if (!aggregateContext.TryCreateDtmi(typeString, out Dtmi supplementalTypeId)) + { + if (typeString.StartsWith("dtmi:")) + { + parsingErrorCollection.Notify( + "typeInvalidDtmi", + elementId: elementId, + cotype: typeString, + element: elt, + layer: layer); + return false; + } + else if (typeString.Contains(":")) + { + parsingErrorCollection.Notify( + "typeNotDtmiNorTerm", + elementId: elementId, + cotype: typeString, + element: elt, + layer: layer); + return false; + } + else + { + if (aggregateContext.IsComplete) + { + parsingErrorCollection.Notify( + "typeUndefinedTerm", + elementId: elementId, + cotype: typeString, + element: elt, + version: aggregateContext.DtdlVersion.ToString(), + layer: layer); + return false; + } + } + + undefinedTypes.Add(typeString); + return true; + } + + if (!aggregateContext.SupplementalTypeCollection.TryGetSupplementalTypeInfo(supplementalTypeId, out DTSupplementalTypeInfo supplementalTypeInfo)) + { + if (aggregateContext.IsComplete) + { + parsingErrorCollection.Notify( + "typeIrrelevantDtmiOrTerm", + elementId: elementId, + cotype: typeString, + element: elt, + version: aggregateContext.DtdlVersion.ToString(), + layer: layer); + return false; + } + + undefinedTypes.Add(typeString); + return true; + } + + if (supplementalTypeInfo.IsAbstract) + { + parsingErrorCollection.Notify( + "abstractSupplementalType", + elementId: elementId, + cotype: ContextCollection.GetTermOrUri(supplementalTypeId), + element: elt, + layer: layer); + return false; + } + + switch (supplementalTypeInfo.ExtensionKind) + { + case DTExtensionKind.LatentType: + { + string sourceName1 = null; + int sourceLine1 = 0; + if (propProp != null && propProp.TryGetSourceLocation(out sourceName1, out sourceLine1) && elt.TryGetSourceLocation(out string sourceName2, out int startLine2, out int endLine2)) + { + elt.TryGetSourceLocationForType(out _, out int sourceLine3); + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeLocatedCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer, + sourceName1: sourceName1, + startLine1: sourceLine1, + sourceName2: sourceName2, + startLine2: startLine2, + endLine2: endLine2, + startLine3: sourceLine3); + } + else + { + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer); + } + } + + return false; + case DTExtensionKind.NamedLatentType: + { + string sourceName1 = null; + int sourceLine1 = 0; + if (propProp != null && propProp.TryGetSourceLocation(out sourceName1, out sourceLine1) && elt.TryGetSourceLocation(out string sourceName2, out int startLine2, out int endLine2)) + { + elt.TryGetSourceLocationForType(out _, out int sourceLine3); + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeLocatedCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer, + sourceName1: sourceName1, + startLine1: sourceLine1, + sourceName2: sourceName2, + startLine2: startLine2, + endLine2: endLine2, + startLine3: sourceLine3); + } + else + { + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer); + } + } + + return false; + case DTExtensionKind.Unit: + { + string sourceName1 = null; + int sourceLine1 = 0; + if (propProp != null && propProp.TryGetSourceLocation(out sourceName1, out sourceLine1) && elt.TryGetSourceLocation(out string sourceName2, out int startLine2, out int endLine2)) + { + elt.TryGetSourceLocationForType(out _, out int sourceLine3); + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeLocatedCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer, + sourceName1: sourceName1, + startLine1: sourceLine1, + sourceName2: sourceName2, + startLine2: startLine2, + endLine2: endLine2, + startLine3: sourceLine3); + } + else + { + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer); + } + } + + return false; + case DTExtensionKind.UnitAttribute: + { + string sourceName1 = null; + int sourceLine1 = 0; + if (propProp != null && propProp.TryGetSourceLocation(out sourceName1, out sourceLine1) && elt.TryGetSourceLocation(out string sourceName2, out int startLine2, out int endLine2)) + { + elt.TryGetSourceLocationForType(out _, out int sourceLine3); + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeLocatedCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer, + sourceName1: sourceName1, + startLine1: sourceLine1, + sourceName2: sourceName2, + startLine2: startLine2, + endLine2: endLine2, + startLine3: sourceLine3); + } + else + { + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer); + } + } + + return false; + } + + supplementalTypeIds.Add(supplementalTypeId); + + return true; + } + + /// + /// Parse elements encoded in a into objects of subclasses of type DTUnsignedByteInfo. + /// + /// The model to add the element to. + /// A list of ParsedObjectPropertyInfo to add any object properties, which will be assigned after all parsing has completed. + /// List of ElementPropertyConstraint to be checked after object property assignment. + /// List of to be added to . + /// An AggregateContext object representing information retrieved from JSON-LD context blocks. + /// A ParsingErrorCollection to which any parsing errors are added. + /// The holding the to parse. + /// Name of the layer currently being parsed. + /// The identifier of the parent of the element. + /// Identifier of the partition or top-level element under which this element is defined. + /// The name of the property by which the parent refers to this element, used for auto ID generation. + /// A DTMI segment identifier, used for auto ID generation. + /// A property used for the key if the parent exposes a collection of these elements as a dictionary. + /// The minimum count of element values required. + /// A boolean value indicating whether the property allows multiple values. + /// A boolean value indicating whether an @id must be present. + /// A boolean value indicating whether a @type must be present. + /// Treat all nested definitions as though defined globally. + /// Allow elements to define IDs that have reserved prefixes. + /// Tolerate specific minor invalidities to support backward compatibility. + /// A set of allowed versions for the element. + internal static new void ParseValueCollection(Model model, List objectPropertyInfoList, List elementPropertyConstraints, List valueConstraints, AggregateContext aggregateContext, ParsingErrorCollection parsingErrorCollection, JsonLdProperty valueCollectionProp, string layer, Dtmi parentId, Dtmi definedIn, string propName, string dtmiSeg, string keyProp, int minCount, bool isPlural, bool idRequired, bool typeRequired, bool globalize, bool allowReservedIds, bool tolerateSolecisms, HashSet allowedVersions) + { + int valueCount = 0; + + foreach (JsonLdValue value in valueCollectionProp.Values.Values) + { + if (!isPlural && valueCount > 0) + { + parsingErrorCollection.Notify( + "objectMultipleValues", + elementId: parentId, + propertyName: propName, + incidentValues: valueCollectionProp.Values, + layer: layer); + return; + } + + switch (value.ValueType) + { + case JsonLdValueType.String: + if (parentId != null) + { + if (TryParseIdString(objectPropertyInfoList, elementPropertyConstraints, valueConstraints, aggregateContext, parsingErrorCollection, value.StringValue, layer, parentId, propName, valueCollectionProp, keyProp, allowedVersions)) + { + ++valueCount; + } + else + { + parsingErrorCollection.Notify( + "badDtmiOrTerm", + elementId: parentId, + propertyName: propName, + propertyValue: value.StringValue, + incidentProperty: valueCollectionProp, + incidentValue: value, + version: aggregateContext.DtdlVersion.ToString(), + layer: layer); + } + } + + break; + case JsonLdValueType.Element: + if (TryParseElement(model, objectPropertyInfoList, elementPropertyConstraints, valueConstraints, aggregateContext, parsingErrorCollection, value.ElementValue, layer, parentId, definedIn, propName, valueCollectionProp, dtmiSeg, keyProp, idRequired, typeRequired, globalize, allowReservedIds, tolerateSolecisms, allowedVersions, "UnsignedByte")) + { + ++valueCount; + } + + break; + default: + parsingErrorCollection.Notify( + "refNotStringOrObject", + elementId: parentId, + propertyName: propName, + incidentProperty: valueCollectionProp, + incidentValue: value, + layer: layer); + break; + } + } + + if (valueCount < minCount) + { + parsingErrorCollection.Notify( + "objectCountBelowMin", + elementId: parentId, + propertyName: propName, + observedCount: valueCount, + expectedCount: minCount, + incidentProperty: valueCollectionProp, + layer: layer); + } + } + + /// + internal override bool CheckDepthOfElementSchemaOrSchema(int depth, int depthLimit, bool allowSelf, List tooDeepElementIds, out Dictionary tooDeepElts, ParsingErrorCollection parsingErrorCollection) + { + tooDeepElts = null; + return true; + } + + /// + /// Determine whether a JsonElement matches this DTDL element. + /// + /// The JsonElement to match. + /// If the instance is a property in a JSON object, the name corresponding to ; otherwise, null. + /// True if the JsonElement matches; false otherwise. + internal override bool DoesInstanceMatch(JsonElement instanceElt, string instanceName) + { + switch (this.DtdlVersion) + { + case 4: + return this.DoesInstanceMatchV4(instanceElt, instanceName); + } + + return false; + } + + /// + /// Indicate whether the property with a given is a dictionary that holds a given . + /// + /// The name of the property to check. + /// The key for the dictionary property. + /// True if the property is present, is a dictionary, and holds the given key. + internal override bool DoesPropertyDictContainKey(string propertyName, string key) + { + if (base.DoesPropertyDictContainKey(propertyName, key)) + { + return true; + } + + switch (propertyName) + { + default: + return false; + } + } + + /// + internal override bool TryGetChild(string childrenPropertyName, string keyPropertyName, string keyPropertyValue, out DTEntityInfo child) + { + switch (childrenPropertyName) + { + default: + break; + } + + child = null; + return false; + } + + /// + internal override bool TryGetDescendantSchemaArray(out Dtmi elementId, out Dictionary excludedElts) + { + if (this.checkedForDescendantSchemaArray) + { + elementId = this.idOfDescendantSchemaArray; + excludedElts = this.eltsOfDescendantSchemaArray; + return this.idOfDescendantSchemaArray != null; + } + + this.checkedForDescendantSchemaArray = true; + + elementId = null; + excludedElts = null; + return false; + } + + /// + internal override bool TryGetDescendantSchemaOrContentsComponentNarrow(out Dtmi elementId, out Dictionary excludedElts) + { + if (this.checkedForDescendantSchemaOrContentsComponentNarrow) + { + elementId = this.idOfDescendantSchemaOrContentsComponentNarrow; + excludedElts = this.eltsOfDescendantSchemaOrContentsComponentNarrow; + return this.idOfDescendantSchemaOrContentsComponentNarrow != null; + } + + this.checkedForDescendantSchemaOrContentsComponentNarrow = true; + + elementId = null; + excludedElts = null; + return false; + } + + /// + /// Try to set an object property with a given . + /// + /// The name of the property whose element value to set if the property is recognized. + /// The key property for dictionary properties. + /// The representing the source of the property by which the parent refers to this element. + /// The reference element to set. + /// The key property for dictionary properties. + /// The key value for dictionary properties. + /// A ParsingErrorCollection to which any parsing errors are added. + /// True if the property name is recognized. + internal override bool TrySetObjectProperty(string propertyName, string layer, JsonLdProperty propProp, DTEntityInfo element, string keyProp, string keyValue, ParsingErrorCollection parsingErrorCollection) + { + if (base.TrySetObjectProperty(propertyName, layer, propProp, element, keyProp, keyValue, parsingErrorCollection)) + { + return true; + } + + switch (propertyName) + { + default: + break; + } + + foreach (DTSupplementalTypeInfo supplementalType in this.supplementalTypes) + { + if (supplementalType.TrySetObjectProperty(this.Id, propertyName, element, keyValue, layer, propProp, ref this.supplementalProperties, this.supplementalSingularPropertyLayers, this.JsonLdElements, parsingErrorCollection)) + { + return true; + } + } + + return false; + } + + /// + /// Validate a JsonElement to determine whether it is a numeric value that conforms to the XSD definition of 'unsignedByte'. + /// + /// The JsonElement to validate. + /// If the instance is a property in a JSON object, the name corresponding to ; otherwise, null. + /// A list of strings to which to add any validation failures. + internal override bool ValidateInstance(JsonElement instanceElt, string instanceName, List violations) + { + switch (this.DtdlVersion) + { + case 4: + return this.ValidateInstanceV4(instanceElt, instanceName, violations); + } + + return true; + } + + /// + internal override HashSet GetTransitiveExtendsNarrow(int depth, int depthLimit, bool allowSelf, List tooDeepElementIds, out Dictionary tooDeepElts, ParsingErrorCollection parsingErrorCollection) + { + HashSet closure = new HashSet(); + + tooDeepElts = null; + return closure; + } + + /// + internal override IEnumerable GetChildren(string childrenPropertyName) + { + switch (childrenPropertyName) + { + default: + return new List(); + } + } + + /// + internal override int GetCountOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrow(bool allowSelf, ParsingErrorCollection parsingErrorCollection) + { + if (this.countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowStatus == TraversalStatus.Complete) + { + return this.countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowValue; + } + + if (this.countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowStatus == TraversalStatus.InProgress) + { + if (allowSelf) + { + this.countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowStatus = TraversalStatus.Complete; + } + else + { + parsingErrorCollection.Notify( + "recursiveStructureNarrow", + elementId: this.Id, + propertyDisjunction: "'contents' or 'fields' or 'enumValues' or 'request' or 'response' or 'properties' or 'schema' or 'elementSchema' or 'mapValue'", + element: this.JsonLdElements.First().Value); + } + + return 0; + } + + this.countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowStatus = TraversalStatus.InProgress; + this.countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowStatus = TraversalStatus.Complete; + return this.countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowValue; + } + + /// + internal override int GetCountOfExtendsNarrow(bool allowSelf, ParsingErrorCollection parsingErrorCollection) + { + if (this.countOfExtendsNarrowStatus == TraversalStatus.Complete) + { + return this.countOfExtendsNarrowValue; + } + + if (this.countOfExtendsNarrowStatus == TraversalStatus.InProgress) + { + if (allowSelf) + { + this.countOfExtendsNarrowStatus = TraversalStatus.Complete; + } + else + { + parsingErrorCollection.Notify( + "recursiveStructureNarrow", + elementId: this.Id, + propertyDisjunction: "'extends'", + element: this.JsonLdElements.First().Value); + } + + return 0; + } + + this.countOfExtendsNarrowStatus = TraversalStatus.InProgress; + this.countOfExtendsNarrowStatus = TraversalStatus.Complete; + return this.countOfExtendsNarrowValue; + } + + /// + /// Add a supplemental type. + /// + /// Identifier for the supplemental type to add. + /// DTSupplementalTypeInfo for the supplemental type. + /// A ParsingErrorCollection to which any parsing errors are added. + internal override void AddType(Dtmi id, DTSupplementalTypeInfo supplementalType, ParsingErrorCollection parsingErrorCollection) + { + if (this.supplementalTypeIds.Add(id)) + { + this.supplementalTypes.Add(supplementalType); + } + } + + /// + internal override void ApplyTransformations(Model model, ParsingErrorCollection parsingErrorCollection) + { + switch (this.DtdlVersion) + { + case 4: + this.ApplyTransformationsV4(model, parsingErrorCollection); + break; + } + } + + /// + internal override void CheckDescendantEnumValueDatatype(Dtmi ancestorId, Dictionary ancestorElts, Type datatype, ParsingErrorCollection parsingErrorCollection) + { + if (this.checkedDescendantEnumValueDatatype != datatype) + { + this.checkedDescendantEnumValueDatatype = datatype; + } + } + + /// + internal override void CheckRestrictions(ParsingErrorCollection parsingErrorCollection) + { + this.CheckForDisallowedCocotypes(this.supplementalTypeIds, this.supplementalTypes, parsingErrorCollection); + + foreach (DTSupplementalTypeInfo supplementalType in this.supplementalTypes) + { + supplementalType.CheckRestrictions(this.supplementalProperties, parsingErrorCollection, this.Id, this.JsonLdElements); + } + + switch (this.DtdlVersion) + { + case 4: + this.CheckRestrictionsV4(parsingErrorCollection); + break; + } + } + + /// + /// Parse the properties in a JSON UnsignedByte object. + /// + /// Model to which to add object properties. + /// List of object info structs for deferred assignments. + /// List of ElementPropertyConstraint to be checked after object property assignment. + /// An AggregateContext object representing information retrieved from JSON-LD context blocks. + /// A set of supplemental type IDs. + /// A list of undefind type strings. + /// A ParsingErrorCollection to which any parsing errors are added. + /// The to parse. + /// Name of the layer currently being parsed. + /// Identifier of the partition or top-level element under which this element is defined. + /// Treat all nested definitions as though defined globally. + /// Allow elements to define IDs that have reserved prefixes. + /// Tolerate specific minor invalidities to support backward compatibility. + internal override void ParsePropertiesV4(Model model, List objectPropertyInfoList, List elementPropertyConstraints, AggregateContext aggregateContext, HashSet immediateSupplementalTypeIds, List immediateUndefinedTypes, ParsingErrorCollection parsingErrorCollection, JsonLdElement elt, string layer, Dtmi definedIn, bool globalize, bool allowReservedIds, bool tolerateSolecisms) + { + this.LanguageMajorVersion = 4; + + JsonLdProperty commentProperty = null; + JsonLdProperty descriptionProperty = null; + JsonLdProperty displayNameProperty = null; + Dictionary supplementalJsonLdProperties = new Dictionary(); + + foreach (JsonLdProperty prop in elt.Properties) + { + switch (prop.Name) + { + case "comment": + case "dtmi:dtdl:property:comment;4": + if (commentProperty != null) + { + parsingErrorCollection.Notify( + "duplicatePropertyName", + elementId: this.Id, + propertyName: "comment", + incidentProperty: prop, + extantProperty: commentProperty, + layer: layer); + } + else + { + commentProperty = prop; + int? maxLength = aggregateContext.LimitSpecifier switch + { + "" => 512, + "onvif_1" => 515, + _ => null, + }; + + string newComment = ValueParser.ParseSingularStringValueCollection(aggregateContext, this.Id, "comment", prop.Values, maxLength, null, layer, parsingErrorCollection, isOptional: true); + if (this.commentPropertyLayer != null) + { + if (this.Comment != newComment) + { + JsonLdProperty extantProp = this.JsonLdElements[this.commentPropertyLayer].Properties.FirstOrDefault(p => p.Name == "comment"); + parsingErrorCollection.Notify( + "inconsistentStringValues", + elementId: this.Id, + propertyName: "comment", + propertyValue: newComment.ToString(), + valueRestriction: this.Comment.ToString(), + incidentProperty: prop, + extantProperty: extantProp, + layer: layer); + } + } + else + { + this.Comment = newComment; + this.commentPropertyLayer = layer; + + if (this.commentValueConstraints != null) + { + foreach (ValueConstraint valueConstraint in this.commentValueConstraints) + { + if (valueConstraint.RequiredLiteral != null && !valueConstraint.RequiredLiteral.Equals(newComment)) + { + parsingErrorCollection.Notify( + "notRequiredStringValue", + elementId: this.Id, + propertyName: "comment", + propertyValue: newComment.ToString(), + valueRestriction: valueConstraint.RequiredLiteral.ToString(), + incidentProperty: prop, + layer: layer); + } + } + } + + ((Dictionary)this.StringProperties)["comment"] = newComment; + } + } + + continue; + case "description": + case "dtmi:dtdl:property:description;4": + if (descriptionProperty != null) + { + parsingErrorCollection.Notify( + "duplicatePropertyName", + elementId: this.Id, + propertyName: "description", + incidentProperty: prop, + extantProperty: descriptionProperty, + layer: layer); + } + else + { + descriptionProperty = prop; + int? maxLength = aggregateContext.LimitSpecifier switch + { + "" => 512, + "onvif_1" => 514, + _ => null, + }; + + Dictionary newDescription = ValueParser.ParseLangStringValueCollection(aggregateContext, this.Id, "description", prop.Values, "en", maxLength, null, layer, parsingErrorCollection); + List descriptionCodes = Helpers.GetKeysWithDifferingLiteralValues(this.Description, newDescription); + if (descriptionCodes.Any()) + { + JsonLdProperty extantProp = Helpers.TryGetSingleUniqueValue(descriptionCodes.Select(c => this.descriptionPropertyLayer[c]), out string uniqueCodeLayer) && this.JsonLdElements[uniqueCodeLayer].Properties.Any(p => p.Name == "description") ? this.JsonLdElements[uniqueCodeLayer].Properties.First(p => p.Name == "description") : null; + parsingErrorCollection.Notify( + "inconsistentLangStringValues", + elementId: this.Id, + propertyName: "description", + langCode: string.Join(" and ", descriptionCodes.Select(c => $"'{c}'")), + observedCount: descriptionCodes.Count, + incidentProperty: prop, + extantProperty: extantProp, + layer: layer); + } + else if (this.Description.Any()) + { + foreach (KeyValuePair kvp in newDescription) + { + ((Dictionary)this.Description)[kvp.Key] = kvp.Value; + this.descriptionPropertyLayer[kvp.Key] = layer; + } + } + else + { + this.Description = newDescription; + this.descriptionPropertyLayer = newDescription.ToDictionary(e => e.Key, e => layer); + } + } + + continue; + case "displayName": + case "dtmi:dtdl:property:displayName;4": + if (displayNameProperty != null) + { + parsingErrorCollection.Notify( + "duplicatePropertyName", + elementId: this.Id, + propertyName: "displayName", + incidentProperty: prop, + extantProperty: displayNameProperty, + layer: layer); + } + else + { + displayNameProperty = prop; + int? maxLength = aggregateContext.LimitSpecifier switch + { + "" => 512, + "onvif_1" => 513, + _ => null, + }; + + Dictionary newDisplayName = ValueParser.ParseLangStringValueCollection(aggregateContext, this.Id, "displayName", prop.Values, "en", maxLength, null, layer, parsingErrorCollection); + List displayNameCodes = Helpers.GetKeysWithDifferingLiteralValues(this.DisplayName, newDisplayName); + if (displayNameCodes.Any()) + { + JsonLdProperty extantProp = Helpers.TryGetSingleUniqueValue(displayNameCodes.Select(c => this.displayNamePropertyLayer[c]), out string uniqueCodeLayer) && this.JsonLdElements[uniqueCodeLayer].Properties.Any(p => p.Name == "displayName") ? this.JsonLdElements[uniqueCodeLayer].Properties.First(p => p.Name == "displayName") : null; + parsingErrorCollection.Notify( + "inconsistentLangStringValues", + elementId: this.Id, + propertyName: "displayName", + langCode: string.Join(" and ", displayNameCodes.Select(c => $"'{c}'")), + observedCount: displayNameCodes.Count, + incidentProperty: prop, + extantProperty: extantProp, + layer: layer); + } + else if (this.DisplayName.Any()) + { + foreach (KeyValuePair kvp in newDisplayName) + { + ((Dictionary)this.DisplayName)[kvp.Key] = kvp.Value; + this.displayNamePropertyLayer[kvp.Key] = layer; + } + } + else + { + this.DisplayName = newDisplayName; + this.displayNamePropertyLayer = newDisplayName.ToDictionary(e => e.Key, e => layer); + } + } + + continue; + } + + if (this.TryParseSupplementalProperty(model, immediateSupplementalTypeIds, objectPropertyInfoList, elementPropertyConstraints, aggregateContext, layer, definedIn, parsingErrorCollection, prop.Name, globalize, allowReservedIds, tolerateSolecisms, prop, supplementalJsonLdProperties)) + { + continue; + } + + if (aggregateContext.TryCreateDtmi(prop.Name, out Dtmi _)) + { + if (aggregateContext.IsComplete) + { + parsingErrorCollection.Notify( + "propertyIrrelevantDtmiOrTerm", + elementId: this.Id, + propertyName: prop.Name, + incidentProperty: prop, + element: elt, + layer: layer); + continue; + } + } + else if (prop.Name.StartsWith("dtmi:")) + { + parsingErrorCollection.Notify( + "propertyInvalidDtmi", + elementId: this.Id, + propertyName: prop.Name, + incidentProperty: prop, + element: elt, + layer: layer); + continue; + } + else if (prop.Name.Contains(":")) + { + parsingErrorCollection.Notify( + "propertyNotDtmiNorTerm", + elementId: this.Id, + propertyName: prop.Name, + incidentProperty: prop, + element: elt, + layer: layer); + continue; + } + else + { + if (aggregateContext.IsComplete) + { + parsingErrorCollection.Notify( + "propertyUndefinedTerm", + elementId: this.Id, + propertyName: prop.Name, + incidentProperty: prop, + element: elt, + version: aggregateContext.DtdlVersion.ToString(), + layer: layer); + continue; + } + } + + if (!immediateUndefinedTypes.Any()) + { + if (elt.Types != null) + { + parsingErrorCollection.Notify( + "noTypeThatAllows", + elementId: this.Id, + propertyName: prop.Name, + incidentProperty: prop, + element: elt, + layer: layer); + } + else + { + parsingErrorCollection.Notify( + "inferredTypeDoesNotAllow", + elementId: this.Id, + referenceType: "UnsignedByte", + propertyName: prop.Name, + incidentProperty: prop, + element: elt, + layer: layer); + } + + continue; + } + + using (JsonDocument propDoc = JsonDocument.Parse(prop.Values.GetJsonText())) + { + this.UndefinedPropertyDictionary[prop.Name] = propDoc.RootElement.Clone(); + } + } + + foreach (Dtmi supplementalTypeId in immediateSupplementalTypeIds) + { + if (aggregateContext.SupplementalTypeCollection.TryGetSupplementalTypeInfo(supplementalTypeId, out DTSupplementalTypeInfo supplementalTypeInfo)) + { + supplementalTypeInfo.CheckForRequiredProperties(parsingErrorCollection, this.Id, elt, supplementalJsonLdProperties); + } + } + } + + /// + /// Record JSON-LD source as appropriate and check length of text against limit. + /// + /// The name of the layer whose source to record. + /// A JsonLdElement containing the JSON-LD source of the element. + /// An AggregateContext object representing information retrieved from JSON-LD context blocks. + /// A ParsingErrorCollection to which any parsing errors are added. + /// True if the element is at the document root. + /// True if the element has been globalized. + internal override void RecordSourceAsAppropriate(string layer, JsonLdElement elt, AggregateContext aggregateContext, ParsingErrorCollection parsingErrorCollection, bool atRoot, bool globalized) + { + } + + /// + /// Write a JSON representation of the DTDL element represented by an object of this class. + /// + /// A Utf8JsonWriter object with which to write the JSON representation. + /// True if the mothed should add a ClassId property to the JSON object. + internal override void WriteToJson(Utf8JsonWriter jsonWriter, bool includeClassId) + { + base.WriteToJson(jsonWriter, includeClassId: false); + + if (includeClassId) + { + jsonWriter.WriteString("ClassId", $"dtmi:dtdl:class:UnsignedByte;{this.LanguageMajorVersion}"); + } + } + + private bool DoesInstanceMatchV4(JsonElement instanceElt, string instanceName) + { + return true; + } + + private bool TryParseSupplementalProperty(Model model, HashSet immediateSupplementalTypeIds, List objectPropertyInfoList, List elementPropertyConstraints, AggregateContext aggregateContext, string layer, Dtmi definedIn, ParsingErrorCollection parsingErrorCollection, string propName, bool globalize, bool allowReservedIds, bool tolerateSolecisms, JsonLdProperty valueCollectionProp, Dictionary supplementalJsonLdProperties) + { + if (!aggregateContext.TryCreateDtmi(propName, out Dtmi propDtmi)) + { + return false; + } + + foreach (Dtmi supplementalTypeId in immediateSupplementalTypeIds) + { + if (aggregateContext.SupplementalTypeCollection.TryGetSupplementalTypeInfo(supplementalTypeId, out DTSupplementalTypeInfo supplementalTypeInfo) && supplementalTypeInfo.TryParseProperty(model, objectPropertyInfoList, elementPropertyConstraints, aggregateContext, parsingErrorCollection, layer, this.Id, definedIn, propDtmi.ToString(), globalize, allowReservedIds, tolerateSolecisms, valueCollectionProp, ref this.supplementalProperties, supplementalJsonLdProperties, this.supplementalSingularPropertyLayers, this.JsonLdElements)) + { + return true; + } + } + + return false; + } + + private bool ValidateInstanceV4(JsonElement instanceElt, string instanceName, List violations) + { + if (instanceElt.ValueKind != JsonValueKind.Number) + { + violations.Add($">>{instanceElt.GetRawText()}<< is not a numeric value"); + return false; + } + + if (!byte.TryParse(instanceElt.GetRawText(), out byte _)) + { + violations.Add($"{instanceElt.GetRawText()} does not conform to the XSD definition of 'unsignedByte'"); + return false; + } + + if (!ElementValueInstanceRegexPatternV4.IsMatch(instanceElt.GetRawText())) + { + violations.Add($"\"{instanceElt.GetRawText()}\" does not conform to the XSD definition of 'unsignedByte'"); + return false; + } + + return true; + } + + private void ApplyTransformationsV4(Model model, ParsingErrorCollection parsingErrorCollection) + { + } + + /// + private void CheckRestrictionsV4(ParsingErrorCollection parsingErrorCollection) + { + } + } +} diff --git a/dotnet/src/DTDLParser/generated/DTUnsignedIntegerInfo.g.cs b/dotnet/src/DTDLParser/generated/DTUnsignedIntegerInfo.g.cs new file mode 100644 index 00000000..3b9558d6 --- /dev/null +++ b/dotnet/src/DTDLParser/generated/DTUnsignedIntegerInfo.g.cs @@ -0,0 +1,1895 @@ +/* This is an auto-generated file. Do not modify. */ + +namespace DTDLParser.Models +{ + using System; + using System.Collections.Generic; + using System.ComponentModel; + using System.Globalization; + using System.IO; + using System.Linq; + using System.Text; + using System.Text.Json; + using System.Text.RegularExpressions; + using System.Threading; + using System.Threading.Tasks; + using DTDLParser; + + /// + /// Class DTUnsignedIntegerInfo corresponds to an element of type UnsignedInteger in a DTDL model. + /// + public class DTUnsignedIntegerInfo : DTNumericSchemaInfo, ITypeChecker, IConstrainer, IEquatable + { + private static readonly Dictionary> ConcreteKinds = new Dictionary>(); + + private static readonly Dictionary BadTypeActionFormat = new Dictionary(); + + private static readonly Dictionary BadTypeCauseFormat = new Dictionary(); + + private static readonly Dictionary BadTypeLocatedCauseFormat = new Dictionary(); + + private static readonly HashSet PropertyNames = new HashSet(); + + private static readonly HashSet VersionlessTypes = new HashSet(); + + private static readonly Regex ElementValueInstanceRegexPatternV4 = new Regex(@"^[0-9]+$", RegexOptions.Compiled); + + private bool checkedForDescendantSchemaArray = false; + + private bool checkedForDescendantSchemaOrContentsComponentNarrow = false; + + private Dictionary supplementalPropertySources = new Dictionary(); + + private Dictionary eltsOfDescendantSchemaArray = null; + + private Dictionary eltsOfDescendantSchemaOrContentsComponentNarrow = null; + + private Dictionary supplementalProperties; + + private Dictionary descriptionPropertyLayer = null; + + private Dictionary displayNamePropertyLayer = null; + + private Dictionary supplementalSingularPropertyLayers = new Dictionary(); + + private Dtmi idOfDescendantSchemaArray = null; + + private Dtmi idOfDescendantSchemaOrContentsComponentNarrow = null; + + private HashSet supplementalTypeIds; + + private int countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowValue = 0; + + private int countOfExtendsNarrowValue = 0; + + private List supplementalTypes; + + private List commentValueConstraints = null; + + private List descriptionValueConstraints = null; + + private List displayNameValueConstraints = null; + + private string commentPropertyLayer = null; + + private TraversalStatus countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowStatus = TraversalStatus.NotStarted; + + private TraversalStatus countOfExtendsNarrowStatus = TraversalStatus.NotStarted; + + private Type checkedDescendantEnumValueDatatype = null; + + static DTUnsignedIntegerInfo() + { + VersionlessTypes.Add("dtmi:dtdl:class:Entity"); + VersionlessTypes.Add("dtmi:dtdl:class:NumericSchema"); + VersionlessTypes.Add("dtmi:dtdl:class:PrimitiveSchema"); + VersionlessTypes.Add("dtmi:dtdl:class:Schema"); + VersionlessTypes.Add("dtmi:dtdl:class:UnsignedInteger"); + + PropertyNames.Add("comment"); + PropertyNames.Add("description"); + PropertyNames.Add("displayName"); + PropertyNames.Add("languageMajorVersion"); + + ConcreteKinds[4] = new HashSet(); + ConcreteKinds[4].Add(DTEntityKind.UnsignedInteger); + + BadTypeActionFormat[4] = "Use this standard value for property '{property}'{line1}: unsignedInteger."; + + BadTypeCauseFormat[4] = "{layer}{primaryId:p} property '{property}' has value{secondaryId:e} that is not a standard value for this property."; + + BadTypeLocatedCauseFormat[4] = "In {sourceName1}, property '{property}'{line1} has value{secondaryId:e}{line2} that is not a standard value for this property."; + } + + /// + /// Initializes a new instance of the class. + /// + /// Version of DTDL used to define the UnsignedInteger. + /// Identifier for the UnsignedInteger. + /// Identifier of the parent element in which this UnsignedInteger is defined. + /// Name of the property by which the parent DTDL element refers to this UnsignedInteger. + /// Identifier of the partition in which this UnsignedInteger is defined. + internal DTUnsignedIntegerInfo(int dtdlVersion, Dtmi id, Dtmi childOf, string myPropertyName, Dtmi definedIn) + : base(dtdlVersion, id, childOf, myPropertyName, definedIn, DTEntityKind.UnsignedInteger) + { + this.supplementalTypeIds = new HashSet(); + this.supplementalProperties = new Dictionary(); + this.supplementalTypes = new List(); + + this.IsPartition = false; + + this.MaybePartial = false; + } + + /// + /// Initializes a new instance of the class. + /// + /// Version of DTDL used to define the UnsignedInteger. + /// Identifier for the UnsignedInteger. + /// Identifier of the parent element in which this UnsignedInteger is defined. + /// Name of the property by which the parent DTDL element refers to this UnsignedInteger. + /// Identifier of the partition in which this UnsignedInteger is defined. + /// The kind of Entity, which may be other than UnsignedInteger if this constructor is called from a derived class. + internal DTUnsignedIntegerInfo(int dtdlVersion, Dtmi id, Dtmi childOf, string myPropertyName, Dtmi definedIn, DTEntityKind entityKind) + : base(dtdlVersion, id, childOf, myPropertyName, definedIn, entityKind) + { + this.supplementalTypeIds = new HashSet(); + this.supplementalProperties = new Dictionary(); + this.supplementalTypes = new List(); + + this.IsPartition = false; + + this.MaybePartial = false; + } + + /// + /// Get the DTMI that identifies type UnsignedInteger in the version of DTDL used to define this element. + /// + /// The DTMI for the DTDL type UnsignedInteger. + public override Dtmi ClassId + { + get + { + return new Dtmi($"dtmi:dtdl:class:UnsignedInteger;{this.LanguageMajorVersion}"); + } + } + + /// + /// Gets the supplemantal properties of the DTDL element that corresponds to this object. + /// + /// A dictionary that maps each string-valued property name to an object that holds the value of the property with the given name. + /// + /// If the property is a literal in the DTDL model, the object holds a literal value. + /// If the property is another DTDL element in the model, the object is the C# object that corresponds to this element. + /// + public override IDictionary SupplementalProperties + { + get + { + return this.supplementalProperties; + } + } + + /// + /// Gets a collection of identifiers, each of which is a Dtmi that indicates a supplemental type that applies to the DTDL element that corresponds to this object. + /// + /// A collection of DTMIs indicating the supplemental types that apply to the DTDL element. + public override IReadOnlyCollection SupplementalTypes + { + get + { + return this.supplementalTypeIds; + } + } + + /// + /// Gets a value indicating whether this class is a partition point for the object model. + /// + internal override bool IsPartition { get; } + + /// + /// Gets material properties allowed by the type of DTDL element. + /// + internal override HashSet MaterialProperties + { + get + { + return PropertyNames; + } + } + + /// + /// Determines whether two DTUnsignedIntegerInfo objects are not equal. + /// + /// One DTUnsignedIntegerInfo object to compare. + /// Another DTUnsignedIntegerInfo object to compare to the first. + /// True if not equal. + public static bool operator !=(DTUnsignedIntegerInfo x, DTUnsignedIntegerInfo y) + { + if (ReferenceEquals(null, x)) + { + return !ReferenceEquals(null, y); + } + + return !x.Equals(y); + } + + /// + /// Determines whether two DTUnsignedIntegerInfo objects are equal. + /// + /// One DTUnsignedIntegerInfo object to compare. + /// Another DTUnsignedIntegerInfo object to compare to the first. + /// True if equal. + public static bool operator ==(DTUnsignedIntegerInfo x, DTUnsignedIntegerInfo y) + { + if (ReferenceEquals(null, x)) + { + return ReferenceEquals(null, y); + } + + return x.Equals(y); + } + + /// + /// Compares to another DTUnsignedIntegerInfo object, recursing through the entire subtree of object properties. + /// + /// The other DTUnsignedIntegerInfo object to compare to. + /// True if equal. + public virtual bool DeepEquals(DTUnsignedIntegerInfo other) + { + return base.DeepEquals(other) + && Helpers.AreDictionariesDeepOrLiteralEqual(this.supplementalProperties, other.supplementalProperties) + && this.supplementalTypeIds.SetEquals(other.supplementalTypeIds) + ; + } + + /// + public override bool DeepEquals(DTNumericSchemaInfo other) + { + return this.EntityKind == other?.EntityKind && this.DeepEquals((DTUnsignedIntegerInfo)other); + } + + /// + public override bool DeepEquals(DTPrimitiveSchemaInfo other) + { + return this.EntityKind == other?.EntityKind && this.DeepEquals((DTUnsignedIntegerInfo)other); + } + + /// + public override bool DeepEquals(DTSchemaInfo other) + { + return this.EntityKind == other?.EntityKind && this.DeepEquals((DTUnsignedIntegerInfo)other); + } + + /// + public override bool DeepEquals(DTEntityInfo other) + { + return this.EntityKind == other?.EntityKind && this.DeepEquals((DTUnsignedIntegerInfo)other); + } + + /// + /// Compares to another DTUnsignedIntegerInfo object. + /// + /// The other DTUnsignedIntegerInfo object to compare to. + /// True if equal. + public virtual bool Equals(DTUnsignedIntegerInfo other) + { + return base.Equals(other) + && Helpers.AreDictionariesIdOrLiteralEqual(this.supplementalProperties, other.supplementalProperties) + && this.supplementalTypeIds.SetEquals(other.supplementalTypeIds) + ; + } + + /// + public override bool Equals(DTNumericSchemaInfo other) + { + return this.EntityKind == other?.EntityKind && this.Equals((DTUnsignedIntegerInfo)other); + } + + /// + public override bool Equals(DTPrimitiveSchemaInfo other) + { + return this.EntityKind == other?.EntityKind && this.Equals((DTUnsignedIntegerInfo)other); + } + + /// + public override bool Equals(DTSchemaInfo other) + { + return this.EntityKind == other?.EntityKind && this.Equals((DTUnsignedIntegerInfo)other); + } + + /// + public override bool Equals(DTEntityInfo other) + { + return this.EntityKind == other?.EntityKind && this.Equals((DTUnsignedIntegerInfo)other); + } + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object otherObj) + { + return otherObj is DTUnsignedIntegerInfo other && this.Equals(other); + } + + /// + bool ITypeChecker.DoesHaveType(Dtmi typeId) + { + return VersionlessTypes.Contains(typeId.Versionless) + || this.supplementalTypes.Any(ps => ((ITypeChecker)ps).DoesHaveType(typeId)) + ; + } + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() + { + int hashCode = base.GetHashCode(); + + unchecked + { + hashCode = (hashCode * 131) + Helpers.GetDictionaryIdOrLiteralHashCode(this.supplementalProperties); + hashCode = (hashCode * 131) + Helpers.GetSetLiteralHashCode(this.supplementalTypeIds); + } + + return hashCode; + } + + /// + /// Validate a JsonElement to determine whether it is a numeric value that conforms to the XSD definition of 'unsignedInt'. + /// + /// The JsonElement to validate. + /// A list of strings that each indicate a validation failure; the list is empty if the JsonElement conforms. + public override IReadOnlyCollection ValidateInstance(JsonElement instanceElt) + { + List violations = new List(); + this.ValidateInstance(instanceElt, null, violations); + return violations; + } + + /// + void IConstrainer.AddPropertyValueConstraint(string propertyName, ValueConstraint valueConstraint) + { + switch (propertyName) + { + case "comment": + if (this.commentValueConstraints == null) + { + this.commentValueConstraints = new List(); + } + + this.commentValueConstraints.Add(valueConstraint); + break; + case "description": + if (this.descriptionValueConstraints == null) + { + this.descriptionValueConstraints = new List(); + } + + this.descriptionValueConstraints.Add(valueConstraint); + break; + case "displayName": + if (this.displayNameValueConstraints == null) + { + this.displayNameValueConstraints = new List(); + } + + this.displayNameValueConstraints.Add(valueConstraint); + break; + } + } + + /// + void IConstrainer.AddSiblingConstraint(SiblingConstraint siblingConstraint) + { + if (this.SiblingConstraints == null) + { + this.SiblingConstraints = new List(); + } + + this.SiblingConstraints.Add(siblingConstraint); + } + + /// + /// Parse an element encoded in a into an object that is a subclass of type DTUnsignedIntegerInfo. + /// + /// The model to add the element to. + /// A list of ParsedObjectPropertyInfo to add any object properties, which will be assigned after all parsing has completed. + /// List of ElementPropertyConstraint to be checked after object property assignment. + /// List of to be added to . + /// An AggregateContext object representing information retrieved from JSON-LD context blocks. + /// A ParsingErrorCollection to which any parsing errors are added. + /// The to parse. + /// Name of the layer currently being parsed. + /// The identifier of the parent of the element. + /// Identifier of the partition or top-level element under which this element is defined. + /// The name of the property by which the parent refers to this element, used for auto ID generation. + /// The representing the source of the property by which the parent refers to this element. + /// A DTMI segment identifier, used for auto ID generation. + /// A property used for the key if the parent exposes a collection of these elements as a dictionary. + /// A boolean value indicating whether an @id must be present. + /// A boolean value indicating whether a @type must be present. + /// Treat all nested definitions as though defined globally. + /// Allow elements to define IDs that have reserved prefixes. + /// Tolerate specific minor invalidities to support backward compatibility. + /// A set of allowed versions for the element. + /// The type name to infer if no @type specified on element. + /// True if the parses correctly as an appropriate element. + internal static new bool TryParseElement(Model model, List objectPropertyInfoList, List elementPropertyConstraints, List valueConstraints, AggregateContext aggregateContext, ParsingErrorCollection parsingErrorCollection, JsonLdElement elt, string layer, Dtmi parentId, Dtmi definedIn, string propName, JsonLdProperty propProp, string dtmiSeg, string keyProp, bool idRequired, bool typeRequired, bool globalize, bool allowReservedIds, bool tolerateSolecisms, HashSet allowedVersions, string inferredType) + { + AggregateContext childAggregateContext = aggregateContext.GetChildContext(elt, parsingErrorCollection); + + bool allowIdReferenceSyntax = tolerateSolecisms && aggregateContext.DtdlVersion < 3; + + if (elt.PropertyCount == 1 && elt.Id != null) + { + if (allowIdReferenceSyntax) + { + if (TryParseIdString(objectPropertyInfoList, elementPropertyConstraints, valueConstraints, childAggregateContext, parsingErrorCollection, elt.Id, layer, parentId, propName, propProp, keyProp, allowedVersions)) + { + return true; + } + else + { + parsingErrorCollection.Notify( + "idRefBadDtmiOrTerm", + elementId: parentId, + propertyName: propName, + propertyValue: elt.Id, + element: elt, + version: aggregateContext.DtdlVersion.ToString(), + layer: layer); + return false; + } + } + else + { + parsingErrorCollection.Notify( + "idReference", + elementId: parentId, + propertyName: propName, + identifier: elt.Id, + element: elt, + layer: layer); + return false; + } + } + + if (elt.Graph != null) + { + parsingErrorCollection.Notify( + "graphDisallowed", + elementId: parentId, + propertyName: propName, + element: elt); + } + + if (childAggregateContext.RestrictKeywords) + { + if (elt.Language != null) + { + parsingErrorCollection.Notify( + "keywordDisallowed", + elementId: parentId, + propertyName: propName, + keyword: "@language", + element: elt); + } + + if (elt.Value != null) + { + parsingErrorCollection.Notify( + "keywordDisallowed", + elementId: parentId, + propertyName: propName, + keyword: "@value", + element: elt); + } + + foreach (string keyword in elt.Keywords) + { + parsingErrorCollection.Notify( + "keywordDisallowed", + elementId: parentId, + propertyName: propName, + keyword: keyword, + element: elt); + } + } + + if (allowedVersions != null && !allowedVersions.Contains(childAggregateContext.DtdlVersion)) + { + parsingErrorCollection.Notify( + "disallowedVersionDefinition", + elementId: parentId, + propertyName: propName, + version: childAggregateContext.DtdlVersion.ToString(), + versionRestriction: string.Join(" ,", allowedVersions), + contextComponent: childAggregateContext.DtdlContextComponent, + layer: layer); + } + + bool tolerateReservedIds = tolerateSolecisms && aggregateContext.DtdlVersion < 3; + + Dtmi elementId = IdValidator.ParseIdProperty(childAggregateContext, elt, childAggregateContext.MergeDefinitions ? layer : null, parentId, propName, dtmiSeg, idRequired, allowReservedIds || tolerateReservedIds, parsingErrorCollection); + + Dtmi baseElementId = childAggregateContext.MergeDefinitions || elementId.Tail == string.Empty ? elementId.Fragmentless : elementId; + string elementLayer = childAggregateContext.MergeDefinitions ? elementId.Tail : string.Empty; + + bool ignoreElementsWithAutoIDsAndDuplicateNames = tolerateSolecisms && aggregateContext.DtdlVersion < 3; + + if (model.Dict.TryGetValue(baseElementId, out DTEntityInfo baseElement)) + { + if (baseElement.JsonLdElements.TryGetValue(elementLayer, out JsonLdElement duplicateElt)) + { + if (!baseElementId.IsReserved) + { + parsingErrorCollection.Notify( + "duplicateDefinition", + elementId: baseElementId, + element: elt, + extantElement: duplicateElt, + layer: layer); + } + else if (!ignoreElementsWithAutoIDsAndDuplicateNames && dtmiSeg != null) + { + JsonLdProperty dtmiSegProp = elt.Properties.First(p => p.Name == dtmiSeg || (Dtmi.TryCreateDtmi(p.Name, out Dtmi d) && ContextCollection.GetTermOrUri(d) == dtmiSeg)); + JsonLdProperty dupSegProp = duplicateElt.Properties.First(p => p.Name == dtmiSeg || (Dtmi.TryCreateDtmi(p.Name, out Dtmi d) && ContextCollection.GetTermOrUri(d) == dtmiSeg)); + parsingErrorCollection.Notify( + "nonUniquePropertyValue", + elementId: parentId, + propertyName: propName, + nestedName: dtmiSeg, + nestedValue: dtmiSegProp.Values.Values.First().StringValue, + incidentProperty: dupSegProp, + extantProperty: dtmiSegProp); + } + + return false; + } + + if (baseElement.DtdlVersion != childAggregateContext.DtdlVersion) + { + parsingErrorCollection.Notify( + "inconsistentContext", + elementId: baseElementId, + version: childAggregateContext.DtdlVersion.ToString(), + versionRestriction: baseElement.DtdlVersion.ToString(), + layer: elementLayer); + return false; + } + } + + if (typeRequired && elt.Types == null) + { + string sourceName1 = null; + int sourceLine1 = 0; + if (propProp != null && propProp.TryGetSourceLocation(out sourceName1, out sourceLine1) && elt.TryGetSourceLocation(out string sourceName2, out int startLine2, out int endLine2)) + { + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeLocatedCauseFormat[childAggregateContext.DtdlVersion], + BadTypeActionFormat[childAggregateContext.DtdlVersion], + primaryId: parentId, + property: propName, + secondaryId: baseElementId, + layer: layer, + sourceName1: sourceName1, + startLine1: sourceLine1, + sourceName2: sourceName2, + startLine2: startLine2, + endLine2: endLine2); + } + else + { + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeCauseFormat[childAggregateContext.DtdlVersion], + BadTypeActionFormat[childAggregateContext.DtdlVersion], + primaryId: parentId, + property: propName, + secondaryId: baseElementId, + layer: layer); + } + + return false; + } + + DTUnsignedIntegerInfo elementInfo = (DTUnsignedIntegerInfo)baseElement; + HashSet immediateSupplementalTypeIds; + List immediateUndefinedTypes; + bool typeArrayParsed; + if (elt.Types == null) + { + typeArrayParsed = TryParseTypeStrings(new List() { inferredType }, baseElementId, elementLayer, elt, parentId, definedIn, propName, propProp, ref elementInfo, childAggregateContext, out immediateSupplementalTypeIds, out immediateUndefinedTypes, parsingErrorCollection); + } + else + { + typeArrayParsed = TryParseTypeStrings(elt.Types, baseElementId, elementLayer, elt, parentId, definedIn, propName, propProp, ref elementInfo, childAggregateContext, out immediateSupplementalTypeIds, out immediateUndefinedTypes, parsingErrorCollection); + } + + if (!typeArrayParsed || ReferenceEquals(null, elementInfo)) + { + return false; + } + + switch (childAggregateContext.DtdlVersion) + { + case 4: + elementInfo.ParsePropertiesV4(model, objectPropertyInfoList, elementPropertyConstraints, childAggregateContext, immediateSupplementalTypeIds, immediateUndefinedTypes, parsingErrorCollection, elt, elementLayer, definedIn, globalize, allowReservedIds, tolerateSolecisms); + break; + } + + elementInfo.LimitSpecifier = aggregateContext.LimitSpecifier; + + elementInfo.RecordSourceAsAppropriate(elementLayer, elt, childAggregateContext, parsingErrorCollection, atRoot: parentId == null, globalized: globalize); + + model.Dict[baseElementId] = elementInfo; + + if (parentId != null) + { + objectPropertyInfoList.Add(new ParsedObjectPropertyInfo() { ElementId = parentId, PropertyName = propName, Layer = layer, JsonLdProperty = propProp, ReferencedElementId = baseElementId, KeyProperty = keyProp, ExpectedKinds = null, AllowedVersions = null, ChildOf = null, BadTypeCauseFormat = null, BadTypeLocatedCauseFormat = null, BadTypeActionFormat = null }); + + if (valueConstraints != null && elementPropertyConstraints != null) + { + foreach (ValueConstraint valueConstraint in valueConstraints) + { + elementPropertyConstraints.Add(new ElementPropertyConstraint() { ParentId = parentId, PropertyName = propName, ElementId = baseElementId, ValueConstraint = valueConstraint }); + } + } + } + + return true; + } + + /// + /// Parse a string property value as an identifier for type DTUnsignedIntegerInfo. + /// + /// A list of ParsedObjectPropertyInfo to add any object properties, which will be assigned after all parsing has completed. + /// List of ElementPropertyConstraint to be checked after object property assignment. + /// List of to be added to . + /// An AggregateContext object representing information retrieved from JSON-LD context blocks. + /// A ParsingErrorCollection to which any parsing errors are added. + /// The identifier string to parse. + /// Name of the layer currently being parsed. + /// The identifier of the parent of the element. + /// The name of the property by which the parent refers to this element, used for auto ID generation. + /// The representing the source of the property by which the parent refers to this element. + /// A property used for the key if the parent exposes a collection of these elements as a dictionary. + /// A set of allowed versions for the element. + /// True if the string parses correctly as an identifier. + internal static new bool TryParseIdString(List objectPropertyInfoList, List elementPropertyConstraints, List valueConstraints, AggregateContext aggregateContext, ParsingErrorCollection parsingErrorCollection, string idString, string layer, Dtmi parentId, string propName, JsonLdProperty propProp, string keyProp, HashSet allowedVersions) + { + if (!aggregateContext.TryCreateDtmi(idString, out Dtmi elementId)) + { + return false; + } + + objectPropertyInfoList.Add(new ParsedObjectPropertyInfo() { ElementId = parentId, PropertyName = propName, Layer = layer, JsonLdProperty = propProp, ReferencedIdString = idString, ReferencedElementId = elementId, KeyProperty = keyProp, ExpectedKinds = ConcreteKinds[aggregateContext.DtdlVersion], AllowedVersions = allowedVersions, ChildOf = null, BadTypeCauseFormat = BadTypeCauseFormat[aggregateContext.DtdlVersion], BadTypeLocatedCauseFormat = BadTypeLocatedCauseFormat[aggregateContext.DtdlVersion], BadTypeActionFormat = BadTypeActionFormat[aggregateContext.DtdlVersion] }); + + if (valueConstraints != null && elementPropertyConstraints != null) + { + foreach (ValueConstraint valueConstraint in valueConstraints) + { + elementPropertyConstraints.Add(new ElementPropertyConstraint() { ParentId = parentId, PropertyName = propName, ElementId = elementId, ValueConstraint = valueConstraint }); + } + } + + return true; + } + + /// + /// Parse a list of @type values containing material or supplemental types. + /// + /// The list of strings to parse. + /// The identifier of the element of this type to create. + /// Name of the layer currently being parsed. + /// The currently being parsed. + /// The identifier of the parent of the element. + /// Identifier of the partition or top-level element under which this element is defined. + /// The name of the property by which the parent refers to this element, used for auto ID generation. + /// The representing the source of the property by which the parent refers to this element. + /// The created. + /// An AggregateContext object representing information retrieved from JSON-LD context blocks. + /// A set of supplemental type IDs from the type array. + /// A list of undefind type strings from the type array. + /// A ParsingErrorCollection to which any parsing errors are added. + /// True if no errors detected in type array. + internal static bool TryParseTypeStrings(List typeStrings, Dtmi elementId, string layer, JsonLdElement elt, Dtmi parentId, Dtmi definedIn, string propName, JsonLdProperty propProp, ref DTUnsignedIntegerInfo elementInfo, AggregateContext aggregateContext, out HashSet immediateSupplementalTypeIds, out List immediateUndefinedTypes, ParsingErrorCollection parsingErrorCollection) + { + immediateSupplementalTypeIds = new HashSet(); + immediateUndefinedTypes = new List(); + + HashSet materialKinds = new HashSet(); + + bool anyFailures = false; + foreach (string typeString in typeStrings) + { + switch (aggregateContext.DtdlVersion) + { + case 4: + if (!TryParseTypeStringV4(typeString, elementId, layer, elt, parentId, definedIn, propName, propProp, materialKinds, immediateSupplementalTypeIds, ref elementInfo, ref immediateUndefinedTypes, aggregateContext, parsingErrorCollection)) + { + anyFailures = true; + } + + break; + } + } + + if (anyFailures) + { + return false; + } + + if (ReferenceEquals(null, elementInfo)) + { + string sourceName1 = null; + int sourceLine1 = 0; + if (propProp != null && propProp.TryGetSourceLocation(out sourceName1, out sourceLine1) && elt.TryGetSourceLocation(out string sourceName2, out int startLine2, out int endLine2)) + { + elt.TryGetSourceLocationForType(out _, out int sourceLine3); + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeLocatedCauseFormat[aggregateContext.DtdlVersion], + BadTypeActionFormat[aggregateContext.DtdlVersion], + primaryId: parentId, + property: propName, + secondaryId: elementId, + layer: layer, + sourceName1: sourceName1, + startLine1: sourceLine1, + sourceName2: sourceName2, + startLine2: startLine2, + endLine2: endLine2, + startLine3: sourceLine3); + } + else + { + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeCauseFormat[aggregateContext.DtdlVersion], + BadTypeActionFormat[aggregateContext.DtdlVersion], + primaryId: parentId, + property: propName, + secondaryId: elementId, + layer: layer); + } + + return false; + } + + if (!materialKinds.Any()) + { + parsingErrorCollection.Notify( + "layerMissingMaterialType", + elementId: elementId, + elementType: elementInfo.EntityKind.ToString(), + element: elt, + layer: layer); + return false; + } + + materialKinds.Add(elementInfo.EntityKind); + if (materialKinds.Count() > 1) + { + parsingErrorCollection.Notify( + "multipleMaterialTypes", + elementId: elementId, + valueConjunction: string.Join(" and ", materialKinds), + element: elt, + layer: layer); + return false; + } + + elementInfo.UndefinedTypeStrings.UnionWith(immediateUndefinedTypes); + + bool requiresMergeability = layer != string.Empty && !elementId.IsReserved; + bool isMergeable = false; + foreach (Dtmi supplementalTypeId in immediateSupplementalTypeIds) + { + if (aggregateContext.SupplementalTypeCollection.TryGetSupplementalTypeInfo(supplementalTypeId, out DTSupplementalTypeInfo supplementalTypeInfo)) + { + if (!supplementalTypeInfo.AllowedCotypeKinds.Contains(elementInfo.EntityKind)) + { + parsingErrorCollection.Notify( + "invalidCotype", + elementId: elementId, + cotype: ContextCollection.GetTermOrUri(supplementalTypeId), + typeRestriction: string.Join(" or ", supplementalTypeInfo.AllowedCotypeKinds), + element: elt, + layer: layer); + } + else if (!supplementalTypeInfo.AllowedCotypeVersions.Contains(elementInfo.DtdlVersion)) + { + parsingErrorCollection.Notify( + "invalidCotypeVersion", + elementId: elementId, + cotype: ContextCollection.GetTermOrUri(supplementalTypeId), + versionRestriction: string.Join(" or ", supplementalTypeInfo.AllowedCotypeVersions), + element: elt, + layer: layer); + } + else + { + elementInfo.AddType(supplementalTypeId, supplementalTypeInfo, parsingErrorCollection); + foreach (Dtmi requiredCocotype in supplementalTypeInfo.RequiredCocotypes) + { + if (!immediateSupplementalTypeIds.Contains(requiredCocotype)) + { + string requiredCocotypeTerm = ContextCollection.GetTermOrUri(requiredCocotype); + parsingErrorCollection.Notify( + "missingCocotype", + elementId: elementId, + elementType: ContextCollection.GetTermOrUri(supplementalTypeId), + cotype: requiredCocotypeTerm, + element: elt); + } + } + } + + isMergeable = isMergeable || supplementalTypeInfo.IsMergeable; + } + } + + if (requiresMergeability && !isMergeable) + { + parsingErrorCollection.Notify( + "disallowedIdFragment", + elementId: elementId, + element: elt, + layer: layer); + } + + return true; + } + + /// + /// Parse a string @type value, whether material or supplemental. + /// + /// The string value to parse. + /// The identifier of the element of this type to create. + /// Name of the layer currently being parsed. + /// The currently being parsed. + /// The identifier of the parent of the element. + /// Identifier of the partition or top-level element under which this element is defined. + /// The name of the property by which the parent refers to this element. + /// The representing the source of the property by which the parent refers to this element. + /// A set of material kinds to update with the material kind of the type, if any. + /// A set of supplemental type IDs to update with the supplemental type, if any. + /// The element created if the type is material. + /// A list of string values of any undefined supplemental types. + /// An AggregateContext object representing information retrieved from JSON-LD context blocks. + /// A ParsingErrorCollection to which any parsing errors are added. + /// True if the parse is sucessful. + internal static bool TryParseTypeStringV4(string typeString, Dtmi elementId, string layer, JsonLdElement elt, Dtmi parentId, Dtmi definedIn, string propName, JsonLdProperty propProp, HashSet materialKinds, HashSet supplementalTypeIds, ref DTUnsignedIntegerInfo elementInfo, ref List undefinedTypes, AggregateContext aggregateContext, ParsingErrorCollection parsingErrorCollection) + { + if (MaterialTypeNameCollection.IsMaterialType(typeString)) + { + string sourceName1 = null; + int sourceLine1 = 0; + if (propProp != null && propProp.TryGetSourceLocation(out sourceName1, out sourceLine1) && elt.TryGetSourceLocation(out string sourceName2, out int startLine2, out int endLine2)) + { + elt.TryGetSourceLocationForType(out _, out int sourceLine3); + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeLocatedCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer, + sourceName1: sourceName1, + startLine1: sourceLine1, + sourceName2: sourceName2, + startLine2: startLine2, + endLine2: endLine2, + startLine3: sourceLine3); + } + else + { + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer); + } + + return false; + } + + if (!aggregateContext.TryCreateDtmi(typeString, out Dtmi supplementalTypeId)) + { + if (typeString.StartsWith("dtmi:")) + { + parsingErrorCollection.Notify( + "typeInvalidDtmi", + elementId: elementId, + cotype: typeString, + element: elt, + layer: layer); + return false; + } + else if (typeString.Contains(":")) + { + parsingErrorCollection.Notify( + "typeNotDtmiNorTerm", + elementId: elementId, + cotype: typeString, + element: elt, + layer: layer); + return false; + } + else + { + if (aggregateContext.IsComplete) + { + parsingErrorCollection.Notify( + "typeUndefinedTerm", + elementId: elementId, + cotype: typeString, + element: elt, + version: aggregateContext.DtdlVersion.ToString(), + layer: layer); + return false; + } + } + + undefinedTypes.Add(typeString); + return true; + } + + if (!aggregateContext.SupplementalTypeCollection.TryGetSupplementalTypeInfo(supplementalTypeId, out DTSupplementalTypeInfo supplementalTypeInfo)) + { + if (aggregateContext.IsComplete) + { + parsingErrorCollection.Notify( + "typeIrrelevantDtmiOrTerm", + elementId: elementId, + cotype: typeString, + element: elt, + version: aggregateContext.DtdlVersion.ToString(), + layer: layer); + return false; + } + + undefinedTypes.Add(typeString); + return true; + } + + if (supplementalTypeInfo.IsAbstract) + { + parsingErrorCollection.Notify( + "abstractSupplementalType", + elementId: elementId, + cotype: ContextCollection.GetTermOrUri(supplementalTypeId), + element: elt, + layer: layer); + return false; + } + + switch (supplementalTypeInfo.ExtensionKind) + { + case DTExtensionKind.LatentType: + { + string sourceName1 = null; + int sourceLine1 = 0; + if (propProp != null && propProp.TryGetSourceLocation(out sourceName1, out sourceLine1) && elt.TryGetSourceLocation(out string sourceName2, out int startLine2, out int endLine2)) + { + elt.TryGetSourceLocationForType(out _, out int sourceLine3); + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeLocatedCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer, + sourceName1: sourceName1, + startLine1: sourceLine1, + sourceName2: sourceName2, + startLine2: startLine2, + endLine2: endLine2, + startLine3: sourceLine3); + } + else + { + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer); + } + } + + return false; + case DTExtensionKind.NamedLatentType: + { + string sourceName1 = null; + int sourceLine1 = 0; + if (propProp != null && propProp.TryGetSourceLocation(out sourceName1, out sourceLine1) && elt.TryGetSourceLocation(out string sourceName2, out int startLine2, out int endLine2)) + { + elt.TryGetSourceLocationForType(out _, out int sourceLine3); + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeLocatedCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer, + sourceName1: sourceName1, + startLine1: sourceLine1, + sourceName2: sourceName2, + startLine2: startLine2, + endLine2: endLine2, + startLine3: sourceLine3); + } + else + { + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer); + } + } + + return false; + case DTExtensionKind.Unit: + { + string sourceName1 = null; + int sourceLine1 = 0; + if (propProp != null && propProp.TryGetSourceLocation(out sourceName1, out sourceLine1) && elt.TryGetSourceLocation(out string sourceName2, out int startLine2, out int endLine2)) + { + elt.TryGetSourceLocationForType(out _, out int sourceLine3); + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeLocatedCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer, + sourceName1: sourceName1, + startLine1: sourceLine1, + sourceName2: sourceName2, + startLine2: startLine2, + endLine2: endLine2, + startLine3: sourceLine3); + } + else + { + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer); + } + } + + return false; + case DTExtensionKind.UnitAttribute: + { + string sourceName1 = null; + int sourceLine1 = 0; + if (propProp != null && propProp.TryGetSourceLocation(out sourceName1, out sourceLine1) && elt.TryGetSourceLocation(out string sourceName2, out int startLine2, out int endLine2)) + { + elt.TryGetSourceLocationForType(out _, out int sourceLine3); + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeLocatedCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer, + sourceName1: sourceName1, + startLine1: sourceLine1, + sourceName2: sourceName2, + startLine2: startLine2, + endLine2: endLine2, + startLine3: sourceLine3); + } + else + { + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer); + } + } + + return false; + } + + supplementalTypeIds.Add(supplementalTypeId); + + return true; + } + + /// + /// Parse elements encoded in a into objects of subclasses of type DTUnsignedIntegerInfo. + /// + /// The model to add the element to. + /// A list of ParsedObjectPropertyInfo to add any object properties, which will be assigned after all parsing has completed. + /// List of ElementPropertyConstraint to be checked after object property assignment. + /// List of to be added to . + /// An AggregateContext object representing information retrieved from JSON-LD context blocks. + /// A ParsingErrorCollection to which any parsing errors are added. + /// The holding the to parse. + /// Name of the layer currently being parsed. + /// The identifier of the parent of the element. + /// Identifier of the partition or top-level element under which this element is defined. + /// The name of the property by which the parent refers to this element, used for auto ID generation. + /// A DTMI segment identifier, used for auto ID generation. + /// A property used for the key if the parent exposes a collection of these elements as a dictionary. + /// The minimum count of element values required. + /// A boolean value indicating whether the property allows multiple values. + /// A boolean value indicating whether an @id must be present. + /// A boolean value indicating whether a @type must be present. + /// Treat all nested definitions as though defined globally. + /// Allow elements to define IDs that have reserved prefixes. + /// Tolerate specific minor invalidities to support backward compatibility. + /// A set of allowed versions for the element. + internal static new void ParseValueCollection(Model model, List objectPropertyInfoList, List elementPropertyConstraints, List valueConstraints, AggregateContext aggregateContext, ParsingErrorCollection parsingErrorCollection, JsonLdProperty valueCollectionProp, string layer, Dtmi parentId, Dtmi definedIn, string propName, string dtmiSeg, string keyProp, int minCount, bool isPlural, bool idRequired, bool typeRequired, bool globalize, bool allowReservedIds, bool tolerateSolecisms, HashSet allowedVersions) + { + int valueCount = 0; + + foreach (JsonLdValue value in valueCollectionProp.Values.Values) + { + if (!isPlural && valueCount > 0) + { + parsingErrorCollection.Notify( + "objectMultipleValues", + elementId: parentId, + propertyName: propName, + incidentValues: valueCollectionProp.Values, + layer: layer); + return; + } + + switch (value.ValueType) + { + case JsonLdValueType.String: + if (parentId != null) + { + if (TryParseIdString(objectPropertyInfoList, elementPropertyConstraints, valueConstraints, aggregateContext, parsingErrorCollection, value.StringValue, layer, parentId, propName, valueCollectionProp, keyProp, allowedVersions)) + { + ++valueCount; + } + else + { + parsingErrorCollection.Notify( + "badDtmiOrTerm", + elementId: parentId, + propertyName: propName, + propertyValue: value.StringValue, + incidentProperty: valueCollectionProp, + incidentValue: value, + version: aggregateContext.DtdlVersion.ToString(), + layer: layer); + } + } + + break; + case JsonLdValueType.Element: + if (TryParseElement(model, objectPropertyInfoList, elementPropertyConstraints, valueConstraints, aggregateContext, parsingErrorCollection, value.ElementValue, layer, parentId, definedIn, propName, valueCollectionProp, dtmiSeg, keyProp, idRequired, typeRequired, globalize, allowReservedIds, tolerateSolecisms, allowedVersions, "UnsignedInteger")) + { + ++valueCount; + } + + break; + default: + parsingErrorCollection.Notify( + "refNotStringOrObject", + elementId: parentId, + propertyName: propName, + incidentProperty: valueCollectionProp, + incidentValue: value, + layer: layer); + break; + } + } + + if (valueCount < minCount) + { + parsingErrorCollection.Notify( + "objectCountBelowMin", + elementId: parentId, + propertyName: propName, + observedCount: valueCount, + expectedCount: minCount, + incidentProperty: valueCollectionProp, + layer: layer); + } + } + + /// + internal override bool CheckDepthOfElementSchemaOrSchema(int depth, int depthLimit, bool allowSelf, List tooDeepElementIds, out Dictionary tooDeepElts, ParsingErrorCollection parsingErrorCollection) + { + tooDeepElts = null; + return true; + } + + /// + /// Determine whether a JsonElement matches this DTDL element. + /// + /// The JsonElement to match. + /// If the instance is a property in a JSON object, the name corresponding to ; otherwise, null. + /// True if the JsonElement matches; false otherwise. + internal override bool DoesInstanceMatch(JsonElement instanceElt, string instanceName) + { + switch (this.DtdlVersion) + { + case 4: + return this.DoesInstanceMatchV4(instanceElt, instanceName); + } + + return false; + } + + /// + /// Indicate whether the property with a given is a dictionary that holds a given . + /// + /// The name of the property to check. + /// The key for the dictionary property. + /// True if the property is present, is a dictionary, and holds the given key. + internal override bool DoesPropertyDictContainKey(string propertyName, string key) + { + if (base.DoesPropertyDictContainKey(propertyName, key)) + { + return true; + } + + switch (propertyName) + { + default: + return false; + } + } + + /// + internal override bool TryGetChild(string childrenPropertyName, string keyPropertyName, string keyPropertyValue, out DTEntityInfo child) + { + switch (childrenPropertyName) + { + default: + break; + } + + child = null; + return false; + } + + /// + internal override bool TryGetDescendantSchemaArray(out Dtmi elementId, out Dictionary excludedElts) + { + if (this.checkedForDescendantSchemaArray) + { + elementId = this.idOfDescendantSchemaArray; + excludedElts = this.eltsOfDescendantSchemaArray; + return this.idOfDescendantSchemaArray != null; + } + + this.checkedForDescendantSchemaArray = true; + + elementId = null; + excludedElts = null; + return false; + } + + /// + internal override bool TryGetDescendantSchemaOrContentsComponentNarrow(out Dtmi elementId, out Dictionary excludedElts) + { + if (this.checkedForDescendantSchemaOrContentsComponentNarrow) + { + elementId = this.idOfDescendantSchemaOrContentsComponentNarrow; + excludedElts = this.eltsOfDescendantSchemaOrContentsComponentNarrow; + return this.idOfDescendantSchemaOrContentsComponentNarrow != null; + } + + this.checkedForDescendantSchemaOrContentsComponentNarrow = true; + + elementId = null; + excludedElts = null; + return false; + } + + /// + /// Try to set an object property with a given . + /// + /// The name of the property whose element value to set if the property is recognized. + /// The key property for dictionary properties. + /// The representing the source of the property by which the parent refers to this element. + /// The reference element to set. + /// The key property for dictionary properties. + /// The key value for dictionary properties. + /// A ParsingErrorCollection to which any parsing errors are added. + /// True if the property name is recognized. + internal override bool TrySetObjectProperty(string propertyName, string layer, JsonLdProperty propProp, DTEntityInfo element, string keyProp, string keyValue, ParsingErrorCollection parsingErrorCollection) + { + if (base.TrySetObjectProperty(propertyName, layer, propProp, element, keyProp, keyValue, parsingErrorCollection)) + { + return true; + } + + switch (propertyName) + { + default: + break; + } + + foreach (DTSupplementalTypeInfo supplementalType in this.supplementalTypes) + { + if (supplementalType.TrySetObjectProperty(this.Id, propertyName, element, keyValue, layer, propProp, ref this.supplementalProperties, this.supplementalSingularPropertyLayers, this.JsonLdElements, parsingErrorCollection)) + { + return true; + } + } + + return false; + } + + /// + /// Validate a JsonElement to determine whether it is a numeric value that conforms to the XSD definition of 'unsignedInt'. + /// + /// The JsonElement to validate. + /// If the instance is a property in a JSON object, the name corresponding to ; otherwise, null. + /// A list of strings to which to add any validation failures. + internal override bool ValidateInstance(JsonElement instanceElt, string instanceName, List violations) + { + switch (this.DtdlVersion) + { + case 4: + return this.ValidateInstanceV4(instanceElt, instanceName, violations); + } + + return true; + } + + /// + internal override HashSet GetTransitiveExtendsNarrow(int depth, int depthLimit, bool allowSelf, List tooDeepElementIds, out Dictionary tooDeepElts, ParsingErrorCollection parsingErrorCollection) + { + HashSet closure = new HashSet(); + + tooDeepElts = null; + return closure; + } + + /// + internal override IEnumerable GetChildren(string childrenPropertyName) + { + switch (childrenPropertyName) + { + default: + return new List(); + } + } + + /// + internal override int GetCountOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrow(bool allowSelf, ParsingErrorCollection parsingErrorCollection) + { + if (this.countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowStatus == TraversalStatus.Complete) + { + return this.countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowValue; + } + + if (this.countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowStatus == TraversalStatus.InProgress) + { + if (allowSelf) + { + this.countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowStatus = TraversalStatus.Complete; + } + else + { + parsingErrorCollection.Notify( + "recursiveStructureNarrow", + elementId: this.Id, + propertyDisjunction: "'contents' or 'fields' or 'enumValues' or 'request' or 'response' or 'properties' or 'schema' or 'elementSchema' or 'mapValue'", + element: this.JsonLdElements.First().Value); + } + + return 0; + } + + this.countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowStatus = TraversalStatus.InProgress; + this.countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowStatus = TraversalStatus.Complete; + return this.countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowValue; + } + + /// + internal override int GetCountOfExtendsNarrow(bool allowSelf, ParsingErrorCollection parsingErrorCollection) + { + if (this.countOfExtendsNarrowStatus == TraversalStatus.Complete) + { + return this.countOfExtendsNarrowValue; + } + + if (this.countOfExtendsNarrowStatus == TraversalStatus.InProgress) + { + if (allowSelf) + { + this.countOfExtendsNarrowStatus = TraversalStatus.Complete; + } + else + { + parsingErrorCollection.Notify( + "recursiveStructureNarrow", + elementId: this.Id, + propertyDisjunction: "'extends'", + element: this.JsonLdElements.First().Value); + } + + return 0; + } + + this.countOfExtendsNarrowStatus = TraversalStatus.InProgress; + this.countOfExtendsNarrowStatus = TraversalStatus.Complete; + return this.countOfExtendsNarrowValue; + } + + /// + /// Add a supplemental type. + /// + /// Identifier for the supplemental type to add. + /// DTSupplementalTypeInfo for the supplemental type. + /// A ParsingErrorCollection to which any parsing errors are added. + internal override void AddType(Dtmi id, DTSupplementalTypeInfo supplementalType, ParsingErrorCollection parsingErrorCollection) + { + if (this.supplementalTypeIds.Add(id)) + { + this.supplementalTypes.Add(supplementalType); + } + } + + /// + internal override void ApplyTransformations(Model model, ParsingErrorCollection parsingErrorCollection) + { + switch (this.DtdlVersion) + { + case 4: + this.ApplyTransformationsV4(model, parsingErrorCollection); + break; + } + } + + /// + internal override void CheckDescendantEnumValueDatatype(Dtmi ancestorId, Dictionary ancestorElts, Type datatype, ParsingErrorCollection parsingErrorCollection) + { + if (this.checkedDescendantEnumValueDatatype != datatype) + { + this.checkedDescendantEnumValueDatatype = datatype; + } + } + + /// + internal override void CheckRestrictions(ParsingErrorCollection parsingErrorCollection) + { + this.CheckForDisallowedCocotypes(this.supplementalTypeIds, this.supplementalTypes, parsingErrorCollection); + + foreach (DTSupplementalTypeInfo supplementalType in this.supplementalTypes) + { + supplementalType.CheckRestrictions(this.supplementalProperties, parsingErrorCollection, this.Id, this.JsonLdElements); + } + + switch (this.DtdlVersion) + { + case 4: + this.CheckRestrictionsV4(parsingErrorCollection); + break; + } + } + + /// + /// Parse the properties in a JSON UnsignedInteger object. + /// + /// Model to which to add object properties. + /// List of object info structs for deferred assignments. + /// List of ElementPropertyConstraint to be checked after object property assignment. + /// An AggregateContext object representing information retrieved from JSON-LD context blocks. + /// A set of supplemental type IDs. + /// A list of undefind type strings. + /// A ParsingErrorCollection to which any parsing errors are added. + /// The to parse. + /// Name of the layer currently being parsed. + /// Identifier of the partition or top-level element under which this element is defined. + /// Treat all nested definitions as though defined globally. + /// Allow elements to define IDs that have reserved prefixes. + /// Tolerate specific minor invalidities to support backward compatibility. + internal override void ParsePropertiesV4(Model model, List objectPropertyInfoList, List elementPropertyConstraints, AggregateContext aggregateContext, HashSet immediateSupplementalTypeIds, List immediateUndefinedTypes, ParsingErrorCollection parsingErrorCollection, JsonLdElement elt, string layer, Dtmi definedIn, bool globalize, bool allowReservedIds, bool tolerateSolecisms) + { + this.LanguageMajorVersion = 4; + + JsonLdProperty commentProperty = null; + JsonLdProperty descriptionProperty = null; + JsonLdProperty displayNameProperty = null; + Dictionary supplementalJsonLdProperties = new Dictionary(); + + foreach (JsonLdProperty prop in elt.Properties) + { + switch (prop.Name) + { + case "comment": + case "dtmi:dtdl:property:comment;4": + if (commentProperty != null) + { + parsingErrorCollection.Notify( + "duplicatePropertyName", + elementId: this.Id, + propertyName: "comment", + incidentProperty: prop, + extantProperty: commentProperty, + layer: layer); + } + else + { + commentProperty = prop; + int? maxLength = aggregateContext.LimitSpecifier switch + { + "" => 512, + "onvif_1" => 515, + _ => null, + }; + + string newComment = ValueParser.ParseSingularStringValueCollection(aggregateContext, this.Id, "comment", prop.Values, maxLength, null, layer, parsingErrorCollection, isOptional: true); + if (this.commentPropertyLayer != null) + { + if (this.Comment != newComment) + { + JsonLdProperty extantProp = this.JsonLdElements[this.commentPropertyLayer].Properties.FirstOrDefault(p => p.Name == "comment"); + parsingErrorCollection.Notify( + "inconsistentStringValues", + elementId: this.Id, + propertyName: "comment", + propertyValue: newComment.ToString(), + valueRestriction: this.Comment.ToString(), + incidentProperty: prop, + extantProperty: extantProp, + layer: layer); + } + } + else + { + this.Comment = newComment; + this.commentPropertyLayer = layer; + + if (this.commentValueConstraints != null) + { + foreach (ValueConstraint valueConstraint in this.commentValueConstraints) + { + if (valueConstraint.RequiredLiteral != null && !valueConstraint.RequiredLiteral.Equals(newComment)) + { + parsingErrorCollection.Notify( + "notRequiredStringValue", + elementId: this.Id, + propertyName: "comment", + propertyValue: newComment.ToString(), + valueRestriction: valueConstraint.RequiredLiteral.ToString(), + incidentProperty: prop, + layer: layer); + } + } + } + + ((Dictionary)this.StringProperties)["comment"] = newComment; + } + } + + continue; + case "description": + case "dtmi:dtdl:property:description;4": + if (descriptionProperty != null) + { + parsingErrorCollection.Notify( + "duplicatePropertyName", + elementId: this.Id, + propertyName: "description", + incidentProperty: prop, + extantProperty: descriptionProperty, + layer: layer); + } + else + { + descriptionProperty = prop; + int? maxLength = aggregateContext.LimitSpecifier switch + { + "" => 512, + "onvif_1" => 514, + _ => null, + }; + + Dictionary newDescription = ValueParser.ParseLangStringValueCollection(aggregateContext, this.Id, "description", prop.Values, "en", maxLength, null, layer, parsingErrorCollection); + List descriptionCodes = Helpers.GetKeysWithDifferingLiteralValues(this.Description, newDescription); + if (descriptionCodes.Any()) + { + JsonLdProperty extantProp = Helpers.TryGetSingleUniqueValue(descriptionCodes.Select(c => this.descriptionPropertyLayer[c]), out string uniqueCodeLayer) && this.JsonLdElements[uniqueCodeLayer].Properties.Any(p => p.Name == "description") ? this.JsonLdElements[uniqueCodeLayer].Properties.First(p => p.Name == "description") : null; + parsingErrorCollection.Notify( + "inconsistentLangStringValues", + elementId: this.Id, + propertyName: "description", + langCode: string.Join(" and ", descriptionCodes.Select(c => $"'{c}'")), + observedCount: descriptionCodes.Count, + incidentProperty: prop, + extantProperty: extantProp, + layer: layer); + } + else if (this.Description.Any()) + { + foreach (KeyValuePair kvp in newDescription) + { + ((Dictionary)this.Description)[kvp.Key] = kvp.Value; + this.descriptionPropertyLayer[kvp.Key] = layer; + } + } + else + { + this.Description = newDescription; + this.descriptionPropertyLayer = newDescription.ToDictionary(e => e.Key, e => layer); + } + } + + continue; + case "displayName": + case "dtmi:dtdl:property:displayName;4": + if (displayNameProperty != null) + { + parsingErrorCollection.Notify( + "duplicatePropertyName", + elementId: this.Id, + propertyName: "displayName", + incidentProperty: prop, + extantProperty: displayNameProperty, + layer: layer); + } + else + { + displayNameProperty = prop; + int? maxLength = aggregateContext.LimitSpecifier switch + { + "" => 512, + "onvif_1" => 513, + _ => null, + }; + + Dictionary newDisplayName = ValueParser.ParseLangStringValueCollection(aggregateContext, this.Id, "displayName", prop.Values, "en", maxLength, null, layer, parsingErrorCollection); + List displayNameCodes = Helpers.GetKeysWithDifferingLiteralValues(this.DisplayName, newDisplayName); + if (displayNameCodes.Any()) + { + JsonLdProperty extantProp = Helpers.TryGetSingleUniqueValue(displayNameCodes.Select(c => this.displayNamePropertyLayer[c]), out string uniqueCodeLayer) && this.JsonLdElements[uniqueCodeLayer].Properties.Any(p => p.Name == "displayName") ? this.JsonLdElements[uniqueCodeLayer].Properties.First(p => p.Name == "displayName") : null; + parsingErrorCollection.Notify( + "inconsistentLangStringValues", + elementId: this.Id, + propertyName: "displayName", + langCode: string.Join(" and ", displayNameCodes.Select(c => $"'{c}'")), + observedCount: displayNameCodes.Count, + incidentProperty: prop, + extantProperty: extantProp, + layer: layer); + } + else if (this.DisplayName.Any()) + { + foreach (KeyValuePair kvp in newDisplayName) + { + ((Dictionary)this.DisplayName)[kvp.Key] = kvp.Value; + this.displayNamePropertyLayer[kvp.Key] = layer; + } + } + else + { + this.DisplayName = newDisplayName; + this.displayNamePropertyLayer = newDisplayName.ToDictionary(e => e.Key, e => layer); + } + } + + continue; + } + + if (this.TryParseSupplementalProperty(model, immediateSupplementalTypeIds, objectPropertyInfoList, elementPropertyConstraints, aggregateContext, layer, definedIn, parsingErrorCollection, prop.Name, globalize, allowReservedIds, tolerateSolecisms, prop, supplementalJsonLdProperties)) + { + continue; + } + + if (aggregateContext.TryCreateDtmi(prop.Name, out Dtmi _)) + { + if (aggregateContext.IsComplete) + { + parsingErrorCollection.Notify( + "propertyIrrelevantDtmiOrTerm", + elementId: this.Id, + propertyName: prop.Name, + incidentProperty: prop, + element: elt, + layer: layer); + continue; + } + } + else if (prop.Name.StartsWith("dtmi:")) + { + parsingErrorCollection.Notify( + "propertyInvalidDtmi", + elementId: this.Id, + propertyName: prop.Name, + incidentProperty: prop, + element: elt, + layer: layer); + continue; + } + else if (prop.Name.Contains(":")) + { + parsingErrorCollection.Notify( + "propertyNotDtmiNorTerm", + elementId: this.Id, + propertyName: prop.Name, + incidentProperty: prop, + element: elt, + layer: layer); + continue; + } + else + { + if (aggregateContext.IsComplete) + { + parsingErrorCollection.Notify( + "propertyUndefinedTerm", + elementId: this.Id, + propertyName: prop.Name, + incidentProperty: prop, + element: elt, + version: aggregateContext.DtdlVersion.ToString(), + layer: layer); + continue; + } + } + + if (!immediateUndefinedTypes.Any()) + { + if (elt.Types != null) + { + parsingErrorCollection.Notify( + "noTypeThatAllows", + elementId: this.Id, + propertyName: prop.Name, + incidentProperty: prop, + element: elt, + layer: layer); + } + else + { + parsingErrorCollection.Notify( + "inferredTypeDoesNotAllow", + elementId: this.Id, + referenceType: "UnsignedInteger", + propertyName: prop.Name, + incidentProperty: prop, + element: elt, + layer: layer); + } + + continue; + } + + using (JsonDocument propDoc = JsonDocument.Parse(prop.Values.GetJsonText())) + { + this.UndefinedPropertyDictionary[prop.Name] = propDoc.RootElement.Clone(); + } + } + + foreach (Dtmi supplementalTypeId in immediateSupplementalTypeIds) + { + if (aggregateContext.SupplementalTypeCollection.TryGetSupplementalTypeInfo(supplementalTypeId, out DTSupplementalTypeInfo supplementalTypeInfo)) + { + supplementalTypeInfo.CheckForRequiredProperties(parsingErrorCollection, this.Id, elt, supplementalJsonLdProperties); + } + } + } + + /// + /// Record JSON-LD source as appropriate and check length of text against limit. + /// + /// The name of the layer whose source to record. + /// A JsonLdElement containing the JSON-LD source of the element. + /// An AggregateContext object representing information retrieved from JSON-LD context blocks. + /// A ParsingErrorCollection to which any parsing errors are added. + /// True if the element is at the document root. + /// True if the element has been globalized. + internal override void RecordSourceAsAppropriate(string layer, JsonLdElement elt, AggregateContext aggregateContext, ParsingErrorCollection parsingErrorCollection, bool atRoot, bool globalized) + { + } + + /// + /// Write a JSON representation of the DTDL element represented by an object of this class. + /// + /// A Utf8JsonWriter object with which to write the JSON representation. + /// True if the mothed should add a ClassId property to the JSON object. + internal override void WriteToJson(Utf8JsonWriter jsonWriter, bool includeClassId) + { + base.WriteToJson(jsonWriter, includeClassId: false); + + if (includeClassId) + { + jsonWriter.WriteString("ClassId", $"dtmi:dtdl:class:UnsignedInteger;{this.LanguageMajorVersion}"); + } + } + + private bool DoesInstanceMatchV4(JsonElement instanceElt, string instanceName) + { + return true; + } + + private bool TryParseSupplementalProperty(Model model, HashSet immediateSupplementalTypeIds, List objectPropertyInfoList, List elementPropertyConstraints, AggregateContext aggregateContext, string layer, Dtmi definedIn, ParsingErrorCollection parsingErrorCollection, string propName, bool globalize, bool allowReservedIds, bool tolerateSolecisms, JsonLdProperty valueCollectionProp, Dictionary supplementalJsonLdProperties) + { + if (!aggregateContext.TryCreateDtmi(propName, out Dtmi propDtmi)) + { + return false; + } + + foreach (Dtmi supplementalTypeId in immediateSupplementalTypeIds) + { + if (aggregateContext.SupplementalTypeCollection.TryGetSupplementalTypeInfo(supplementalTypeId, out DTSupplementalTypeInfo supplementalTypeInfo) && supplementalTypeInfo.TryParseProperty(model, objectPropertyInfoList, elementPropertyConstraints, aggregateContext, parsingErrorCollection, layer, this.Id, definedIn, propDtmi.ToString(), globalize, allowReservedIds, tolerateSolecisms, valueCollectionProp, ref this.supplementalProperties, supplementalJsonLdProperties, this.supplementalSingularPropertyLayers, this.JsonLdElements)) + { + return true; + } + } + + return false; + } + + private bool ValidateInstanceV4(JsonElement instanceElt, string instanceName, List violations) + { + if (instanceElt.ValueKind != JsonValueKind.Number) + { + violations.Add($">>{instanceElt.GetRawText()}<< is not a numeric value"); + return false; + } + + if (!uint.TryParse(instanceElt.GetRawText(), out uint _)) + { + violations.Add($"{instanceElt.GetRawText()} does not conform to the XSD definition of 'unsignedInt'"); + return false; + } + + if (!ElementValueInstanceRegexPatternV4.IsMatch(instanceElt.GetRawText())) + { + violations.Add($"\"{instanceElt.GetRawText()}\" does not conform to the XSD definition of 'unsignedInt'"); + return false; + } + + return true; + } + + private void ApplyTransformationsV4(Model model, ParsingErrorCollection parsingErrorCollection) + { + } + + /// + private void CheckRestrictionsV4(ParsingErrorCollection parsingErrorCollection) + { + } + } +} diff --git a/dotnet/src/DTDLParser/generated/DTUnsignedLongInfo.g.cs b/dotnet/src/DTDLParser/generated/DTUnsignedLongInfo.g.cs new file mode 100644 index 00000000..fdb12de8 --- /dev/null +++ b/dotnet/src/DTDLParser/generated/DTUnsignedLongInfo.g.cs @@ -0,0 +1,1895 @@ +/* This is an auto-generated file. Do not modify. */ + +namespace DTDLParser.Models +{ + using System; + using System.Collections.Generic; + using System.ComponentModel; + using System.Globalization; + using System.IO; + using System.Linq; + using System.Text; + using System.Text.Json; + using System.Text.RegularExpressions; + using System.Threading; + using System.Threading.Tasks; + using DTDLParser; + + /// + /// Class DTUnsignedLongInfo corresponds to an element of type UnsignedLong in a DTDL model. + /// + public class DTUnsignedLongInfo : DTNumericSchemaInfo, ITypeChecker, IConstrainer, IEquatable + { + private static readonly Dictionary> ConcreteKinds = new Dictionary>(); + + private static readonly Dictionary BadTypeActionFormat = new Dictionary(); + + private static readonly Dictionary BadTypeCauseFormat = new Dictionary(); + + private static readonly Dictionary BadTypeLocatedCauseFormat = new Dictionary(); + + private static readonly HashSet PropertyNames = new HashSet(); + + private static readonly HashSet VersionlessTypes = new HashSet(); + + private static readonly Regex ElementValueInstanceRegexPatternV4 = new Regex(@"^[0-9]+$", RegexOptions.Compiled); + + private bool checkedForDescendantSchemaArray = false; + + private bool checkedForDescendantSchemaOrContentsComponentNarrow = false; + + private Dictionary supplementalPropertySources = new Dictionary(); + + private Dictionary eltsOfDescendantSchemaArray = null; + + private Dictionary eltsOfDescendantSchemaOrContentsComponentNarrow = null; + + private Dictionary supplementalProperties; + + private Dictionary descriptionPropertyLayer = null; + + private Dictionary displayNamePropertyLayer = null; + + private Dictionary supplementalSingularPropertyLayers = new Dictionary(); + + private Dtmi idOfDescendantSchemaArray = null; + + private Dtmi idOfDescendantSchemaOrContentsComponentNarrow = null; + + private HashSet supplementalTypeIds; + + private int countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowValue = 0; + + private int countOfExtendsNarrowValue = 0; + + private List supplementalTypes; + + private List commentValueConstraints = null; + + private List descriptionValueConstraints = null; + + private List displayNameValueConstraints = null; + + private string commentPropertyLayer = null; + + private TraversalStatus countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowStatus = TraversalStatus.NotStarted; + + private TraversalStatus countOfExtendsNarrowStatus = TraversalStatus.NotStarted; + + private Type checkedDescendantEnumValueDatatype = null; + + static DTUnsignedLongInfo() + { + VersionlessTypes.Add("dtmi:dtdl:class:Entity"); + VersionlessTypes.Add("dtmi:dtdl:class:NumericSchema"); + VersionlessTypes.Add("dtmi:dtdl:class:PrimitiveSchema"); + VersionlessTypes.Add("dtmi:dtdl:class:Schema"); + VersionlessTypes.Add("dtmi:dtdl:class:UnsignedLong"); + + PropertyNames.Add("comment"); + PropertyNames.Add("description"); + PropertyNames.Add("displayName"); + PropertyNames.Add("languageMajorVersion"); + + ConcreteKinds[4] = new HashSet(); + ConcreteKinds[4].Add(DTEntityKind.UnsignedLong); + + BadTypeActionFormat[4] = "Use this standard value for property '{property}'{line1}: unsignedLong."; + + BadTypeCauseFormat[4] = "{layer}{primaryId:p} property '{property}' has value{secondaryId:e} that is not a standard value for this property."; + + BadTypeLocatedCauseFormat[4] = "In {sourceName1}, property '{property}'{line1} has value{secondaryId:e}{line2} that is not a standard value for this property."; + } + + /// + /// Initializes a new instance of the class. + /// + /// Version of DTDL used to define the UnsignedLong. + /// Identifier for the UnsignedLong. + /// Identifier of the parent element in which this UnsignedLong is defined. + /// Name of the property by which the parent DTDL element refers to this UnsignedLong. + /// Identifier of the partition in which this UnsignedLong is defined. + internal DTUnsignedLongInfo(int dtdlVersion, Dtmi id, Dtmi childOf, string myPropertyName, Dtmi definedIn) + : base(dtdlVersion, id, childOf, myPropertyName, definedIn, DTEntityKind.UnsignedLong) + { + this.supplementalTypeIds = new HashSet(); + this.supplementalProperties = new Dictionary(); + this.supplementalTypes = new List(); + + this.IsPartition = false; + + this.MaybePartial = false; + } + + /// + /// Initializes a new instance of the class. + /// + /// Version of DTDL used to define the UnsignedLong. + /// Identifier for the UnsignedLong. + /// Identifier of the parent element in which this UnsignedLong is defined. + /// Name of the property by which the parent DTDL element refers to this UnsignedLong. + /// Identifier of the partition in which this UnsignedLong is defined. + /// The kind of Entity, which may be other than UnsignedLong if this constructor is called from a derived class. + internal DTUnsignedLongInfo(int dtdlVersion, Dtmi id, Dtmi childOf, string myPropertyName, Dtmi definedIn, DTEntityKind entityKind) + : base(dtdlVersion, id, childOf, myPropertyName, definedIn, entityKind) + { + this.supplementalTypeIds = new HashSet(); + this.supplementalProperties = new Dictionary(); + this.supplementalTypes = new List(); + + this.IsPartition = false; + + this.MaybePartial = false; + } + + /// + /// Get the DTMI that identifies type UnsignedLong in the version of DTDL used to define this element. + /// + /// The DTMI for the DTDL type UnsignedLong. + public override Dtmi ClassId + { + get + { + return new Dtmi($"dtmi:dtdl:class:UnsignedLong;{this.LanguageMajorVersion}"); + } + } + + /// + /// Gets the supplemantal properties of the DTDL element that corresponds to this object. + /// + /// A dictionary that maps each string-valued property name to an object that holds the value of the property with the given name. + /// + /// If the property is a literal in the DTDL model, the object holds a literal value. + /// If the property is another DTDL element in the model, the object is the C# object that corresponds to this element. + /// + public override IDictionary SupplementalProperties + { + get + { + return this.supplementalProperties; + } + } + + /// + /// Gets a collection of identifiers, each of which is a Dtmi that indicates a supplemental type that applies to the DTDL element that corresponds to this object. + /// + /// A collection of DTMIs indicating the supplemental types that apply to the DTDL element. + public override IReadOnlyCollection SupplementalTypes + { + get + { + return this.supplementalTypeIds; + } + } + + /// + /// Gets a value indicating whether this class is a partition point for the object model. + /// + internal override bool IsPartition { get; } + + /// + /// Gets material properties allowed by the type of DTDL element. + /// + internal override HashSet MaterialProperties + { + get + { + return PropertyNames; + } + } + + /// + /// Determines whether two DTUnsignedLongInfo objects are not equal. + /// + /// One DTUnsignedLongInfo object to compare. + /// Another DTUnsignedLongInfo object to compare to the first. + /// True if not equal. + public static bool operator !=(DTUnsignedLongInfo x, DTUnsignedLongInfo y) + { + if (ReferenceEquals(null, x)) + { + return !ReferenceEquals(null, y); + } + + return !x.Equals(y); + } + + /// + /// Determines whether two DTUnsignedLongInfo objects are equal. + /// + /// One DTUnsignedLongInfo object to compare. + /// Another DTUnsignedLongInfo object to compare to the first. + /// True if equal. + public static bool operator ==(DTUnsignedLongInfo x, DTUnsignedLongInfo y) + { + if (ReferenceEquals(null, x)) + { + return ReferenceEquals(null, y); + } + + return x.Equals(y); + } + + /// + /// Compares to another DTUnsignedLongInfo object, recursing through the entire subtree of object properties. + /// + /// The other DTUnsignedLongInfo object to compare to. + /// True if equal. + public virtual bool DeepEquals(DTUnsignedLongInfo other) + { + return base.DeepEquals(other) + && Helpers.AreDictionariesDeepOrLiteralEqual(this.supplementalProperties, other.supplementalProperties) + && this.supplementalTypeIds.SetEquals(other.supplementalTypeIds) + ; + } + + /// + public override bool DeepEquals(DTNumericSchemaInfo other) + { + return this.EntityKind == other?.EntityKind && this.DeepEquals((DTUnsignedLongInfo)other); + } + + /// + public override bool DeepEquals(DTPrimitiveSchemaInfo other) + { + return this.EntityKind == other?.EntityKind && this.DeepEquals((DTUnsignedLongInfo)other); + } + + /// + public override bool DeepEquals(DTSchemaInfo other) + { + return this.EntityKind == other?.EntityKind && this.DeepEquals((DTUnsignedLongInfo)other); + } + + /// + public override bool DeepEquals(DTEntityInfo other) + { + return this.EntityKind == other?.EntityKind && this.DeepEquals((DTUnsignedLongInfo)other); + } + + /// + /// Compares to another DTUnsignedLongInfo object. + /// + /// The other DTUnsignedLongInfo object to compare to. + /// True if equal. + public virtual bool Equals(DTUnsignedLongInfo other) + { + return base.Equals(other) + && Helpers.AreDictionariesIdOrLiteralEqual(this.supplementalProperties, other.supplementalProperties) + && this.supplementalTypeIds.SetEquals(other.supplementalTypeIds) + ; + } + + /// + public override bool Equals(DTNumericSchemaInfo other) + { + return this.EntityKind == other?.EntityKind && this.Equals((DTUnsignedLongInfo)other); + } + + /// + public override bool Equals(DTPrimitiveSchemaInfo other) + { + return this.EntityKind == other?.EntityKind && this.Equals((DTUnsignedLongInfo)other); + } + + /// + public override bool Equals(DTSchemaInfo other) + { + return this.EntityKind == other?.EntityKind && this.Equals((DTUnsignedLongInfo)other); + } + + /// + public override bool Equals(DTEntityInfo other) + { + return this.EntityKind == other?.EntityKind && this.Equals((DTUnsignedLongInfo)other); + } + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object otherObj) + { + return otherObj is DTUnsignedLongInfo other && this.Equals(other); + } + + /// + bool ITypeChecker.DoesHaveType(Dtmi typeId) + { + return VersionlessTypes.Contains(typeId.Versionless) + || this.supplementalTypes.Any(ps => ((ITypeChecker)ps).DoesHaveType(typeId)) + ; + } + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() + { + int hashCode = base.GetHashCode(); + + unchecked + { + hashCode = (hashCode * 131) + Helpers.GetDictionaryIdOrLiteralHashCode(this.supplementalProperties); + hashCode = (hashCode * 131) + Helpers.GetSetLiteralHashCode(this.supplementalTypeIds); + } + + return hashCode; + } + + /// + /// Validate a JsonElement to determine whether it is a numeric value that conforms to the XSD definition of 'unsignedLong'. + /// + /// The JsonElement to validate. + /// A list of strings that each indicate a validation failure; the list is empty if the JsonElement conforms. + public override IReadOnlyCollection ValidateInstance(JsonElement instanceElt) + { + List violations = new List(); + this.ValidateInstance(instanceElt, null, violations); + return violations; + } + + /// + void IConstrainer.AddPropertyValueConstraint(string propertyName, ValueConstraint valueConstraint) + { + switch (propertyName) + { + case "comment": + if (this.commentValueConstraints == null) + { + this.commentValueConstraints = new List(); + } + + this.commentValueConstraints.Add(valueConstraint); + break; + case "description": + if (this.descriptionValueConstraints == null) + { + this.descriptionValueConstraints = new List(); + } + + this.descriptionValueConstraints.Add(valueConstraint); + break; + case "displayName": + if (this.displayNameValueConstraints == null) + { + this.displayNameValueConstraints = new List(); + } + + this.displayNameValueConstraints.Add(valueConstraint); + break; + } + } + + /// + void IConstrainer.AddSiblingConstraint(SiblingConstraint siblingConstraint) + { + if (this.SiblingConstraints == null) + { + this.SiblingConstraints = new List(); + } + + this.SiblingConstraints.Add(siblingConstraint); + } + + /// + /// Parse an element encoded in a into an object that is a subclass of type DTUnsignedLongInfo. + /// + /// The model to add the element to. + /// A list of ParsedObjectPropertyInfo to add any object properties, which will be assigned after all parsing has completed. + /// List of ElementPropertyConstraint to be checked after object property assignment. + /// List of to be added to . + /// An AggregateContext object representing information retrieved from JSON-LD context blocks. + /// A ParsingErrorCollection to which any parsing errors are added. + /// The to parse. + /// Name of the layer currently being parsed. + /// The identifier of the parent of the element. + /// Identifier of the partition or top-level element under which this element is defined. + /// The name of the property by which the parent refers to this element, used for auto ID generation. + /// The representing the source of the property by which the parent refers to this element. + /// A DTMI segment identifier, used for auto ID generation. + /// A property used for the key if the parent exposes a collection of these elements as a dictionary. + /// A boolean value indicating whether an @id must be present. + /// A boolean value indicating whether a @type must be present. + /// Treat all nested definitions as though defined globally. + /// Allow elements to define IDs that have reserved prefixes. + /// Tolerate specific minor invalidities to support backward compatibility. + /// A set of allowed versions for the element. + /// The type name to infer if no @type specified on element. + /// True if the parses correctly as an appropriate element. + internal static new bool TryParseElement(Model model, List objectPropertyInfoList, List elementPropertyConstraints, List valueConstraints, AggregateContext aggregateContext, ParsingErrorCollection parsingErrorCollection, JsonLdElement elt, string layer, Dtmi parentId, Dtmi definedIn, string propName, JsonLdProperty propProp, string dtmiSeg, string keyProp, bool idRequired, bool typeRequired, bool globalize, bool allowReservedIds, bool tolerateSolecisms, HashSet allowedVersions, string inferredType) + { + AggregateContext childAggregateContext = aggregateContext.GetChildContext(elt, parsingErrorCollection); + + bool allowIdReferenceSyntax = tolerateSolecisms && aggregateContext.DtdlVersion < 3; + + if (elt.PropertyCount == 1 && elt.Id != null) + { + if (allowIdReferenceSyntax) + { + if (TryParseIdString(objectPropertyInfoList, elementPropertyConstraints, valueConstraints, childAggregateContext, parsingErrorCollection, elt.Id, layer, parentId, propName, propProp, keyProp, allowedVersions)) + { + return true; + } + else + { + parsingErrorCollection.Notify( + "idRefBadDtmiOrTerm", + elementId: parentId, + propertyName: propName, + propertyValue: elt.Id, + element: elt, + version: aggregateContext.DtdlVersion.ToString(), + layer: layer); + return false; + } + } + else + { + parsingErrorCollection.Notify( + "idReference", + elementId: parentId, + propertyName: propName, + identifier: elt.Id, + element: elt, + layer: layer); + return false; + } + } + + if (elt.Graph != null) + { + parsingErrorCollection.Notify( + "graphDisallowed", + elementId: parentId, + propertyName: propName, + element: elt); + } + + if (childAggregateContext.RestrictKeywords) + { + if (elt.Language != null) + { + parsingErrorCollection.Notify( + "keywordDisallowed", + elementId: parentId, + propertyName: propName, + keyword: "@language", + element: elt); + } + + if (elt.Value != null) + { + parsingErrorCollection.Notify( + "keywordDisallowed", + elementId: parentId, + propertyName: propName, + keyword: "@value", + element: elt); + } + + foreach (string keyword in elt.Keywords) + { + parsingErrorCollection.Notify( + "keywordDisallowed", + elementId: parentId, + propertyName: propName, + keyword: keyword, + element: elt); + } + } + + if (allowedVersions != null && !allowedVersions.Contains(childAggregateContext.DtdlVersion)) + { + parsingErrorCollection.Notify( + "disallowedVersionDefinition", + elementId: parentId, + propertyName: propName, + version: childAggregateContext.DtdlVersion.ToString(), + versionRestriction: string.Join(" ,", allowedVersions), + contextComponent: childAggregateContext.DtdlContextComponent, + layer: layer); + } + + bool tolerateReservedIds = tolerateSolecisms && aggregateContext.DtdlVersion < 3; + + Dtmi elementId = IdValidator.ParseIdProperty(childAggregateContext, elt, childAggregateContext.MergeDefinitions ? layer : null, parentId, propName, dtmiSeg, idRequired, allowReservedIds || tolerateReservedIds, parsingErrorCollection); + + Dtmi baseElementId = childAggregateContext.MergeDefinitions || elementId.Tail == string.Empty ? elementId.Fragmentless : elementId; + string elementLayer = childAggregateContext.MergeDefinitions ? elementId.Tail : string.Empty; + + bool ignoreElementsWithAutoIDsAndDuplicateNames = tolerateSolecisms && aggregateContext.DtdlVersion < 3; + + if (model.Dict.TryGetValue(baseElementId, out DTEntityInfo baseElement)) + { + if (baseElement.JsonLdElements.TryGetValue(elementLayer, out JsonLdElement duplicateElt)) + { + if (!baseElementId.IsReserved) + { + parsingErrorCollection.Notify( + "duplicateDefinition", + elementId: baseElementId, + element: elt, + extantElement: duplicateElt, + layer: layer); + } + else if (!ignoreElementsWithAutoIDsAndDuplicateNames && dtmiSeg != null) + { + JsonLdProperty dtmiSegProp = elt.Properties.First(p => p.Name == dtmiSeg || (Dtmi.TryCreateDtmi(p.Name, out Dtmi d) && ContextCollection.GetTermOrUri(d) == dtmiSeg)); + JsonLdProperty dupSegProp = duplicateElt.Properties.First(p => p.Name == dtmiSeg || (Dtmi.TryCreateDtmi(p.Name, out Dtmi d) && ContextCollection.GetTermOrUri(d) == dtmiSeg)); + parsingErrorCollection.Notify( + "nonUniquePropertyValue", + elementId: parentId, + propertyName: propName, + nestedName: dtmiSeg, + nestedValue: dtmiSegProp.Values.Values.First().StringValue, + incidentProperty: dupSegProp, + extantProperty: dtmiSegProp); + } + + return false; + } + + if (baseElement.DtdlVersion != childAggregateContext.DtdlVersion) + { + parsingErrorCollection.Notify( + "inconsistentContext", + elementId: baseElementId, + version: childAggregateContext.DtdlVersion.ToString(), + versionRestriction: baseElement.DtdlVersion.ToString(), + layer: elementLayer); + return false; + } + } + + if (typeRequired && elt.Types == null) + { + string sourceName1 = null; + int sourceLine1 = 0; + if (propProp != null && propProp.TryGetSourceLocation(out sourceName1, out sourceLine1) && elt.TryGetSourceLocation(out string sourceName2, out int startLine2, out int endLine2)) + { + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeLocatedCauseFormat[childAggregateContext.DtdlVersion], + BadTypeActionFormat[childAggregateContext.DtdlVersion], + primaryId: parentId, + property: propName, + secondaryId: baseElementId, + layer: layer, + sourceName1: sourceName1, + startLine1: sourceLine1, + sourceName2: sourceName2, + startLine2: startLine2, + endLine2: endLine2); + } + else + { + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeCauseFormat[childAggregateContext.DtdlVersion], + BadTypeActionFormat[childAggregateContext.DtdlVersion], + primaryId: parentId, + property: propName, + secondaryId: baseElementId, + layer: layer); + } + + return false; + } + + DTUnsignedLongInfo elementInfo = (DTUnsignedLongInfo)baseElement; + HashSet immediateSupplementalTypeIds; + List immediateUndefinedTypes; + bool typeArrayParsed; + if (elt.Types == null) + { + typeArrayParsed = TryParseTypeStrings(new List() { inferredType }, baseElementId, elementLayer, elt, parentId, definedIn, propName, propProp, ref elementInfo, childAggregateContext, out immediateSupplementalTypeIds, out immediateUndefinedTypes, parsingErrorCollection); + } + else + { + typeArrayParsed = TryParseTypeStrings(elt.Types, baseElementId, elementLayer, elt, parentId, definedIn, propName, propProp, ref elementInfo, childAggregateContext, out immediateSupplementalTypeIds, out immediateUndefinedTypes, parsingErrorCollection); + } + + if (!typeArrayParsed || ReferenceEquals(null, elementInfo)) + { + return false; + } + + switch (childAggregateContext.DtdlVersion) + { + case 4: + elementInfo.ParsePropertiesV4(model, objectPropertyInfoList, elementPropertyConstraints, childAggregateContext, immediateSupplementalTypeIds, immediateUndefinedTypes, parsingErrorCollection, elt, elementLayer, definedIn, globalize, allowReservedIds, tolerateSolecisms); + break; + } + + elementInfo.LimitSpecifier = aggregateContext.LimitSpecifier; + + elementInfo.RecordSourceAsAppropriate(elementLayer, elt, childAggregateContext, parsingErrorCollection, atRoot: parentId == null, globalized: globalize); + + model.Dict[baseElementId] = elementInfo; + + if (parentId != null) + { + objectPropertyInfoList.Add(new ParsedObjectPropertyInfo() { ElementId = parentId, PropertyName = propName, Layer = layer, JsonLdProperty = propProp, ReferencedElementId = baseElementId, KeyProperty = keyProp, ExpectedKinds = null, AllowedVersions = null, ChildOf = null, BadTypeCauseFormat = null, BadTypeLocatedCauseFormat = null, BadTypeActionFormat = null }); + + if (valueConstraints != null && elementPropertyConstraints != null) + { + foreach (ValueConstraint valueConstraint in valueConstraints) + { + elementPropertyConstraints.Add(new ElementPropertyConstraint() { ParentId = parentId, PropertyName = propName, ElementId = baseElementId, ValueConstraint = valueConstraint }); + } + } + } + + return true; + } + + /// + /// Parse a string property value as an identifier for type DTUnsignedLongInfo. + /// + /// A list of ParsedObjectPropertyInfo to add any object properties, which will be assigned after all parsing has completed. + /// List of ElementPropertyConstraint to be checked after object property assignment. + /// List of to be added to . + /// An AggregateContext object representing information retrieved from JSON-LD context blocks. + /// A ParsingErrorCollection to which any parsing errors are added. + /// The identifier string to parse. + /// Name of the layer currently being parsed. + /// The identifier of the parent of the element. + /// The name of the property by which the parent refers to this element, used for auto ID generation. + /// The representing the source of the property by which the parent refers to this element. + /// A property used for the key if the parent exposes a collection of these elements as a dictionary. + /// A set of allowed versions for the element. + /// True if the string parses correctly as an identifier. + internal static new bool TryParseIdString(List objectPropertyInfoList, List elementPropertyConstraints, List valueConstraints, AggregateContext aggregateContext, ParsingErrorCollection parsingErrorCollection, string idString, string layer, Dtmi parentId, string propName, JsonLdProperty propProp, string keyProp, HashSet allowedVersions) + { + if (!aggregateContext.TryCreateDtmi(idString, out Dtmi elementId)) + { + return false; + } + + objectPropertyInfoList.Add(new ParsedObjectPropertyInfo() { ElementId = parentId, PropertyName = propName, Layer = layer, JsonLdProperty = propProp, ReferencedIdString = idString, ReferencedElementId = elementId, KeyProperty = keyProp, ExpectedKinds = ConcreteKinds[aggregateContext.DtdlVersion], AllowedVersions = allowedVersions, ChildOf = null, BadTypeCauseFormat = BadTypeCauseFormat[aggregateContext.DtdlVersion], BadTypeLocatedCauseFormat = BadTypeLocatedCauseFormat[aggregateContext.DtdlVersion], BadTypeActionFormat = BadTypeActionFormat[aggregateContext.DtdlVersion] }); + + if (valueConstraints != null && elementPropertyConstraints != null) + { + foreach (ValueConstraint valueConstraint in valueConstraints) + { + elementPropertyConstraints.Add(new ElementPropertyConstraint() { ParentId = parentId, PropertyName = propName, ElementId = elementId, ValueConstraint = valueConstraint }); + } + } + + return true; + } + + /// + /// Parse a list of @type values containing material or supplemental types. + /// + /// The list of strings to parse. + /// The identifier of the element of this type to create. + /// Name of the layer currently being parsed. + /// The currently being parsed. + /// The identifier of the parent of the element. + /// Identifier of the partition or top-level element under which this element is defined. + /// The name of the property by which the parent refers to this element, used for auto ID generation. + /// The representing the source of the property by which the parent refers to this element. + /// The created. + /// An AggregateContext object representing information retrieved from JSON-LD context blocks. + /// A set of supplemental type IDs from the type array. + /// A list of undefind type strings from the type array. + /// A ParsingErrorCollection to which any parsing errors are added. + /// True if no errors detected in type array. + internal static bool TryParseTypeStrings(List typeStrings, Dtmi elementId, string layer, JsonLdElement elt, Dtmi parentId, Dtmi definedIn, string propName, JsonLdProperty propProp, ref DTUnsignedLongInfo elementInfo, AggregateContext aggregateContext, out HashSet immediateSupplementalTypeIds, out List immediateUndefinedTypes, ParsingErrorCollection parsingErrorCollection) + { + immediateSupplementalTypeIds = new HashSet(); + immediateUndefinedTypes = new List(); + + HashSet materialKinds = new HashSet(); + + bool anyFailures = false; + foreach (string typeString in typeStrings) + { + switch (aggregateContext.DtdlVersion) + { + case 4: + if (!TryParseTypeStringV4(typeString, elementId, layer, elt, parentId, definedIn, propName, propProp, materialKinds, immediateSupplementalTypeIds, ref elementInfo, ref immediateUndefinedTypes, aggregateContext, parsingErrorCollection)) + { + anyFailures = true; + } + + break; + } + } + + if (anyFailures) + { + return false; + } + + if (ReferenceEquals(null, elementInfo)) + { + string sourceName1 = null; + int sourceLine1 = 0; + if (propProp != null && propProp.TryGetSourceLocation(out sourceName1, out sourceLine1) && elt.TryGetSourceLocation(out string sourceName2, out int startLine2, out int endLine2)) + { + elt.TryGetSourceLocationForType(out _, out int sourceLine3); + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeLocatedCauseFormat[aggregateContext.DtdlVersion], + BadTypeActionFormat[aggregateContext.DtdlVersion], + primaryId: parentId, + property: propName, + secondaryId: elementId, + layer: layer, + sourceName1: sourceName1, + startLine1: sourceLine1, + sourceName2: sourceName2, + startLine2: startLine2, + endLine2: endLine2, + startLine3: sourceLine3); + } + else + { + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeCauseFormat[aggregateContext.DtdlVersion], + BadTypeActionFormat[aggregateContext.DtdlVersion], + primaryId: parentId, + property: propName, + secondaryId: elementId, + layer: layer); + } + + return false; + } + + if (!materialKinds.Any()) + { + parsingErrorCollection.Notify( + "layerMissingMaterialType", + elementId: elementId, + elementType: elementInfo.EntityKind.ToString(), + element: elt, + layer: layer); + return false; + } + + materialKinds.Add(elementInfo.EntityKind); + if (materialKinds.Count() > 1) + { + parsingErrorCollection.Notify( + "multipleMaterialTypes", + elementId: elementId, + valueConjunction: string.Join(" and ", materialKinds), + element: elt, + layer: layer); + return false; + } + + elementInfo.UndefinedTypeStrings.UnionWith(immediateUndefinedTypes); + + bool requiresMergeability = layer != string.Empty && !elementId.IsReserved; + bool isMergeable = false; + foreach (Dtmi supplementalTypeId in immediateSupplementalTypeIds) + { + if (aggregateContext.SupplementalTypeCollection.TryGetSupplementalTypeInfo(supplementalTypeId, out DTSupplementalTypeInfo supplementalTypeInfo)) + { + if (!supplementalTypeInfo.AllowedCotypeKinds.Contains(elementInfo.EntityKind)) + { + parsingErrorCollection.Notify( + "invalidCotype", + elementId: elementId, + cotype: ContextCollection.GetTermOrUri(supplementalTypeId), + typeRestriction: string.Join(" or ", supplementalTypeInfo.AllowedCotypeKinds), + element: elt, + layer: layer); + } + else if (!supplementalTypeInfo.AllowedCotypeVersions.Contains(elementInfo.DtdlVersion)) + { + parsingErrorCollection.Notify( + "invalidCotypeVersion", + elementId: elementId, + cotype: ContextCollection.GetTermOrUri(supplementalTypeId), + versionRestriction: string.Join(" or ", supplementalTypeInfo.AllowedCotypeVersions), + element: elt, + layer: layer); + } + else + { + elementInfo.AddType(supplementalTypeId, supplementalTypeInfo, parsingErrorCollection); + foreach (Dtmi requiredCocotype in supplementalTypeInfo.RequiredCocotypes) + { + if (!immediateSupplementalTypeIds.Contains(requiredCocotype)) + { + string requiredCocotypeTerm = ContextCollection.GetTermOrUri(requiredCocotype); + parsingErrorCollection.Notify( + "missingCocotype", + elementId: elementId, + elementType: ContextCollection.GetTermOrUri(supplementalTypeId), + cotype: requiredCocotypeTerm, + element: elt); + } + } + } + + isMergeable = isMergeable || supplementalTypeInfo.IsMergeable; + } + } + + if (requiresMergeability && !isMergeable) + { + parsingErrorCollection.Notify( + "disallowedIdFragment", + elementId: elementId, + element: elt, + layer: layer); + } + + return true; + } + + /// + /// Parse a string @type value, whether material or supplemental. + /// + /// The string value to parse. + /// The identifier of the element of this type to create. + /// Name of the layer currently being parsed. + /// The currently being parsed. + /// The identifier of the parent of the element. + /// Identifier of the partition or top-level element under which this element is defined. + /// The name of the property by which the parent refers to this element. + /// The representing the source of the property by which the parent refers to this element. + /// A set of material kinds to update with the material kind of the type, if any. + /// A set of supplemental type IDs to update with the supplemental type, if any. + /// The element created if the type is material. + /// A list of string values of any undefined supplemental types. + /// An AggregateContext object representing information retrieved from JSON-LD context blocks. + /// A ParsingErrorCollection to which any parsing errors are added. + /// True if the parse is sucessful. + internal static bool TryParseTypeStringV4(string typeString, Dtmi elementId, string layer, JsonLdElement elt, Dtmi parentId, Dtmi definedIn, string propName, JsonLdProperty propProp, HashSet materialKinds, HashSet supplementalTypeIds, ref DTUnsignedLongInfo elementInfo, ref List undefinedTypes, AggregateContext aggregateContext, ParsingErrorCollection parsingErrorCollection) + { + if (MaterialTypeNameCollection.IsMaterialType(typeString)) + { + string sourceName1 = null; + int sourceLine1 = 0; + if (propProp != null && propProp.TryGetSourceLocation(out sourceName1, out sourceLine1) && elt.TryGetSourceLocation(out string sourceName2, out int startLine2, out int endLine2)) + { + elt.TryGetSourceLocationForType(out _, out int sourceLine3); + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeLocatedCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer, + sourceName1: sourceName1, + startLine1: sourceLine1, + sourceName2: sourceName2, + startLine2: startLine2, + endLine2: endLine2, + startLine3: sourceLine3); + } + else + { + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer); + } + + return false; + } + + if (!aggregateContext.TryCreateDtmi(typeString, out Dtmi supplementalTypeId)) + { + if (typeString.StartsWith("dtmi:")) + { + parsingErrorCollection.Notify( + "typeInvalidDtmi", + elementId: elementId, + cotype: typeString, + element: elt, + layer: layer); + return false; + } + else if (typeString.Contains(":")) + { + parsingErrorCollection.Notify( + "typeNotDtmiNorTerm", + elementId: elementId, + cotype: typeString, + element: elt, + layer: layer); + return false; + } + else + { + if (aggregateContext.IsComplete) + { + parsingErrorCollection.Notify( + "typeUndefinedTerm", + elementId: elementId, + cotype: typeString, + element: elt, + version: aggregateContext.DtdlVersion.ToString(), + layer: layer); + return false; + } + } + + undefinedTypes.Add(typeString); + return true; + } + + if (!aggregateContext.SupplementalTypeCollection.TryGetSupplementalTypeInfo(supplementalTypeId, out DTSupplementalTypeInfo supplementalTypeInfo)) + { + if (aggregateContext.IsComplete) + { + parsingErrorCollection.Notify( + "typeIrrelevantDtmiOrTerm", + elementId: elementId, + cotype: typeString, + element: elt, + version: aggregateContext.DtdlVersion.ToString(), + layer: layer); + return false; + } + + undefinedTypes.Add(typeString); + return true; + } + + if (supplementalTypeInfo.IsAbstract) + { + parsingErrorCollection.Notify( + "abstractSupplementalType", + elementId: elementId, + cotype: ContextCollection.GetTermOrUri(supplementalTypeId), + element: elt, + layer: layer); + return false; + } + + switch (supplementalTypeInfo.ExtensionKind) + { + case DTExtensionKind.LatentType: + { + string sourceName1 = null; + int sourceLine1 = 0; + if (propProp != null && propProp.TryGetSourceLocation(out sourceName1, out sourceLine1) && elt.TryGetSourceLocation(out string sourceName2, out int startLine2, out int endLine2)) + { + elt.TryGetSourceLocationForType(out _, out int sourceLine3); + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeLocatedCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer, + sourceName1: sourceName1, + startLine1: sourceLine1, + sourceName2: sourceName2, + startLine2: startLine2, + endLine2: endLine2, + startLine3: sourceLine3); + } + else + { + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer); + } + } + + return false; + case DTExtensionKind.NamedLatentType: + { + string sourceName1 = null; + int sourceLine1 = 0; + if (propProp != null && propProp.TryGetSourceLocation(out sourceName1, out sourceLine1) && elt.TryGetSourceLocation(out string sourceName2, out int startLine2, out int endLine2)) + { + elt.TryGetSourceLocationForType(out _, out int sourceLine3); + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeLocatedCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer, + sourceName1: sourceName1, + startLine1: sourceLine1, + sourceName2: sourceName2, + startLine2: startLine2, + endLine2: endLine2, + startLine3: sourceLine3); + } + else + { + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer); + } + } + + return false; + case DTExtensionKind.Unit: + { + string sourceName1 = null; + int sourceLine1 = 0; + if (propProp != null && propProp.TryGetSourceLocation(out sourceName1, out sourceLine1) && elt.TryGetSourceLocation(out string sourceName2, out int startLine2, out int endLine2)) + { + elt.TryGetSourceLocationForType(out _, out int sourceLine3); + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeLocatedCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer, + sourceName1: sourceName1, + startLine1: sourceLine1, + sourceName2: sourceName2, + startLine2: startLine2, + endLine2: endLine2, + startLine3: sourceLine3); + } + else + { + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer); + } + } + + return false; + case DTExtensionKind.UnitAttribute: + { + string sourceName1 = null; + int sourceLine1 = 0; + if (propProp != null && propProp.TryGetSourceLocation(out sourceName1, out sourceLine1) && elt.TryGetSourceLocation(out string sourceName2, out int startLine2, out int endLine2)) + { + elt.TryGetSourceLocationForType(out _, out int sourceLine3); + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeLocatedCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer, + sourceName1: sourceName1, + startLine1: sourceLine1, + sourceName2: sourceName2, + startLine2: startLine2, + endLine2: endLine2, + startLine3: sourceLine3); + } + else + { + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer); + } + } + + return false; + } + + supplementalTypeIds.Add(supplementalTypeId); + + return true; + } + + /// + /// Parse elements encoded in a into objects of subclasses of type DTUnsignedLongInfo. + /// + /// The model to add the element to. + /// A list of ParsedObjectPropertyInfo to add any object properties, which will be assigned after all parsing has completed. + /// List of ElementPropertyConstraint to be checked after object property assignment. + /// List of to be added to . + /// An AggregateContext object representing information retrieved from JSON-LD context blocks. + /// A ParsingErrorCollection to which any parsing errors are added. + /// The holding the to parse. + /// Name of the layer currently being parsed. + /// The identifier of the parent of the element. + /// Identifier of the partition or top-level element under which this element is defined. + /// The name of the property by which the parent refers to this element, used for auto ID generation. + /// A DTMI segment identifier, used for auto ID generation. + /// A property used for the key if the parent exposes a collection of these elements as a dictionary. + /// The minimum count of element values required. + /// A boolean value indicating whether the property allows multiple values. + /// A boolean value indicating whether an @id must be present. + /// A boolean value indicating whether a @type must be present. + /// Treat all nested definitions as though defined globally. + /// Allow elements to define IDs that have reserved prefixes. + /// Tolerate specific minor invalidities to support backward compatibility. + /// A set of allowed versions for the element. + internal static new void ParseValueCollection(Model model, List objectPropertyInfoList, List elementPropertyConstraints, List valueConstraints, AggregateContext aggregateContext, ParsingErrorCollection parsingErrorCollection, JsonLdProperty valueCollectionProp, string layer, Dtmi parentId, Dtmi definedIn, string propName, string dtmiSeg, string keyProp, int minCount, bool isPlural, bool idRequired, bool typeRequired, bool globalize, bool allowReservedIds, bool tolerateSolecisms, HashSet allowedVersions) + { + int valueCount = 0; + + foreach (JsonLdValue value in valueCollectionProp.Values.Values) + { + if (!isPlural && valueCount > 0) + { + parsingErrorCollection.Notify( + "objectMultipleValues", + elementId: parentId, + propertyName: propName, + incidentValues: valueCollectionProp.Values, + layer: layer); + return; + } + + switch (value.ValueType) + { + case JsonLdValueType.String: + if (parentId != null) + { + if (TryParseIdString(objectPropertyInfoList, elementPropertyConstraints, valueConstraints, aggregateContext, parsingErrorCollection, value.StringValue, layer, parentId, propName, valueCollectionProp, keyProp, allowedVersions)) + { + ++valueCount; + } + else + { + parsingErrorCollection.Notify( + "badDtmiOrTerm", + elementId: parentId, + propertyName: propName, + propertyValue: value.StringValue, + incidentProperty: valueCollectionProp, + incidentValue: value, + version: aggregateContext.DtdlVersion.ToString(), + layer: layer); + } + } + + break; + case JsonLdValueType.Element: + if (TryParseElement(model, objectPropertyInfoList, elementPropertyConstraints, valueConstraints, aggregateContext, parsingErrorCollection, value.ElementValue, layer, parentId, definedIn, propName, valueCollectionProp, dtmiSeg, keyProp, idRequired, typeRequired, globalize, allowReservedIds, tolerateSolecisms, allowedVersions, "UnsignedLong")) + { + ++valueCount; + } + + break; + default: + parsingErrorCollection.Notify( + "refNotStringOrObject", + elementId: parentId, + propertyName: propName, + incidentProperty: valueCollectionProp, + incidentValue: value, + layer: layer); + break; + } + } + + if (valueCount < minCount) + { + parsingErrorCollection.Notify( + "objectCountBelowMin", + elementId: parentId, + propertyName: propName, + observedCount: valueCount, + expectedCount: minCount, + incidentProperty: valueCollectionProp, + layer: layer); + } + } + + /// + internal override bool CheckDepthOfElementSchemaOrSchema(int depth, int depthLimit, bool allowSelf, List tooDeepElementIds, out Dictionary tooDeepElts, ParsingErrorCollection parsingErrorCollection) + { + tooDeepElts = null; + return true; + } + + /// + /// Determine whether a JsonElement matches this DTDL element. + /// + /// The JsonElement to match. + /// If the instance is a property in a JSON object, the name corresponding to ; otherwise, null. + /// True if the JsonElement matches; false otherwise. + internal override bool DoesInstanceMatch(JsonElement instanceElt, string instanceName) + { + switch (this.DtdlVersion) + { + case 4: + return this.DoesInstanceMatchV4(instanceElt, instanceName); + } + + return false; + } + + /// + /// Indicate whether the property with a given is a dictionary that holds a given . + /// + /// The name of the property to check. + /// The key for the dictionary property. + /// True if the property is present, is a dictionary, and holds the given key. + internal override bool DoesPropertyDictContainKey(string propertyName, string key) + { + if (base.DoesPropertyDictContainKey(propertyName, key)) + { + return true; + } + + switch (propertyName) + { + default: + return false; + } + } + + /// + internal override bool TryGetChild(string childrenPropertyName, string keyPropertyName, string keyPropertyValue, out DTEntityInfo child) + { + switch (childrenPropertyName) + { + default: + break; + } + + child = null; + return false; + } + + /// + internal override bool TryGetDescendantSchemaArray(out Dtmi elementId, out Dictionary excludedElts) + { + if (this.checkedForDescendantSchemaArray) + { + elementId = this.idOfDescendantSchemaArray; + excludedElts = this.eltsOfDescendantSchemaArray; + return this.idOfDescendantSchemaArray != null; + } + + this.checkedForDescendantSchemaArray = true; + + elementId = null; + excludedElts = null; + return false; + } + + /// + internal override bool TryGetDescendantSchemaOrContentsComponentNarrow(out Dtmi elementId, out Dictionary excludedElts) + { + if (this.checkedForDescendantSchemaOrContentsComponentNarrow) + { + elementId = this.idOfDescendantSchemaOrContentsComponentNarrow; + excludedElts = this.eltsOfDescendantSchemaOrContentsComponentNarrow; + return this.idOfDescendantSchemaOrContentsComponentNarrow != null; + } + + this.checkedForDescendantSchemaOrContentsComponentNarrow = true; + + elementId = null; + excludedElts = null; + return false; + } + + /// + /// Try to set an object property with a given . + /// + /// The name of the property whose element value to set if the property is recognized. + /// The key property for dictionary properties. + /// The representing the source of the property by which the parent refers to this element. + /// The reference element to set. + /// The key property for dictionary properties. + /// The key value for dictionary properties. + /// A ParsingErrorCollection to which any parsing errors are added. + /// True if the property name is recognized. + internal override bool TrySetObjectProperty(string propertyName, string layer, JsonLdProperty propProp, DTEntityInfo element, string keyProp, string keyValue, ParsingErrorCollection parsingErrorCollection) + { + if (base.TrySetObjectProperty(propertyName, layer, propProp, element, keyProp, keyValue, parsingErrorCollection)) + { + return true; + } + + switch (propertyName) + { + default: + break; + } + + foreach (DTSupplementalTypeInfo supplementalType in this.supplementalTypes) + { + if (supplementalType.TrySetObjectProperty(this.Id, propertyName, element, keyValue, layer, propProp, ref this.supplementalProperties, this.supplementalSingularPropertyLayers, this.JsonLdElements, parsingErrorCollection)) + { + return true; + } + } + + return false; + } + + /// + /// Validate a JsonElement to determine whether it is a numeric value that conforms to the XSD definition of 'unsignedLong'. + /// + /// The JsonElement to validate. + /// If the instance is a property in a JSON object, the name corresponding to ; otherwise, null. + /// A list of strings to which to add any validation failures. + internal override bool ValidateInstance(JsonElement instanceElt, string instanceName, List violations) + { + switch (this.DtdlVersion) + { + case 4: + return this.ValidateInstanceV4(instanceElt, instanceName, violations); + } + + return true; + } + + /// + internal override HashSet GetTransitiveExtendsNarrow(int depth, int depthLimit, bool allowSelf, List tooDeepElementIds, out Dictionary tooDeepElts, ParsingErrorCollection parsingErrorCollection) + { + HashSet closure = new HashSet(); + + tooDeepElts = null; + return closure; + } + + /// + internal override IEnumerable GetChildren(string childrenPropertyName) + { + switch (childrenPropertyName) + { + default: + return new List(); + } + } + + /// + internal override int GetCountOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrow(bool allowSelf, ParsingErrorCollection parsingErrorCollection) + { + if (this.countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowStatus == TraversalStatus.Complete) + { + return this.countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowValue; + } + + if (this.countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowStatus == TraversalStatus.InProgress) + { + if (allowSelf) + { + this.countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowStatus = TraversalStatus.Complete; + } + else + { + parsingErrorCollection.Notify( + "recursiveStructureNarrow", + elementId: this.Id, + propertyDisjunction: "'contents' or 'fields' or 'enumValues' or 'request' or 'response' or 'properties' or 'schema' or 'elementSchema' or 'mapValue'", + element: this.JsonLdElements.First().Value); + } + + return 0; + } + + this.countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowStatus = TraversalStatus.InProgress; + this.countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowStatus = TraversalStatus.Complete; + return this.countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowValue; + } + + /// + internal override int GetCountOfExtendsNarrow(bool allowSelf, ParsingErrorCollection parsingErrorCollection) + { + if (this.countOfExtendsNarrowStatus == TraversalStatus.Complete) + { + return this.countOfExtendsNarrowValue; + } + + if (this.countOfExtendsNarrowStatus == TraversalStatus.InProgress) + { + if (allowSelf) + { + this.countOfExtendsNarrowStatus = TraversalStatus.Complete; + } + else + { + parsingErrorCollection.Notify( + "recursiveStructureNarrow", + elementId: this.Id, + propertyDisjunction: "'extends'", + element: this.JsonLdElements.First().Value); + } + + return 0; + } + + this.countOfExtendsNarrowStatus = TraversalStatus.InProgress; + this.countOfExtendsNarrowStatus = TraversalStatus.Complete; + return this.countOfExtendsNarrowValue; + } + + /// + /// Add a supplemental type. + /// + /// Identifier for the supplemental type to add. + /// DTSupplementalTypeInfo for the supplemental type. + /// A ParsingErrorCollection to which any parsing errors are added. + internal override void AddType(Dtmi id, DTSupplementalTypeInfo supplementalType, ParsingErrorCollection parsingErrorCollection) + { + if (this.supplementalTypeIds.Add(id)) + { + this.supplementalTypes.Add(supplementalType); + } + } + + /// + internal override void ApplyTransformations(Model model, ParsingErrorCollection parsingErrorCollection) + { + switch (this.DtdlVersion) + { + case 4: + this.ApplyTransformationsV4(model, parsingErrorCollection); + break; + } + } + + /// + internal override void CheckDescendantEnumValueDatatype(Dtmi ancestorId, Dictionary ancestorElts, Type datatype, ParsingErrorCollection parsingErrorCollection) + { + if (this.checkedDescendantEnumValueDatatype != datatype) + { + this.checkedDescendantEnumValueDatatype = datatype; + } + } + + /// + internal override void CheckRestrictions(ParsingErrorCollection parsingErrorCollection) + { + this.CheckForDisallowedCocotypes(this.supplementalTypeIds, this.supplementalTypes, parsingErrorCollection); + + foreach (DTSupplementalTypeInfo supplementalType in this.supplementalTypes) + { + supplementalType.CheckRestrictions(this.supplementalProperties, parsingErrorCollection, this.Id, this.JsonLdElements); + } + + switch (this.DtdlVersion) + { + case 4: + this.CheckRestrictionsV4(parsingErrorCollection); + break; + } + } + + /// + /// Parse the properties in a JSON UnsignedLong object. + /// + /// Model to which to add object properties. + /// List of object info structs for deferred assignments. + /// List of ElementPropertyConstraint to be checked after object property assignment. + /// An AggregateContext object representing information retrieved from JSON-LD context blocks. + /// A set of supplemental type IDs. + /// A list of undefind type strings. + /// A ParsingErrorCollection to which any parsing errors are added. + /// The to parse. + /// Name of the layer currently being parsed. + /// Identifier of the partition or top-level element under which this element is defined. + /// Treat all nested definitions as though defined globally. + /// Allow elements to define IDs that have reserved prefixes. + /// Tolerate specific minor invalidities to support backward compatibility. + internal override void ParsePropertiesV4(Model model, List objectPropertyInfoList, List elementPropertyConstraints, AggregateContext aggregateContext, HashSet immediateSupplementalTypeIds, List immediateUndefinedTypes, ParsingErrorCollection parsingErrorCollection, JsonLdElement elt, string layer, Dtmi definedIn, bool globalize, bool allowReservedIds, bool tolerateSolecisms) + { + this.LanguageMajorVersion = 4; + + JsonLdProperty commentProperty = null; + JsonLdProperty descriptionProperty = null; + JsonLdProperty displayNameProperty = null; + Dictionary supplementalJsonLdProperties = new Dictionary(); + + foreach (JsonLdProperty prop in elt.Properties) + { + switch (prop.Name) + { + case "comment": + case "dtmi:dtdl:property:comment;4": + if (commentProperty != null) + { + parsingErrorCollection.Notify( + "duplicatePropertyName", + elementId: this.Id, + propertyName: "comment", + incidentProperty: prop, + extantProperty: commentProperty, + layer: layer); + } + else + { + commentProperty = prop; + int? maxLength = aggregateContext.LimitSpecifier switch + { + "" => 512, + "onvif_1" => 515, + _ => null, + }; + + string newComment = ValueParser.ParseSingularStringValueCollection(aggregateContext, this.Id, "comment", prop.Values, maxLength, null, layer, parsingErrorCollection, isOptional: true); + if (this.commentPropertyLayer != null) + { + if (this.Comment != newComment) + { + JsonLdProperty extantProp = this.JsonLdElements[this.commentPropertyLayer].Properties.FirstOrDefault(p => p.Name == "comment"); + parsingErrorCollection.Notify( + "inconsistentStringValues", + elementId: this.Id, + propertyName: "comment", + propertyValue: newComment.ToString(), + valueRestriction: this.Comment.ToString(), + incidentProperty: prop, + extantProperty: extantProp, + layer: layer); + } + } + else + { + this.Comment = newComment; + this.commentPropertyLayer = layer; + + if (this.commentValueConstraints != null) + { + foreach (ValueConstraint valueConstraint in this.commentValueConstraints) + { + if (valueConstraint.RequiredLiteral != null && !valueConstraint.RequiredLiteral.Equals(newComment)) + { + parsingErrorCollection.Notify( + "notRequiredStringValue", + elementId: this.Id, + propertyName: "comment", + propertyValue: newComment.ToString(), + valueRestriction: valueConstraint.RequiredLiteral.ToString(), + incidentProperty: prop, + layer: layer); + } + } + } + + ((Dictionary)this.StringProperties)["comment"] = newComment; + } + } + + continue; + case "description": + case "dtmi:dtdl:property:description;4": + if (descriptionProperty != null) + { + parsingErrorCollection.Notify( + "duplicatePropertyName", + elementId: this.Id, + propertyName: "description", + incidentProperty: prop, + extantProperty: descriptionProperty, + layer: layer); + } + else + { + descriptionProperty = prop; + int? maxLength = aggregateContext.LimitSpecifier switch + { + "" => 512, + "onvif_1" => 514, + _ => null, + }; + + Dictionary newDescription = ValueParser.ParseLangStringValueCollection(aggregateContext, this.Id, "description", prop.Values, "en", maxLength, null, layer, parsingErrorCollection); + List descriptionCodes = Helpers.GetKeysWithDifferingLiteralValues(this.Description, newDescription); + if (descriptionCodes.Any()) + { + JsonLdProperty extantProp = Helpers.TryGetSingleUniqueValue(descriptionCodes.Select(c => this.descriptionPropertyLayer[c]), out string uniqueCodeLayer) && this.JsonLdElements[uniqueCodeLayer].Properties.Any(p => p.Name == "description") ? this.JsonLdElements[uniqueCodeLayer].Properties.First(p => p.Name == "description") : null; + parsingErrorCollection.Notify( + "inconsistentLangStringValues", + elementId: this.Id, + propertyName: "description", + langCode: string.Join(" and ", descriptionCodes.Select(c => $"'{c}'")), + observedCount: descriptionCodes.Count, + incidentProperty: prop, + extantProperty: extantProp, + layer: layer); + } + else if (this.Description.Any()) + { + foreach (KeyValuePair kvp in newDescription) + { + ((Dictionary)this.Description)[kvp.Key] = kvp.Value; + this.descriptionPropertyLayer[kvp.Key] = layer; + } + } + else + { + this.Description = newDescription; + this.descriptionPropertyLayer = newDescription.ToDictionary(e => e.Key, e => layer); + } + } + + continue; + case "displayName": + case "dtmi:dtdl:property:displayName;4": + if (displayNameProperty != null) + { + parsingErrorCollection.Notify( + "duplicatePropertyName", + elementId: this.Id, + propertyName: "displayName", + incidentProperty: prop, + extantProperty: displayNameProperty, + layer: layer); + } + else + { + displayNameProperty = prop; + int? maxLength = aggregateContext.LimitSpecifier switch + { + "" => 512, + "onvif_1" => 513, + _ => null, + }; + + Dictionary newDisplayName = ValueParser.ParseLangStringValueCollection(aggregateContext, this.Id, "displayName", prop.Values, "en", maxLength, null, layer, parsingErrorCollection); + List displayNameCodes = Helpers.GetKeysWithDifferingLiteralValues(this.DisplayName, newDisplayName); + if (displayNameCodes.Any()) + { + JsonLdProperty extantProp = Helpers.TryGetSingleUniqueValue(displayNameCodes.Select(c => this.displayNamePropertyLayer[c]), out string uniqueCodeLayer) && this.JsonLdElements[uniqueCodeLayer].Properties.Any(p => p.Name == "displayName") ? this.JsonLdElements[uniqueCodeLayer].Properties.First(p => p.Name == "displayName") : null; + parsingErrorCollection.Notify( + "inconsistentLangStringValues", + elementId: this.Id, + propertyName: "displayName", + langCode: string.Join(" and ", displayNameCodes.Select(c => $"'{c}'")), + observedCount: displayNameCodes.Count, + incidentProperty: prop, + extantProperty: extantProp, + layer: layer); + } + else if (this.DisplayName.Any()) + { + foreach (KeyValuePair kvp in newDisplayName) + { + ((Dictionary)this.DisplayName)[kvp.Key] = kvp.Value; + this.displayNamePropertyLayer[kvp.Key] = layer; + } + } + else + { + this.DisplayName = newDisplayName; + this.displayNamePropertyLayer = newDisplayName.ToDictionary(e => e.Key, e => layer); + } + } + + continue; + } + + if (this.TryParseSupplementalProperty(model, immediateSupplementalTypeIds, objectPropertyInfoList, elementPropertyConstraints, aggregateContext, layer, definedIn, parsingErrorCollection, prop.Name, globalize, allowReservedIds, tolerateSolecisms, prop, supplementalJsonLdProperties)) + { + continue; + } + + if (aggregateContext.TryCreateDtmi(prop.Name, out Dtmi _)) + { + if (aggregateContext.IsComplete) + { + parsingErrorCollection.Notify( + "propertyIrrelevantDtmiOrTerm", + elementId: this.Id, + propertyName: prop.Name, + incidentProperty: prop, + element: elt, + layer: layer); + continue; + } + } + else if (prop.Name.StartsWith("dtmi:")) + { + parsingErrorCollection.Notify( + "propertyInvalidDtmi", + elementId: this.Id, + propertyName: prop.Name, + incidentProperty: prop, + element: elt, + layer: layer); + continue; + } + else if (prop.Name.Contains(":")) + { + parsingErrorCollection.Notify( + "propertyNotDtmiNorTerm", + elementId: this.Id, + propertyName: prop.Name, + incidentProperty: prop, + element: elt, + layer: layer); + continue; + } + else + { + if (aggregateContext.IsComplete) + { + parsingErrorCollection.Notify( + "propertyUndefinedTerm", + elementId: this.Id, + propertyName: prop.Name, + incidentProperty: prop, + element: elt, + version: aggregateContext.DtdlVersion.ToString(), + layer: layer); + continue; + } + } + + if (!immediateUndefinedTypes.Any()) + { + if (elt.Types != null) + { + parsingErrorCollection.Notify( + "noTypeThatAllows", + elementId: this.Id, + propertyName: prop.Name, + incidentProperty: prop, + element: elt, + layer: layer); + } + else + { + parsingErrorCollection.Notify( + "inferredTypeDoesNotAllow", + elementId: this.Id, + referenceType: "UnsignedLong", + propertyName: prop.Name, + incidentProperty: prop, + element: elt, + layer: layer); + } + + continue; + } + + using (JsonDocument propDoc = JsonDocument.Parse(prop.Values.GetJsonText())) + { + this.UndefinedPropertyDictionary[prop.Name] = propDoc.RootElement.Clone(); + } + } + + foreach (Dtmi supplementalTypeId in immediateSupplementalTypeIds) + { + if (aggregateContext.SupplementalTypeCollection.TryGetSupplementalTypeInfo(supplementalTypeId, out DTSupplementalTypeInfo supplementalTypeInfo)) + { + supplementalTypeInfo.CheckForRequiredProperties(parsingErrorCollection, this.Id, elt, supplementalJsonLdProperties); + } + } + } + + /// + /// Record JSON-LD source as appropriate and check length of text against limit. + /// + /// The name of the layer whose source to record. + /// A JsonLdElement containing the JSON-LD source of the element. + /// An AggregateContext object representing information retrieved from JSON-LD context blocks. + /// A ParsingErrorCollection to which any parsing errors are added. + /// True if the element is at the document root. + /// True if the element has been globalized. + internal override void RecordSourceAsAppropriate(string layer, JsonLdElement elt, AggregateContext aggregateContext, ParsingErrorCollection parsingErrorCollection, bool atRoot, bool globalized) + { + } + + /// + /// Write a JSON representation of the DTDL element represented by an object of this class. + /// + /// A Utf8JsonWriter object with which to write the JSON representation. + /// True if the mothed should add a ClassId property to the JSON object. + internal override void WriteToJson(Utf8JsonWriter jsonWriter, bool includeClassId) + { + base.WriteToJson(jsonWriter, includeClassId: false); + + if (includeClassId) + { + jsonWriter.WriteString("ClassId", $"dtmi:dtdl:class:UnsignedLong;{this.LanguageMajorVersion}"); + } + } + + private bool DoesInstanceMatchV4(JsonElement instanceElt, string instanceName) + { + return true; + } + + private bool TryParseSupplementalProperty(Model model, HashSet immediateSupplementalTypeIds, List objectPropertyInfoList, List elementPropertyConstraints, AggregateContext aggregateContext, string layer, Dtmi definedIn, ParsingErrorCollection parsingErrorCollection, string propName, bool globalize, bool allowReservedIds, bool tolerateSolecisms, JsonLdProperty valueCollectionProp, Dictionary supplementalJsonLdProperties) + { + if (!aggregateContext.TryCreateDtmi(propName, out Dtmi propDtmi)) + { + return false; + } + + foreach (Dtmi supplementalTypeId in immediateSupplementalTypeIds) + { + if (aggregateContext.SupplementalTypeCollection.TryGetSupplementalTypeInfo(supplementalTypeId, out DTSupplementalTypeInfo supplementalTypeInfo) && supplementalTypeInfo.TryParseProperty(model, objectPropertyInfoList, elementPropertyConstraints, aggregateContext, parsingErrorCollection, layer, this.Id, definedIn, propDtmi.ToString(), globalize, allowReservedIds, tolerateSolecisms, valueCollectionProp, ref this.supplementalProperties, supplementalJsonLdProperties, this.supplementalSingularPropertyLayers, this.JsonLdElements)) + { + return true; + } + } + + return false; + } + + private bool ValidateInstanceV4(JsonElement instanceElt, string instanceName, List violations) + { + if (instanceElt.ValueKind != JsonValueKind.Number) + { + violations.Add($">>{instanceElt.GetRawText()}<< is not a numeric value"); + return false; + } + + if (!ulong.TryParse(instanceElt.GetRawText(), out ulong _)) + { + violations.Add($"{instanceElt.GetRawText()} does not conform to the XSD definition of 'unsignedLong'"); + return false; + } + + if (!ElementValueInstanceRegexPatternV4.IsMatch(instanceElt.GetRawText())) + { + violations.Add($"\"{instanceElt.GetRawText()}\" does not conform to the XSD definition of 'unsignedLong'"); + return false; + } + + return true; + } + + private void ApplyTransformationsV4(Model model, ParsingErrorCollection parsingErrorCollection) + { + } + + /// + private void CheckRestrictionsV4(ParsingErrorCollection parsingErrorCollection) + { + } + } +} diff --git a/dotnet/src/DTDLParser/generated/DTUnsignedShortInfo.g.cs b/dotnet/src/DTDLParser/generated/DTUnsignedShortInfo.g.cs new file mode 100644 index 00000000..717f40aa --- /dev/null +++ b/dotnet/src/DTDLParser/generated/DTUnsignedShortInfo.g.cs @@ -0,0 +1,1895 @@ +/* This is an auto-generated file. Do not modify. */ + +namespace DTDLParser.Models +{ + using System; + using System.Collections.Generic; + using System.ComponentModel; + using System.Globalization; + using System.IO; + using System.Linq; + using System.Text; + using System.Text.Json; + using System.Text.RegularExpressions; + using System.Threading; + using System.Threading.Tasks; + using DTDLParser; + + /// + /// Class DTUnsignedShortInfo corresponds to an element of type UnsignedShort in a DTDL model. + /// + public class DTUnsignedShortInfo : DTNumericSchemaInfo, ITypeChecker, IConstrainer, IEquatable + { + private static readonly Dictionary> ConcreteKinds = new Dictionary>(); + + private static readonly Dictionary BadTypeActionFormat = new Dictionary(); + + private static readonly Dictionary BadTypeCauseFormat = new Dictionary(); + + private static readonly Dictionary BadTypeLocatedCauseFormat = new Dictionary(); + + private static readonly HashSet PropertyNames = new HashSet(); + + private static readonly HashSet VersionlessTypes = new HashSet(); + + private static readonly Regex ElementValueInstanceRegexPatternV4 = new Regex(@"^[0-9]+$", RegexOptions.Compiled); + + private bool checkedForDescendantSchemaArray = false; + + private bool checkedForDescendantSchemaOrContentsComponentNarrow = false; + + private Dictionary supplementalPropertySources = new Dictionary(); + + private Dictionary eltsOfDescendantSchemaArray = null; + + private Dictionary eltsOfDescendantSchemaOrContentsComponentNarrow = null; + + private Dictionary supplementalProperties; + + private Dictionary descriptionPropertyLayer = null; + + private Dictionary displayNamePropertyLayer = null; + + private Dictionary supplementalSingularPropertyLayers = new Dictionary(); + + private Dtmi idOfDescendantSchemaArray = null; + + private Dtmi idOfDescendantSchemaOrContentsComponentNarrow = null; + + private HashSet supplementalTypeIds; + + private int countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowValue = 0; + + private int countOfExtendsNarrowValue = 0; + + private List supplementalTypes; + + private List commentValueConstraints = null; + + private List descriptionValueConstraints = null; + + private List displayNameValueConstraints = null; + + private string commentPropertyLayer = null; + + private TraversalStatus countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowStatus = TraversalStatus.NotStarted; + + private TraversalStatus countOfExtendsNarrowStatus = TraversalStatus.NotStarted; + + private Type checkedDescendantEnumValueDatatype = null; + + static DTUnsignedShortInfo() + { + VersionlessTypes.Add("dtmi:dtdl:class:Entity"); + VersionlessTypes.Add("dtmi:dtdl:class:NumericSchema"); + VersionlessTypes.Add("dtmi:dtdl:class:PrimitiveSchema"); + VersionlessTypes.Add("dtmi:dtdl:class:Schema"); + VersionlessTypes.Add("dtmi:dtdl:class:UnsignedShort"); + + PropertyNames.Add("comment"); + PropertyNames.Add("description"); + PropertyNames.Add("displayName"); + PropertyNames.Add("languageMajorVersion"); + + ConcreteKinds[4] = new HashSet(); + ConcreteKinds[4].Add(DTEntityKind.UnsignedShort); + + BadTypeActionFormat[4] = "Use this standard value for property '{property}'{line1}: unsignedShort."; + + BadTypeCauseFormat[4] = "{layer}{primaryId:p} property '{property}' has value{secondaryId:e} that is not a standard value for this property."; + + BadTypeLocatedCauseFormat[4] = "In {sourceName1}, property '{property}'{line1} has value{secondaryId:e}{line2} that is not a standard value for this property."; + } + + /// + /// Initializes a new instance of the class. + /// + /// Version of DTDL used to define the UnsignedShort. + /// Identifier for the UnsignedShort. + /// Identifier of the parent element in which this UnsignedShort is defined. + /// Name of the property by which the parent DTDL element refers to this UnsignedShort. + /// Identifier of the partition in which this UnsignedShort is defined. + internal DTUnsignedShortInfo(int dtdlVersion, Dtmi id, Dtmi childOf, string myPropertyName, Dtmi definedIn) + : base(dtdlVersion, id, childOf, myPropertyName, definedIn, DTEntityKind.UnsignedShort) + { + this.supplementalTypeIds = new HashSet(); + this.supplementalProperties = new Dictionary(); + this.supplementalTypes = new List(); + + this.IsPartition = false; + + this.MaybePartial = false; + } + + /// + /// Initializes a new instance of the class. + /// + /// Version of DTDL used to define the UnsignedShort. + /// Identifier for the UnsignedShort. + /// Identifier of the parent element in which this UnsignedShort is defined. + /// Name of the property by which the parent DTDL element refers to this UnsignedShort. + /// Identifier of the partition in which this UnsignedShort is defined. + /// The kind of Entity, which may be other than UnsignedShort if this constructor is called from a derived class. + internal DTUnsignedShortInfo(int dtdlVersion, Dtmi id, Dtmi childOf, string myPropertyName, Dtmi definedIn, DTEntityKind entityKind) + : base(dtdlVersion, id, childOf, myPropertyName, definedIn, entityKind) + { + this.supplementalTypeIds = new HashSet(); + this.supplementalProperties = new Dictionary(); + this.supplementalTypes = new List(); + + this.IsPartition = false; + + this.MaybePartial = false; + } + + /// + /// Get the DTMI that identifies type UnsignedShort in the version of DTDL used to define this element. + /// + /// The DTMI for the DTDL type UnsignedShort. + public override Dtmi ClassId + { + get + { + return new Dtmi($"dtmi:dtdl:class:UnsignedShort;{this.LanguageMajorVersion}"); + } + } + + /// + /// Gets the supplemantal properties of the DTDL element that corresponds to this object. + /// + /// A dictionary that maps each string-valued property name to an object that holds the value of the property with the given name. + /// + /// If the property is a literal in the DTDL model, the object holds a literal value. + /// If the property is another DTDL element in the model, the object is the C# object that corresponds to this element. + /// + public override IDictionary SupplementalProperties + { + get + { + return this.supplementalProperties; + } + } + + /// + /// Gets a collection of identifiers, each of which is a Dtmi that indicates a supplemental type that applies to the DTDL element that corresponds to this object. + /// + /// A collection of DTMIs indicating the supplemental types that apply to the DTDL element. + public override IReadOnlyCollection SupplementalTypes + { + get + { + return this.supplementalTypeIds; + } + } + + /// + /// Gets a value indicating whether this class is a partition point for the object model. + /// + internal override bool IsPartition { get; } + + /// + /// Gets material properties allowed by the type of DTDL element. + /// + internal override HashSet MaterialProperties + { + get + { + return PropertyNames; + } + } + + /// + /// Determines whether two DTUnsignedShortInfo objects are not equal. + /// + /// One DTUnsignedShortInfo object to compare. + /// Another DTUnsignedShortInfo object to compare to the first. + /// True if not equal. + public static bool operator !=(DTUnsignedShortInfo x, DTUnsignedShortInfo y) + { + if (ReferenceEquals(null, x)) + { + return !ReferenceEquals(null, y); + } + + return !x.Equals(y); + } + + /// + /// Determines whether two DTUnsignedShortInfo objects are equal. + /// + /// One DTUnsignedShortInfo object to compare. + /// Another DTUnsignedShortInfo object to compare to the first. + /// True if equal. + public static bool operator ==(DTUnsignedShortInfo x, DTUnsignedShortInfo y) + { + if (ReferenceEquals(null, x)) + { + return ReferenceEquals(null, y); + } + + return x.Equals(y); + } + + /// + /// Compares to another DTUnsignedShortInfo object, recursing through the entire subtree of object properties. + /// + /// The other DTUnsignedShortInfo object to compare to. + /// True if equal. + public virtual bool DeepEquals(DTUnsignedShortInfo other) + { + return base.DeepEquals(other) + && Helpers.AreDictionariesDeepOrLiteralEqual(this.supplementalProperties, other.supplementalProperties) + && this.supplementalTypeIds.SetEquals(other.supplementalTypeIds) + ; + } + + /// + public override bool DeepEquals(DTNumericSchemaInfo other) + { + return this.EntityKind == other?.EntityKind && this.DeepEquals((DTUnsignedShortInfo)other); + } + + /// + public override bool DeepEquals(DTPrimitiveSchemaInfo other) + { + return this.EntityKind == other?.EntityKind && this.DeepEquals((DTUnsignedShortInfo)other); + } + + /// + public override bool DeepEquals(DTSchemaInfo other) + { + return this.EntityKind == other?.EntityKind && this.DeepEquals((DTUnsignedShortInfo)other); + } + + /// + public override bool DeepEquals(DTEntityInfo other) + { + return this.EntityKind == other?.EntityKind && this.DeepEquals((DTUnsignedShortInfo)other); + } + + /// + /// Compares to another DTUnsignedShortInfo object. + /// + /// The other DTUnsignedShortInfo object to compare to. + /// True if equal. + public virtual bool Equals(DTUnsignedShortInfo other) + { + return base.Equals(other) + && Helpers.AreDictionariesIdOrLiteralEqual(this.supplementalProperties, other.supplementalProperties) + && this.supplementalTypeIds.SetEquals(other.supplementalTypeIds) + ; + } + + /// + public override bool Equals(DTNumericSchemaInfo other) + { + return this.EntityKind == other?.EntityKind && this.Equals((DTUnsignedShortInfo)other); + } + + /// + public override bool Equals(DTPrimitiveSchemaInfo other) + { + return this.EntityKind == other?.EntityKind && this.Equals((DTUnsignedShortInfo)other); + } + + /// + public override bool Equals(DTSchemaInfo other) + { + return this.EntityKind == other?.EntityKind && this.Equals((DTUnsignedShortInfo)other); + } + + /// + public override bool Equals(DTEntityInfo other) + { + return this.EntityKind == other?.EntityKind && this.Equals((DTUnsignedShortInfo)other); + } + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object otherObj) + { + return otherObj is DTUnsignedShortInfo other && this.Equals(other); + } + + /// + bool ITypeChecker.DoesHaveType(Dtmi typeId) + { + return VersionlessTypes.Contains(typeId.Versionless) + || this.supplementalTypes.Any(ps => ((ITypeChecker)ps).DoesHaveType(typeId)) + ; + } + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() + { + int hashCode = base.GetHashCode(); + + unchecked + { + hashCode = (hashCode * 131) + Helpers.GetDictionaryIdOrLiteralHashCode(this.supplementalProperties); + hashCode = (hashCode * 131) + Helpers.GetSetLiteralHashCode(this.supplementalTypeIds); + } + + return hashCode; + } + + /// + /// Validate a JsonElement to determine whether it is a numeric value that conforms to the XSD definition of 'unsignedShort'. + /// + /// The JsonElement to validate. + /// A list of strings that each indicate a validation failure; the list is empty if the JsonElement conforms. + public override IReadOnlyCollection ValidateInstance(JsonElement instanceElt) + { + List violations = new List(); + this.ValidateInstance(instanceElt, null, violations); + return violations; + } + + /// + void IConstrainer.AddPropertyValueConstraint(string propertyName, ValueConstraint valueConstraint) + { + switch (propertyName) + { + case "comment": + if (this.commentValueConstraints == null) + { + this.commentValueConstraints = new List(); + } + + this.commentValueConstraints.Add(valueConstraint); + break; + case "description": + if (this.descriptionValueConstraints == null) + { + this.descriptionValueConstraints = new List(); + } + + this.descriptionValueConstraints.Add(valueConstraint); + break; + case "displayName": + if (this.displayNameValueConstraints == null) + { + this.displayNameValueConstraints = new List(); + } + + this.displayNameValueConstraints.Add(valueConstraint); + break; + } + } + + /// + void IConstrainer.AddSiblingConstraint(SiblingConstraint siblingConstraint) + { + if (this.SiblingConstraints == null) + { + this.SiblingConstraints = new List(); + } + + this.SiblingConstraints.Add(siblingConstraint); + } + + /// + /// Parse an element encoded in a into an object that is a subclass of type DTUnsignedShortInfo. + /// + /// The model to add the element to. + /// A list of ParsedObjectPropertyInfo to add any object properties, which will be assigned after all parsing has completed. + /// List of ElementPropertyConstraint to be checked after object property assignment. + /// List of to be added to . + /// An AggregateContext object representing information retrieved from JSON-LD context blocks. + /// A ParsingErrorCollection to which any parsing errors are added. + /// The to parse. + /// Name of the layer currently being parsed. + /// The identifier of the parent of the element. + /// Identifier of the partition or top-level element under which this element is defined. + /// The name of the property by which the parent refers to this element, used for auto ID generation. + /// The representing the source of the property by which the parent refers to this element. + /// A DTMI segment identifier, used for auto ID generation. + /// A property used for the key if the parent exposes a collection of these elements as a dictionary. + /// A boolean value indicating whether an @id must be present. + /// A boolean value indicating whether a @type must be present. + /// Treat all nested definitions as though defined globally. + /// Allow elements to define IDs that have reserved prefixes. + /// Tolerate specific minor invalidities to support backward compatibility. + /// A set of allowed versions for the element. + /// The type name to infer if no @type specified on element. + /// True if the parses correctly as an appropriate element. + internal static new bool TryParseElement(Model model, List objectPropertyInfoList, List elementPropertyConstraints, List valueConstraints, AggregateContext aggregateContext, ParsingErrorCollection parsingErrorCollection, JsonLdElement elt, string layer, Dtmi parentId, Dtmi definedIn, string propName, JsonLdProperty propProp, string dtmiSeg, string keyProp, bool idRequired, bool typeRequired, bool globalize, bool allowReservedIds, bool tolerateSolecisms, HashSet allowedVersions, string inferredType) + { + AggregateContext childAggregateContext = aggregateContext.GetChildContext(elt, parsingErrorCollection); + + bool allowIdReferenceSyntax = tolerateSolecisms && aggregateContext.DtdlVersion < 3; + + if (elt.PropertyCount == 1 && elt.Id != null) + { + if (allowIdReferenceSyntax) + { + if (TryParseIdString(objectPropertyInfoList, elementPropertyConstraints, valueConstraints, childAggregateContext, parsingErrorCollection, elt.Id, layer, parentId, propName, propProp, keyProp, allowedVersions)) + { + return true; + } + else + { + parsingErrorCollection.Notify( + "idRefBadDtmiOrTerm", + elementId: parentId, + propertyName: propName, + propertyValue: elt.Id, + element: elt, + version: aggregateContext.DtdlVersion.ToString(), + layer: layer); + return false; + } + } + else + { + parsingErrorCollection.Notify( + "idReference", + elementId: parentId, + propertyName: propName, + identifier: elt.Id, + element: elt, + layer: layer); + return false; + } + } + + if (elt.Graph != null) + { + parsingErrorCollection.Notify( + "graphDisallowed", + elementId: parentId, + propertyName: propName, + element: elt); + } + + if (childAggregateContext.RestrictKeywords) + { + if (elt.Language != null) + { + parsingErrorCollection.Notify( + "keywordDisallowed", + elementId: parentId, + propertyName: propName, + keyword: "@language", + element: elt); + } + + if (elt.Value != null) + { + parsingErrorCollection.Notify( + "keywordDisallowed", + elementId: parentId, + propertyName: propName, + keyword: "@value", + element: elt); + } + + foreach (string keyword in elt.Keywords) + { + parsingErrorCollection.Notify( + "keywordDisallowed", + elementId: parentId, + propertyName: propName, + keyword: keyword, + element: elt); + } + } + + if (allowedVersions != null && !allowedVersions.Contains(childAggregateContext.DtdlVersion)) + { + parsingErrorCollection.Notify( + "disallowedVersionDefinition", + elementId: parentId, + propertyName: propName, + version: childAggregateContext.DtdlVersion.ToString(), + versionRestriction: string.Join(" ,", allowedVersions), + contextComponent: childAggregateContext.DtdlContextComponent, + layer: layer); + } + + bool tolerateReservedIds = tolerateSolecisms && aggregateContext.DtdlVersion < 3; + + Dtmi elementId = IdValidator.ParseIdProperty(childAggregateContext, elt, childAggregateContext.MergeDefinitions ? layer : null, parentId, propName, dtmiSeg, idRequired, allowReservedIds || tolerateReservedIds, parsingErrorCollection); + + Dtmi baseElementId = childAggregateContext.MergeDefinitions || elementId.Tail == string.Empty ? elementId.Fragmentless : elementId; + string elementLayer = childAggregateContext.MergeDefinitions ? elementId.Tail : string.Empty; + + bool ignoreElementsWithAutoIDsAndDuplicateNames = tolerateSolecisms && aggregateContext.DtdlVersion < 3; + + if (model.Dict.TryGetValue(baseElementId, out DTEntityInfo baseElement)) + { + if (baseElement.JsonLdElements.TryGetValue(elementLayer, out JsonLdElement duplicateElt)) + { + if (!baseElementId.IsReserved) + { + parsingErrorCollection.Notify( + "duplicateDefinition", + elementId: baseElementId, + element: elt, + extantElement: duplicateElt, + layer: layer); + } + else if (!ignoreElementsWithAutoIDsAndDuplicateNames && dtmiSeg != null) + { + JsonLdProperty dtmiSegProp = elt.Properties.First(p => p.Name == dtmiSeg || (Dtmi.TryCreateDtmi(p.Name, out Dtmi d) && ContextCollection.GetTermOrUri(d) == dtmiSeg)); + JsonLdProperty dupSegProp = duplicateElt.Properties.First(p => p.Name == dtmiSeg || (Dtmi.TryCreateDtmi(p.Name, out Dtmi d) && ContextCollection.GetTermOrUri(d) == dtmiSeg)); + parsingErrorCollection.Notify( + "nonUniquePropertyValue", + elementId: parentId, + propertyName: propName, + nestedName: dtmiSeg, + nestedValue: dtmiSegProp.Values.Values.First().StringValue, + incidentProperty: dupSegProp, + extantProperty: dtmiSegProp); + } + + return false; + } + + if (baseElement.DtdlVersion != childAggregateContext.DtdlVersion) + { + parsingErrorCollection.Notify( + "inconsistentContext", + elementId: baseElementId, + version: childAggregateContext.DtdlVersion.ToString(), + versionRestriction: baseElement.DtdlVersion.ToString(), + layer: elementLayer); + return false; + } + } + + if (typeRequired && elt.Types == null) + { + string sourceName1 = null; + int sourceLine1 = 0; + if (propProp != null && propProp.TryGetSourceLocation(out sourceName1, out sourceLine1) && elt.TryGetSourceLocation(out string sourceName2, out int startLine2, out int endLine2)) + { + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeLocatedCauseFormat[childAggregateContext.DtdlVersion], + BadTypeActionFormat[childAggregateContext.DtdlVersion], + primaryId: parentId, + property: propName, + secondaryId: baseElementId, + layer: layer, + sourceName1: sourceName1, + startLine1: sourceLine1, + sourceName2: sourceName2, + startLine2: startLine2, + endLine2: endLine2); + } + else + { + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeCauseFormat[childAggregateContext.DtdlVersion], + BadTypeActionFormat[childAggregateContext.DtdlVersion], + primaryId: parentId, + property: propName, + secondaryId: baseElementId, + layer: layer); + } + + return false; + } + + DTUnsignedShortInfo elementInfo = (DTUnsignedShortInfo)baseElement; + HashSet immediateSupplementalTypeIds; + List immediateUndefinedTypes; + bool typeArrayParsed; + if (elt.Types == null) + { + typeArrayParsed = TryParseTypeStrings(new List() { inferredType }, baseElementId, elementLayer, elt, parentId, definedIn, propName, propProp, ref elementInfo, childAggregateContext, out immediateSupplementalTypeIds, out immediateUndefinedTypes, parsingErrorCollection); + } + else + { + typeArrayParsed = TryParseTypeStrings(elt.Types, baseElementId, elementLayer, elt, parentId, definedIn, propName, propProp, ref elementInfo, childAggregateContext, out immediateSupplementalTypeIds, out immediateUndefinedTypes, parsingErrorCollection); + } + + if (!typeArrayParsed || ReferenceEquals(null, elementInfo)) + { + return false; + } + + switch (childAggregateContext.DtdlVersion) + { + case 4: + elementInfo.ParsePropertiesV4(model, objectPropertyInfoList, elementPropertyConstraints, childAggregateContext, immediateSupplementalTypeIds, immediateUndefinedTypes, parsingErrorCollection, elt, elementLayer, definedIn, globalize, allowReservedIds, tolerateSolecisms); + break; + } + + elementInfo.LimitSpecifier = aggregateContext.LimitSpecifier; + + elementInfo.RecordSourceAsAppropriate(elementLayer, elt, childAggregateContext, parsingErrorCollection, atRoot: parentId == null, globalized: globalize); + + model.Dict[baseElementId] = elementInfo; + + if (parentId != null) + { + objectPropertyInfoList.Add(new ParsedObjectPropertyInfo() { ElementId = parentId, PropertyName = propName, Layer = layer, JsonLdProperty = propProp, ReferencedElementId = baseElementId, KeyProperty = keyProp, ExpectedKinds = null, AllowedVersions = null, ChildOf = null, BadTypeCauseFormat = null, BadTypeLocatedCauseFormat = null, BadTypeActionFormat = null }); + + if (valueConstraints != null && elementPropertyConstraints != null) + { + foreach (ValueConstraint valueConstraint in valueConstraints) + { + elementPropertyConstraints.Add(new ElementPropertyConstraint() { ParentId = parentId, PropertyName = propName, ElementId = baseElementId, ValueConstraint = valueConstraint }); + } + } + } + + return true; + } + + /// + /// Parse a string property value as an identifier for type DTUnsignedShortInfo. + /// + /// A list of ParsedObjectPropertyInfo to add any object properties, which will be assigned after all parsing has completed. + /// List of ElementPropertyConstraint to be checked after object property assignment. + /// List of to be added to . + /// An AggregateContext object representing information retrieved from JSON-LD context blocks. + /// A ParsingErrorCollection to which any parsing errors are added. + /// The identifier string to parse. + /// Name of the layer currently being parsed. + /// The identifier of the parent of the element. + /// The name of the property by which the parent refers to this element, used for auto ID generation. + /// The representing the source of the property by which the parent refers to this element. + /// A property used for the key if the parent exposes a collection of these elements as a dictionary. + /// A set of allowed versions for the element. + /// True if the string parses correctly as an identifier. + internal static new bool TryParseIdString(List objectPropertyInfoList, List elementPropertyConstraints, List valueConstraints, AggregateContext aggregateContext, ParsingErrorCollection parsingErrorCollection, string idString, string layer, Dtmi parentId, string propName, JsonLdProperty propProp, string keyProp, HashSet allowedVersions) + { + if (!aggregateContext.TryCreateDtmi(idString, out Dtmi elementId)) + { + return false; + } + + objectPropertyInfoList.Add(new ParsedObjectPropertyInfo() { ElementId = parentId, PropertyName = propName, Layer = layer, JsonLdProperty = propProp, ReferencedIdString = idString, ReferencedElementId = elementId, KeyProperty = keyProp, ExpectedKinds = ConcreteKinds[aggregateContext.DtdlVersion], AllowedVersions = allowedVersions, ChildOf = null, BadTypeCauseFormat = BadTypeCauseFormat[aggregateContext.DtdlVersion], BadTypeLocatedCauseFormat = BadTypeLocatedCauseFormat[aggregateContext.DtdlVersion], BadTypeActionFormat = BadTypeActionFormat[aggregateContext.DtdlVersion] }); + + if (valueConstraints != null && elementPropertyConstraints != null) + { + foreach (ValueConstraint valueConstraint in valueConstraints) + { + elementPropertyConstraints.Add(new ElementPropertyConstraint() { ParentId = parentId, PropertyName = propName, ElementId = elementId, ValueConstraint = valueConstraint }); + } + } + + return true; + } + + /// + /// Parse a list of @type values containing material or supplemental types. + /// + /// The list of strings to parse. + /// The identifier of the element of this type to create. + /// Name of the layer currently being parsed. + /// The currently being parsed. + /// The identifier of the parent of the element. + /// Identifier of the partition or top-level element under which this element is defined. + /// The name of the property by which the parent refers to this element, used for auto ID generation. + /// The representing the source of the property by which the parent refers to this element. + /// The created. + /// An AggregateContext object representing information retrieved from JSON-LD context blocks. + /// A set of supplemental type IDs from the type array. + /// A list of undefind type strings from the type array. + /// A ParsingErrorCollection to which any parsing errors are added. + /// True if no errors detected in type array. + internal static bool TryParseTypeStrings(List typeStrings, Dtmi elementId, string layer, JsonLdElement elt, Dtmi parentId, Dtmi definedIn, string propName, JsonLdProperty propProp, ref DTUnsignedShortInfo elementInfo, AggregateContext aggregateContext, out HashSet immediateSupplementalTypeIds, out List immediateUndefinedTypes, ParsingErrorCollection parsingErrorCollection) + { + immediateSupplementalTypeIds = new HashSet(); + immediateUndefinedTypes = new List(); + + HashSet materialKinds = new HashSet(); + + bool anyFailures = false; + foreach (string typeString in typeStrings) + { + switch (aggregateContext.DtdlVersion) + { + case 4: + if (!TryParseTypeStringV4(typeString, elementId, layer, elt, parentId, definedIn, propName, propProp, materialKinds, immediateSupplementalTypeIds, ref elementInfo, ref immediateUndefinedTypes, aggregateContext, parsingErrorCollection)) + { + anyFailures = true; + } + + break; + } + } + + if (anyFailures) + { + return false; + } + + if (ReferenceEquals(null, elementInfo)) + { + string sourceName1 = null; + int sourceLine1 = 0; + if (propProp != null && propProp.TryGetSourceLocation(out sourceName1, out sourceLine1) && elt.TryGetSourceLocation(out string sourceName2, out int startLine2, out int endLine2)) + { + elt.TryGetSourceLocationForType(out _, out int sourceLine3); + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeLocatedCauseFormat[aggregateContext.DtdlVersion], + BadTypeActionFormat[aggregateContext.DtdlVersion], + primaryId: parentId, + property: propName, + secondaryId: elementId, + layer: layer, + sourceName1: sourceName1, + startLine1: sourceLine1, + sourceName2: sourceName2, + startLine2: startLine2, + endLine2: endLine2, + startLine3: sourceLine3); + } + else + { + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeCauseFormat[aggregateContext.DtdlVersion], + BadTypeActionFormat[aggregateContext.DtdlVersion], + primaryId: parentId, + property: propName, + secondaryId: elementId, + layer: layer); + } + + return false; + } + + if (!materialKinds.Any()) + { + parsingErrorCollection.Notify( + "layerMissingMaterialType", + elementId: elementId, + elementType: elementInfo.EntityKind.ToString(), + element: elt, + layer: layer); + return false; + } + + materialKinds.Add(elementInfo.EntityKind); + if (materialKinds.Count() > 1) + { + parsingErrorCollection.Notify( + "multipleMaterialTypes", + elementId: elementId, + valueConjunction: string.Join(" and ", materialKinds), + element: elt, + layer: layer); + return false; + } + + elementInfo.UndefinedTypeStrings.UnionWith(immediateUndefinedTypes); + + bool requiresMergeability = layer != string.Empty && !elementId.IsReserved; + bool isMergeable = false; + foreach (Dtmi supplementalTypeId in immediateSupplementalTypeIds) + { + if (aggregateContext.SupplementalTypeCollection.TryGetSupplementalTypeInfo(supplementalTypeId, out DTSupplementalTypeInfo supplementalTypeInfo)) + { + if (!supplementalTypeInfo.AllowedCotypeKinds.Contains(elementInfo.EntityKind)) + { + parsingErrorCollection.Notify( + "invalidCotype", + elementId: elementId, + cotype: ContextCollection.GetTermOrUri(supplementalTypeId), + typeRestriction: string.Join(" or ", supplementalTypeInfo.AllowedCotypeKinds), + element: elt, + layer: layer); + } + else if (!supplementalTypeInfo.AllowedCotypeVersions.Contains(elementInfo.DtdlVersion)) + { + parsingErrorCollection.Notify( + "invalidCotypeVersion", + elementId: elementId, + cotype: ContextCollection.GetTermOrUri(supplementalTypeId), + versionRestriction: string.Join(" or ", supplementalTypeInfo.AllowedCotypeVersions), + element: elt, + layer: layer); + } + else + { + elementInfo.AddType(supplementalTypeId, supplementalTypeInfo, parsingErrorCollection); + foreach (Dtmi requiredCocotype in supplementalTypeInfo.RequiredCocotypes) + { + if (!immediateSupplementalTypeIds.Contains(requiredCocotype)) + { + string requiredCocotypeTerm = ContextCollection.GetTermOrUri(requiredCocotype); + parsingErrorCollection.Notify( + "missingCocotype", + elementId: elementId, + elementType: ContextCollection.GetTermOrUri(supplementalTypeId), + cotype: requiredCocotypeTerm, + element: elt); + } + } + } + + isMergeable = isMergeable || supplementalTypeInfo.IsMergeable; + } + } + + if (requiresMergeability && !isMergeable) + { + parsingErrorCollection.Notify( + "disallowedIdFragment", + elementId: elementId, + element: elt, + layer: layer); + } + + return true; + } + + /// + /// Parse a string @type value, whether material or supplemental. + /// + /// The string value to parse. + /// The identifier of the element of this type to create. + /// Name of the layer currently being parsed. + /// The currently being parsed. + /// The identifier of the parent of the element. + /// Identifier of the partition or top-level element under which this element is defined. + /// The name of the property by which the parent refers to this element. + /// The representing the source of the property by which the parent refers to this element. + /// A set of material kinds to update with the material kind of the type, if any. + /// A set of supplemental type IDs to update with the supplemental type, if any. + /// The element created if the type is material. + /// A list of string values of any undefined supplemental types. + /// An AggregateContext object representing information retrieved from JSON-LD context blocks. + /// A ParsingErrorCollection to which any parsing errors are added. + /// True if the parse is sucessful. + internal static bool TryParseTypeStringV4(string typeString, Dtmi elementId, string layer, JsonLdElement elt, Dtmi parentId, Dtmi definedIn, string propName, JsonLdProperty propProp, HashSet materialKinds, HashSet supplementalTypeIds, ref DTUnsignedShortInfo elementInfo, ref List undefinedTypes, AggregateContext aggregateContext, ParsingErrorCollection parsingErrorCollection) + { + if (MaterialTypeNameCollection.IsMaterialType(typeString)) + { + string sourceName1 = null; + int sourceLine1 = 0; + if (propProp != null && propProp.TryGetSourceLocation(out sourceName1, out sourceLine1) && elt.TryGetSourceLocation(out string sourceName2, out int startLine2, out int endLine2)) + { + elt.TryGetSourceLocationForType(out _, out int sourceLine3); + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeLocatedCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer, + sourceName1: sourceName1, + startLine1: sourceLine1, + sourceName2: sourceName2, + startLine2: startLine2, + endLine2: endLine2, + startLine3: sourceLine3); + } + else + { + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer); + } + + return false; + } + + if (!aggregateContext.TryCreateDtmi(typeString, out Dtmi supplementalTypeId)) + { + if (typeString.StartsWith("dtmi:")) + { + parsingErrorCollection.Notify( + "typeInvalidDtmi", + elementId: elementId, + cotype: typeString, + element: elt, + layer: layer); + return false; + } + else if (typeString.Contains(":")) + { + parsingErrorCollection.Notify( + "typeNotDtmiNorTerm", + elementId: elementId, + cotype: typeString, + element: elt, + layer: layer); + return false; + } + else + { + if (aggregateContext.IsComplete) + { + parsingErrorCollection.Notify( + "typeUndefinedTerm", + elementId: elementId, + cotype: typeString, + element: elt, + version: aggregateContext.DtdlVersion.ToString(), + layer: layer); + return false; + } + } + + undefinedTypes.Add(typeString); + return true; + } + + if (!aggregateContext.SupplementalTypeCollection.TryGetSupplementalTypeInfo(supplementalTypeId, out DTSupplementalTypeInfo supplementalTypeInfo)) + { + if (aggregateContext.IsComplete) + { + parsingErrorCollection.Notify( + "typeIrrelevantDtmiOrTerm", + elementId: elementId, + cotype: typeString, + element: elt, + version: aggregateContext.DtdlVersion.ToString(), + layer: layer); + return false; + } + + undefinedTypes.Add(typeString); + return true; + } + + if (supplementalTypeInfo.IsAbstract) + { + parsingErrorCollection.Notify( + "abstractSupplementalType", + elementId: elementId, + cotype: ContextCollection.GetTermOrUri(supplementalTypeId), + element: elt, + layer: layer); + return false; + } + + switch (supplementalTypeInfo.ExtensionKind) + { + case DTExtensionKind.LatentType: + { + string sourceName1 = null; + int sourceLine1 = 0; + if (propProp != null && propProp.TryGetSourceLocation(out sourceName1, out sourceLine1) && elt.TryGetSourceLocation(out string sourceName2, out int startLine2, out int endLine2)) + { + elt.TryGetSourceLocationForType(out _, out int sourceLine3); + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeLocatedCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer, + sourceName1: sourceName1, + startLine1: sourceLine1, + sourceName2: sourceName2, + startLine2: startLine2, + endLine2: endLine2, + startLine3: sourceLine3); + } + else + { + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer); + } + } + + return false; + case DTExtensionKind.NamedLatentType: + { + string sourceName1 = null; + int sourceLine1 = 0; + if (propProp != null && propProp.TryGetSourceLocation(out sourceName1, out sourceLine1) && elt.TryGetSourceLocation(out string sourceName2, out int startLine2, out int endLine2)) + { + elt.TryGetSourceLocationForType(out _, out int sourceLine3); + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeLocatedCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer, + sourceName1: sourceName1, + startLine1: sourceLine1, + sourceName2: sourceName2, + startLine2: startLine2, + endLine2: endLine2, + startLine3: sourceLine3); + } + else + { + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer); + } + } + + return false; + case DTExtensionKind.Unit: + { + string sourceName1 = null; + int sourceLine1 = 0; + if (propProp != null && propProp.TryGetSourceLocation(out sourceName1, out sourceLine1) && elt.TryGetSourceLocation(out string sourceName2, out int startLine2, out int endLine2)) + { + elt.TryGetSourceLocationForType(out _, out int sourceLine3); + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeLocatedCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer, + sourceName1: sourceName1, + startLine1: sourceLine1, + sourceName2: sourceName2, + startLine2: startLine2, + endLine2: endLine2, + startLine3: sourceLine3); + } + else + { + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer); + } + } + + return false; + case DTExtensionKind.UnitAttribute: + { + string sourceName1 = null; + int sourceLine1 = 0; + if (propProp != null && propProp.TryGetSourceLocation(out sourceName1, out sourceLine1) && elt.TryGetSourceLocation(out string sourceName2, out int startLine2, out int endLine2)) + { + elt.TryGetSourceLocationForType(out _, out int sourceLine3); + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeLocatedCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer, + sourceName1: sourceName1, + startLine1: sourceLine1, + sourceName2: sourceName2, + startLine2: startLine2, + endLine2: endLine2, + startLine3: sourceLine3); + } + else + { + parsingErrorCollection.Add( + new Uri("dtmi:dtdl:parsingError:badType"), + BadTypeCauseFormat[4], + BadTypeActionFormat[4], + primaryId: parentId, + property: propName, + secondaryId: elementId, + value: typeString, + layer: layer); + } + } + + return false; + } + + supplementalTypeIds.Add(supplementalTypeId); + + return true; + } + + /// + /// Parse elements encoded in a into objects of subclasses of type DTUnsignedShortInfo. + /// + /// The model to add the element to. + /// A list of ParsedObjectPropertyInfo to add any object properties, which will be assigned after all parsing has completed. + /// List of ElementPropertyConstraint to be checked after object property assignment. + /// List of to be added to . + /// An AggregateContext object representing information retrieved from JSON-LD context blocks. + /// A ParsingErrorCollection to which any parsing errors are added. + /// The holding the to parse. + /// Name of the layer currently being parsed. + /// The identifier of the parent of the element. + /// Identifier of the partition or top-level element under which this element is defined. + /// The name of the property by which the parent refers to this element, used for auto ID generation. + /// A DTMI segment identifier, used for auto ID generation. + /// A property used for the key if the parent exposes a collection of these elements as a dictionary. + /// The minimum count of element values required. + /// A boolean value indicating whether the property allows multiple values. + /// A boolean value indicating whether an @id must be present. + /// A boolean value indicating whether a @type must be present. + /// Treat all nested definitions as though defined globally. + /// Allow elements to define IDs that have reserved prefixes. + /// Tolerate specific minor invalidities to support backward compatibility. + /// A set of allowed versions for the element. + internal static new void ParseValueCollection(Model model, List objectPropertyInfoList, List elementPropertyConstraints, List valueConstraints, AggregateContext aggregateContext, ParsingErrorCollection parsingErrorCollection, JsonLdProperty valueCollectionProp, string layer, Dtmi parentId, Dtmi definedIn, string propName, string dtmiSeg, string keyProp, int minCount, bool isPlural, bool idRequired, bool typeRequired, bool globalize, bool allowReservedIds, bool tolerateSolecisms, HashSet allowedVersions) + { + int valueCount = 0; + + foreach (JsonLdValue value in valueCollectionProp.Values.Values) + { + if (!isPlural && valueCount > 0) + { + parsingErrorCollection.Notify( + "objectMultipleValues", + elementId: parentId, + propertyName: propName, + incidentValues: valueCollectionProp.Values, + layer: layer); + return; + } + + switch (value.ValueType) + { + case JsonLdValueType.String: + if (parentId != null) + { + if (TryParseIdString(objectPropertyInfoList, elementPropertyConstraints, valueConstraints, aggregateContext, parsingErrorCollection, value.StringValue, layer, parentId, propName, valueCollectionProp, keyProp, allowedVersions)) + { + ++valueCount; + } + else + { + parsingErrorCollection.Notify( + "badDtmiOrTerm", + elementId: parentId, + propertyName: propName, + propertyValue: value.StringValue, + incidentProperty: valueCollectionProp, + incidentValue: value, + version: aggregateContext.DtdlVersion.ToString(), + layer: layer); + } + } + + break; + case JsonLdValueType.Element: + if (TryParseElement(model, objectPropertyInfoList, elementPropertyConstraints, valueConstraints, aggregateContext, parsingErrorCollection, value.ElementValue, layer, parentId, definedIn, propName, valueCollectionProp, dtmiSeg, keyProp, idRequired, typeRequired, globalize, allowReservedIds, tolerateSolecisms, allowedVersions, "UnsignedShort")) + { + ++valueCount; + } + + break; + default: + parsingErrorCollection.Notify( + "refNotStringOrObject", + elementId: parentId, + propertyName: propName, + incidentProperty: valueCollectionProp, + incidentValue: value, + layer: layer); + break; + } + } + + if (valueCount < minCount) + { + parsingErrorCollection.Notify( + "objectCountBelowMin", + elementId: parentId, + propertyName: propName, + observedCount: valueCount, + expectedCount: minCount, + incidentProperty: valueCollectionProp, + layer: layer); + } + } + + /// + internal override bool CheckDepthOfElementSchemaOrSchema(int depth, int depthLimit, bool allowSelf, List tooDeepElementIds, out Dictionary tooDeepElts, ParsingErrorCollection parsingErrorCollection) + { + tooDeepElts = null; + return true; + } + + /// + /// Determine whether a JsonElement matches this DTDL element. + /// + /// The JsonElement to match. + /// If the instance is a property in a JSON object, the name corresponding to ; otherwise, null. + /// True if the JsonElement matches; false otherwise. + internal override bool DoesInstanceMatch(JsonElement instanceElt, string instanceName) + { + switch (this.DtdlVersion) + { + case 4: + return this.DoesInstanceMatchV4(instanceElt, instanceName); + } + + return false; + } + + /// + /// Indicate whether the property with a given is a dictionary that holds a given . + /// + /// The name of the property to check. + /// The key for the dictionary property. + /// True if the property is present, is a dictionary, and holds the given key. + internal override bool DoesPropertyDictContainKey(string propertyName, string key) + { + if (base.DoesPropertyDictContainKey(propertyName, key)) + { + return true; + } + + switch (propertyName) + { + default: + return false; + } + } + + /// + internal override bool TryGetChild(string childrenPropertyName, string keyPropertyName, string keyPropertyValue, out DTEntityInfo child) + { + switch (childrenPropertyName) + { + default: + break; + } + + child = null; + return false; + } + + /// + internal override bool TryGetDescendantSchemaArray(out Dtmi elementId, out Dictionary excludedElts) + { + if (this.checkedForDescendantSchemaArray) + { + elementId = this.idOfDescendantSchemaArray; + excludedElts = this.eltsOfDescendantSchemaArray; + return this.idOfDescendantSchemaArray != null; + } + + this.checkedForDescendantSchemaArray = true; + + elementId = null; + excludedElts = null; + return false; + } + + /// + internal override bool TryGetDescendantSchemaOrContentsComponentNarrow(out Dtmi elementId, out Dictionary excludedElts) + { + if (this.checkedForDescendantSchemaOrContentsComponentNarrow) + { + elementId = this.idOfDescendantSchemaOrContentsComponentNarrow; + excludedElts = this.eltsOfDescendantSchemaOrContentsComponentNarrow; + return this.idOfDescendantSchemaOrContentsComponentNarrow != null; + } + + this.checkedForDescendantSchemaOrContentsComponentNarrow = true; + + elementId = null; + excludedElts = null; + return false; + } + + /// + /// Try to set an object property with a given . + /// + /// The name of the property whose element value to set if the property is recognized. + /// The key property for dictionary properties. + /// The representing the source of the property by which the parent refers to this element. + /// The reference element to set. + /// The key property for dictionary properties. + /// The key value for dictionary properties. + /// A ParsingErrorCollection to which any parsing errors are added. + /// True if the property name is recognized. + internal override bool TrySetObjectProperty(string propertyName, string layer, JsonLdProperty propProp, DTEntityInfo element, string keyProp, string keyValue, ParsingErrorCollection parsingErrorCollection) + { + if (base.TrySetObjectProperty(propertyName, layer, propProp, element, keyProp, keyValue, parsingErrorCollection)) + { + return true; + } + + switch (propertyName) + { + default: + break; + } + + foreach (DTSupplementalTypeInfo supplementalType in this.supplementalTypes) + { + if (supplementalType.TrySetObjectProperty(this.Id, propertyName, element, keyValue, layer, propProp, ref this.supplementalProperties, this.supplementalSingularPropertyLayers, this.JsonLdElements, parsingErrorCollection)) + { + return true; + } + } + + return false; + } + + /// + /// Validate a JsonElement to determine whether it is a numeric value that conforms to the XSD definition of 'unsignedShort'. + /// + /// The JsonElement to validate. + /// If the instance is a property in a JSON object, the name corresponding to ; otherwise, null. + /// A list of strings to which to add any validation failures. + internal override bool ValidateInstance(JsonElement instanceElt, string instanceName, List violations) + { + switch (this.DtdlVersion) + { + case 4: + return this.ValidateInstanceV4(instanceElt, instanceName, violations); + } + + return true; + } + + /// + internal override HashSet GetTransitiveExtendsNarrow(int depth, int depthLimit, bool allowSelf, List tooDeepElementIds, out Dictionary tooDeepElts, ParsingErrorCollection parsingErrorCollection) + { + HashSet closure = new HashSet(); + + tooDeepElts = null; + return closure; + } + + /// + internal override IEnumerable GetChildren(string childrenPropertyName) + { + switch (childrenPropertyName) + { + default: + return new List(); + } + } + + /// + internal override int GetCountOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrow(bool allowSelf, ParsingErrorCollection parsingErrorCollection) + { + if (this.countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowStatus == TraversalStatus.Complete) + { + return this.countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowValue; + } + + if (this.countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowStatus == TraversalStatus.InProgress) + { + if (allowSelf) + { + this.countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowStatus = TraversalStatus.Complete; + } + else + { + parsingErrorCollection.Notify( + "recursiveStructureNarrow", + elementId: this.Id, + propertyDisjunction: "'contents' or 'fields' or 'enumValues' or 'request' or 'response' or 'properties' or 'schema' or 'elementSchema' or 'mapValue'", + element: this.JsonLdElements.First().Value); + } + + return 0; + } + + this.countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowStatus = TraversalStatus.InProgress; + this.countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowStatus = TraversalStatus.Complete; + return this.countOfContentsOrFieldsOrEnumValuesOrRequestOrResponseOrPropertiesOrSchemaOrElementSchemaOrMapValueNarrowValue; + } + + /// + internal override int GetCountOfExtendsNarrow(bool allowSelf, ParsingErrorCollection parsingErrorCollection) + { + if (this.countOfExtendsNarrowStatus == TraversalStatus.Complete) + { + return this.countOfExtendsNarrowValue; + } + + if (this.countOfExtendsNarrowStatus == TraversalStatus.InProgress) + { + if (allowSelf) + { + this.countOfExtendsNarrowStatus = TraversalStatus.Complete; + } + else + { + parsingErrorCollection.Notify( + "recursiveStructureNarrow", + elementId: this.Id, + propertyDisjunction: "'extends'", + element: this.JsonLdElements.First().Value); + } + + return 0; + } + + this.countOfExtendsNarrowStatus = TraversalStatus.InProgress; + this.countOfExtendsNarrowStatus = TraversalStatus.Complete; + return this.countOfExtendsNarrowValue; + } + + /// + /// Add a supplemental type. + /// + /// Identifier for the supplemental type to add. + /// DTSupplementalTypeInfo for the supplemental type. + /// A ParsingErrorCollection to which any parsing errors are added. + internal override void AddType(Dtmi id, DTSupplementalTypeInfo supplementalType, ParsingErrorCollection parsingErrorCollection) + { + if (this.supplementalTypeIds.Add(id)) + { + this.supplementalTypes.Add(supplementalType); + } + } + + /// + internal override void ApplyTransformations(Model model, ParsingErrorCollection parsingErrorCollection) + { + switch (this.DtdlVersion) + { + case 4: + this.ApplyTransformationsV4(model, parsingErrorCollection); + break; + } + } + + /// + internal override void CheckDescendantEnumValueDatatype(Dtmi ancestorId, Dictionary ancestorElts, Type datatype, ParsingErrorCollection parsingErrorCollection) + { + if (this.checkedDescendantEnumValueDatatype != datatype) + { + this.checkedDescendantEnumValueDatatype = datatype; + } + } + + /// + internal override void CheckRestrictions(ParsingErrorCollection parsingErrorCollection) + { + this.CheckForDisallowedCocotypes(this.supplementalTypeIds, this.supplementalTypes, parsingErrorCollection); + + foreach (DTSupplementalTypeInfo supplementalType in this.supplementalTypes) + { + supplementalType.CheckRestrictions(this.supplementalProperties, parsingErrorCollection, this.Id, this.JsonLdElements); + } + + switch (this.DtdlVersion) + { + case 4: + this.CheckRestrictionsV4(parsingErrorCollection); + break; + } + } + + /// + /// Parse the properties in a JSON UnsignedShort object. + /// + /// Model to which to add object properties. + /// List of object info structs for deferred assignments. + /// List of ElementPropertyConstraint to be checked after object property assignment. + /// An AggregateContext object representing information retrieved from JSON-LD context blocks. + /// A set of supplemental type IDs. + /// A list of undefind type strings. + /// A ParsingErrorCollection to which any parsing errors are added. + /// The to parse. + /// Name of the layer currently being parsed. + /// Identifier of the partition or top-level element under which this element is defined. + /// Treat all nested definitions as though defined globally. + /// Allow elements to define IDs that have reserved prefixes. + /// Tolerate specific minor invalidities to support backward compatibility. + internal override void ParsePropertiesV4(Model model, List objectPropertyInfoList, List elementPropertyConstraints, AggregateContext aggregateContext, HashSet immediateSupplementalTypeIds, List immediateUndefinedTypes, ParsingErrorCollection parsingErrorCollection, JsonLdElement elt, string layer, Dtmi definedIn, bool globalize, bool allowReservedIds, bool tolerateSolecisms) + { + this.LanguageMajorVersion = 4; + + JsonLdProperty commentProperty = null; + JsonLdProperty descriptionProperty = null; + JsonLdProperty displayNameProperty = null; + Dictionary supplementalJsonLdProperties = new Dictionary(); + + foreach (JsonLdProperty prop in elt.Properties) + { + switch (prop.Name) + { + case "comment": + case "dtmi:dtdl:property:comment;4": + if (commentProperty != null) + { + parsingErrorCollection.Notify( + "duplicatePropertyName", + elementId: this.Id, + propertyName: "comment", + incidentProperty: prop, + extantProperty: commentProperty, + layer: layer); + } + else + { + commentProperty = prop; + int? maxLength = aggregateContext.LimitSpecifier switch + { + "" => 512, + "onvif_1" => 515, + _ => null, + }; + + string newComment = ValueParser.ParseSingularStringValueCollection(aggregateContext, this.Id, "comment", prop.Values, maxLength, null, layer, parsingErrorCollection, isOptional: true); + if (this.commentPropertyLayer != null) + { + if (this.Comment != newComment) + { + JsonLdProperty extantProp = this.JsonLdElements[this.commentPropertyLayer].Properties.FirstOrDefault(p => p.Name == "comment"); + parsingErrorCollection.Notify( + "inconsistentStringValues", + elementId: this.Id, + propertyName: "comment", + propertyValue: newComment.ToString(), + valueRestriction: this.Comment.ToString(), + incidentProperty: prop, + extantProperty: extantProp, + layer: layer); + } + } + else + { + this.Comment = newComment; + this.commentPropertyLayer = layer; + + if (this.commentValueConstraints != null) + { + foreach (ValueConstraint valueConstraint in this.commentValueConstraints) + { + if (valueConstraint.RequiredLiteral != null && !valueConstraint.RequiredLiteral.Equals(newComment)) + { + parsingErrorCollection.Notify( + "notRequiredStringValue", + elementId: this.Id, + propertyName: "comment", + propertyValue: newComment.ToString(), + valueRestriction: valueConstraint.RequiredLiteral.ToString(), + incidentProperty: prop, + layer: layer); + } + } + } + + ((Dictionary)this.StringProperties)["comment"] = newComment; + } + } + + continue; + case "description": + case "dtmi:dtdl:property:description;4": + if (descriptionProperty != null) + { + parsingErrorCollection.Notify( + "duplicatePropertyName", + elementId: this.Id, + propertyName: "description", + incidentProperty: prop, + extantProperty: descriptionProperty, + layer: layer); + } + else + { + descriptionProperty = prop; + int? maxLength = aggregateContext.LimitSpecifier switch + { + "" => 512, + "onvif_1" => 514, + _ => null, + }; + + Dictionary newDescription = ValueParser.ParseLangStringValueCollection(aggregateContext, this.Id, "description", prop.Values, "en", maxLength, null, layer, parsingErrorCollection); + List descriptionCodes = Helpers.GetKeysWithDifferingLiteralValues(this.Description, newDescription); + if (descriptionCodes.Any()) + { + JsonLdProperty extantProp = Helpers.TryGetSingleUniqueValue(descriptionCodes.Select(c => this.descriptionPropertyLayer[c]), out string uniqueCodeLayer) && this.JsonLdElements[uniqueCodeLayer].Properties.Any(p => p.Name == "description") ? this.JsonLdElements[uniqueCodeLayer].Properties.First(p => p.Name == "description") : null; + parsingErrorCollection.Notify( + "inconsistentLangStringValues", + elementId: this.Id, + propertyName: "description", + langCode: string.Join(" and ", descriptionCodes.Select(c => $"'{c}'")), + observedCount: descriptionCodes.Count, + incidentProperty: prop, + extantProperty: extantProp, + layer: layer); + } + else if (this.Description.Any()) + { + foreach (KeyValuePair kvp in newDescription) + { + ((Dictionary)this.Description)[kvp.Key] = kvp.Value; + this.descriptionPropertyLayer[kvp.Key] = layer; + } + } + else + { + this.Description = newDescription; + this.descriptionPropertyLayer = newDescription.ToDictionary(e => e.Key, e => layer); + } + } + + continue; + case "displayName": + case "dtmi:dtdl:property:displayName;4": + if (displayNameProperty != null) + { + parsingErrorCollection.Notify( + "duplicatePropertyName", + elementId: this.Id, + propertyName: "displayName", + incidentProperty: prop, + extantProperty: displayNameProperty, + layer: layer); + } + else + { + displayNameProperty = prop; + int? maxLength = aggregateContext.LimitSpecifier switch + { + "" => 512, + "onvif_1" => 513, + _ => null, + }; + + Dictionary newDisplayName = ValueParser.ParseLangStringValueCollection(aggregateContext, this.Id, "displayName", prop.Values, "en", maxLength, null, layer, parsingErrorCollection); + List displayNameCodes = Helpers.GetKeysWithDifferingLiteralValues(this.DisplayName, newDisplayName); + if (displayNameCodes.Any()) + { + JsonLdProperty extantProp = Helpers.TryGetSingleUniqueValue(displayNameCodes.Select(c => this.displayNamePropertyLayer[c]), out string uniqueCodeLayer) && this.JsonLdElements[uniqueCodeLayer].Properties.Any(p => p.Name == "displayName") ? this.JsonLdElements[uniqueCodeLayer].Properties.First(p => p.Name == "displayName") : null; + parsingErrorCollection.Notify( + "inconsistentLangStringValues", + elementId: this.Id, + propertyName: "displayName", + langCode: string.Join(" and ", displayNameCodes.Select(c => $"'{c}'")), + observedCount: displayNameCodes.Count, + incidentProperty: prop, + extantProperty: extantProp, + layer: layer); + } + else if (this.DisplayName.Any()) + { + foreach (KeyValuePair kvp in newDisplayName) + { + ((Dictionary)this.DisplayName)[kvp.Key] = kvp.Value; + this.displayNamePropertyLayer[kvp.Key] = layer; + } + } + else + { + this.DisplayName = newDisplayName; + this.displayNamePropertyLayer = newDisplayName.ToDictionary(e => e.Key, e => layer); + } + } + + continue; + } + + if (this.TryParseSupplementalProperty(model, immediateSupplementalTypeIds, objectPropertyInfoList, elementPropertyConstraints, aggregateContext, layer, definedIn, parsingErrorCollection, prop.Name, globalize, allowReservedIds, tolerateSolecisms, prop, supplementalJsonLdProperties)) + { + continue; + } + + if (aggregateContext.TryCreateDtmi(prop.Name, out Dtmi _)) + { + if (aggregateContext.IsComplete) + { + parsingErrorCollection.Notify( + "propertyIrrelevantDtmiOrTerm", + elementId: this.Id, + propertyName: prop.Name, + incidentProperty: prop, + element: elt, + layer: layer); + continue; + } + } + else if (prop.Name.StartsWith("dtmi:")) + { + parsingErrorCollection.Notify( + "propertyInvalidDtmi", + elementId: this.Id, + propertyName: prop.Name, + incidentProperty: prop, + element: elt, + layer: layer); + continue; + } + else if (prop.Name.Contains(":")) + { + parsingErrorCollection.Notify( + "propertyNotDtmiNorTerm", + elementId: this.Id, + propertyName: prop.Name, + incidentProperty: prop, + element: elt, + layer: layer); + continue; + } + else + { + if (aggregateContext.IsComplete) + { + parsingErrorCollection.Notify( + "propertyUndefinedTerm", + elementId: this.Id, + propertyName: prop.Name, + incidentProperty: prop, + element: elt, + version: aggregateContext.DtdlVersion.ToString(), + layer: layer); + continue; + } + } + + if (!immediateUndefinedTypes.Any()) + { + if (elt.Types != null) + { + parsingErrorCollection.Notify( + "noTypeThatAllows", + elementId: this.Id, + propertyName: prop.Name, + incidentProperty: prop, + element: elt, + layer: layer); + } + else + { + parsingErrorCollection.Notify( + "inferredTypeDoesNotAllow", + elementId: this.Id, + referenceType: "UnsignedShort", + propertyName: prop.Name, + incidentProperty: prop, + element: elt, + layer: layer); + } + + continue; + } + + using (JsonDocument propDoc = JsonDocument.Parse(prop.Values.GetJsonText())) + { + this.UndefinedPropertyDictionary[prop.Name] = propDoc.RootElement.Clone(); + } + } + + foreach (Dtmi supplementalTypeId in immediateSupplementalTypeIds) + { + if (aggregateContext.SupplementalTypeCollection.TryGetSupplementalTypeInfo(supplementalTypeId, out DTSupplementalTypeInfo supplementalTypeInfo)) + { + supplementalTypeInfo.CheckForRequiredProperties(parsingErrorCollection, this.Id, elt, supplementalJsonLdProperties); + } + } + } + + /// + /// Record JSON-LD source as appropriate and check length of text against limit. + /// + /// The name of the layer whose source to record. + /// A JsonLdElement containing the JSON-LD source of the element. + /// An AggregateContext object representing information retrieved from JSON-LD context blocks. + /// A ParsingErrorCollection to which any parsing errors are added. + /// True if the element is at the document root. + /// True if the element has been globalized. + internal override void RecordSourceAsAppropriate(string layer, JsonLdElement elt, AggregateContext aggregateContext, ParsingErrorCollection parsingErrorCollection, bool atRoot, bool globalized) + { + } + + /// + /// Write a JSON representation of the DTDL element represented by an object of this class. + /// + /// A Utf8JsonWriter object with which to write the JSON representation. + /// True if the mothed should add a ClassId property to the JSON object. + internal override void WriteToJson(Utf8JsonWriter jsonWriter, bool includeClassId) + { + base.WriteToJson(jsonWriter, includeClassId: false); + + if (includeClassId) + { + jsonWriter.WriteString("ClassId", $"dtmi:dtdl:class:UnsignedShort;{this.LanguageMajorVersion}"); + } + } + + private bool DoesInstanceMatchV4(JsonElement instanceElt, string instanceName) + { + return true; + } + + private bool TryParseSupplementalProperty(Model model, HashSet immediateSupplementalTypeIds, List objectPropertyInfoList, List elementPropertyConstraints, AggregateContext aggregateContext, string layer, Dtmi definedIn, ParsingErrorCollection parsingErrorCollection, string propName, bool globalize, bool allowReservedIds, bool tolerateSolecisms, JsonLdProperty valueCollectionProp, Dictionary supplementalJsonLdProperties) + { + if (!aggregateContext.TryCreateDtmi(propName, out Dtmi propDtmi)) + { + return false; + } + + foreach (Dtmi supplementalTypeId in immediateSupplementalTypeIds) + { + if (aggregateContext.SupplementalTypeCollection.TryGetSupplementalTypeInfo(supplementalTypeId, out DTSupplementalTypeInfo supplementalTypeInfo) && supplementalTypeInfo.TryParseProperty(model, objectPropertyInfoList, elementPropertyConstraints, aggregateContext, parsingErrorCollection, layer, this.Id, definedIn, propDtmi.ToString(), globalize, allowReservedIds, tolerateSolecisms, valueCollectionProp, ref this.supplementalProperties, supplementalJsonLdProperties, this.supplementalSingularPropertyLayers, this.JsonLdElements)) + { + return true; + } + } + + return false; + } + + private bool ValidateInstanceV4(JsonElement instanceElt, string instanceName, List violations) + { + if (instanceElt.ValueKind != JsonValueKind.Number) + { + violations.Add($">>{instanceElt.GetRawText()}<< is not a numeric value"); + return false; + } + + if (!ushort.TryParse(instanceElt.GetRawText(), out ushort _)) + { + violations.Add($"{instanceElt.GetRawText()} does not conform to the XSD definition of 'unsignedShort'"); + return false; + } + + if (!ElementValueInstanceRegexPatternV4.IsMatch(instanceElt.GetRawText())) + { + violations.Add($"\"{instanceElt.GetRawText()}\" does not conform to the XSD definition of 'unsignedShort'"); + return false; + } + + return true; + } + + private void ApplyTransformationsV4(Model model, ParsingErrorCollection parsingErrorCollection) + { + } + + /// + private void CheckRestrictionsV4(ParsingErrorCollection parsingErrorCollection) + { + } + } +} diff --git a/dotnet/src/DTDLParser/generated/MaterialTypeNameCollection.g.cs b/dotnet/src/DTDLParser/generated/MaterialTypeNameCollection.g.cs index 8aa26e07..d51198f4 100644 --- a/dotnet/src/DTDLParser/generated/MaterialTypeNameCollection.g.cs +++ b/dotnet/src/DTDLParser/generated/MaterialTypeNameCollection.g.cs @@ -32,6 +32,8 @@ static MaterialTypeNameCollection() TypeNames.Add("dtmi:dtdl:class:Boolean;2"); TypeNames.Add("dtmi:dtdl:class:Boolean;3"); TypeNames.Add("dtmi:dtdl:class:Boolean;4"); + TypeNames.Add("Byte"); + TypeNames.Add("dtmi:dtdl:class:Byte;4"); TypeNames.Add("Bytes"); TypeNames.Add("dtmi:dtdl:class:Bytes;4"); TypeNames.Add("Command"); @@ -162,6 +164,8 @@ static MaterialTypeNameCollection() TypeNames.Add("dtmi:dtdl:class:SchemaField;2"); TypeNames.Add("dtmi:dtdl:class:SchemaField;3"); TypeNames.Add("dtmi:dtdl:class:SchemaField;4"); + TypeNames.Add("Short"); + TypeNames.Add("dtmi:dtdl:class:Short;4"); TypeNames.Add("String"); TypeNames.Add("dtmi:dtdl:class:String;2"); TypeNames.Add("dtmi:dtdl:class:String;3"); @@ -186,6 +190,14 @@ static MaterialTypeNameCollection() TypeNames.Add("dtmi:dtdl:class:UnitAttribute;2"); TypeNames.Add("dtmi:dtdl:class:UnitAttribute;3"); TypeNames.Add("dtmi:dtdl:class:UnitAttribute;4"); + TypeNames.Add("UnsignedByte"); + TypeNames.Add("dtmi:dtdl:class:UnsignedByte;4"); + TypeNames.Add("UnsignedInteger"); + TypeNames.Add("dtmi:dtdl:class:UnsignedInteger;4"); + TypeNames.Add("UnsignedLong"); + TypeNames.Add("dtmi:dtdl:class:UnsignedLong;4"); + TypeNames.Add("UnsignedShort"); + TypeNames.Add("dtmi:dtdl:class:UnsignedShort;4"); TypeNames.Add("Uuid"); TypeNames.Add("dtmi:dtdl:class:Uuid;4"); } diff --git a/dotnet/src/DTDLParser/generated/ModelElements.g.json b/dotnet/src/DTDLParser/generated/ModelElements.g.json index fba56000..99123c2a 100644 --- a/dotnet/src/DTDLParser/generated/ModelElements.g.json +++ b/dotnet/src/DTDLParser/generated/ModelElements.g.json @@ -268,6 +268,17 @@ }, "displayName": "boolean" }, + { + "@context": "dtmi:dtdl:context;4", + "@id": "dtmi:dtdl:instance:Schema:byte;4", + "@type": [ + "Byte" + ], + "description": { + "en-US": "a signed integral numeric value that is expressible in 1 byte" + }, + "displayName": "byte" + }, { "@context": "dtmi:dtdl:context;4", "@id": "dtmi:dtdl:instance:Schema:double;4", @@ -320,6 +331,61 @@ }, "displayName": "long" }, + { + "@context": "dtmi:dtdl:context;4", + "@id": "dtmi:dtdl:instance:Schema:short;4", + "@type": [ + "Short" + ], + "description": { + "en-US": "a signed integral numeric value that is expressible in 2 bytes" + }, + "displayName": "short" + }, + { + "@context": "dtmi:dtdl:context;4", + "@id": "dtmi:dtdl:instance:Schema:unsignedByte;4", + "@type": [ + "UnsignedByte" + ], + "description": { + "en-US": "an unsigned integral numeric value that is expressible in 1 byte" + }, + "displayName": "unsignedByte" + }, + { + "@context": "dtmi:dtdl:context;4", + "@id": "dtmi:dtdl:instance:Schema:unsignedInteger;4", + "@type": [ + "UnsignedInteger" + ], + "description": { + "en-US": "an unsigned integral numeric value that is expressible in 4 bytes" + }, + "displayName": "unsignedInteger" + }, + { + "@context": "dtmi:dtdl:context;4", + "@id": "dtmi:dtdl:instance:Schema:unsignedLong;4", + "@type": [ + "UnsignedLong" + ], + "description": { + "en-US": "an unsigned integral numeric value that is expressible in 8 bytes" + }, + "displayName": "unsignedLong" + }, + { + "@context": "dtmi:dtdl:context;4", + "@id": "dtmi:dtdl:instance:Schema:unsignedShort;4", + "@type": [ + "UnsignedShort" + ], + "description": { + "en-US": "an unsigned integral numeric value that is expressible in 2 bytes" + }, + "displayName": "unsignedShort" + }, { "@context": "dtmi:dtdl:context;4", "@id": "dtmi:dtdl:instance:Schema:date;4", diff --git a/dotnet/src/DTDLParser/generated/SupplementalTypeCollection.g.cs b/dotnet/src/DTDLParser/generated/SupplementalTypeCollection.g.cs index 41fbb1c6..a01ab39b 100644 --- a/dotnet/src/DTDLParser/generated/SupplementalTypeCollection.g.cs +++ b/dotnet/src/DTDLParser/generated/SupplementalTypeCollection.g.cs @@ -287,7 +287,7 @@ static SupplementalTypeCollection() adjunctTypeInfoEV3.AllowedCotypeVersions = new HashSet() { 2, 3 }; DTSupplementalTypeInfo adjunctTypeInfoEV4 = new DTSupplementalTypeInfo(DTExtensionKind.None, dtdlContextIdV4, adjunctTypeTypeIdEV4, isAbstract: true, isMergeable: false, null); - adjunctTypeInfoEV4.AllowedCotypeKinds = new HashSet() { DTEntityKind.Array, DTEntityKind.Boolean, DTEntityKind.Bytes, DTEntityKind.Command, DTEntityKind.CommandPayload, DTEntityKind.CommandRequest, DTEntityKind.CommandResponse, DTEntityKind.CommandType, DTEntityKind.Component, DTEntityKind.Date, DTEntityKind.DateTime, DTEntityKind.Double, DTEntityKind.Duration, DTEntityKind.Enum, DTEntityKind.EnumValue, DTEntityKind.Field, DTEntityKind.Float, DTEntityKind.Integer, DTEntityKind.Interface, DTEntityKind.LatentType, DTEntityKind.Long, DTEntityKind.Map, DTEntityKind.MapKey, DTEntityKind.MapValue, DTEntityKind.NamedLatentType, DTEntityKind.Object, DTEntityKind.Property, DTEntityKind.Relationship, DTEntityKind.String, DTEntityKind.Telemetry, DTEntityKind.Time, DTEntityKind.Unit, DTEntityKind.UnitAttribute, DTEntityKind.Uuid }; + adjunctTypeInfoEV4.AllowedCotypeKinds = new HashSet() { DTEntityKind.Array, DTEntityKind.Boolean, DTEntityKind.Byte, DTEntityKind.Bytes, DTEntityKind.Command, DTEntityKind.CommandPayload, DTEntityKind.CommandRequest, DTEntityKind.CommandResponse, DTEntityKind.CommandType, DTEntityKind.Component, DTEntityKind.Date, DTEntityKind.DateTime, DTEntityKind.Double, DTEntityKind.Duration, DTEntityKind.Enum, DTEntityKind.EnumValue, DTEntityKind.Field, DTEntityKind.Float, DTEntityKind.Integer, DTEntityKind.Interface, DTEntityKind.LatentType, DTEntityKind.Long, DTEntityKind.Map, DTEntityKind.MapKey, DTEntityKind.MapValue, DTEntityKind.NamedLatentType, DTEntityKind.Object, DTEntityKind.Property, DTEntityKind.Relationship, DTEntityKind.Short, DTEntityKind.String, DTEntityKind.Telemetry, DTEntityKind.Time, DTEntityKind.Unit, DTEntityKind.UnitAttribute, DTEntityKind.UnsignedByte, DTEntityKind.UnsignedInteger, DTEntityKind.UnsignedLong, DTEntityKind.UnsignedShort, DTEntityKind.Uuid }; adjunctTypeInfoEV4.AllowedCotypeVersions = new HashSet() { 2, 3, 4 }; DTSupplementalTypeInfo aliasInfoEV3 = new DTSupplementalTypeInfo(DTExtensionKind.None, dtdlContextIdV3, aliasTypeIdEV3, isAbstract: false, isMergeable: false, null); @@ -297,7 +297,7 @@ static SupplementalTypeCollection() DTSupplementalTypeInfo aliasInfoEV4 = new DTSupplementalTypeInfo(DTExtensionKind.None, dtdlContextIdV4, aliasTypeIdEV4, isAbstract: false, isMergeable: false, null); aliasInfoEV4.AddProperty("dtmi:dtdl:property:aliasFor;4", new Dtmi("dtmi:dtdl:class:Entity;4"), 1, 1, null, null, null, regex: null, hasUniqueValue: false, isPlural: false, isOptional: false, defaultLanguage: null, dtmiSeg: null, dictionaryKey: null, idRequired: false, typeRequired: true, childOf: null, instanceProperty: null, requiredValues: null, requiredValuesString: null, requiredLiteral: null); - aliasInfoEV4.AllowedCotypeKinds = new HashSet() { DTEntityKind.Array, DTEntityKind.Boolean, DTEntityKind.Bytes, DTEntityKind.Command, DTEntityKind.CommandRequest, DTEntityKind.CommandResponse, DTEntityKind.CommandType, DTEntityKind.Component, DTEntityKind.Date, DTEntityKind.DateTime, DTEntityKind.Double, DTEntityKind.Duration, DTEntityKind.Enum, DTEntityKind.EnumValue, DTEntityKind.Field, DTEntityKind.Float, DTEntityKind.Integer, DTEntityKind.Interface, DTEntityKind.LatentType, DTEntityKind.Long, DTEntityKind.Map, DTEntityKind.MapKey, DTEntityKind.MapValue, DTEntityKind.NamedLatentType, DTEntityKind.Object, DTEntityKind.Property, DTEntityKind.Relationship, DTEntityKind.String, DTEntityKind.Telemetry, DTEntityKind.Time, DTEntityKind.Unit, DTEntityKind.UnitAttribute, DTEntityKind.Uuid }; + aliasInfoEV4.AllowedCotypeKinds = new HashSet() { DTEntityKind.Array, DTEntityKind.Boolean, DTEntityKind.Byte, DTEntityKind.Bytes, DTEntityKind.Command, DTEntityKind.CommandRequest, DTEntityKind.CommandResponse, DTEntityKind.CommandType, DTEntityKind.Component, DTEntityKind.Date, DTEntityKind.DateTime, DTEntityKind.Double, DTEntityKind.Duration, DTEntityKind.Enum, DTEntityKind.EnumValue, DTEntityKind.Field, DTEntityKind.Float, DTEntityKind.Integer, DTEntityKind.Interface, DTEntityKind.LatentType, DTEntityKind.Long, DTEntityKind.Map, DTEntityKind.MapKey, DTEntityKind.MapValue, DTEntityKind.NamedLatentType, DTEntityKind.Object, DTEntityKind.Property, DTEntityKind.Relationship, DTEntityKind.Short, DTEntityKind.String, DTEntityKind.Telemetry, DTEntityKind.Time, DTEntityKind.Unit, DTEntityKind.UnitAttribute, DTEntityKind.UnsignedByte, DTEntityKind.UnsignedInteger, DTEntityKind.UnsignedLong, DTEntityKind.UnsignedShort, DTEntityKind.Uuid }; aliasInfoEV4.AllowedCotypeVersions = new HashSet() { 4 }; DTSupplementalTypeInfo semanticTypeInfoEV2 = new DTSupplementalTypeInfo(DTExtensionKind.None, dtdlContextIdV2, semanticTypeTypeIdEV2, isAbstract: true, isMergeable: false, null); @@ -741,7 +741,7 @@ static SupplementalTypeCollection() DTSupplementalTypeInfo binaryUnitInfoCV2 = new DTSupplementalTypeInfo(DTExtensionKind.AdjunctType, dtdlExtensionQuantitativeTypesContextIdV2, binaryUnitTypeIdCV2, isAbstract: false, isMergeable: false, adjunctTypeTypeIdEV4); binaryUnitInfoCV2.AddProperty("dtmi:dtdl:extension:quantitativeTypes:v2:property:baseUnit", new Dtmi("dtmi:dtdl:class:EnumValue;4"), 1, 1, null, null, null, regex: null, hasUniqueValue: false, isPlural: false, isOptional: false, defaultLanguage: null, dtmiSeg: null, dictionaryKey: null, idRequired: false, typeRequired: true, childOf: null, instanceProperty: null, requiredValues: null, requiredValuesString: null, requiredLiteral: null); binaryUnitInfoCV2.AddProperty("dtmi:dtdl:extension:quantitativeTypes:v2:property:prefix", new Dtmi("dtmi:dtdl:class:EnumValue;4"), 1, null, null, null, null, regex: null, hasUniqueValue: false, isPlural: false, isOptional: true, defaultLanguage: null, dtmiSeg: null, dictionaryKey: null, idRequired: false, typeRequired: true, childOf: null, instanceProperty: null, requiredValues: null, requiredValuesString: null, requiredLiteral: null); - binaryUnitInfoCV2.AllowedCotypeKinds = new HashSet() { DTEntityKind.Array, DTEntityKind.Boolean, DTEntityKind.Bytes, DTEntityKind.Command, DTEntityKind.CommandPayload, DTEntityKind.CommandRequest, DTEntityKind.CommandResponse, DTEntityKind.CommandType, DTEntityKind.Component, DTEntityKind.Date, DTEntityKind.DateTime, DTEntityKind.Double, DTEntityKind.Duration, DTEntityKind.Enum, DTEntityKind.EnumValue, DTEntityKind.Field, DTEntityKind.Float, DTEntityKind.Integer, DTEntityKind.Interface, DTEntityKind.LatentType, DTEntityKind.Long, DTEntityKind.Map, DTEntityKind.MapKey, DTEntityKind.MapValue, DTEntityKind.NamedLatentType, DTEntityKind.Object, DTEntityKind.Property, DTEntityKind.Relationship, DTEntityKind.String, DTEntityKind.Telemetry, DTEntityKind.Time, DTEntityKind.Unit, DTEntityKind.UnitAttribute, DTEntityKind.Uuid }; + binaryUnitInfoCV2.AllowedCotypeKinds = new HashSet() { DTEntityKind.Array, DTEntityKind.Boolean, DTEntityKind.Byte, DTEntityKind.Bytes, DTEntityKind.Command, DTEntityKind.CommandPayload, DTEntityKind.CommandRequest, DTEntityKind.CommandResponse, DTEntityKind.CommandType, DTEntityKind.Component, DTEntityKind.Date, DTEntityKind.DateTime, DTEntityKind.Double, DTEntityKind.Duration, DTEntityKind.Enum, DTEntityKind.EnumValue, DTEntityKind.Field, DTEntityKind.Float, DTEntityKind.Integer, DTEntityKind.Interface, DTEntityKind.LatentType, DTEntityKind.Long, DTEntityKind.Map, DTEntityKind.MapKey, DTEntityKind.MapValue, DTEntityKind.NamedLatentType, DTEntityKind.Object, DTEntityKind.Property, DTEntityKind.Relationship, DTEntityKind.Short, DTEntityKind.String, DTEntityKind.Telemetry, DTEntityKind.Time, DTEntityKind.Unit, DTEntityKind.UnitAttribute, DTEntityKind.UnsignedByte, DTEntityKind.UnsignedInteger, DTEntityKind.UnsignedLong, DTEntityKind.UnsignedShort, DTEntityKind.Uuid }; binaryUnitInfoCV2.AllowedCotypeVersions = new HashSet() { 2, 3, 4 }; DTSupplementalTypeInfo capacitanceInfoCV2 = new DTSupplementalTypeInfo(DTExtensionKind.SemanticType, dtdlExtensionQuantitativeTypesContextIdV2, capacitanceTypeIdCV2, isAbstract: false, isMergeable: false, quantitativeTypeTypeIdCV2); diff --git a/dotnet/src/Remodel/generated/Remodeler.g.cs b/dotnet/src/Remodel/generated/Remodeler.g.cs index 325a0417..34a60b16 100644 --- a/dotnet/src/Remodel/generated/Remodeler.g.cs +++ b/dotnet/src/Remodel/generated/Remodeler.g.cs @@ -73,6 +73,7 @@ static Remodeler() termIriRegexes.Add(@"dtmi:dtdl:extension:quantitativeTypes:v2:unitprefix:(\w*)"); termIriRegexes.Add(@"dtmi:dtdl:extension:quantitativeTypes:v2:property:(\w*)"); termIriRegexes.Add(@"dtmi:dtdl:extension:quantitativeTypes:v2:enum:PowerUnit"); + termIriRegexes.Add(@"dtmi:dtdl:extension:requirement:v1:(\w*)"); termIriRegexes.Add(@"dtmi:iotcentral:class:(\w*);2"); termIriRegexes.Add(@"dtmi:iotcentral:schema:(\w*);2"); diff --git a/dotnet/tests/ParserUnitTest/generated/ParserUnitTest.g.cs b/dotnet/tests/ParserUnitTest/generated/ParserUnitTest.g.cs index 596519ab..a1a00927 100644 --- a/dotnet/tests/ParserUnitTest/generated/ParserUnitTest.g.cs +++ b/dotnet/tests/ParserUnitTest/generated/ParserUnitTest.g.cs @@ -80,6 +80,7 @@ public void TestParser_A(string testName) [DataRow("BooleanInstancesV2")] [DataRow("BooleanInstancesV3")] [DataRow("BooleanInstancesV4")] + [DataRow("ByteInstancesV4")] [DataRow("BytesInstancesV4")] public void TestParser_B(string testName) { @@ -1970,6 +1971,7 @@ public void TestParser_R(string testName) [DataRow("SchemaV2")] [DataRow("SchemaV3")] [DataRow("SchemaV4")] + [DataRow("ShortInstancesV4")] [DataRow("StringInstancesV2")] [DataRow("StringInstancesV3")] [DataRow("StringInstancesV4")] @@ -2322,6 +2324,10 @@ public void TestParser_T(string testName) [DataRow("UnresolvableContextVersionAndDisallowUndefinedExtensionsV2")] [DataRow("UnresolvableContextVersionAndDisallowUndefinedExtensionsV3")] [DataRow("UnresolvableContextVersionAndDisallowUndefinedExtensionsV4")] + [DataRow("UnsignedByteInstancesV4")] + [DataRow("UnsignedIntegerInstancesV4")] + [DataRow("UnsignedLongInstancesV4")] + [DataRow("UnsignedShortInstancesV4")] [DataRow("UuidInstancesV4")] public void TestParser_U(string testName) { diff --git a/dtdl/dtdl_digest.json b/dtdl/dtdl_digest.json index 3c3adb8f..67b675dd 100644 --- a/dtdl/dtdl_digest.json +++ b/dtdl/dtdl_digest.json @@ -517,6 +517,8 @@ "asynchronous": "dtmi:dtdl:instance:CommandType:asynchronous;4", "boolean": "dtmi:dtdl:instance:Schema:boolean;4", "Boolean": "dtmi:dtdl:class:Boolean;4", + "byte": "dtmi:dtdl:instance:Schema:byte;4", + "Byte": "dtmi:dtdl:class:Byte;4", "bytes": "dtmi:dtdl:instance:Schema:bytes;4", "Bytes": "dtmi:dtdl:class:Bytes;4", "Command": "dtmi:dtdl:class:Command;4", @@ -593,6 +595,8 @@ "schemas": "dtmi:dtdl:property:schemas;4", "SemanticType": "dtmi:dtdl:class:SemanticType;4", "SemanticUnit": "dtmi:dtdl:class:SemanticUnit;4", + "short": "dtmi:dtdl:instance:Schema:short;4", + "Short": "dtmi:dtdl:class:Short;4", "string": "dtmi:dtdl:instance:Schema:string;4", "String": "dtmi:dtdl:class:String;4", "symbol": "dtmi:dtdl:property:symbol;4", @@ -604,6 +608,14 @@ "Time": "dtmi:dtdl:class:Time;4", "Unit": "dtmi:dtdl:class:Unit;4", "UnitAttribute": "dtmi:dtdl:class:UnitAttribute;4", + "unsignedByte": "dtmi:dtdl:instance:Schema:unsignedByte;4", + "UnsignedByte": "dtmi:dtdl:class:UnsignedByte;4", + "unsignedInteger": "dtmi:dtdl:instance:Schema:unsignedInteger;4", + "UnsignedInteger": "dtmi:dtdl:class:UnsignedInteger;4", + "unsignedLong": "dtmi:dtdl:instance:Schema:unsignedLong;4", + "UnsignedLong": "dtmi:dtdl:class:UnsignedLong;4", + "unsignedShort": "dtmi:dtdl:instance:Schema:unsignedShort;4", + "UnsignedShort": "dtmi:dtdl:class:UnsignedShort;4", "uuid": "dtmi:dtdl:instance:Schema:uuid;4", "Uuid": "dtmi:dtdl:class:Uuid;4", "valueSchema": "dtmi:dtdl:property:valueSchema;4", @@ -2233,6 +2245,17 @@ }, "displayName": "boolean" }, + { + "@context": "dtmi:dtdl:context;4", + "@id": "dtmi:dtdl:instance:Schema:byte;4", + "@type": [ + "Byte" + ], + "description": { + "en-US": "a signed integral numeric value that is expressible in 1 byte" + }, + "displayName": "byte" + }, { "@context": "dtmi:dtdl:context;4", "@id": "dtmi:dtdl:instance:Schema:double;4", @@ -2285,6 +2308,61 @@ }, "displayName": "long" }, + { + "@context": "dtmi:dtdl:context;4", + "@id": "dtmi:dtdl:instance:Schema:short;4", + "@type": [ + "Short" + ], + "description": { + "en-US": "a signed integral numeric value that is expressible in 2 bytes" + }, + "displayName": "short" + }, + { + "@context": "dtmi:dtdl:context;4", + "@id": "dtmi:dtdl:instance:Schema:unsignedByte;4", + "@type": [ + "UnsignedByte" + ], + "description": { + "en-US": "an unsigned integral numeric value that is expressible in 1 byte" + }, + "displayName": "unsignedByte" + }, + { + "@context": "dtmi:dtdl:context;4", + "@id": "dtmi:dtdl:instance:Schema:unsignedInteger;4", + "@type": [ + "UnsignedInteger" + ], + "description": { + "en-US": "an unsigned integral numeric value that is expressible in 4 bytes" + }, + "displayName": "unsignedInteger" + }, + { + "@context": "dtmi:dtdl:context;4", + "@id": "dtmi:dtdl:instance:Schema:unsignedLong;4", + "@type": [ + "UnsignedLong" + ], + "description": { + "en-US": "an unsigned integral numeric value that is expressible in 8 bytes" + }, + "displayName": "unsignedLong" + }, + { + "@context": "dtmi:dtdl:context;4", + "@id": "dtmi:dtdl:instance:Schema:unsignedShort;4", + "@type": [ + "UnsignedShort" + ], + "description": { + "en-US": "an unsigned integral numeric value that is expressible in 2 bytes" + }, + "displayName": "unsignedShort" + }, { "@context": "dtmi:dtdl:context;4", "@id": "dtmi:dtdl:instance:Schema:date;4", @@ -15309,6 +15387,194 @@ ], "typeOptionalVersions": [] }, + "Byte": { + "abstract": false, + "badTypeActionFormat": { + "4": "Use this standard value for property '{property}'{line1}: byte." + }, + "badTypeCauseFormat": { + "4": "{layer}{primaryId:p} property '{property}' has value{secondaryId:e} that is not a standard value for this property." + }, + "badTypeLocatedCauseFormat": { + "4": "In {sourceName1}, property '{property}'{line1} has value{secondaryId:e}{line2} that is not a standard value for this property." + }, + "concreteSubclasses": { + "4": [ + "Byte" + ] + }, + "dtdlVersions": [ + 4 + ], + "elementalSubclasses": { + "4": [ + "Byte" + ] + }, + "elements": { + "4": [ + { + "description": { + "en-us": "a signed integral numeric value that is expressible in 1 byte" + }, + "id": "dtmi:dtdl:instance:Schema:byte;4", + "name": "byte" + } + ] + }, + "extensibleMaterialSubclasses": { + "4": [] + }, + "idRequiredVersions": [], + "idRequiredWhen": { + "4": [ + { + "class": "Enum", + "property": "valueSchema" + } + ] + }, + "instance": { + "4": { + "eachChild": {}, + "element": { + "datatype": "byte", + "jsonType": "number" + } + }, + "conformanceText": "the XSD definition of 'byte'", + "criteriaText": "is a numeric value that conforms to the XSD definition of 'byte'", + "typeText": "a numeric value" + }, + "maybePartial": false, + "overt": true, + "parentClass": "NumericSchema", + "partition": false, + "properties": { + "comment": { + "_": { + "abstract": false, + "datatype": "string", + "description": { + "en-us": "A comment for model authors." + }, + "inherited": true, + "inheritedFrom": "Entity", + "literal": true, + "optional": true, + "plural": false, + "shadowed": false + }, + "4": { + "allowed": true, + "deprecated": false, + "hidden": false, + "idRequired": false, + "maxCount": 1, + "maxLength": { + "": 512, + "onvif_1": 515 + }, + "typeRequired": true, + "uniqueAmong": [] + } + }, + "description": { + "_": { + "abstract": false, + "datatype": "langString", + "description": { + "en-us": "A localizable description for display." + }, + "inherited": true, + "inheritedFrom": "Entity", + "literal": true, + "optional": true, + "plural": true, + "shadowed": false + }, + "4": { + "allowed": true, + "defaultLanguage": "en", + "deprecated": false, + "hidden": false, + "idRequired": false, + "maxLength": { + "": 512, + "onvif_1": 514 + }, + "typeRequired": true, + "uniqueAmong": [] + } + }, + "displayName": { + "_": { + "abstract": false, + "datatype": "langString", + "description": { + "en-us": "A localizable name for display." + }, + "inherited": true, + "inheritedFrom": "Entity", + "literal": true, + "optional": true, + "plural": true, + "shadowed": false + }, + "4": { + "allowed": true, + "defaultLanguage": "en", + "deprecated": false, + "hidden": false, + "idRequired": false, + "maxLength": { + "": 512, + "onvif_1": 513 + }, + "typeRequired": true, + "uniqueAmong": [] + } + }, + "languageMajorVersion": { + "_": { + "abstract": false, + "datatype": "integer", + "description": { + "en-us": "The major version of DTDL used to author this element." + }, + "inherited": true, + "inheritedFrom": "Entity", + "literal": true, + "optional": false, + "plural": false, + "shadowed": false + }, + "4": { + "allowed": false, + "deprecated": false, + "hidden": false, + "idRequired": false, + "typeRequired": true, + "uniqueAmong": [], + "value": 4 + } + } + }, + "rootable": false, + "standardElementIds": { + "4": [ + "dtmi:dtdl:instance:Schema:byte;4" + ] + }, + "typeIds": [ + "dtmi:dtdl:class:Byte", + "dtmi:dtdl:class:Entity", + "dtmi:dtdl:class:NumericSchema", + "dtmi:dtdl:class:PrimitiveSchema", + "dtmi:dtdl:class:Schema" + ], + "typeOptionalVersions": [] + }, "Bytes": { "abstract": false, "badTypeActionFormat": { @@ -20170,6 +20436,7 @@ "4": [ "Array", "Boolean", + "Byte", "Bytes", "Command", "CommandRequest", @@ -20193,9 +20460,14 @@ "Object", "Property", "Relationship", + "Short", "String", "Telemetry", "Time", + "UnsignedByte", + "UnsignedInteger", + "UnsignedLong", + "UnsignedShort", "Uuid" ] }, @@ -20233,6 +20505,7 @@ ], "4": [ "Boolean", + "Byte", "Bytes", "CommandType", "Date", @@ -20242,8 +20515,13 @@ "Float", "Integer", "Long", + "Short", "String", "Time", + "UnsignedByte", + "UnsignedInteger", + "UnsignedLong", + "UnsignedShort", "Uuid" ] }, @@ -20540,6 +20818,13 @@ "id": "dtmi:dtdl:instance:Schema:boolean;4", "name": "boolean" }, + { + "description": { + "en-us": "a signed integral numeric value that is expressible in 1 byte" + }, + "id": "dtmi:dtdl:instance:Schema:byte;4", + "name": "byte" + }, { "description": { "en-us": "an array of bytes" @@ -20596,6 +20881,13 @@ "id": "dtmi:dtdl:instance:Schema:long;4", "name": "long" }, + { + "description": { + "en-us": "a signed integral numeric value that is expressible in 2 bytes" + }, + "id": "dtmi:dtdl:instance:Schema:short;4", + "name": "short" + }, { "description": { "en-us": "a UTF8 string" @@ -20610,6 +20902,34 @@ "id": "dtmi:dtdl:instance:Schema:time;4", "name": "time" }, + { + "description": { + "en-us": "an unsigned integral numeric value that is expressible in 1 byte" + }, + "id": "dtmi:dtdl:instance:Schema:unsignedByte;4", + "name": "unsignedByte" + }, + { + "description": { + "en-us": "an unsigned integral numeric value that is expressible in 4 bytes" + }, + "id": "dtmi:dtdl:instance:Schema:unsignedInteger;4", + "name": "unsignedInteger" + }, + { + "description": { + "en-us": "an unsigned integral numeric value that is expressible in 8 bytes" + }, + "id": "dtmi:dtdl:instance:Schema:unsignedLong;4", + "name": "unsignedLong" + }, + { + "description": { + "en-us": "an unsigned integral numeric value that is expressible in 2 bytes" + }, + "id": "dtmi:dtdl:instance:Schema:unsignedShort;4", + "name": "unsignedShort" + }, { "description": { "en-us": "a UUID string per RFC 9562" @@ -25889,7 +26209,7 @@ "badTypeActionFormat": { "2": "Use one of these standard values for property '{property}'{line1}: double, float, integer, long.", "3": "Use one of these standard values for property '{property}'{line1}: double, float, integer, long.", - "4": "Use one of these standard values for property '{property}'{line1}: double, float, integer, long." + "4": "Use one of these standard values for property '{property}'{line1}: byte, double, float, integer, long, short, unsignedByte, unsignedInteger, unsignedLong, unsignedShort." }, "badTypeCauseFormat": { "2": "{layer}{primaryId:p} property '{property}' has value{secondaryId:e} that is not a standard value for this property.", @@ -25915,10 +26235,16 @@ "Long" ], "4": [ + "Byte", "Double", "Float", "Integer", - "Long" + "Long", + "Short", + "UnsignedByte", + "UnsignedInteger", + "UnsignedLong", + "UnsignedShort" ] }, "dtdlVersions": [ @@ -25940,10 +26266,16 @@ "Long" ], "4": [ + "Byte", "Double", "Float", "Integer", - "Long" + "Long", + "Short", + "UnsignedByte", + "UnsignedInteger", + "UnsignedLong", + "UnsignedShort" ] }, "elements": { @@ -26008,6 +26340,13 @@ } ], "4": [ + { + "description": { + "en-us": "a signed integral numeric value that is expressible in 1 byte" + }, + "id": "dtmi:dtdl:instance:Schema:byte;4", + "name": "byte" + }, { "description": { "en-us": "a finite numeric value that is expressible in IEEE 754 double-precision floating point format, conformant with xsd:double" @@ -26035,6 +26374,41 @@ }, "id": "dtmi:dtdl:instance:Schema:long;4", "name": "long" + }, + { + "description": { + "en-us": "a signed integral numeric value that is expressible in 2 bytes" + }, + "id": "dtmi:dtdl:instance:Schema:short;4", + "name": "short" + }, + { + "description": { + "en-us": "an unsigned integral numeric value that is expressible in 1 byte" + }, + "id": "dtmi:dtdl:instance:Schema:unsignedByte;4", + "name": "unsignedByte" + }, + { + "description": { + "en-us": "an unsigned integral numeric value that is expressible in 4 bytes" + }, + "id": "dtmi:dtdl:instance:Schema:unsignedInteger;4", + "name": "unsignedInteger" + }, + { + "description": { + "en-us": "an unsigned integral numeric value that is expressible in 8 bytes" + }, + "id": "dtmi:dtdl:instance:Schema:unsignedLong;4", + "name": "unsignedLong" + }, + { + "description": { + "en-us": "an unsigned integral numeric value that is expressible in 2 bytes" + }, + "id": "dtmi:dtdl:instance:Schema:unsignedShort;4", + "name": "unsignedShort" } ] }, @@ -26816,7 +27190,7 @@ "badTypeActionFormat": { "2": "Use one of these standard values for property '{property}'{line1}: boolean, date, dateTime, double, duration, float, integer, long, string, time.", "3": "Use one of these standard values for property '{property}'{line1}: boolean, date, dateTime, double, duration, float, integer, long, string, time.", - "4": "Use one of these standard values for property '{property}'{line1}: boolean, bytes, date, dateTime, double, duration, float, integer, long, string, time, uuid." + "4": "Use one of these standard values for property '{property}'{line1}: boolean, byte, bytes, date, dateTime, double, duration, float, integer, long, short, string, time, unsignedByte, unsignedInteger, unsignedLong, unsignedShort, uuid." }, "badTypeCauseFormat": { "2": "{layer}{primaryId:p} property '{property}' has value{secondaryId:e} that is not a standard value for this property.", @@ -26855,6 +27229,7 @@ ], "4": [ "Boolean", + "Byte", "Bytes", "Date", "DateTime", @@ -26863,8 +27238,13 @@ "Float", "Integer", "Long", + "Short", "String", "Time", + "UnsignedByte", + "UnsignedInteger", + "UnsignedLong", + "UnsignedShort", "Uuid" ] }, @@ -26900,6 +27280,7 @@ ], "4": [ "Boolean", + "Byte", "Bytes", "Date", "DateTime", @@ -26908,8 +27289,13 @@ "Float", "Integer", "Long", + "Short", "String", "Time", + "UnsignedByte", + "UnsignedInteger", + "UnsignedLong", + "UnsignedShort", "Uuid" ] }, @@ -27066,6 +27452,13 @@ "id": "dtmi:dtdl:instance:Schema:boolean;4", "name": "boolean" }, + { + "description": { + "en-us": "a signed integral numeric value that is expressible in 1 byte" + }, + "id": "dtmi:dtdl:instance:Schema:byte;4", + "name": "byte" + }, { "description": { "en-us": "an array of bytes" @@ -27122,6 +27515,13 @@ "id": "dtmi:dtdl:instance:Schema:long;4", "name": "long" }, + { + "description": { + "en-us": "a signed integral numeric value that is expressible in 2 bytes" + }, + "id": "dtmi:dtdl:instance:Schema:short;4", + "name": "short" + }, { "description": { "en-us": "a UTF8 string" @@ -27136,6 +27536,34 @@ "id": "dtmi:dtdl:instance:Schema:time;4", "name": "time" }, + { + "description": { + "en-us": "an unsigned integral numeric value that is expressible in 1 byte" + }, + "id": "dtmi:dtdl:instance:Schema:unsignedByte;4", + "name": "unsignedByte" + }, + { + "description": { + "en-us": "an unsigned integral numeric value that is expressible in 4 bytes" + }, + "id": "dtmi:dtdl:instance:Schema:unsignedInteger;4", + "name": "unsignedInteger" + }, + { + "description": { + "en-us": "an unsigned integral numeric value that is expressible in 8 bytes" + }, + "id": "dtmi:dtdl:instance:Schema:unsignedLong;4", + "name": "unsignedLong" + }, + { + "description": { + "en-us": "an unsigned integral numeric value that is expressible in 2 bytes" + }, + "id": "dtmi:dtdl:instance:Schema:unsignedShort;4", + "name": "unsignedShort" + }, { "description": { "en-us": "a UUID string per RFC 9562" @@ -28446,7 +28874,7 @@ "badTypeActionFormat": { "2": "Provide a @type{line3} in the set of allowable types, or provide a value for property '{property}'{line1} with @type in the set of allowable types, or use one of these standard values for property '{property}'{line1}: boolean, date, dateTime, double, duration, float, integer, long, string, time.", "3": "Provide a @type{line3} in the set of allowable types, or provide a value for property '{property}'{line1} with @type in the set of allowable types, or use one of these standard values for property '{property}'{line1}: boolean, date, dateTime, double, duration, float, integer, long, string, time.", - "4": "Provide a @type{line3} in the set of allowable types, or provide a value for property '{property}'{line1} with @type in the set of allowable types, or use one of these standard values for property '{property}'{line1}: boolean, bytes, date, dateTime, double, duration, float, integer, long, string, time, uuid." + "4": "Provide a @type{line3} in the set of allowable types, or provide a value for property '{property}'{line1} with @type in the set of allowable types, or use one of these standard values for property '{property}'{line1}: boolean, byte, bytes, date, dateTime, double, duration, float, integer, long, short, string, time, unsignedByte, unsignedInteger, unsignedLong, unsignedShort, uuid." }, "badTypeCauseFormat": { "2": "{layer}{primaryId:p} property '{property}' has value{secondaryId:e} that does not have @type of Array, Enum, Map, or Object, and it is not a standard value for this property.", @@ -28494,6 +28922,7 @@ "4": [ "Array", "Boolean", + "Byte", "Bytes", "Date", "DateTime", @@ -28505,8 +28934,13 @@ "Long", "Map", "Object", + "Short", "String", "Time", + "UnsignedByte", + "UnsignedInteger", + "UnsignedLong", + "UnsignedShort", "Uuid" ] }, @@ -28542,6 +28976,7 @@ ], "4": [ "Boolean", + "Byte", "Bytes", "Date", "DateTime", @@ -28550,8 +28985,13 @@ "Float", "Integer", "Long", + "Short", "String", "Time", + "UnsignedByte", + "UnsignedInteger", + "UnsignedLong", + "UnsignedShort", "Uuid" ] }, @@ -28806,6 +29246,13 @@ "id": "dtmi:dtdl:instance:Schema:boolean;4", "name": "boolean" }, + { + "description": { + "en-us": "a signed integral numeric value that is expressible in 1 byte" + }, + "id": "dtmi:dtdl:instance:Schema:byte;4", + "name": "byte" + }, { "description": { "en-us": "an array of bytes" @@ -28862,6 +29309,13 @@ "id": "dtmi:dtdl:instance:Schema:long;4", "name": "long" }, + { + "description": { + "en-us": "a signed integral numeric value that is expressible in 2 bytes" + }, + "id": "dtmi:dtdl:instance:Schema:short;4", + "name": "short" + }, { "description": { "en-us": "a UTF8 string" @@ -28876,6 +29330,34 @@ "id": "dtmi:dtdl:instance:Schema:time;4", "name": "time" }, + { + "description": { + "en-us": "an unsigned integral numeric value that is expressible in 1 byte" + }, + "id": "dtmi:dtdl:instance:Schema:unsignedByte;4", + "name": "unsignedByte" + }, + { + "description": { + "en-us": "an unsigned integral numeric value that is expressible in 4 bytes" + }, + "id": "dtmi:dtdl:instance:Schema:unsignedInteger;4", + "name": "unsignedInteger" + }, + { + "description": { + "en-us": "an unsigned integral numeric value that is expressible in 8 bytes" + }, + "id": "dtmi:dtdl:instance:Schema:unsignedLong;4", + "name": "unsignedLong" + }, + { + "description": { + "en-us": "an unsigned integral numeric value that is expressible in 2 bytes" + }, + "id": "dtmi:dtdl:instance:Schema:unsignedShort;4", + "name": "unsignedShort" + }, { "description": { "en-us": "a UUID string per RFC 9562" @@ -29549,115 +30031,68 @@ ], "typeOptionalVersions": [] }, - "String": { + "Short": { "abstract": false, "badTypeActionFormat": { - "2": "Use this standard value for property '{property}'{line1}: string.", - "3": "Use this standard value for property '{property}'{line1}: string.", - "4": "Use this standard value for property '{property}'{line1}: string." + "4": "Use this standard value for property '{property}'{line1}: short." }, "badTypeCauseFormat": { - "2": "{layer}{primaryId:p} property '{property}' has value{secondaryId:e} that is not a standard value for this property.", - "3": "{layer}{primaryId:p} property '{property}' has value{secondaryId:e} that is not a standard value for this property.", "4": "{layer}{primaryId:p} property '{property}' has value{secondaryId:e} that is not a standard value for this property." }, "badTypeLocatedCauseFormat": { - "2": "In {sourceName1}, property '{property}'{line1} has value{secondaryId:e}{line2} that is not a standard value for this property.", - "3": "In {sourceName1}, property '{property}'{line1} has value{secondaryId:e}{line2} that is not a standard value for this property.", "4": "In {sourceName1}, property '{property}'{line1} has value{secondaryId:e}{line2} that is not a standard value for this property." }, "concreteSubclasses": { - "2": [ - "String" - ], - "3": [ - "String" - ], "4": [ - "String" + "Short" ] }, "dtdlVersions": [ - 2, - 3, 4 ], "elementalSubclasses": { - "2": [ - "String" - ], - "3": [ - "String" - ], "4": [ - "String" + "Short" ] }, "elements": { - "2": [ - { - "description": { - "en-us": "a UTF8 string" - }, - "id": "dtmi:dtdl:instance:Schema:string;2", - "name": "string" - } - ], - "3": [ - { - "description": { - "en-us": "a UTF8 string" - }, - "id": "dtmi:dtdl:instance:Schema:string;3", - "name": "string" - } - ], "4": [ { "description": { - "en-us": "a UTF8 string" + "en-us": "a signed integral numeric value that is expressible in 2 bytes" }, - "id": "dtmi:dtdl:instance:Schema:string;4", - "name": "string" + "id": "dtmi:dtdl:instance:Schema:short;4", + "name": "short" } ] }, "extensibleMaterialSubclasses": { - "2": [], - "3": [], "4": [] }, - "idRequiredVersions": [ - 2, - 3, - 4 - ], - "idRequiredWhen": {}, - "instance": { - "2": { - "eachChild": {}, - "element": { - "jsonType": "string" - } - }, - "3": { - "eachChild": {}, - "element": { - "jsonType": "string" + "idRequiredVersions": [], + "idRequiredWhen": { + "4": [ + { + "class": "Enum", + "property": "valueSchema" } - }, + ] + }, + "instance": { "4": { "eachChild": {}, "element": { - "jsonType": "string" + "datatype": "short", + "jsonType": "number" } }, - "criteriaText": "is a string value", - "typeText": "a string value" + "conformanceText": "the XSD definition of 'short'", + "criteriaText": "is a numeric value that conforms to the XSD definition of 'short'", + "typeText": "a numeric value" }, "maybePartial": false, "overt": true, - "parentClass": "PrimitiveSchema", + "parentClass": "NumericSchema", "partition": false, "properties": { "comment": { @@ -29674,30 +30109,6 @@ "plural": false, "shadowed": false }, - "2": { - "allowed": true, - "deprecated": false, - "hidden": false, - "idRequired": false, - "maxCount": 1, - "maxLength": { - "": 512 - }, - "typeRequired": true, - "uniqueAmong": [] - }, - "3": { - "allowed": true, - "deprecated": false, - "hidden": false, - "idRequired": false, - "maxCount": 1, - "maxLength": { - "": 512 - }, - "typeRequired": true, - "uniqueAmong": [] - }, "4": { "allowed": true, "deprecated": false, @@ -29726,30 +30137,6 @@ "plural": true, "shadowed": false }, - "2": { - "allowed": true, - "defaultLanguage": "en", - "deprecated": false, - "hidden": false, - "idRequired": false, - "maxLength": { - "": 512 - }, - "typeRequired": true, - "uniqueAmong": [] - }, - "3": { - "allowed": true, - "defaultLanguage": "en", - "deprecated": false, - "hidden": false, - "idRequired": false, - "maxLength": { - "": 512 - }, - "typeRequired": true, - "uniqueAmong": [] - }, "4": { "allowed": true, "defaultLanguage": "en", @@ -29778,30 +30165,6 @@ "plural": true, "shadowed": false }, - "2": { - "allowed": true, - "defaultLanguage": "en", - "deprecated": false, - "hidden": false, - "idRequired": false, - "maxLength": { - "": 64 - }, - "typeRequired": true, - "uniqueAmong": [] - }, - "3": { - "allowed": true, - "defaultLanguage": "en", - "deprecated": false, - "hidden": false, - "idRequired": false, - "maxLength": { - "": 512 - }, - "typeRequired": true, - "uniqueAmong": [] - }, "4": { "allowed": true, "defaultLanguage": "en", @@ -29830,24 +30193,6 @@ "plural": false, "shadowed": false }, - "2": { - "allowed": false, - "deprecated": false, - "hidden": false, - "idRequired": false, - "typeRequired": true, - "uniqueAmong": [], - "value": 2 - }, - "3": { - "allowed": false, - "deprecated": false, - "hidden": false, - "idRequired": false, - "typeRequired": true, - "uniqueAmong": [], - "value": 3 - }, "4": { "allowed": false, "deprecated": false, @@ -29861,50 +30206,45 @@ }, "rootable": false, "standardElementIds": { - "2": [ - "dtmi:dtdl:instance:Schema:string;2" - ], - "3": [ - "dtmi:dtdl:instance:Schema:string;3" - ], "4": [ - "dtmi:dtdl:instance:Schema:string;4" + "dtmi:dtdl:instance:Schema:short;4" ] }, "typeIds": [ "dtmi:dtdl:class:Entity", + "dtmi:dtdl:class:NumericSchema", "dtmi:dtdl:class:PrimitiveSchema", "dtmi:dtdl:class:Schema", - "dtmi:dtdl:class:String" + "dtmi:dtdl:class:Short" ], "typeOptionalVersions": [] }, - "Telemetry": { + "String": { "abstract": false, "badTypeActionFormat": { - "2": "Provide a @type{line3} of Telemetry, or provide a value for property '{property}'{line1} with @type of Telemetry.", - "3": "Provide a @type{line3} of Telemetry, or provide a value for property '{property}'{line1} with @type of Telemetry.", - "4": "Provide a @type{line3} of Telemetry, or provide a value for property '{property}'{line1} with @type of Telemetry." + "2": "Use this standard value for property '{property}'{line1}: string.", + "3": "Use this standard value for property '{property}'{line1}: string.", + "4": "Use this standard value for property '{property}'{line1}: string." }, "badTypeCauseFormat": { - "2": "{layer}{primaryId:p} property '{property}' has value{secondaryId:e} that does not have @type of Telemetry.", - "3": "{layer}{primaryId:p} property '{property}' has value{secondaryId:e} that does not have @type of Telemetry.", - "4": "{layer}{primaryId:p} property '{property}' has value{secondaryId:e} that does not have @type of Telemetry." + "2": "{layer}{primaryId:p} property '{property}' has value{secondaryId:e} that is not a standard value for this property.", + "3": "{layer}{primaryId:p} property '{property}' has value{secondaryId:e} that is not a standard value for this property.", + "4": "{layer}{primaryId:p} property '{property}' has value{secondaryId:e} that is not a standard value for this property." }, "badTypeLocatedCauseFormat": { - "2": "In {sourceName1}, property '{property}'{line1} has value{secondaryId:e}{line2} that does not have @type of Telemetry.", - "3": "In {sourceName1}, property '{property}'{line1} has value{secondaryId:e}{line2} that does not have @type of Telemetry.", - "4": "In {sourceName1}, property '{property}'{line1} has value{secondaryId:e}{line2} that does not have @type of Telemetry." + "2": "In {sourceName1}, property '{property}'{line1} has value{secondaryId:e}{line2} that is not a standard value for this property.", + "3": "In {sourceName1}, property '{property}'{line1} has value{secondaryId:e}{line2} that is not a standard value for this property.", + "4": "In {sourceName1}, property '{property}'{line1} has value{secondaryId:e}{line2} that is not a standard value for this property." }, "concreteSubclasses": { "2": [ - "Telemetry" + "String" ], "3": [ - "Telemetry" + "String" ], "4": [ - "Telemetry" + "String" ] }, "dtdlVersions": [ @@ -29913,29 +30253,359 @@ 4 ], "elementalSubclasses": { - "2": [], - "3": [], - "4": [] + "2": [ + "String" + ], + "3": [ + "String" + ], + "4": [ + "String" + ] }, "elements": { - "2": [], - "3": [], - "4": [] + "2": [ + { + "description": { + "en-us": "a UTF8 string" + }, + "id": "dtmi:dtdl:instance:Schema:string;2", + "name": "string" + } + ], + "3": [ + { + "description": { + "en-us": "a UTF8 string" + }, + "id": "dtmi:dtdl:instance:Schema:string;3", + "name": "string" + } + ], + "4": [ + { + "description": { + "en-us": "a UTF8 string" + }, + "id": "dtmi:dtdl:instance:Schema:string;4", + "name": "string" + } + ] }, "extensibleMaterialSubclasses": { "2": [], "3": [], "4": [] }, - "idRequiredVersions": [], - "idRequiredWhen": { - "2": [], - "3": [], - "4": [] + "idRequiredVersions": [ + 2, + 3, + 4 + ], + "idRequiredWhen": {}, + "instance": { + "2": { + "eachChild": {}, + "element": { + "jsonType": "string" + } + }, + "3": { + "eachChild": {}, + "element": { + "jsonType": "string" + } + }, + "4": { + "eachChild": {}, + "element": { + "jsonType": "string" + } + }, + "criteriaText": "is a string value", + "typeText": "a string value" }, "maybePartial": false, "overt": true, - "parentClass": "Content", + "parentClass": "PrimitiveSchema", + "partition": false, + "properties": { + "comment": { + "_": { + "abstract": false, + "datatype": "string", + "description": { + "en-us": "A comment for model authors." + }, + "inherited": true, + "inheritedFrom": "Entity", + "literal": true, + "optional": true, + "plural": false, + "shadowed": false + }, + "2": { + "allowed": true, + "deprecated": false, + "hidden": false, + "idRequired": false, + "maxCount": 1, + "maxLength": { + "": 512 + }, + "typeRequired": true, + "uniqueAmong": [] + }, + "3": { + "allowed": true, + "deprecated": false, + "hidden": false, + "idRequired": false, + "maxCount": 1, + "maxLength": { + "": 512 + }, + "typeRequired": true, + "uniqueAmong": [] + }, + "4": { + "allowed": true, + "deprecated": false, + "hidden": false, + "idRequired": false, + "maxCount": 1, + "maxLength": { + "": 512, + "onvif_1": 515 + }, + "typeRequired": true, + "uniqueAmong": [] + } + }, + "description": { + "_": { + "abstract": false, + "datatype": "langString", + "description": { + "en-us": "A localizable description for display." + }, + "inherited": true, + "inheritedFrom": "Entity", + "literal": true, + "optional": true, + "plural": true, + "shadowed": false + }, + "2": { + "allowed": true, + "defaultLanguage": "en", + "deprecated": false, + "hidden": false, + "idRequired": false, + "maxLength": { + "": 512 + }, + "typeRequired": true, + "uniqueAmong": [] + }, + "3": { + "allowed": true, + "defaultLanguage": "en", + "deprecated": false, + "hidden": false, + "idRequired": false, + "maxLength": { + "": 512 + }, + "typeRequired": true, + "uniqueAmong": [] + }, + "4": { + "allowed": true, + "defaultLanguage": "en", + "deprecated": false, + "hidden": false, + "idRequired": false, + "maxLength": { + "": 512, + "onvif_1": 514 + }, + "typeRequired": true, + "uniqueAmong": [] + } + }, + "displayName": { + "_": { + "abstract": false, + "datatype": "langString", + "description": { + "en-us": "A localizable name for display." + }, + "inherited": true, + "inheritedFrom": "Entity", + "literal": true, + "optional": true, + "plural": true, + "shadowed": false + }, + "2": { + "allowed": true, + "defaultLanguage": "en", + "deprecated": false, + "hidden": false, + "idRequired": false, + "maxLength": { + "": 64 + }, + "typeRequired": true, + "uniqueAmong": [] + }, + "3": { + "allowed": true, + "defaultLanguage": "en", + "deprecated": false, + "hidden": false, + "idRequired": false, + "maxLength": { + "": 512 + }, + "typeRequired": true, + "uniqueAmong": [] + }, + "4": { + "allowed": true, + "defaultLanguage": "en", + "deprecated": false, + "hidden": false, + "idRequired": false, + "maxLength": { + "": 512, + "onvif_1": 513 + }, + "typeRequired": true, + "uniqueAmong": [] + } + }, + "languageMajorVersion": { + "_": { + "abstract": false, + "datatype": "integer", + "description": { + "en-us": "The major version of DTDL used to author this element." + }, + "inherited": true, + "inheritedFrom": "Entity", + "literal": true, + "optional": false, + "plural": false, + "shadowed": false + }, + "2": { + "allowed": false, + "deprecated": false, + "hidden": false, + "idRequired": false, + "typeRequired": true, + "uniqueAmong": [], + "value": 2 + }, + "3": { + "allowed": false, + "deprecated": false, + "hidden": false, + "idRequired": false, + "typeRequired": true, + "uniqueAmong": [], + "value": 3 + }, + "4": { + "allowed": false, + "deprecated": false, + "hidden": false, + "idRequired": false, + "typeRequired": true, + "uniqueAmong": [], + "value": 4 + } + } + }, + "rootable": false, + "standardElementIds": { + "2": [ + "dtmi:dtdl:instance:Schema:string;2" + ], + "3": [ + "dtmi:dtdl:instance:Schema:string;3" + ], + "4": [ + "dtmi:dtdl:instance:Schema:string;4" + ] + }, + "typeIds": [ + "dtmi:dtdl:class:Entity", + "dtmi:dtdl:class:PrimitiveSchema", + "dtmi:dtdl:class:Schema", + "dtmi:dtdl:class:String" + ], + "typeOptionalVersions": [] + }, + "Telemetry": { + "abstract": false, + "badTypeActionFormat": { + "2": "Provide a @type{line3} of Telemetry, or provide a value for property '{property}'{line1} with @type of Telemetry.", + "3": "Provide a @type{line3} of Telemetry, or provide a value for property '{property}'{line1} with @type of Telemetry.", + "4": "Provide a @type{line3} of Telemetry, or provide a value for property '{property}'{line1} with @type of Telemetry." + }, + "badTypeCauseFormat": { + "2": "{layer}{primaryId:p} property '{property}' has value{secondaryId:e} that does not have @type of Telemetry.", + "3": "{layer}{primaryId:p} property '{property}' has value{secondaryId:e} that does not have @type of Telemetry.", + "4": "{layer}{primaryId:p} property '{property}' has value{secondaryId:e} that does not have @type of Telemetry." + }, + "badTypeLocatedCauseFormat": { + "2": "In {sourceName1}, property '{property}'{line1} has value{secondaryId:e}{line2} that does not have @type of Telemetry.", + "3": "In {sourceName1}, property '{property}'{line1} has value{secondaryId:e}{line2} that does not have @type of Telemetry.", + "4": "In {sourceName1}, property '{property}'{line1} has value{secondaryId:e}{line2} that does not have @type of Telemetry." + }, + "concreteSubclasses": { + "2": [ + "Telemetry" + ], + "3": [ + "Telemetry" + ], + "4": [ + "Telemetry" + ] + }, + "dtdlVersions": [ + 2, + 3, + 4 + ], + "elementalSubclasses": { + "2": [], + "3": [], + "4": [] + }, + "elements": { + "2": [], + "3": [], + "4": [] + }, + "extensibleMaterialSubclasses": { + "2": [], + "3": [], + "4": [] + }, + "idRequiredVersions": [], + "idRequiredWhen": { + "2": [], + "3": [], + "4": [] + }, + "maybePartial": false, + "overt": true, + "parentClass": "Content", "partition": false, "properties": { "comment": { @@ -31696,6 +32366,762 @@ ], "typeOptionalVersions": [] }, + "UnsignedByte": { + "abstract": false, + "badTypeActionFormat": { + "4": "Use this standard value for property '{property}'{line1}: unsignedByte." + }, + "badTypeCauseFormat": { + "4": "{layer}{primaryId:p} property '{property}' has value{secondaryId:e} that is not a standard value for this property." + }, + "badTypeLocatedCauseFormat": { + "4": "In {sourceName1}, property '{property}'{line1} has value{secondaryId:e}{line2} that is not a standard value for this property." + }, + "concreteSubclasses": { + "4": [ + "UnsignedByte" + ] + }, + "dtdlVersions": [ + 4 + ], + "elementalSubclasses": { + "4": [ + "UnsignedByte" + ] + }, + "elements": { + "4": [ + { + "description": { + "en-us": "an unsigned integral numeric value that is expressible in 1 byte" + }, + "id": "dtmi:dtdl:instance:Schema:unsignedByte;4", + "name": "unsignedByte" + } + ] + }, + "extensibleMaterialSubclasses": { + "4": [] + }, + "idRequiredVersions": [], + "idRequiredWhen": { + "4": [ + { + "class": "Enum", + "property": "valueSchema" + } + ] + }, + "instance": { + "4": { + "eachChild": {}, + "element": { + "datatype": "unsignedByte", + "jsonType": "number", + "pattern": "^[0-9]+$" + } + }, + "conformanceText": "the XSD definition of 'unsignedByte'", + "criteriaText": "is a numeric value that conforms to the XSD definition of 'unsignedByte'", + "typeText": "a numeric value" + }, + "maybePartial": false, + "overt": true, + "parentClass": "NumericSchema", + "partition": false, + "properties": { + "comment": { + "_": { + "abstract": false, + "datatype": "string", + "description": { + "en-us": "A comment for model authors." + }, + "inherited": true, + "inheritedFrom": "Entity", + "literal": true, + "optional": true, + "plural": false, + "shadowed": false + }, + "4": { + "allowed": true, + "deprecated": false, + "hidden": false, + "idRequired": false, + "maxCount": 1, + "maxLength": { + "": 512, + "onvif_1": 515 + }, + "typeRequired": true, + "uniqueAmong": [] + } + }, + "description": { + "_": { + "abstract": false, + "datatype": "langString", + "description": { + "en-us": "A localizable description for display." + }, + "inherited": true, + "inheritedFrom": "Entity", + "literal": true, + "optional": true, + "plural": true, + "shadowed": false + }, + "4": { + "allowed": true, + "defaultLanguage": "en", + "deprecated": false, + "hidden": false, + "idRequired": false, + "maxLength": { + "": 512, + "onvif_1": 514 + }, + "typeRequired": true, + "uniqueAmong": [] + } + }, + "displayName": { + "_": { + "abstract": false, + "datatype": "langString", + "description": { + "en-us": "A localizable name for display." + }, + "inherited": true, + "inheritedFrom": "Entity", + "literal": true, + "optional": true, + "plural": true, + "shadowed": false + }, + "4": { + "allowed": true, + "defaultLanguage": "en", + "deprecated": false, + "hidden": false, + "idRequired": false, + "maxLength": { + "": 512, + "onvif_1": 513 + }, + "typeRequired": true, + "uniqueAmong": [] + } + }, + "languageMajorVersion": { + "_": { + "abstract": false, + "datatype": "integer", + "description": { + "en-us": "The major version of DTDL used to author this element." + }, + "inherited": true, + "inheritedFrom": "Entity", + "literal": true, + "optional": false, + "plural": false, + "shadowed": false + }, + "4": { + "allowed": false, + "deprecated": false, + "hidden": false, + "idRequired": false, + "typeRequired": true, + "uniqueAmong": [], + "value": 4 + } + } + }, + "rootable": false, + "standardElementIds": { + "4": [ + "dtmi:dtdl:instance:Schema:unsignedByte;4" + ] + }, + "typeIds": [ + "dtmi:dtdl:class:Entity", + "dtmi:dtdl:class:NumericSchema", + "dtmi:dtdl:class:PrimitiveSchema", + "dtmi:dtdl:class:Schema", + "dtmi:dtdl:class:UnsignedByte" + ], + "typeOptionalVersions": [] + }, + "UnsignedInteger": { + "abstract": false, + "badTypeActionFormat": { + "4": "Use this standard value for property '{property}'{line1}: unsignedInteger." + }, + "badTypeCauseFormat": { + "4": "{layer}{primaryId:p} property '{property}' has value{secondaryId:e} that is not a standard value for this property." + }, + "badTypeLocatedCauseFormat": { + "4": "In {sourceName1}, property '{property}'{line1} has value{secondaryId:e}{line2} that is not a standard value for this property." + }, + "concreteSubclasses": { + "4": [ + "UnsignedInteger" + ] + }, + "dtdlVersions": [ + 4 + ], + "elementalSubclasses": { + "4": [ + "UnsignedInteger" + ] + }, + "elements": { + "4": [ + { + "description": { + "en-us": "an unsigned integral numeric value that is expressible in 4 bytes" + }, + "id": "dtmi:dtdl:instance:Schema:unsignedInteger;4", + "name": "unsignedInteger" + } + ] + }, + "extensibleMaterialSubclasses": { + "4": [] + }, + "idRequiredVersions": [], + "idRequiredWhen": { + "4": [ + { + "class": "Enum", + "property": "valueSchema" + } + ] + }, + "instance": { + "4": { + "eachChild": {}, + "element": { + "datatype": "unsignedInt", + "jsonType": "number", + "pattern": "^[0-9]+$" + } + }, + "conformanceText": "the XSD definition of 'unsignedInt'", + "criteriaText": "is a numeric value that conforms to the XSD definition of 'unsignedInt'", + "typeText": "a numeric value" + }, + "maybePartial": false, + "overt": true, + "parentClass": "NumericSchema", + "partition": false, + "properties": { + "comment": { + "_": { + "abstract": false, + "datatype": "string", + "description": { + "en-us": "A comment for model authors." + }, + "inherited": true, + "inheritedFrom": "Entity", + "literal": true, + "optional": true, + "plural": false, + "shadowed": false + }, + "4": { + "allowed": true, + "deprecated": false, + "hidden": false, + "idRequired": false, + "maxCount": 1, + "maxLength": { + "": 512, + "onvif_1": 515 + }, + "typeRequired": true, + "uniqueAmong": [] + } + }, + "description": { + "_": { + "abstract": false, + "datatype": "langString", + "description": { + "en-us": "A localizable description for display." + }, + "inherited": true, + "inheritedFrom": "Entity", + "literal": true, + "optional": true, + "plural": true, + "shadowed": false + }, + "4": { + "allowed": true, + "defaultLanguage": "en", + "deprecated": false, + "hidden": false, + "idRequired": false, + "maxLength": { + "": 512, + "onvif_1": 514 + }, + "typeRequired": true, + "uniqueAmong": [] + } + }, + "displayName": { + "_": { + "abstract": false, + "datatype": "langString", + "description": { + "en-us": "A localizable name for display." + }, + "inherited": true, + "inheritedFrom": "Entity", + "literal": true, + "optional": true, + "plural": true, + "shadowed": false + }, + "4": { + "allowed": true, + "defaultLanguage": "en", + "deprecated": false, + "hidden": false, + "idRequired": false, + "maxLength": { + "": 512, + "onvif_1": 513 + }, + "typeRequired": true, + "uniqueAmong": [] + } + }, + "languageMajorVersion": { + "_": { + "abstract": false, + "datatype": "integer", + "description": { + "en-us": "The major version of DTDL used to author this element." + }, + "inherited": true, + "inheritedFrom": "Entity", + "literal": true, + "optional": false, + "plural": false, + "shadowed": false + }, + "4": { + "allowed": false, + "deprecated": false, + "hidden": false, + "idRequired": false, + "typeRequired": true, + "uniqueAmong": [], + "value": 4 + } + } + }, + "rootable": false, + "standardElementIds": { + "4": [ + "dtmi:dtdl:instance:Schema:unsignedInteger;4" + ] + }, + "typeIds": [ + "dtmi:dtdl:class:Entity", + "dtmi:dtdl:class:NumericSchema", + "dtmi:dtdl:class:PrimitiveSchema", + "dtmi:dtdl:class:Schema", + "dtmi:dtdl:class:UnsignedInteger" + ], + "typeOptionalVersions": [] + }, + "UnsignedLong": { + "abstract": false, + "badTypeActionFormat": { + "4": "Use this standard value for property '{property}'{line1}: unsignedLong." + }, + "badTypeCauseFormat": { + "4": "{layer}{primaryId:p} property '{property}' has value{secondaryId:e} that is not a standard value for this property." + }, + "badTypeLocatedCauseFormat": { + "4": "In {sourceName1}, property '{property}'{line1} has value{secondaryId:e}{line2} that is not a standard value for this property." + }, + "concreteSubclasses": { + "4": [ + "UnsignedLong" + ] + }, + "dtdlVersions": [ + 4 + ], + "elementalSubclasses": { + "4": [ + "UnsignedLong" + ] + }, + "elements": { + "4": [ + { + "description": { + "en-us": "an unsigned integral numeric value that is expressible in 8 bytes" + }, + "id": "dtmi:dtdl:instance:Schema:unsignedLong;4", + "name": "unsignedLong" + } + ] + }, + "extensibleMaterialSubclasses": { + "4": [] + }, + "idRequiredVersions": [], + "idRequiredWhen": { + "4": [ + { + "class": "Enum", + "property": "valueSchema" + } + ] + }, + "instance": { + "4": { + "eachChild": {}, + "element": { + "datatype": "unsignedLong", + "jsonType": "number", + "pattern": "^[0-9]+$" + } + }, + "conformanceText": "the XSD definition of 'unsignedLong'", + "criteriaText": "is a numeric value that conforms to the XSD definition of 'unsignedLong'", + "typeText": "a numeric value" + }, + "maybePartial": false, + "overt": true, + "parentClass": "NumericSchema", + "partition": false, + "properties": { + "comment": { + "_": { + "abstract": false, + "datatype": "string", + "description": { + "en-us": "A comment for model authors." + }, + "inherited": true, + "inheritedFrom": "Entity", + "literal": true, + "optional": true, + "plural": false, + "shadowed": false + }, + "4": { + "allowed": true, + "deprecated": false, + "hidden": false, + "idRequired": false, + "maxCount": 1, + "maxLength": { + "": 512, + "onvif_1": 515 + }, + "typeRequired": true, + "uniqueAmong": [] + } + }, + "description": { + "_": { + "abstract": false, + "datatype": "langString", + "description": { + "en-us": "A localizable description for display." + }, + "inherited": true, + "inheritedFrom": "Entity", + "literal": true, + "optional": true, + "plural": true, + "shadowed": false + }, + "4": { + "allowed": true, + "defaultLanguage": "en", + "deprecated": false, + "hidden": false, + "idRequired": false, + "maxLength": { + "": 512, + "onvif_1": 514 + }, + "typeRequired": true, + "uniqueAmong": [] + } + }, + "displayName": { + "_": { + "abstract": false, + "datatype": "langString", + "description": { + "en-us": "A localizable name for display." + }, + "inherited": true, + "inheritedFrom": "Entity", + "literal": true, + "optional": true, + "plural": true, + "shadowed": false + }, + "4": { + "allowed": true, + "defaultLanguage": "en", + "deprecated": false, + "hidden": false, + "idRequired": false, + "maxLength": { + "": 512, + "onvif_1": 513 + }, + "typeRequired": true, + "uniqueAmong": [] + } + }, + "languageMajorVersion": { + "_": { + "abstract": false, + "datatype": "integer", + "description": { + "en-us": "The major version of DTDL used to author this element." + }, + "inherited": true, + "inheritedFrom": "Entity", + "literal": true, + "optional": false, + "plural": false, + "shadowed": false + }, + "4": { + "allowed": false, + "deprecated": false, + "hidden": false, + "idRequired": false, + "typeRequired": true, + "uniqueAmong": [], + "value": 4 + } + } + }, + "rootable": false, + "standardElementIds": { + "4": [ + "dtmi:dtdl:instance:Schema:unsignedLong;4" + ] + }, + "typeIds": [ + "dtmi:dtdl:class:Entity", + "dtmi:dtdl:class:NumericSchema", + "dtmi:dtdl:class:PrimitiveSchema", + "dtmi:dtdl:class:Schema", + "dtmi:dtdl:class:UnsignedLong" + ], + "typeOptionalVersions": [] + }, + "UnsignedShort": { + "abstract": false, + "badTypeActionFormat": { + "4": "Use this standard value for property '{property}'{line1}: unsignedShort." + }, + "badTypeCauseFormat": { + "4": "{layer}{primaryId:p} property '{property}' has value{secondaryId:e} that is not a standard value for this property." + }, + "badTypeLocatedCauseFormat": { + "4": "In {sourceName1}, property '{property}'{line1} has value{secondaryId:e}{line2} that is not a standard value for this property." + }, + "concreteSubclasses": { + "4": [ + "UnsignedShort" + ] + }, + "dtdlVersions": [ + 4 + ], + "elementalSubclasses": { + "4": [ + "UnsignedShort" + ] + }, + "elements": { + "4": [ + { + "description": { + "en-us": "an unsigned integral numeric value that is expressible in 2 bytes" + }, + "id": "dtmi:dtdl:instance:Schema:unsignedShort;4", + "name": "unsignedShort" + } + ] + }, + "extensibleMaterialSubclasses": { + "4": [] + }, + "idRequiredVersions": [], + "idRequiredWhen": { + "4": [ + { + "class": "Enum", + "property": "valueSchema" + } + ] + }, + "instance": { + "4": { + "eachChild": {}, + "element": { + "datatype": "unsignedShort", + "jsonType": "number", + "pattern": "^[0-9]+$" + } + }, + "conformanceText": "the XSD definition of 'unsignedShort'", + "criteriaText": "is a numeric value that conforms to the XSD definition of 'unsignedShort'", + "typeText": "a numeric value" + }, + "maybePartial": false, + "overt": true, + "parentClass": "NumericSchema", + "partition": false, + "properties": { + "comment": { + "_": { + "abstract": false, + "datatype": "string", + "description": { + "en-us": "A comment for model authors." + }, + "inherited": true, + "inheritedFrom": "Entity", + "literal": true, + "optional": true, + "plural": false, + "shadowed": false + }, + "4": { + "allowed": true, + "deprecated": false, + "hidden": false, + "idRequired": false, + "maxCount": 1, + "maxLength": { + "": 512, + "onvif_1": 515 + }, + "typeRequired": true, + "uniqueAmong": [] + } + }, + "description": { + "_": { + "abstract": false, + "datatype": "langString", + "description": { + "en-us": "A localizable description for display." + }, + "inherited": true, + "inheritedFrom": "Entity", + "literal": true, + "optional": true, + "plural": true, + "shadowed": false + }, + "4": { + "allowed": true, + "defaultLanguage": "en", + "deprecated": false, + "hidden": false, + "idRequired": false, + "maxLength": { + "": 512, + "onvif_1": 514 + }, + "typeRequired": true, + "uniqueAmong": [] + } + }, + "displayName": { + "_": { + "abstract": false, + "datatype": "langString", + "description": { + "en-us": "A localizable name for display." + }, + "inherited": true, + "inheritedFrom": "Entity", + "literal": true, + "optional": true, + "plural": true, + "shadowed": false + }, + "4": { + "allowed": true, + "defaultLanguage": "en", + "deprecated": false, + "hidden": false, + "idRequired": false, + "maxLength": { + "": 512, + "onvif_1": 513 + }, + "typeRequired": true, + "uniqueAmong": [] + } + }, + "languageMajorVersion": { + "_": { + "abstract": false, + "datatype": "integer", + "description": { + "en-us": "The major version of DTDL used to author this element." + }, + "inherited": true, + "inheritedFrom": "Entity", + "literal": true, + "optional": false, + "plural": false, + "shadowed": false + }, + "4": { + "allowed": false, + "deprecated": false, + "hidden": false, + "idRequired": false, + "typeRequired": true, + "uniqueAmong": [], + "value": 4 + } + } + }, + "rootable": false, + "standardElementIds": { + "4": [ + "dtmi:dtdl:instance:Schema:unsignedShort;4" + ] + }, + "typeIds": [ + "dtmi:dtdl:class:Entity", + "dtmi:dtdl:class:NumericSchema", + "dtmi:dtdl:class:PrimitiveSchema", + "dtmi:dtdl:class:Schema", + "dtmi:dtdl:class:UnsignedShort" + ], + "typeOptionalVersions": [] + }, "Uuid": { "abstract": false, "badTypeActionFormat": { @@ -32139,6 +33565,7 @@ "cotypes": [ "Array", "Boolean", + "Byte", "Bytes", "Command", "CommandPayload", @@ -32165,11 +33592,16 @@ "Object", "Property", "Relationship", + "Short", "String", "Telemetry", "Time", "Unit", "UnitAttribute", + "UnsignedByte", + "UnsignedInteger", + "UnsignedLong", + "UnsignedShort", "Uuid" ], "cotypeVersions": [ @@ -32253,6 +33685,7 @@ "cotypes": [ "Array", "Boolean", + "Byte", "Bytes", "Command", "CommandRequest", @@ -32278,11 +33711,16 @@ "Object", "Property", "Relationship", + "Short", "String", "Telemetry", "Time", "Unit", "UnitAttribute", + "UnsignedByte", + "UnsignedInteger", + "UnsignedLong", + "UnsignedShort", "Uuid" ], "cotypeVersions": [ @@ -35699,6 +37137,7 @@ "cotypes": [ "Array", "Boolean", + "Byte", "Bytes", "Command", "CommandPayload", @@ -35725,11 +37164,16 @@ "Object", "Property", "Relationship", + "Short", "String", "Telemetry", "Time", "Unit", "UnitAttribute", + "UnsignedByte", + "UnsignedInteger", + "UnsignedLong", + "UnsignedShort", "Uuid" ], "cotypeVersions": [ diff --git a/images/generated/DevelopFlowDiagram.svg b/images/generated/DevelopFlowDiagram.svg index d4750dc7..aee41602 100644 --- a/images/generated/DevelopFlowDiagram.svg +++ b/images/generated/DevelopFlowDiagram.svg @@ -1,7 +1,7 @@ - - -