예제 #1
0
 private static void RemoveExtensionSetupSlices(SDTreeNode node)
 {
     if (node.IsSetupSliceForExtension)
     {
         node.Parent.RemoveChild(node);
     }
 }
예제 #2
0
        private SDTreeNode GenerateTree(ElementDefinition[] elements)
        {
            ElementDefinition rootElement = elements.GetRootElement();

            if (rootElement == null)
            {
                throw new Exception("Could not find root element");
            }

            SDTreeNode rootNode = new SDTreeNode(rootElement);

            Stack <SDTreeNode> stack = new Stack <SDTreeNode>();

            stack.Push(rootNode);

            while (stack.Any())
            {
                SDTreeNode node = stack.Pop();

                foreach (ElementDefinition element in elements.GetChildren(node.Element))
                {
                    SDTreeNode childNode = new SDTreeNode(element);
                    node.AddChild(childNode);
                    stack.Push(childNode);
                }
            }

            return(rootNode);
        }
예제 #3
0
        public SDTreeNode GenerateDifferentialTree()
        {
            SDTreeNode snapshotTree = GenerateSnapshotTree(true);

            snapshotTree.DepthFirstTreeWalk(t => RemoveUnchangedNodes(t));

            return(snapshotTree);
        }
예제 #4
0
        private static bool HasZeroMaxCardinality(SDTreeNode treeNode)
        {
            if (treeNode == null)
            {
                return(false);
            }

            return(treeNode.Element.IsRemoved() || HasZeroMaxCardinality(treeNode.Parent));
        }
예제 #5
0
 private void RemoveUnchangedNodes(SDTreeNode node)
 {
     if (!node.ThisOrChildrenHaveChangedFromBase)
     {
         if (node.Parent != null)
         {
             node.Parent.RemoveChild(node);
         }
     }
 }
예제 #6
0
 private static void RemoveZeroMaxCardinalityNodes(SDTreeNode node)
 {
     if (node.HasZeroMaxCardinality())
     {
         if (node.Parent != null)
         {
             node.Parent.RemoveChild(node);
         }
     }
 }
예제 #7
0
        public void AddChild(SDTreeNode child)
        {
            if (child.Parent != null)
            {
                child.Parent.RemoveChild(child);
            }

            _children.Add(child);
            child.Parent = this;
        }
예제 #8
0
        public SDTreeNodeNavigator(SDTreeNode treeNode)
        {
            if (treeNode == null)
            {
                throw new ArgumentNullException("treeNode");
            }

            _treeNode = treeNode;
            _stack    = new Stack <SDTreeNode>();
            _stack.Push(treeNode);
        }
예제 #9
0
        private void GroupOpenSliceElements(SDTreeNode node)
        {
            if (node.IsSetupSlice && (!node.IsSetupSliceForExtension))
            {
                List <SDTreeNode> nodesToGroup = new List <SDTreeNode>();

                foreach (SDTreeNode childNode in node.Children)
                {
                    if (!childNode.IsSlice)
                    {
                        nodesToGroup.Add(childNode);
                    }
                }

                if (node.Element.slicing.rules.value == SlicingRuleslist.open)
                {
                    ElementDefinition openSliceElement = new ElementDefinition();
                    openSliceElement.path       = new @string();
                    openSliceElement.path.value = node.Element.path.value + "#n";
                    openSliceElement.name       = new @string();
                    // openSliceElement.name.value = "open";
                    // also fix cardinalities
                    openSliceElement.type = node.GetElementDefinitionType();
                    SDTreeNode openSlice = new SDTreeNode(openSliceElement);
                    openSlice.AddChildren(nodesToGroup.ToArray());
                    node.AddChild(openSlice);
                }
                else if (node.Element.slicing.rules.value == SlicingRuleslist.openAtEnd)
                {
                    ElementDefinition openAtEndSliceElement = new ElementDefinition();
                    openAtEndSliceElement.path       = new @string();
                    openAtEndSliceElement.path.value = node.Element.path.value + "#n";
                    openAtEndSliceElement.name       = new @string();
                    // openAtEndSliceElement.name.value = "openAtEnd";
                    // also fix cardinalities
                    openAtEndSliceElement.type = node.GetElementDefinitionType();
                    SDTreeNode openAtEndSlice = new SDTreeNode(openAtEndSliceElement);
                    openAtEndSlice.AddChildren(nodesToGroup.ToArray());
                    node.AddChild(openAtEndSlice);
                }
                else
                {
                    foreach (SDTreeNode childNodeToRemove in nodesToGroup)
                    {
                        node.RemoveChild(childNodeToRemove);
                    }
                }
            }
        }
예제 #10
0
        public bool IsLastChild()
        {
            if (Parent == null)
            {
                return(true);
            }

            SDTreeNode lastChild = Parent.Children.LastOrDefault();

            if (lastChild == null)
            {
                throw new Exception("Anomolous tree structure detected");
            }

            return(lastChild == this);
        }
예제 #11
0
        public bool MoveNext()
        {
            if (!_stack.Any())
            {
                return(false);
            }

            _currentNode = _stack.Pop();

            foreach (SDTreeNode childNode in _currentNode.Children.Reverse())
            {
                _stack.Push(childNode);
            }

            return(true);
        }
예제 #12
0
        public void AddExtensionDefinitions(SDTreeNode treeNode, IStructureDefinitionResolver resolver)
        {
            if (!treeNode.GetNodeType().IsExtension())
            {
                return;
            }

            ElementDefinitionType[] type = treeNode.GetElementDefinitionType();

            if (type == null)
            {
                return;
            }

            if (type.Length != 1)
            {
                return;
            }

            if (type.First().profile == null)
            {
                return;
            }

            if (type.First().profile.Length != 1)
            {
                return;
            }

            uri profileUri = type.First().profile.First();

            if (profileUri == null)
            {
                return;
            }

            StructureDefinition structureDefinition = resolver.GetStructureDefinition(profileUri.value);

            if (structureDefinition == null)
            {
                throw new Exception("Could not find extension " + profileUri.value);
            }

            treeNode.ExtensionDefinition = structureDefinition;
        }
예제 #13
0
        public void DepthFirstTreeWalk(Action <SDTreeNode> function)
        {
            Stack <SDTreeNode> stack = new Stack <SDTreeNode>();

            stack.Push(this);

            while (stack.Any())
            {
                SDTreeNode node = stack.Pop();

                function(node);

                foreach (SDTreeNode childNode in node.Children.Reverse())
                {
                    stack.Push(childNode);
                }
            }
        }
예제 #14
0
        private static void GroupSlices(SDTreeNode node)
        {
            SDTreeNode[] childSetupSlices = node.Children.Where(t => t.IsSetupSlice && (!t.IsSetupSliceForExtension)).ToArray();

            if (childSetupSlices.Any())
            {
                foreach (SDTreeNode childSetupSlice in childSetupSlices)
                {
                    SDTreeNode[] childSlices = node.Children.Where(t => t.Path.StartsWith(childSetupSlice.Path + "#")).ToArray();

                    foreach (SDTreeNode childSlice in childSlices)
                    {
                        childSlice.IsSlice = true;
                        node.RemoveChild(childSlice);
                        childSetupSlice.AddChild(childSlice);
                    }
                }
            }
        }
예제 #15
0
        private void AddMissingComplexDataTypeElements(SDTreeNode node)
        {
            StructureDefinition dataTypeDefinition;
            ElementDefinition   dataTypeRootElement;

            ElementDefinition[] dataTypeChildElements;

            // if is element in multi level complex type, recall context
            if (multiLevelComplexTypeRevisit.ContainsKey(node))
            {
                dataTypeDefinition    = multiLevelComplexTypeRevisit[node].ComplexDataTypeDefinition;
                dataTypeRootElement   = multiLevelComplexTypeRevisit[node].MultiLevelElementDefinition;
                dataTypeChildElements = dataTypeDefinition.differential.element.GetChildren(dataTypeRootElement).ToArray();
            }
            else  // else check whether is root of complex type
            {
                // don't expand profiles with multi choice types
                if (node.GetElementDefinitionType() == null)
                {
                    return;
                }

                if (node.GetElementDefinitionType().Count() != 1)
                {
                    return;
                }

                ElementDefinitionType elementType = node.GetElementDefinitionType().Single();

                if (elementType == null)
                {
                    return;
                }

                if (!(elementType.IsComplexType() || elementType.IsReference()))
                {
                    return;
                }

                // don't expand root Extension elements
                if ((node.Path == "Extension") && (elementType.TypeName == "Element"))
                {
                    return;
                }

                dataTypeDefinition = FhirData.Instance.FindDataTypeStructureDefinition(elementType.TypeName);

                if (dataTypeDefinition == null)
                {
                    throw new Exception("Could not find FHIR data type " + elementType.TypeName);
                }

                dataTypeRootElement   = dataTypeDefinition.differential.element.GetRootElement();
                dataTypeChildElements = dataTypeDefinition.differential.element.GetChildren(dataTypeRootElement).ToArray();
            }

            List <SDTreeNode> newChildren = new List <SDTreeNode>();

            foreach (ElementDefinition dataTypeChildElement in dataTypeChildElements)
            {
                string lastPathElement = dataTypeChildElement.GetLastPathValue();

                SDTreeNode[] existingChildren = node.Children.Where(t => t.LastPathElementWithoutSliceIndex == lastPathElement).ToArray();

                List <SDTreeNode> currentNewChildren = new List <SDTreeNode>();

                // if child or children don't exist, add the child
                if (existingChildren.Length == 0)
                {
                    SDTreeNode newChild = new SDTreeNode(dataTypeChildElement);
                    currentNewChildren.Add(newChild);
                }
                else // child or children already exists
                {
                    foreach (SDTreeNode existingChild in existingChildren)
                    {
                        // if is a "fake" element, it needs replacing
                        if (existingChild.Element.IsFake)
                        {
                            SDTreeNode   newChild       = new SDTreeNode(dataTypeChildElement);
                            SDTreeNode[] childsChildren = existingChild.Children;
                            existingChild.RemoveAllChildren();
                            newChild.AddChildren(childsChildren);
                            currentNewChildren.Add(newChild);
                        }
                        else // keep the existing child
                        {
                            existingChild.Element.BaseElementDefinition = dataTypeChildElement;
                            currentNewChildren.Add(existingChild);
                        }
                    }
                }

                newChildren.AddRange(currentNewChildren);

                // if complex data type's children have children....argh!  (should only be for the Timing data type)
                if (dataTypeDefinition.differential.element.GetChildren(dataTypeChildElement).Count() > 0)
                {
                    MultiLevelComplexTypePointer multiLevelComplexTypePointer = new MultiLevelComplexTypePointer()
                    {
                        ComplexDataTypeDefinition   = dataTypeDefinition,
                        MultiLevelElementDefinition = dataTypeChildElement
                    };

                    foreach (SDTreeNode currentChild in currentNewChildren)
                    {
                        multiLevelComplexTypeRevisit.Add(currentChild, multiLevelComplexTypePointer);
                    }
                }
            }

            foreach (SDTreeNode childNode in node.Children)
            {
                if (newChildren.All(t => t.LastPathElement != childNode.LastPathElement))
                {
                    newChildren.Add(childNode);
                }
            }

            node.RemoveAllChildren();
            node.AddChildren(newChildren.ToArray());
        }
예제 #16
0
 public void RemoveChild(SDTreeNode child)
 {
     _children.Remove(child);
     child.Parent = null;
 }
예제 #17
0
        public SDTreeNode GenerateSnapshotTree(bool includeNodesWithZeroMaxCardinality = true)
        {
            // process ElementDefinition list
            //
            // to create list where path values are unique (by indexing slices)
            // and where there are no orphan children by creating fake parents
            //

            ElementDefinition[] elements = _structureDefinition.differential.element;

            // mark elements as changed
            foreach (ElementDefinition element in elements)
            {
                element.HasChangedFromBase = true;
            }

            // sanity checks
            PerformDifferentialElementsSanityCheck(elements, false);

            // populate ElementDefinitions with their ancestor ElementDefinition
            PopulateBaseElementDefinitions(elements);

            // "index" slices to create unique ElementDefinition.path values
            IndexSlices(elements);

            // Merge differential and the direct base StructureDefinition's differential. -- this needs expanding to include all ancestor base StructureDefinitions
            elements = CreateSnapshot(_structureDefinition);

            // Add fake missing parents
            elements = AddFakeMissingParents(elements);

            // build tree
            //
            //

            SDTreeNode rootNode = GenerateTree(elements);

            // process tree
            //
            //

            // Expand out data types
            rootNode.DepthFirstTreeWalk(t => AddMissingComplexDataTypeElements(t));

            // group slices under the slice "setup" node (except extension slices)
            rootNode.DepthFirstTreeWalk(t => GroupSlices(t));

            // remove 0..0 nodes and their children
            if (!includeNodesWithZeroMaxCardinality)
            {
                rootNode.DepthFirstTreeWalk(t => RemoveZeroMaxCardinalityNodes(t));
            }

            // remove setup extension "setup" slice nodes
            rootNode.DepthFirstTreeWalk(t => RemoveExtensionSetupSlices(t));

            // add extension definitions
            rootNode.DepthFirstTreeWalk(t => AddExtensionDefinitions(t, _resolver));

            // group children of slice parent not part of numbered slice
            rootNode.DepthFirstTreeWalk(t => GroupOpenSliceElements(t));

            return(rootNode);
        }