コード例 #1
0
        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");
        }
コード例 #2
0
ファイル: ProcessItem.cs プロジェクト: Gjoll/FhirKhit
        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);
            }
        }
コード例 #3
0
        /// <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;
                    }
                }
            }
        }
コード例 #4
0
        /// <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));
        }
コード例 #5
0
ファイル: ProcessItem.cs プロジェクト: Gjoll/FhirKhit
        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);
        }
コード例 #6
0
        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);
        }
コード例 #7
0
        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);
        }
コード例 #8
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);
        }
コード例 #9
0
        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");
        }
コード例 #10
0
ファイル: ProcessItem.cs プロジェクト: Gjoll/FhirKhit
        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);
        }
コード例 #11
0
        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();
        }
コード例 #12
0
        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);
        }