private static RelativePathElement ParsePathElement()

in src/Azure.IIoT.OpcUa.Publisher/src/Stack/Extensions/RelativePathEx.cs [68:181]


        private static RelativePathElement ParsePathElement(string element,
            IServiceMessageContext context)
        {
            if (string.IsNullOrEmpty(element))
            {
                throw new ArgumentNullException(nameof(element));
            }

            var pathElement = new RelativePathElement
            {
                IncludeSubtypes = true,
                IsInverse = false
            };
            //
            // Parse relative path reference information
            // This should allow
            // - "targeturi" == "/targeturi"
            // - ".targeturi"
            // - "!.parenturi"
            // - "!/parenturi"
            // - "<!#uri>parenturi"
            //
            var index = 0;
            var exit = false;
            var parseReference = false;
            while (index < element.Length && !exit)
            {
                switch (element[index])
                {
                    case '<':
                        if (pathElement.ReferenceTypeId == null)
                        {
                            parseReference = true;
                            break;
                        }
                        throw new FormatException("Reference type set.");
                    case '!':
                        pathElement.IsInverse = true;
                        break;
                    case '#':
                        pathElement.IncludeSubtypes = false;
                        break;
                    case '/':
                        if (pathElement.ReferenceTypeId == null &&
                            !parseReference)
                        {
                            pathElement.ReferenceTypeId =
                                ReferenceTypeIds.HierarchicalReferences;
                            break;
                        }
                        throw new FormatException("Reference type set.");
                    case '.':
                        if (pathElement.ReferenceTypeId == null &&
                            !parseReference)
                        {
                            pathElement.ReferenceTypeId =
                                ReferenceTypeIds.Aggregates;
                            break;
                        }
                        throw new FormatException("Reference type set.");
                    default:
                        if (element[index] == '&')
                        {
                            index++;
                        }
                        if (pathElement.ReferenceTypeId == null &&
                            !parseReference)
                        {
                            // Set to all references
                            pathElement.ReferenceTypeId =
                                ReferenceTypeIds.References;
                        }
                        exit = true;
                        break;
                }
                index++;
            }
            index--;
            if (parseReference)
            {
                var to = index;
                while (to < element.Length)
                {
                    if (element[to] == '>' && element[to - 1] != '&')
                    {
                        break;
                    }
                    to++;
                    if (to == element.Length)
                    {
                        throw new FormatException(
                            "Reference path starts in < but does not end in >");
                    }
                }
                var reference = element[index..to];
                // TODO: Deescape &<, &>, &/, &., &:, &&
                index = to + 1;
                pathElement.ReferenceTypeId = reference.ToNodeId(context);
                if (NodeId.IsNull(pathElement.ReferenceTypeId) &&
                    TypeMaps.ReferenceTypes.Value.TryGetIdentifier(reference,
                        out var id))
                {
                    pathElement.ReferenceTypeId = id;
                }
            }
            var target = element[index..];
            // TODO: Deescape &<, &>, &/, &., &:, &&
            if (string.IsNullOrEmpty(target))
            {
                throw new FormatException("Bad target name is empty");
            }
            pathElement.TargetName = target.ToQualifiedName(context);
            return pathElement;
        }