public void SimpleMod() { StructureDefinition original = this.CreateBaseObservation(); StructureDefinition modified = this.CreateBaseObservation(); SnapshotCreator.Create(original); SnapshotCreator.Create(modified); ElementTreeLoader loader = new ElementTreeLoader(info); ElementTreeNode originalNode = loader.Create(original.Snapshot.Element); ElementTreeNode modifiedNode = loader.Create(modified.Snapshot.Element); Assert.True(modifiedNode.TryGetElementNode("Observation.value[x]", out ElementTreeNode n)); n.ElementDefinition.Max = "0"; ElementTreeDiffer differ = new ElementTreeDiffer(info); differ.Process(originalNode, modifiedNode); List <ElementDefinition> elementDefinitions = new List <ElementDefinition>(); modifiedNode.CopyTo(elementDefinitions); Assert.True(elementDefinitions.Count == 2); Assert.True(elementDefinitions[1].Path == "Observation.value[x]"); Assert.True(elementDefinitions[1].Max == "0"); }
ElementTreeNode GetSnapNodeOriginal(StructureDefinition sDef, ElementTreeLoader l) { const String fcn = "LoadBase"; lock (originalNodes) { if (originalNodes.TryGetValue(sDef.BaseDefinition, out ElementTreeNode retVal) == true) { return(retVal); } StructureDefinition SBaseDef = FhirStructureDefinitions.Self.GetResource(sDef.BaseDefinition); if (SBaseDef == null) { info.ConversionError(this.GetType().Name, fcn, $"Error loading StructureDef '{sDef.Name}'. BaseDefinition {sDef.BaseDefinition} not found "); return(null); } if (SBaseDef.Snapshot == null) { SnapshotCreator.Create(SBaseDef); } retVal = l.Create(SBaseDef.Snapshot.Element);; originalNodes.Add(sDef.BaseDefinition, retVal); return(retVal); } }
/// <summary> /// Fix errors in differentia. /// The tools will celan out the min and max values if they are unchanged from the base, so here /// we put them back in because they are required. /// </summary> /// <param name="processedItem"></param> /// <param name="sDef"></param> void CleanupDifferential(ProcessItem item, StructureDefinition sDef) { foreach (ElementDefinition ed in sDef.Differential.Element.Skip(1)) { if ((ed.Min.HasValue == false) || (String.IsNullOrEmpty(ed.Max))) { if (item.SnapNode == null) { ElementTreeLoader l = new ElementTreeLoader(this); item.SnapNode = l.Create(item.SDef.Snapshot.Element); } ElementTreeNode snapNode; if (item.SnapNode.TryGetElementNode(ed.ElementId, out snapNode) == false) { item.SnapNode.TryGetElementNode(ed.Path, out snapNode); } if (snapNode != null) { ed.Min = snapNode.ElementDefinition.Min; ed.Max = snapNode.ElementDefinition.Max; } } } }
/// <summary> /// Create structure definition editor /// </summary> public SDefEditor(IConversionInfo info, String name, String url, String baseDefinition, String mapName, String fragmentDir, String pageDir) { this.info = info; this.fragmentDir = fragmentDir; this.pageDir = pageDir; this.baseSDef = FhirStructureDefinitions.Self.GetResource(baseDefinition); if (this.baseSDef == null) { throw new Exception($"'Base definition resource {baseDefinition}' not found"); } this.basePath = baseDefinition.LastUriPart(); { ElementTreeLoader l = new ElementTreeLoader(); this.snapNode = l.Create(this.baseSDef.Snapshot.Element); this.snapNodeOriginal = this.snapNode.Clone(); } this.sDef = new StructureDefinition { Name = name, Url = url, BaseDefinition = baseDefinition, Differential = new StructureDefinition.DifferentialComponent() }; this.SDef.AddExtension(Global.ResourceMapNameUrl, new FhirString(mapName)); }
public void NoMod() { StructureDefinition original = this.CreateBaseObservation(); StructureDefinition modified = this.CreateBaseObservation(); SnapshotCreator.Create(original); SnapshotCreator.Create(modified); ElementTreeLoader loader = new ElementTreeLoader(info); ElementTreeNode originalNode = loader.Create(original.Snapshot.Element); ElementTreeNode modifiedNode = loader.Create(modified.Snapshot.Element); ElementTreeDiffer differ = new ElementTreeDiffer(info); differ.Process(originalNode, modifiedNode); List <ElementDefinition> elementDefinitions = new List <ElementDefinition>(); modifiedNode.CopyTo(elementDefinitions); Assert.True(elementDefinitions.Count == 0); }
public SDInfo(IConversionInfo ci, StructureDefinition sd) { this.StructDef = sd; ElementTreeLoader l = new ElementTreeLoader(ci); if (sd.Snapshot == null) { SnapshotCreator.Create(sd); } this.DiffNodes = l.Create(sd.Differential.Element); this.SnapNodes = l.Create(sd.Snapshot.Element); this.InterfaceEditor = new CodeEditor(); this.InterfaceEditor.TryAddUserMacro("ClassName", CS.CSMisc.ClassName(this)); this.InterfaceEditor.TryAddUserMacro("InterfaceName", CS.CSMisc.InterfaceName(this)); this.InterfaceEditor.Load(Path.Combine("Templates", "Interface.txt")); this.AddMacros(this.InterfaceEditor, this); this.SubClassEditor = new CodeEditor(); this.AddMacros(this.SubClassEditor, this); this.SubClassEditor.TryAddUserMacro("FhirBase", this.StructDef.BaseDefinition.LastUriPart()); this.SubClassEditor.TryAddUserMacro("BaseClass", CS.CSMisc.ClassName(this)); this.SubClassEditor.Load(Path.Combine("Templates", "SubClass.txt")); this.ClassEditor = new CodeEditor(); this.AddMacros(this.ClassEditor, this); this.ClassEditor.TryAddUserMacro("ClassName", CS.CSMisc.ClassName(this)); if (this.IsFragment()) { this.ClassEditor.Load(Path.Combine("Templates", "Fragment.txt")); } else { this.ClassEditor.Load(Path.Combine("Templates", "Class.txt")); } this.CodeBlocks = ClassCodeBlocks.Create(this.InterfaceEditor, this.ClassEditor, this.SubClassEditor); }
public bool LoadMerge() { if (this.DiffNode != null) { return(true); } this.FragmentFlag = this.SDef.IsFragment(); ElementTreeLoader l = new ElementTreeLoader(this.info); this.DiffNode = l.Create(this.SDef.Differential.Element); return(true); }
void SetBaseDef(String baseDefinition) { if ( (this.baseDef != null) && (this.baseDef.Url == baseDefinition) ) { return; } this.baseDef = FhirStructureDefinitions.Self.GetResource(baseDefinition); ElementTreeLoader l = new ElementTreeLoader(); this.snapNode = l.Create(this.baseDef.Snapshot.Element); }
public void SlicingTest() { StructureDefinition s = this.CreateBaseObservation(); ElementDefinition e = new ElementDefinition { ElementId = "Observation.component", Path = "Observation.component", Slicing = new ElementDefinition.SlicingComponent { ElementId = "5", Ordered = false, Rules = ElementDefinition.SlicingRules.Open } }; e.Slicing.Discriminator.Add(new ElementDefinition.DiscriminatorComponent { Type = ElementDefinition.DiscriminatorType.Value, Path = "code.coding.code" }); s.Differential.Element.Add(e); ElementTreeLoader loader = new ElementTreeLoader(info); ElementTreeNode head = loader.Create(s.Differential.Element); Assert.True(head.Slices.Count == 1); Assert.True(head.DefaultSlice.Nodes.Count == 1); Assert.True(head.TryGetElementNode("Observation.component", out ElementTreeNode observationComponent) == true); Assert.True(observationComponent.Path == "Observation.component"); Assert.True(observationComponent.Name == "component"); Assert.True(observationComponent.Slices.Count == 1); Assert.True(observationComponent.Slices.GetItemAt(0).ElementDefinition.Slicing.ElementId == "5"); Assert.True(observationComponent.Slices.GetItemAt(0).ElementDefinition.Slicing.Ordered == false); Assert.True(observationComponent.Slices.GetItemAt(0).ElementDefinition.Slicing.Rules == ElementDefinition.SlicingRules.Open); Assert.True(observationComponent.Slices.GetItemAt(0).ElementDefinition.Slicing.Discriminator.Count == 1); Assert.True(observationComponent.Slices.GetItemAt(0).ElementDefinition.Slicing.Discriminator[0].Type == ElementDefinition.DiscriminatorType.Value); Assert.True(observationComponent.Slices.GetItemAt(0).ElementDefinition.Slicing.Discriminator[0].Path == "code.coding.code"); }
public bool LoadBase() { const String fcn = "LoadBase"; if (this.SnapNode != null) { return(true); } this.FragmentFlag = this.SDef.IsFragment(); StructureDefinition sDef = this.SDef; if (sDef == null) { throw new Exception("Internal error. ProcessItem is not a structured definition."); } if (sDef.Snapshot == null) { SnapshotCreator.Create(sDef); } List <ElementDefinition> elements = sDef.Snapshot.Element; this.BasePath = elements[0].Path; ElementTreeLoader l = new ElementTreeLoader(this.info); this.SnapNode = l.Create(elements); if (String.IsNullOrEmpty(sDef.BaseDefinition) == true) { info.ConversionError(this.GetType().Name, fcn, $"Error loading StructureDef '{sDef.Name}'. Empty BaseDefinition "); return(false); } this.SnapNodeOriginal = GetSnapNodeOriginal(sDef, l); return(true); }
public void PatchStructDef(StructureDefinition sd) { //const String fcn = "PatchStructDefObservation"; CodeEditorXml c = new CodeEditorXml(); c.IgnoreMacrosInQuotedStrings = false; ElementTreeLoader l = new ElementTreeLoader(this); ElementTreeNode diffNode = null; if (sd?.Differential?.Element != null) { diffNode = l.Create(sd.Differential.Element); } String[] CollateComponents() { SortedList <String, String> items = new SortedList <String, String>(); if (diffNode == null) { return(items.Values.ToArray()); } if (diffNode.TryGetElementNode("Observation.component", out ElementTreeNode node) == false) { return(items.Values.ToArray()); } if (node.Slices.Count <= 1) { return(items.Values.ToArray()); } foreach (ElementTreeSlice slice in node.Slices.Skip(1)) { String shortDesc = $"{slice.ElementDefinition.Short} [{slice.ElementDefinition.Min}..{slice.ElementDefinition.Max}]"; String anchor = Global.ElementAnchor(slice.ElementDefinition).Replace("{SDName}", sd.Name); items.Add(shortDesc, $"<a href=\"{anchor}\">{shortDesc}</a>"); } return(items.Values.ToArray()); } String[] CollateFragments() { SortedList <String, String> items = new SortedList <String, String>(); foreach (Extension frag in sd.GetExtensions(Global.FragmentUrl)) { FhirUrl fragmentUrl = (FhirUrl)frag.Value; if (this.map.TryGetNode(fragmentUrl.Value, out ResourceMap.Node fragNode) == false) { throw new Exception($"Can not find fragment {frag.Url}"); } String hRef = $"./{fragNode.StructureName}-{fragNode.Name}.html"; items.Add(fragNode.Title, $"<a href=\"{hRef}\">{fragNode.Title}</a>"); } return(items.Values.ToArray()); } String[] CollateHasMembers() { SortedList <String, String> items = new SortedList <String, String>(); if (diffNode == null) { return(items.Values.ToArray()); } if (diffNode.TryGetElementNode("Observation.hasMember", out ElementTreeNode node) == false) { return(items.Values.ToArray()); } if (node.Slices.Count <= 1) { return(items.Values.ToArray()); } foreach (ElementTreeSlice slice in node.Slices.Skip(1)) { String shortDesc = $"{slice.ElementDefinition.Short} [{slice.ElementDefinition.Min}..{slice.ElementDefinition.Max}]"; String anchor = $"StructureDefinition-{sd.Name}-definitions.html#Observation.hasMember:{slice.ElementDefinition.SliceName}"; items.Add(shortDesc, $"<a href=\"{anchor}\">{shortDesc}</a>"); } return(items.Values.ToArray()); } String introName = sd.Url.LastUriPart(); String introPath = Path.Combine(this.pageDir, $"StructureDefinition-{introName}-intro.xml"); // Load and save will expand the macros. c.Load(introPath); { CodeBlockNested componentBlock = c.Blocks.Find("components"); if (componentBlock != null) { String[] componentItems = CollateComponents(); if (componentItems.Length > 0) { c.TryAddUserMacro("ComponentList", componentItems); componentBlock.Reload(); } else { componentBlock.Clear(); } } } { CodeBlockNested hasMemberBlock = c.Blocks.Find("hasMember"); if (hasMemberBlock != null) { String[] hasMembersItems = CollateHasMembers(); if (hasMembersItems.Length > 0) { c.TryAddUserMacro("HasMemberList", hasMembersItems); hasMemberBlock.Reload(); } else { hasMemberBlock.Clear(); } } } { CodeBlockNested fragBlock = c.Blocks.Find("profileFragments"); if (fragBlock != null) { String[] fragments = CollateFragments(); if (fragments.Length > 0) { c.TryAddUserMacro("FragmentList", fragments); fragBlock.Reload(); } else { fragBlock.Clear(); } } } c.Save(); }
public void SliceTest() { StructureDefinition s = this.CreateBaseObservation(); { ElementDefinition e = new ElementDefinition { ElementId = "Observation.code.coding", Path = "Observation.code.coding", Min = 0, Max = "*", Slicing = new ElementDefinition.SlicingComponent { ElementId = "4", Ordered = false, Rules = ElementDefinition.SlicingRules.Open } }; e.Slicing.Discriminator.Add(new ElementDefinition.DiscriminatorComponent { Type = ElementDefinition.DiscriminatorType.Value, Path = "code" }); s.Differential.Element.Add(e); } { ElementDefinition e = new ElementDefinition { ElementId = "Observation.code.coding:SliceName", SliceName = "SliceName", Path = "Observation.code.coding", Min = 1, Max = "1" }; e.Type.Add(new ElementDefinition.TypeRefComponent { Code = "Coding" }); s.Differential.Element.Add(e); } { ElementDefinition e = new ElementDefinition { ElementId = "Observation.code.coding:SliceName.system", Path = "Observation.code.coding.system", Min = 0, Max = "1", Fixed = new FhirUri("http://hl7.org/fhir/us/breast-radiology/CodeSystem/breastrad-BreastAbnormalityCodesCS") }; e.Type.Add(new ElementDefinition.TypeRefComponent { Code = "code" }); s.Differential.Element.Add(e); } { ElementDefinition e = new ElementDefinition { ElementId = "Observation.code.coding:SliceName.code", Path = "Observation.code.coding.code", Min = 0, Max = "1", Fixed = new Code("BreastAbnormalityObservationCode") }; e.Type.Add(new ElementDefinition.TypeRefComponent { Code = "code" }); s.Differential.Element.Add(e); } ElementTreeLoader loader = new ElementTreeLoader(info); ElementTreeNode head = loader.Create(s.Differential.Element); Assert.True(head.Slices.Count == 1); Assert.True(head.DefaultSlice.Nodes.Count == 1); Assert.True(head.TryGetElementNode("Observation.code.coding", out ElementTreeNode coding) == true); Assert.True(coding.Slices.Count == 2); Assert.True(head.TryGetElementNode("Observation.code.coding:SliceName.code", out coding) == true); }