示例#1
0
 internal static FHIRDefinedType?DetermineType(ElementDefinition definition, IElementNavigator instance)
 {
     if (definition.IsChoice())
     {
         if (instance.Type != null)
         {
             return(ModelInfo.FhirTypeNameToFhirType(instance.Type));
         }
         else
         {
             return(null);
         }
     }
     else
     {
         return(definition.Type.First().Code.Value);
     }
 }
            void merge(ElementDefinition snap, ElementDefinition diff, bool mergeElementId)
            {
                // [WMR 20160915] Important! Derived profiles should never inherit the ChangedByDiff extension
                // Caller should make sure that existing extensions have been removed from snap,
                // otherwise associated diff elems will be considered as changed (because they don't have the extension yet).

                // 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)
                {
                    // [WMR 20160906] WRONG! Must also handle snap.Path="Extension.value[x]" vs. diff.Path="Extension.extension.value[x]
                    // if (snap.Path.Substring(0, snap.Path.Length - 3) + diff.Type.First().Code.ToString().Capitalize() != diff.Path)
                    if (!ElementDefinitionNavigator.IsCandidateBasePath(snap.Path, diff.Path))
                    {
                        throw Error.InvalidOperation($"Invalid operation in snapshot generator. Path cannot be changed from '{snap.Path}' to '{diff.Path}', since the type is sliced to '{diff.Type.First().Code}'");
                    }
                    snap.PathElement = mergePrimitiveAttribute(snap.PathElement, diff.PathElement);
                }

                // [WMR 20170421] Element.Id is NOT inherited!
                // Merge custom Element id value from differential in same profile into snapshot
                // [WMR 20170424] NEW
                snap.ElementId = mergeId(snap, diff, mergeElementId);

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

                // Codes are cumulative based on the code value
                // [WMR 20180611] WRONG! Invalid elementComparer
                // snap.Code = mergeCollection(snap.Code, diff.Code, (a, b) => a.Code == b.Code);
                snap.Code = mergeCollection(snap.Code, diff.Code, isEqualCoding);

                // 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.
                // [WMR 20160906] Wrong! Merge extension element properties from base extension element
                //if (isExtensionConstraint)
                //{
                //    snap.Short = "Extension"; OnConstraint(snap.ShortElement);
                //    snap.Definition = "An Extension"; OnConstraint(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 collection has different semantics; any change replaces the inherited type (no item merging)
                // i.e. derived profiles can remove inherited types
                if (!diff.Type.IsNullOrEmpty() && !diff.Type.IsExactly(snap.Type))
                {
                    snap.Type = new List <ElementDefinition.TypeRefComponent>(diff.Type.DeepCopy());
                    foreach (var element in snap.Type)
                    {
                        onConstraint(element);
                    }
                }

                // 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);

                // [WMR 20160909] merge defaultValue and meaningWhenMissing, to handle core definitions; validator can detect invalid constraints
                snap.DefaultValue = mergeComplexAttribute(snap.DefaultValue, diff.DefaultValue);
                snap.MeaningWhenMissingElement = mergePrimitiveAttribute(snap.MeaningWhenMissingElement, diff.MeaningWhenMissingElement);

                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)
                // [WMR 20160917] Note: constraint keys must be unique. The validator will detect duplicate keys, so the derived
                // profile author can correct the conflicting constraint key.
                // [WMR 20160918] MUST merge indentical constraints, otherwise each derived profile accumulates
                // additional identical constraints inherited from e.g. BackboneElement.
                // snap.Constraint = mergeCollection(snap.Constraint, diff.Constraint, (a, b) => false);
                snap.Constraint = mergeCollection(snap.Constraint, diff.Constraint, (a, b) => a.IsExactly(b));

                // [WMR 20160907] merge conditions
                snap.ConditionElement = mergeCollection(snap.ConditionElement, diff.ConditionElement, (a, b) => a.Value == b.Value);

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

                // [WMR 20160907] Validator should catch this
                // 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);

                // [WMR 20160817] TODO: Merge extensions
                // Debug.WriteLineIf(diff.Extension != null && diff.GetChangedByDiff() == null, "[ElementDefnMerger] Warning: Extension merging is not supported yet...");

                // TODO: What happens to extensions present on an ElementDefinition that is overriding another?
                // [WMR 20160907] Merge extensions... match on url, diff completely overrides snapshot
                snap.Extension = mergeCollection(snap.Extension, diff.Extension, (s, d) => s.Url == d.Url);
            }
示例#3
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?
        }