Example #1
0
        public void Merge(ElementDefinition snap, ElementDefinition diff)
        {
            bool isExtensionConstraint = snap.Path == "Extension" || snap.IsExtension();

            // representation cannot be overridden

            snap.NameElement = mergePrimitiveAttribute(snap.NameElement, diff.NameElement);

            // Codes are cumulative based on the code value
            snap.Code = mergeCollection(snap.Code, diff.Code, (a, b) => a.Code == b.Code);

            // For extensions, the base definition is irrelevant since they describe infrastructure, and the diff should contain the real meaning for the elements
            // In case the diff doesn't have these, give some generic defaults.
            if (isExtensionConstraint)
            {
                snap.Short        = "Extension"; markChange(snap.ShortElement);
                snap.Definition   = "An Extension"; markChange(snap.DefinitionElement);
                snap.Comments     = null;
                snap.Requirements = null;
                snap.Label        = "Extension"; markChange(snap.LabelElement);
                snap.AliasElement = new List <FhirString>();
                snap.Mapping      = new List <ElementDefinition.ElementDefinitionMappingComponent>();
            }
            else
            {
                snap.ShortElement        = mergePrimitiveAttribute(snap.ShortElement, diff.ShortElement);
                snap.DefinitionElement   = mergePrimitiveAttribute(snap.DefinitionElement, diff.DefinitionElement, allowAppend: true);
                snap.CommentsElement     = mergePrimitiveAttribute(snap.CommentsElement, diff.CommentsElement, allowAppend: true);
                snap.RequirementsElement = mergePrimitiveAttribute(snap.RequirementsElement, diff.RequirementsElement, allowAppend: true);
                snap.LabelElement        = mergePrimitiveAttribute(snap.LabelElement, diff.LabelElement);

                // Aliases are cumulative based on the string value
                snap.AliasElement = mergeCollection(snap.AliasElement, diff.AliasElement, (a, b) => a.Value == b.Value);

                // Mappings are cumulative, but keep unique on full contents
                snap.Mapping = mergeCollection(snap.Mapping, diff.Mapping, (a, b) => a.IsExactly(b));
            }

            snap.MinElement = mergePrimitiveAttribute(snap.MinElement, diff.MinElement);
            snap.MaxElement = mergePrimitiveAttribute(snap.MaxElement, diff.MaxElement);

            // ElementDefinition.nameReference cannot be overridden by a derived profile

            // defaultValue and meaningWhenMissing can only be set in a resource/datatype/extension definition and cannot be overridden

            snap.Fixed   = mergeComplexAttribute(snap.Fixed, diff.Fixed);
            snap.Pattern = mergeComplexAttribute(snap.Pattern, diff.Pattern);
            snap.Example = mergeComplexAttribute(snap.Example, diff.Example);

            snap.MaxLengthElement = mergePrimitiveAttribute(snap.MaxLengthElement, diff.MaxLengthElement);

            // TODO: [GG] what to do about conditions?  [EK] We have key, so merge Constraint and condition based on that?

            snap.MustSupportElement = mergePrimitiveAttribute(snap.MustSupportElement, diff.MustSupportElement);

            // ElementDefinition.isModifier can only be overridden by a derived extension
            if (isExtensionConstraint)
            {
                snap.IsModifierElement = mergePrimitiveAttribute(snap.IsModifierElement, diff.IsModifierElement);
            }

            snap.IsSummaryElement = mergePrimitiveAttribute(snap.IsSummaryElement, diff.IsSummaryElement);

            snap.Binding = mergeComplexAttribute(snap.Binding, diff.Binding);

            // Type is just overridden
            if (!diff.Type.IsNullOrEmpty() && !diff.IsExactly(snap))
            {
                snap.Type = new List <ElementDefinition.TypeRefComponent>(diff.Type.DeepCopy());
                foreach (var element in snap.Type)
                {
                    markChange(snap);
                }
            }


            // Constraints are cumulative bassed on Constraint.id
            snap.Constraint = mergeCollection(snap.Constraint, diff.Constraint, (a, b) => a.Key == b.Key);

            snap.Slicing = mergeComplexAttribute(snap.Slicing, diff.Slicing);

            // TODO: What happens to extensions present on an ElementDefinition that is overriding another?
        }
Example #2
0
        public void Merge(ElementDefinition snap, ElementDefinition diff)
        {
            bool isExtensionConstraint = snap.Path == "Extension" || snap.IsExtension();

            // paths can be changed under one circumstance: the snap is a choice[x] element, and diff limits the type choices
            // to one. The name can then be changed to choiceXXXX, where XXXX is the name of the type.
            if (snap.Path != diff.Path && snap.IsChoice() && diff.Type.Count() == 1)
            {
                if (snap.Path.Substring(0, snap.Path.Length - 3) + diff.Type.First().Code.ToString().Capitalize() != diff.Path)
                {
                    throw Error.InvalidOperation("Path cannot be changed from {0} to {1}, since the type is sliced to {2}"
                                                 .FormatWith(snap.Path, diff.Path, diff.Type.First().Code));
                }

                snap.PathElement = mergePrimitiveAttribute(snap.PathElement, diff.PathElement);
            }

            // representation cannot be overridden
            snap.NameElement = mergePrimitiveAttribute(snap.NameElement, diff.NameElement);

            // Codes are cumulative based on the code value
            snap.Code = mergeCollection(snap.Code, diff.Code, (a, b) => a.Code == b.Code);

            // For extensions, the base definition is irrelevant since they describe infrastructure, and the diff should contain the real meaning for the elements
            // In case the diff doesn't have these, give some generic defaults.
            if (isExtensionConstraint)
            {
                snap.Short        = "Extension"; markChange(snap.ShortElement);
                snap.Definition   = "An Extension"; markChange(snap.DefinitionElement);
                snap.Comments     = null;
                snap.Requirements = null;
                snap.AliasElement = new List <FhirString>();
                snap.Mapping      = new List <ElementDefinition.MappingComponent>();
            }

            snap.ShortElement        = mergePrimitiveAttribute(snap.ShortElement, diff.ShortElement);
            snap.DefinitionElement   = mergePrimitiveAttribute(snap.DefinitionElement, diff.DefinitionElement, allowAppend: true);
            snap.CommentsElement     = mergePrimitiveAttribute(snap.CommentsElement, diff.CommentsElement, allowAppend: true);
            snap.RequirementsElement = mergePrimitiveAttribute(snap.RequirementsElement, diff.RequirementsElement, allowAppend: true);
            snap.LabelElement        = mergePrimitiveAttribute(snap.LabelElement, diff.LabelElement);

            // Aliases are cumulative based on the string value
            snap.AliasElement = mergeCollection(snap.AliasElement, diff.AliasElement, (a, b) => a.Value == b.Value);

            // Mappings are cumulative, but keep unique on full contents
            snap.Mapping = mergeCollection(snap.Mapping, diff.Mapping, (a, b) => a.IsExactly(b));

            snap.MinElement = mergePrimitiveAttribute(snap.MinElement, diff.MinElement);
            snap.MaxElement = mergePrimitiveAttribute(snap.MaxElement, diff.MaxElement);

            // snap.base should already be there, and is not changed by the diff

            // Type is just overridden
            if (!diff.Type.IsNullOrEmpty() && !diff.IsExactly(snap))
            {
                snap.Type = new List <ElementDefinition.TypeRefComponent>(diff.Type.DeepCopy());
                foreach (var element in snap.Type)
                {
                    markChange(snap);
                }
            }

            // ElementDefinition.nameReference cannot be overridden by a derived profile
            // defaultValue and meaningWhenMissing can only be set in a resource/datatype/extension definition and cannot be overridden

            snap.Fixed    = mergeComplexAttribute(snap.Fixed, diff.Fixed);
            snap.Pattern  = mergeComplexAttribute(snap.Pattern, diff.Pattern);
            snap.Example  = mergeComplexAttribute(snap.Example, diff.Example);
            snap.MinValue = mergeComplexAttribute(snap.MinValue, diff.MinValue);
            snap.MaxValue = mergeComplexAttribute(snap.MaxValue, diff.MaxValue);

            snap.MaxLengthElement = mergePrimitiveAttribute(snap.MaxLengthElement, diff.MaxLengthElement);

            // TODO: [GG] what to do about conditions?  [EK] We have key, so merge Constraint and condition based on that?
            // Constraints are cumulative, so they are always "new" (hence a constant false for the comparer)
            snap.Constraint = mergeCollection(snap.Constraint, diff.Constraint, (a, b) => false);

            snap.MustSupportElement = mergePrimitiveAttribute(snap.MustSupportElement, diff.MustSupportElement);

            // ElementDefinition.isModifier can only be overridden by a derived extension
            if (isExtensionConstraint)
            {
                snap.IsModifierElement = mergePrimitiveAttribute(snap.IsModifierElement, diff.IsModifierElement);
            }

            snap.IsSummaryElement = mergePrimitiveAttribute(snap.IsSummaryElement, diff.IsSummaryElement);

            snap.Binding = mergeComplexAttribute(snap.Binding, diff.Binding);

            snap.Slicing = mergeComplexAttribute(snap.Slicing, diff.Slicing);

            // TODO: What happens to extensions present on an ElementDefinition that is overriding another?
        }