Example #1
0
 public NavigatorPosition(ISourceNode current, IElementDefinitionSummary info, string name, string instanceType)
 {
     SerializationInfo = info;
     Node         = current ?? throw Error.ArgumentNull(nameof(current));
     InstanceType = instanceType;
     Name         = name ?? throw Error.ArgumentNull(nameof(name));
 }
        private static string determineInstanceType(object instance, IElementDefinitionSummary summary)
        {
            var typeName = !summary.IsChoiceElement && !summary.IsResource ?
                           summary.Type.Single().GetTypeName() : ((Base)instance).TypeName;

            return(ModelInfo.IsProfiledQuantity(typeName) ? "Quantity" : typeName);
        }
Example #3
0
 internal ElementNode(string name, object value, string instanceType, IElementDefinitionSummary definition)
 {
     Name         = name ?? throw new ArgumentNullException(nameof(name));
     InstanceType = instanceType;
     Value        = value;
     Definition   = definition;
 }
 private TypedElementOnSourceNode(TypedElementOnSourceNode parent, ISourceNode source, IElementDefinitionSummary definition, string instanceType, string prettyPath)
 {
     _source          = source;
     ShortPath        = prettyPath;
     Provider         = parent.Provider;
     ExceptionHandler = parent.ExceptionHandler;
     Definition       = definition;
     InstanceType     = instanceType;
     _settings        = parent._settings;
 }
        private PocoElementNode(Base instance, PocoElementNode parent, IElementDefinitionSummary definition, string location, string shortPath)
        {
            Current      = instance;
            _mySD        = new Lazy <PocoComplexTypeSerializationInfo>(() => (PocoComplexTypeSerializationInfo)PocoStructureDefinitionSummaryProvider.Provide(Current.GetType()));
            InstanceType = determineInstanceType(Current, definition);
            Definition   = definition ?? throw Error.ArgumentNull(nameof(definition));

            ExceptionHandler = parent.ExceptionHandler;
            Location         = location;
            ShortPath        = shortPath;
        }
 private PocoElementNode(object instance, PocoElementNode parent, string location, string shortPath, int arrayIndex,
                         IElementDefinitionSummary summary)
 {
     Current          = instance;
     InstanceType     = determineInstanceType(instance, summary);
     Provider         = parent.Provider;
     ExceptionHandler = parent.ExceptionHandler;
     Definition       = summary;
     Location         = location;
     ShortPath        = shortPath;
     ArrayIndex       = arrayIndex;
     Provider         = parent.Provider;
 }
 public ElementDefinitionSummary(IElementDefinitionSummary source)
 {
     ElementName         = source.ElementName;
     IsCollection        = source.IsCollection;
     IsChoiceElement     = source.IsChoiceElement;
     IsResource          = source.IsResource;
     Representation      = source.Representation;
     Type                = source.Type;
     Order               = source.Order;
     NonDefaultNamespace = source.NonDefaultNamespace;
     InSummary           = source.InSummary;
     IsRequired          = source.IsRequired;
 }
        private string deriveInstanceType(ISourceNode current, IElementDefinitionSummary info)
        {
            string instanceType          = null;
            var    resourceTypeIndicator = current.GetResourceTypeIndicator();

            if (info.IsResource)
            {
                instanceType = resourceTypeIndicator;
                if (instanceType == null)
                {
                    raiseTypeError($"Element '{current.Name}' should contain a resource, but does not actually contain one", current, location: current.Location);
                }
            }
            else if (!info.IsResource && resourceTypeIndicator != null)
            {
                raiseTypeError($"Element '{current.Name}' is not a contained resource, but seems to contain a resource of type '{resourceTypeIndicator}'.", current, location: current.Location);
                instanceType = resourceTypeIndicator;
            }
            else if (info.IsChoiceElement)
            {
                var suffix = current.Name.Substring(info.ElementName.Length);

                if (string.IsNullOrEmpty(suffix))
                {
                    raiseTypeError($"Choice element '{current.Name}' is not suffixed with a type.", current, location: current.Location);
                    instanceType = null;
                }
                else
                {
                    instanceType = info.Type
                                   .OfType <IStructureDefinitionReference>()
                                   .Select(t => t.ReferredType)
                                   .FirstOrDefault(t => string.Compare(t, suffix, StringComparison.OrdinalIgnoreCase) == 0);

                    if (string.IsNullOrEmpty(instanceType))
                    {
                        raiseTypeError($"Choice element '{current.Name}' is suffixed with unexpected type '{suffix}'", current, location: current.Location);
                    }
                }
            }
            else
            {
                var tp = info.Type.Single();
                instanceType = tp.GetTypeName();
            }

            return(instanceType);
        }
        private static void compareJson(string filename, Func <string, object> navCreator, string expected)
        {
            var nav = navCreator(expected);

            var outputBuilder = new StringBuilder();
            IElementDefinitionSummary serInfo = null;

            switch (nav)
            {
            case ISourceNode isn:
                serInfo = null;
                break;

            case ITypedElement ien:
                serInfo = ien.Definition;
                break;

            default:
                throw Error.InvalidOperation("Fix unit test");
            }

            var serializer = new FhirJsonBuilder(new FhirJsonSerializationSettings {
            });
            string output  = null;

            if (nav is ISourceNode isn2)
            {
                output = isn2.ToJson();
            }
            else if (nav is ITypedElement ien2)
            {
                output = ien2.ToJson();
            }
            else
            {
                throw Error.InvalidOperation("Fix unit test");
            }

            List <string> errors = new List <string>();

            JsonAssert.AreSame(filename, expected, output, errors);
            Console.WriteLine(String.Join("\r\n", errors));
            Assert.AreEqual(0, errors.Count, "Errors were encountered comparing converted content");
        }
Example #10
0
        public static void RoundtripXml(Func <string, object> navCreator)
        {
            var tp = File.ReadAllText(@"TestData\fp-test-patient.xml");

            // will allow whitespace and comments to come through
            var nav = navCreator(tp);

            var outputBuilder = new StringBuilder();
            IElementDefinitionSummary serInfo = null;

            switch (nav)
            {
            case ISourceNode isn:
                serInfo = null;
                break;

            case ITypedElement ien:
                serInfo = ien.Definition;
                break;

            default:
                throw Error.InvalidOperation("Fix unit test");
            }

            string output = null;

            if (nav is ISourceNode isn2)
            {
                output = isn2.ToXml();
            }
            else if (nav is ITypedElement ien2)
            {
                output = ien2.ToXml();
            }
            else
            {
                throw Error.InvalidOperation("Fix unit test");
            }

            XmlAssert.AreSame("fp-test-patient.xml", tp, output);
        }
Example #11
0
        private static void compareJson(Func <string, object> navCreator, string expected)
        {
            var nav = navCreator(expected);

            var outputBuilder = new StringBuilder();
            IElementDefinitionSummary serInfo = null;

            switch (nav)
            {
            case ISourceNode isn:
                serInfo = null;
                break;

            case ITypedElement ien:
                serInfo = ien.Definition;
                break;

            default:
                throw Error.InvalidOperation("Fix unit test");
            }

            var serializer = new FhirJsonBuilder(new FhirJsonSerializationSettings {
            });
            string output  = null;

            if (nav is ISourceNode isn2)
            {
                output = isn2.ToJson();
            }
            else if (nav is ITypedElement ien2)
            {
                output = ien2.ToJson();
            }
            else
            {
                throw Error.InvalidOperation("Fix unit test");
            }

            JsonAssert.AreSame(expected, output);
        }
Example #12
0
        public static ElementNode Root(IStructureDefinitionSummaryProvider provider, string type, string name = null, object value = null)
        {
            if (provider == null)
            {
                throw Error.ArgumentNull(nameof(provider));
            }
            if (type == null)
            {
                throw Error.ArgumentNull(nameof(type));
            }

            var sd = provider.Provide(type);
            IElementDefinitionSummary definition = null;

            // Should we throw if type is not found?
            if (sd != null)
            {
                definition = ElementDefinitionSummary.ForRoot(sd);
            }

            return(new ElementNode(name ?? type, value, type, definition));
        }
        internal bool MustSerializeMember(ITypedElement source, out IElementDefinitionSummary info)
        {
            info = source.Definition;

            if (info == null && !_roundtripMode)
            {
                var message = $"Element '{source.Location}' is missing type information.";

                if (_settings.IgnoreUnknownElements)
                {
                    ExceptionHandler.NotifyOrThrow(source, ExceptionNotification.Warning(
                                                       new MissingTypeInformationException(message)));
                }
                else
                {
                    ExceptionHandler.NotifyOrThrow(source, ExceptionNotification.Error(
                                                       new MissingTypeInformationException(message)));
                }

                return(false);
            }

            return(true);
        }
        private bool tryGetBySuffixedName(Dictionary <string, IElementDefinitionSummary> dis, string name, out IElementDefinitionSummary info)
        {
            // Simplest case, one on one match between name and element name
            if (dis.TryGetValue(name, out info))
            {
                return(true);
            }

            // Now, check the choice elements for a match
            // (this should actually be the longest match, but that's kind of expensive,
            // so as long as we don't add stupid ambiguous choices to a single type, this will work.
            info = dis.Where(kvp => name.StartsWith(kvp.Key) && kvp.Value.IsChoiceElement)
                   .Select(kvp => kvp.Value).FirstOrDefault();

            return(info != null);
        }
        private string deriveInstanceType(ISourceNode current, IElementDefinitionSummary info)
        {
            string instanceType          = null;
            var    resourceTypeIndicator = current.GetResourceTypeIndicator();

            if (info.IsResource)
            {
                instanceType = resourceTypeIndicator;
                if (instanceType == null)
                {
                    raiseTypeError($"Element '{current.Name}' should contain a resource, but does not actually contain one", current, location: current.Location);
                }
            }
            else if (!info.IsResource && resourceTypeIndicator != null)
            {
                raiseTypeError($"Element '{current.Name}' is not a contained resource, but seems to contain a resource of type '{resourceTypeIndicator}'.", current, location: current.Location);
                instanceType = resourceTypeIndicator;
            }
            else if (info.IsChoiceElement)
            {
                var suffix = current.Name.Substring(info.ElementName.Length);

                if (string.IsNullOrEmpty(suffix))
                {
                    raiseTypeError($"Choice element '{current.Name}' is not suffixed with a type.", current, location: current.Location);
                    instanceType = null;
                }
                else
                {
                    instanceType = info.Type
                                   .OfType <IStructureDefinitionReference>()
                                   .Select(t => t.ReferredType)
                                   .FirstOrDefault(t => string.Compare(t, suffix, System.StringComparison.OrdinalIgnoreCase) == 0);

                    if (string.IsNullOrEmpty(instanceType))
                    {
                        raiseTypeError($"Choice element '{current.Name}' is suffixed with unexpected type '{suffix}'", current, location: current.Location);
                    }
                }
            }
            else if (info.Representation == XmlRepresentation.TypeAttr) // May be used by models other then FHIR, e.g. CCDA represented by a StructureDefinition
            {
                if (info.Type.Count() == 1)
                {
                    instanceType = info.Type.Single().GetTypeName();
                }
                else
                {
                    var typeName = current.Children("type").FirstOrDefault()?.Text;
                    if (typeName != null)
                    {
                        instanceType = info.Type.Where(type => typeFromLogicalModelCanonical(type).Equals(typeName)).FirstOrDefault()?.GetTypeName();
                    }
                    else
                    {
                        instanceType = info.DefaultTypeName;
                    }
                }
            }
            else
            {
                var tp = info.Type.Single();
                instanceType = tp.GetTypeName();
            }

            return(instanceType);
        }
        private string deriveInstanceType(ISourceNode current, IElementDefinitionSummary info)
        {
            var resourceTypeIndicator = current.GetResourceTypeIndicator();

            // First, handle the case where this (appears to be) a resource.
            if (info.IsResource)
            {
                if (resourceTypeIndicator == null)
                {
                    raiseTypeError($"Element '{current.Name}' should contain a resource, but does not actually contain one", current, location: current.Location);
                }
                return(resourceTypeIndicator);
            }
            else if (resourceTypeIndicator != null)
            {
                raiseTypeError($"Element '{current.Name}' is not a contained resource, but seems to contain a resource of type '{resourceTypeIndicator}'.", current, location: current.Location);
                return(resourceTypeIndicator);
            }

            // Now, it's a data element. But is a choice, so we need to take
            // a look at the suffix on the element's name to figure out what we
            // are dealing with.
            if (info.IsChoiceElement)
            {
                var suffix = current.Name.Substring(info.ElementName.Length);

                if (string.IsNullOrEmpty(suffix))
                {
                    raiseTypeError($"Choice element '{current.Name}' is not suffixed with a type.", current, location: current.Location);
                    return(null);
                }

                suffix = normalizeSuffix(suffix);

                // If any of the types is the abstract 'DataType' type, we'll just
                // accept whatever type is mentioned, we have no real list to go on =>
                // An example of where this happens is Extension.value[x], which is
                // a POCO that is common to all (FHIR) datamodels, and since value[x] is an
                // "open" types, we have no idea which types are allowed.
                if (info.Type.Any(t => t.GetTypeName() == "DataType"))
                {
                    return(suffix);
                }
                else
                {
                    var isListed = info.Type
                                   .OfType <IStructureDefinitionReference>()
                                   .Select(t => t.ReferredType)
                                   .Any(t => t == suffix);

                    if (!isListed)
                    {
                        raiseTypeError($"Choice element '{current.Name}' is suffixed with unexpected type '{suffix}'", current, location: current.Location);
                    }

                    return(suffix);
                }

                string normalizeSuffix(string s)
                {
                    // Unfortunately, we decided to nicely capitalize the suffix, even for
                    // primitives - luckily then, there's just a single list of primitives,
                    // so we can "correct" them
                    return(_suffixMap.TryGetValue(s, out var corrected) ? corrected : s);
                };
            }
            else if (info.Representation == XmlRepresentation.TypeAttr) // May be used by models other then FHIR, e.g. CCDA represented by a StructureDefinition
            {
                if (info.Type.Count() == 1)
                {
                    return(info.Type.Single().GetTypeName());
                }
                else
                {
                    var typeName = current.Children("type").FirstOrDefault()?.Text;
                    return(typeName != null
                        ? info.Type.Where(type => typeFromLogicalModelCanonical(type).Equals(typeName)).FirstOrDefault()?.GetTypeName()
                        : info.DefaultTypeName);
                }
            }

            var tp = info.Type.Single();

            return(tp.GetTypeName());
        }