// Remove null children of current node, and return true => current node is null public static bool RemoveNullChildren(this ElementNode node) { if (node == null) { return(true); } var children = node.Children().Cast <ElementNode>().ToList(); foreach (var child in children) { // Remove child if it is null => return true if (RemoveNullChildren(child)) { node.Remove(child); } } bool currentNodeIsEmpty = !node.Children().Any() && node.Value == null; bool currentNodeIsFhirResource = node.IsFhirResource(); if (currentNodeIsEmpty && !currentNodeIsFhirResource) { return(true); } else { return(false); } }
public void AccessViaIndexers() { Assert.Equal("Patient.active[0].extension[1].value[0]", patient["active"][0]["extension"][1]["value"][0].Location); Assert.Equal("Patient.active[0].extension[1].value[0]", patient["active"]["extension"][1]["value"].Single().Location); Assert.Equal("Patient.active[0].extension[0].value[0]", patient.Children("active").First() .Children("extension").First() .Children("value").First().Location); Assert.Equal("Patient.active[0].extension[0].value[0]", patient.Children("active") .Children("extension").First() .Children("value").Single().Location); }
public ProcessResult Process(ElementNode node, ProcessContext context = null, Dictionary <string, object> settings = null) { EnsureArg.IsNotNull(node); EnsureArg.IsNotNull(context?.VisitedNodes); EnsureArg.IsNotNull(settings); var result = new ProcessResult(); ElementNode valueNode = null; if (s_primitiveValueTypeNames.Contains(node.InstanceType, StringComparer.InvariantCultureIgnoreCase)) { valueNode = node; } else if (s_quantityTypeNames.Contains(node.InstanceType, StringComparer.InvariantCultureIgnoreCase)) { valueNode = node.Children(Constants.ValueNodeName).Cast <ElementNode>().FirstOrDefault(); } // Perturb will not happen if value node is empty or visited. if (valueNode?.Value == null || context.VisitedNodes.Contains(valueNode)) { return(result); } var perturbSetting = PerturbSetting.CreateFromRuleSettings(settings); AddNoise(valueNode, perturbSetting); context.VisitedNodes.UnionWith(node.Descendants().Cast <ElementNode>()); result.AddProcessRecord(AnonymizationOperations.Perturb, node); return(result); }
public ProcessResult ProcessNodeRecursive(ElementNode node, IAnonymizerProcessor processor, ProcessContext context, Dictionary <string, object> settings) { var result = new ProcessResult(); if (_visitedNodes.Contains(node)) { return(result); } result = processor.Process(node, context, settings); _visitedNodes.Add(node); foreach (var child in node.Children().CastElementNodes()) { if (child.IsFhirResource()) { continue; } result.Update(ProcessNodeRecursive(child, processor, context, settings)); } return(result); }
private static void TransformTypeRulesToPathRules(ElementNode node, Dictionary <string, string> typeRules, List <AnonymizerRule> rules, HashSet <string> rulePaths) { if (node.IsContainedNode() || node.IsEntryNode()) { return; } string path = node.GetFhirPath(); if (rulePaths.Contains(path)) { return; } if (typeRules.ContainsKey(node.InstanceType)) { var rule = new AnonymizerRule(path, typeRules[node.InstanceType], AnonymizerRuleType.TypeRule, node.InstanceType); rules.Add(rule); rulePaths.Add(rule.Path); } var children = node.Children().Cast <ElementNode>(); foreach (var child in children) { TransformTypeRulesToPathRules(child, typeRules, rules, rulePaths); } }
// Post-process to mark all substituted children nodes as visited private void MarkSubstitutedFragmentAsVisited(ElementNode node, HashSet <ElementNode> visitedNodes) { visitedNodes.Add(node); foreach (var child in node.Children().Cast <ElementNode>()) { MarkSubstitutedFragmentAsVisited(child, visitedNodes); } }
public static List <ElementNode> GetEntryResourceChildren(this ElementNode node) { return(node?.Children(s_entryNodeName) .Select(entry => entry?.Children(s_resourceNodeName).FirstOrDefault()) .Where(resource => resource != null) .Cast <ElementNode>() .ToList()); }
public static void RemoveNullChildren(this ElementNode node) { if (node == null) { return; } var children = node.Children().Cast <ElementNode>().ToList(); foreach (var child in children) { RemoveNullChildren(child); } if (!node.Children().Any() && node.Value == null && !Enum.TryParse <ResourceType>(node.InstanceType, true, out _)) { node.Parent.Remove(node); return; } }
private static string TryGetResourceId(ElementNode node) { while (node.Parent != null) { node = node.Parent; } var id = node.Children("id").FirstOrDefault(); return(id != null?id.Value.ToString() : string.Empty); }
public static void Accept(this ElementNode node, AbstractElementNodeVisitor visitor) { bool shouldVisitChild = visitor.Visit(node); if (shouldVisitChild) { foreach (var child in node.Children().Cast <ElementNode>()) { child.Accept(visitor); } } visitor.EndVisit(node); }
public static IEnumerable <ElementNode> ResourceDescendantsWithoutSubResource(this ElementNode node) { foreach (var child in node.Children().Cast <ElementNode>()) { // Skip sub resources in bundle entry and contained list if (child.IsFhirResource()) { continue; } yield return(child); foreach (var n in child.ResourceDescendantsWithoutSubResource()) { yield return(n); } } }
// To keep consistent anonymization changes made by preceding rules, we should figure out whether a node can be removed during substitution private bool GenerateKeepNodeSetForSubstitution(ElementNode node, HashSet <ElementNode> visitedNodes, HashSet <ElementNode> keepNodes) { var shouldKeep = false; // If a child (no matter how deep) has been modified, this node should be kept foreach (var child in node.Children().Cast <ElementNode>()) { shouldKeep |= GenerateKeepNodeSetForSubstitution(child, visitedNodes, keepNodes); } // If this node its self has been modified, it should be kept if (shouldKeep || visitedNodes.Contains(node)) { keepNodes.Add(node); return(true); } return(shouldKeep); }
private void AnonymizeChildNode(ElementNode node, string method, HashSet <string> rulePathSet) { method = method.ToUpperInvariant(); if (node.Value != null && _processors.ContainsKey(method)) { _processors[method].Process(node); } var children = node.Children().Cast <ElementNode>(); foreach (var child in children) { if (!rulePathSet.Contains(child.GetFhirPath())) { AnonymizeChildNode(child, method, rulePathSet); } } }
private void AnonymizeChildNode(ElementNode node, AnonymizerRule rule, HashSet <string> rulePathSet, string resourceId) { var method = rule.Method.ToUpperInvariant(); if (node.Value != null && _processors.ContainsKey(method)) { _processors[method].Process(node); _logger.LogDebug($"{node.GetFhirPath()} in resource ID {resourceId} is applied {method} due to rule \"{rule.Source}:{rule.Method}\""); } var children = node.Children().Cast <ElementNode>(); foreach (var child in children) { if (!rulePathSet.Contains(child.GetFhirPath())) { AnonymizeChildNode(child, rule, rulePathSet, resourceId); } } }
public static void RemoveEmptyNodes(this ElementNode node) { if (node == null) { return; } var children = node.Children().ToList(); foreach (var child in children) { var elementNodeChild = (ElementNode)child; // Remove empty nodes recursively RemoveEmptyNodes(elementNodeChild); if (IsEmptyNode(elementNodeChild)) { node.Remove(elementNodeChild); } } }
public ProcessResult ProcessNodeRecursive(ElementNode node, IAnonymizerProcessor processor, HashSet <ElementNode> visitedNodes) { ProcessResult result = new ProcessResult(); if (visitedNodes.Contains(node)) { return(result); } result = processor.Process(node); visitedNodes.Add(node); foreach (var child in node.Children().Cast <ElementNode>()) { if (child.IsFhirResource()) { continue; } result.Update(ProcessNodeRecursive(child, processor, visitedNodes)); } return(result); }
public static ElementNode GetMeta(this ElementNode node) { return(node?.Children("meta").Cast <ElementNode>().FirstOrDefault()); }
public static string GetNodeId(this ElementNode node) { var id = node.Children("id").FirstOrDefault(); return(id?.Value?.ToString() ?? string.Empty); }
public static bool HasContainedNode(this ElementNode node) { return(node != null && node.Children(Constants.ContainedNodeName).Any()); }
public static List <ElementNode> GetContainedChildren(this ElementNode node) { return(node?.Children(s_containedNodeName).Cast <ElementNode>().ToList()); }
private ProcessResult SubstituteNode(ElementNode node, ElementNode replacementNode, HashSet <ElementNode> visitedNodes, HashSet <ElementNode> keepNodes) { var processResult = new ProcessResult(); if (node == null || replacementNode == null || visitedNodes.Contains(node)) { return(processResult); } // children names to replace, multiple to multiple replacement var replaceChildrenNames = replacementNode.Children().Select(element => element.Name).ToHashSet(); foreach (var name in replaceChildrenNames) { var children = node.Children(name).Cast <ElementNode>().ToList(); var targetChildren = replacementNode.Children(name).Cast <ElementNode>().ToList(); int i = 0; foreach (var child in children) { if (visitedNodes.Contains(child)) { // Skip replacement if child already processed before. i++; continue; } else if (i < targetChildren.Count) { // We still have target nodes, do replacement SubstituteNode(child, targetChildren[i++], visitedNodes, keepNodes); } else if (keepNodes.Contains(child)) { // Substitute with an empty node when no target node available but we need to keep this node SubstituteNode(child, GetDummyNode(), visitedNodes, keepNodes); } else { // Remove source node when no target node available and we don't need to keep the source node node.Remove(child); } } while (i < targetChildren.Count) { // Add extra target nodes, create a new copy before adding node.Add(s_provider, ElementNode.FromElement(targetChildren[i++])); } } // children nodes not presented in replacement value, we need either remove or keep a dummy copy var nonReplacementChildren = node.Children() .Where(element => !replaceChildrenNames.Contains(element.Name)) .Cast <ElementNode>().ToList(); foreach (var child in nonReplacementChildren) { if (visitedNodes.Contains(child)) { continue; } else if (keepNodes.Contains(child)) { SubstituteNode(child, GetDummyNode(), visitedNodes, keepNodes); } else { node.Remove(child); } } node.Value = replacementNode.Value; processResult.AddProcessRecord(AnonymizationOperations.Substitute, node); return(processResult); }