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 SDNodeType GetNodeType() { if (IsSetupSlice) { return(SDNodeType.SetupSlice); } ElementDefinitionType[] types = GetElementDefinitionType(); if (types != null) { if (types.Length == 0) { return(SDNodeType.Unknown); } else if (types.Length == 1) { ElementDefinitionType elementType = types.Single(); if (elementType.IsBackboneElement()) { return(SDNodeType.Element); } else if (elementType.IsPrimitiveType()) { return(SDNodeType.PrimitiveType); } else if (elementType.IsReference()) { return(SDNodeType.Reference); } else if (elementType.IsComplexType()) { return(SDNodeType.ComplexType); } else if (elementType.IsExtension()) { if (ExtensionDefinition != null) { if (ExtensionDefinition.IsComplexExtension()) { return(SDNodeType.ComplexExtension); } } return(SDNodeType.SimpleExtension); } else if (elementType.IsResource()) { return(SDNodeType.Resource); } return(SDNodeType.Unknown); } else { if (types.Any(t => t.IsReference())) { return(SDNodeType.Reference); } return(SDNodeType.Choice); } } else if ((Element.PathBeforeSliceIndexing ?? string.Empty).EndsWith(".extension")) { // hacky but apparently only way to determine extensions within extensions return(SDNodeType.SimpleExtension); } else if (Element.nameReference != null) { return(SDNodeType.ReferenceToAnotherElement); } return(SDNodeType.Unknown); }