private static void RemoveExtensionSetupSlices(SDTreeNode node) { if (node.IsSetupSliceForExtension) { node.Parent.RemoveChild(node); } }
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); }
public SDTreeNode GenerateDifferentialTree() { SDTreeNode snapshotTree = GenerateSnapshotTree(true); snapshotTree.DepthFirstTreeWalk(t => RemoveUnchangedNodes(t)); return(snapshotTree); }
private static bool HasZeroMaxCardinality(SDTreeNode treeNode) { if (treeNode == null) { return(false); } return(treeNode.Element.IsRemoved() || HasZeroMaxCardinality(treeNode.Parent)); }
private void RemoveUnchangedNodes(SDTreeNode node) { if (!node.ThisOrChildrenHaveChangedFromBase) { if (node.Parent != null) { node.Parent.RemoveChild(node); } } }
private static void RemoveZeroMaxCardinalityNodes(SDTreeNode node) { if (node.HasZeroMaxCardinality()) { if (node.Parent != null) { node.Parent.RemoveChild(node); } } }
public void AddChild(SDTreeNode child) { if (child.Parent != null) { child.Parent.RemoveChild(child); } _children.Add(child); child.Parent = this; }
public SDTreeNodeNavigator(SDTreeNode treeNode) { if (treeNode == null) { throw new ArgumentNullException("treeNode"); } _treeNode = treeNode; _stack = new Stack <SDTreeNode>(); _stack.Push(treeNode); }
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); } } } }
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); }
public bool MoveNext() { if (!_stack.Any()) { return(false); } _currentNode = _stack.Pop(); foreach (SDTreeNode childNode in _currentNode.Children.Reverse()) { _stack.Push(childNode); } return(true); }
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; }
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); } } }
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); } } } }
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()); }
public void RemoveChild(SDTreeNode child) { _children.Remove(child); child.Parent = null; }
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); }