/// <summary>
        /// Creates a differential structure with all "skipped" parents filled in.
        /// </summary>
        /// <param name="differential"></param>
        /// <returns>The full tree structure representing the differential</returns>
        /// <remarks>This operation will not touch the source differential, but instead will return a new structure.</remarks>
        public Profile.ConstraintComponent MakeTree()
        {
            var diff = (Profile.ConstraintComponent)_source.DeepCopy();   // We're going to modify the differential

            if (diff.Element == null || diff.Element.Count == 0) return diff;        // nothing to do

            var index = 0;
            var elements = diff.Element;
            while (index < elements.Count)
            {
                var thisPath = elements[index].Path;
                var prevPath = index > 0 ? elements[index - 1].Path : String.Empty;

                if (thisPath.IndexOf('.') == -1)
                {
                    // I am a root node, just one segment of path, I need to be the first element
                    if (index != 0) throw Error.InvalidOperation("Differential has multiple roots");

                    // Else, I am fine, proceed
                    index++;
                }
                else if (ElementNavigator.IsSibling(thisPath, prevPath) || ElementNavigator.IsDirectChildPath(prevPath, thisPath))
                {
                    // The previous path is a sibling, or my direct parent, so everything is alright, proceed to next node
                    index++;
                }
                else
                {
                    var parentPath = ElementNavigator.GetParentPath(thisPath);

                    if (prevPath == String.Empty || !prevPath.StartsWith(parentPath + "."))
                    {
                        // We're missing a path part, insert an empty parent                    
                        var parentElement = new Profile.ElementComponent() { Path = parentPath };
                        elements.Insert(index, parentElement);

                        // Now, we're not sure this parent has parents, so proceed by checking the parent we have just inserted
                        // so -> index is untouched
                    }
                    else
                    {
                        // So, my predecessor an I share ancestry, of which I am sure it has been inserted by this algorithm
                        // before because of my predecessor, so we're fine.
                        index++;
                    }
                }
            }

            return diff;
        }
        public void TestChildAlterations()
        {
            var nav = createTestNav();

            var newENode = new Profile.ElementComponent() { Path = "X.Y.E" };
            var newC3Node = new Profile.ElementComponent() { Path = "X.Y.C3" };

            Assert.IsTrue(nav.JumpToFirst("A.B.C1.D"));
            Assert.IsTrue(nav.InsertFirstChild(newENode));
            Assert.AreEqual(8,nav.OrdinalPosition);
            Assert.IsTrue(nav.MoveToParent());
            Assert.AreEqual("A.B.C1.D", nav.Path);
            Assert.IsTrue(nav.MoveToFirstChild());
            Assert.IsTrue(nav.Delete());   
            Assert.AreEqual("A.B.C1.D", nav.Path);  // should have moved back to parent (single child deleted)

            Assert.IsTrue(nav.JumpToFirst("A.D"));
            Assert.IsTrue(nav.InsertFirstChild(newENode));
            Assert.AreEqual(9,nav.OrdinalPosition);
            Assert.IsTrue(nav.MoveToParent());
            Assert.AreEqual("A.D", nav.Path);
            Assert.IsTrue(nav.MoveToFirstChild());
            Assert.IsTrue(nav.Delete());   
            Assert.AreEqual("A.D", nav.Path);  // should have moved back to parent (single child deleted)

            nav.Reset();
            Assert.IsTrue(nav.MoveToFirstChild());
            Assert.IsTrue(nav.MoveToFirstChild()); // A.B
            Assert.IsTrue(nav.AppendChild(newC3Node));
            Assert.AreEqual("A.B.C3",nav.Path);
            Assert.AreEqual(4, nav.OrdinalPosition);

            Assert.IsTrue(nav.Delete());
            Assert.AreEqual(3, nav.OrdinalPosition);
            Assert.IsTrue(nav.MoveToPrevious());        // A.B.C1
            Assert.IsTrue(nav.Delete());
            Assert.AreEqual(2, nav.OrdinalPosition);
            Assert.IsTrue(nav.Delete());
            Assert.AreEqual(1, nav.OrdinalPosition);    // Moved back to parent?
        }
        public void TestSiblingAlterations()
        {
            var nav = createTestNav();
            var newCNode = new Profile.ElementComponent() { Path = "X.C" };

            Assert.AreEqual(9, nav.Count);

            nav.MoveToFirstChild();
            Assert.IsTrue(nav.MoveToChild("D"));
            Assert.IsTrue(nav.InsertBefore(newCNode));
            Assert.AreEqual("A.C", nav.Path);
            Assert.AreEqual(8, nav.OrdinalPosition);
            Assert.AreEqual(10, nav.Count);

            Assert.IsTrue(nav.Delete());    // delete new "C" node we just created
            Assert.AreEqual(8, nav.OrdinalPosition);
            Assert.AreEqual(9, nav.Count);

            Assert.IsTrue(nav.MoveToPrevious()); // 3rd "A.B" node
            Assert.IsTrue(nav.InsertAfter(newCNode));
            Assert.AreEqual("A.C", nav.Path);
            Assert.AreEqual(8, nav.OrdinalPosition);
            Assert.AreEqual(10, nav.Count);

            Assert.IsTrue(nav.Delete());    // delete new "C" node we just created
            Assert.AreEqual(8, nav.OrdinalPosition); 
            Assert.AreEqual(9, nav.Count);

            Assert.IsTrue(nav.InsertAfter(newCNode));
            Assert.AreEqual("A.C", nav.Path);
            Assert.AreEqual(9, nav.OrdinalPosition);
            Assert.AreEqual(10, nav.Count);

            Assert.IsTrue(nav.Delete());    // delete new "C" node we just created
            Assert.AreEqual(8, nav.OrdinalPosition);
            Assert.AreEqual(9, nav.Count);

            Assert.IsTrue(nav.MoveToParent());
            Assert.IsTrue(nav.MoveToFirstChild());
            Assert.IsTrue(nav.InsertBefore(newCNode));
            Assert.AreEqual("A.C", nav.Path);
            Assert.AreEqual(1, nav.OrdinalPosition);
            Assert.AreEqual(10, nav.Count);
        }
        private Profile.ElementComponent createSliceEntry(Profile.ElementComponent baseDefn, Profile.ElementComponent diff)
        {
            var slicingEntry = new Profile.ElementComponent();

            slicingEntry.PathElement = (FhirString)baseDefn.PathElement.DeepCopy();
            if (diff.Name != null) slicingEntry.NameElement = (FhirString)diff.NameElement.DeepCopy();

            if (diff.Slicing != null) slicingEntry.Slicing = (Profile.ElementSlicingComponent)diff.Slicing.DeepCopy();
            
            slicingEntry.Definition = (Profile.ElementDefinitionComponent)baseDefn.Definition.DeepCopy();

            // If the differential overrides the elementdefn, only some of the fields go into the slicing entry
            if (diff.Definition != null)
            {
                if (diff.Definition.CommentsElement != null) slicingEntry.Definition.CommentsElement = (FhirString)diff.Definition.CommentsElement.DeepCopy();
                if (diff.Definition.ShortElement != null) slicingEntry.Definition.ShortElement = (FhirString)diff.Definition.ShortElement.DeepCopy();
                if (diff.Definition.FormalElement != null) slicingEntry.Definition.FormalElement = (FhirString)diff.Definition.FormalElement.DeepCopy();
                if (diff.Definition.MinElement != null) slicingEntry.Definition.MinElement = (Integer)diff.Definition.MinElement.DeepCopy();
                if (diff.Definition.MaxElement != null) slicingEntry.Definition.MaxElement = (FhirString)diff.Definition.MaxElement.DeepCopy();
            }

            return slicingEntry;
        }
Esempio n. 5
0
        private Profile.ElementComponent createExtensionSlicingEntry(string path)
        {
            // Create a pre-fab extension slice, filled with sensible defaults
            var result = new Profile.ElementComponent();
            result.Path = path;
            result.Slicing = new Profile.ElementSlicingComponent();
            result.Slicing.Discriminator = "url";
            result.Slicing.Ordered = false;
            result.Slicing.Rules = Profile.SlicingRules.Open;

            return result;
        }