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? }
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? }