public void KeepsAnnotations()
        {
            var patient = createPatient();

            ITypedElement identifier = patient["active"][0];

            Assert.Equal("a string annotation", identifier.Annotation <string>());
        }
Esempio n. 2
0
        private void addChildren(ITypedElement node, JObject parent)
        {
            var resourceTypeIndicator = node.Annotation <IResourceTypeSupplier>()?.ResourceType;
            var isResource            = node.Definition?.IsResource ?? resourceTypeIndicator != null;
            var containedResourceType = isResource ? (node.InstanceType ?? resourceTypeIndicator) : null;

            if (containedResourceType != null)
            {
                parent.AddFirst(new JProperty(JsonSerializationDetails.RESOURCETYPE_MEMBER_NAME, containedResourceType));
            }

            foreach (var nameGroup in node.Children().GroupBy(n => n.Name))
            {
                var members = nameGroup.ToList();

                // serialization info should be the same for each element in an
                // array - but do not explicitly check that
                if (!MustSerializeMember(members[0], out var generalInfo))
                {
                    break;
                }
                bool hasTypeInfo = generalInfo != null;

                // If we have type information, we know whather we need an array.
                // failing that, check whether this is a roundtrip and we have the information
                // about arrays in the serialization deails. Failing that, assume the default:
                // for unknown properties is to use an array - safest bet.
                var generalJsonDetails = members[0].GetJsonSerializationDetails();
                var hasIndex           = generalJsonDetails?.ArrayIndex != null;
                var needsArray         = generalInfo?.IsCollection ?? hasIndex;

                var children = members.Select(m => buildNode(m))
                               .Where(c => !(c.first == null && c.second == null)).ToList();

                // Don't add empty nodes to the parent
                if (!children.Any())
                {
                    continue;
                }

                var needsMainProperty   = children.Any(c => c.first != null);
                var needsShadowProperty = children.Any(c => c.second != null);
                var propertyName        = generalInfo?.IsChoiceElement == true ?
                                          members[0].Name + members[0].InstanceType.Capitalize() : members[0].Name;

                if (needsMainProperty)
                {
                    parent.Add(new JProperty(propertyName,
                                             needsArray ? new JArray(children.Select(c => c.first ?? JValue.CreateNull())) : children[0].first));
                }

                if (needsShadowProperty)
                {
                    parent.Add(new JProperty("_" + propertyName,
                                             needsArray ? new JArray(children.Select(c => (JToken)c.second ?? JValue.CreateNull())) : (JToken)children[0].second));
                }
            }
        }
Esempio n. 3
0
        public MaskingNode(ITypedElement source, MaskingNodeSettings settings = null)
        {
            if (source == null)
            {
                throw Error.ArgumentNull(nameof(source));
            }
            if (source.Annotation <ScopedNode>() == null)
            {
                throw Error.Argument("MaskingNavigator can only be used on a navigator chain that contains a ScopedNavigator", nameof(source));
            }

            Source    = source;
            _settings = settings?.Clone() ?? new MaskingNodeSettings();

            if (Source is IExceptionSource ies && ies.ExceptionHandler == null)
            {
                ies.ExceptionHandler = (o, a) => ExceptionHandler.NotifyOrThrow(o, a);
            }
        }
Esempio n. 4
0
        public static void CanReadThroughNavigator(ITypedElement n, bool typed)
        {
            Assert.AreEqual("Patient", n.Name);
            Assert.AreEqual("Patient", n.Annotation <IResourceTypeSupplier>()?.ResourceType);
            if (typed)
            {
                Assert.AreEqual("Patient", n.InstanceType);
            }

            var nav = n.Children().GetEnumerator();

            Assert.IsTrue(nav.MoveNext());
            Assert.AreEqual("id", nav.Current.Name);
            Assert.AreEqual("pat1", nav.Current.Value);
            if (typed)
            {
                Assert.AreEqual("id", nav.Current.InstanceType);
            }

            Assert.IsFalse(nav.Current.Children().Any());

            Assert.IsTrue(nav.MoveNext());
            Assert.AreEqual("text", nav.Current.Name);
            if (typed)
            {
                Assert.AreEqual("Narrative", nav.Current.InstanceType);
            }

            var text = n.Children("text").Children().GetEnumerator();

            Assert.IsTrue(text.MoveNext()); // status
            if (typed)
            {
                Assert.AreEqual("code", text.Current.InstanceType);
            }
            Assert.AreEqual("generated", text.Current.Value);

            Assert.IsTrue(text.MoveNext());
            Assert.AreEqual("div", text.Current.Name);
            Assert.IsTrue(((string)text.Current.Value).StartsWith("<div xmlns="));       // special handling of xhtml
            if (typed)
            {
                Assert.AreEqual("xhtml", text.Current.InstanceType);
            }

            Assert.IsFalse(text.Current.Children().Any()); // cannot move into xhtml
            Assert.AreEqual("div", text.Current.Name);     // still on xhtml <div>
            var b = text.MoveNext();

            Assert.IsFalse(b);             // nothing more in <text>

            Assert.IsTrue(nav.MoveNext()); // contained
            Assert.AreEqual("contained", nav.Current.Name);
            Assert.AreEqual("Patient", nav.Current.Annotation <IResourceTypeSupplier>().ResourceType);
            if (typed)
            {
                Assert.AreEqual("Patient", nav.Current.InstanceType);
            }

            var contained = nav.Current.Children().GetEnumerator();

            Assert.IsTrue(contained.MoveNext()); // id
            if (typed)
            {
                Assert.AreEqual("id", contained.Current.InstanceType);
            }
            Assert.IsTrue(contained.MoveNext()); // identifier
            Assert.AreEqual("identifier", contained.Current.Name);
            if (typed)
            {
                Assert.AreEqual("Identifier", contained.Current.InstanceType);
            }

            var identifier = contained.Current.Children().GetEnumerator();

            Assert.IsTrue(identifier.MoveNext()); // system
            Assert.IsTrue(identifier.MoveNext()); // value
            var ic = identifier.Current;

            Assert.IsFalse(identifier.MoveNext()); // still value

            Assert.AreEqual("value", ic.Name);
            Assert.IsFalse(ic.Children().Any());
            Assert.AreEqual("444222222", ic.Value); // tests whether strings are trimmed

            var name = n.Children("contained").First().Children("name").First();

            Assert.AreEqual("name", name.Name);
            var inname = name.Children().ToList();

            Assert.IsTrue(inname.Any());
            Assert.AreEqual("id", inname[0].Name);
            Assert.AreEqual("firstname", inname[0].Value);
            Assert.AreEqual("use", inname[1].Name);

            var bd = n.Children("birthDate").Single();

            if (typed)
            {
                Assert.AreEqual("date", bd.InstanceType);
                Assert.AreEqual(PartialDateTime.Parse("1974-12-25"), bd.Value);
            }
            else
            {
                Assert.AreEqual("1974-12-25", bd.Value);
            }



            if (typed)
            {
                var dec = n.Children("deceased").Single();
                Assert.AreEqual("boolean", dec.InstanceType);
                Assert.AreEqual(false, dec.Value);
            }
            else
            {
                var dec = n.Children("deceasedBoolean").Single();
                Assert.AreEqual("false", dec.Value);
            }
        }
        private void build(ITypedElement source, XContainer parent)
        {
            var xmlDetails     = source.GetXmlSerializationDetails();
            var sourceComments = (source as IAnnotated)?.Annotation <SourceComments>();

            if (!MustSerializeMember(source, out var serializationInfo))
            {
                return;
            }
            bool hasTypeInfo = serializationInfo != null;

            var value = source.Value != null?
                        PrimitiveTypeConverter.ConvertTo <string>(source.Value) : null;

            if (_settings.TrimWhitespaces)
            {
                value = value?.Trim();
            }

            // xhtml children require special treament:
            // - They don't use an xml "value" attribute to represent the value, instead their Value is inserted verbatim into the parent
            // - They cannot have child nodes - the "Value" on the node contains all children as raw xml text
            var isXhtml = source.InstanceType == "xhtml" ||
                          serializationInfo?.Representation == XmlRepresentation.XHtml ||
                          xmlDetails?.Namespace?.GetName("div") == XmlNs.XHTMLDIV;

            if (isXhtml && !String.IsNullOrWhiteSpace(value))
            {
                // The value *should* be valid xhtml - however if people just provide a plain
                // string, lets add a <div> around it.
                if (!value.TrimStart().StartsWith("<div"))
                {
                    value = $"<div xmlns='http://www.w3.org/1999/xhtml'>{value}</div>";
                }

                var      sanitized = SerializationUtil.SanitizeXml(value);
                XElement xe        = XElement.Parse(sanitized);

                // The div should be in the XHTMLNS namespace, correct if it
                // is not the case.
                xe.Name = XmlNs.XHTMLNS + xe.Name.LocalName;
                parent.Add(xe);

                //using (var divWriter = parent.CreateWriter())
                //using (var nodeReader = SerializationUtil.XmlReaderFromXmlText(value))
                //    divWriter.WriteNode(nodeReader, false);
                return;
            }

            var usesAttribute = serializationInfo?.Representation == XmlRepresentation.XmlAttr ||
                                (xmlDetails?.NodeType == XmlNodeType.Attribute);
            var ns = serializationInfo?.NonDefaultNamespace ??
                     xmlDetails?.Namespace.NamespaceName ??
                     (usesAttribute ? "" : XmlNs.FHIR);
            bool atRoot    = parent is XDocument;
            var  localName = serializationInfo?.IsChoiceElement == true ?
                             source.Name + source.InstanceType.Capitalize() : source.Name;

            // If the node is represented by an attribute (e.g. an "id" child), write
            // an attribute with the child's name + the child's Value into the parent
            if (usesAttribute && !String.IsNullOrWhiteSpace(value) && !atRoot)
            {
                parent.Add(new XAttribute(XName.Get(localName, ns), value));
                return;
            }
            // else: fall through - value will be serialized as an element

            var me = new XElement(XName.Get(localName, ns));

            if (xmlDetails?.SchemaLocation != null)
            {
                me.Add(new XAttribute(XmlNs.XSCHEMALOCATION, xmlDetails.SchemaLocation));
            }

            // If the node has a value, add the standard FHIR value attribute
            if (value != null)
            {
                me.Add(new XAttribute("value", value));
            }

            // If this needs to be serialized as a contained resource, do so
            var containedResourceType = atRoot ? null :
                                        (serializationInfo?.IsResource == true ?
                                         source.InstanceType :
                                         source.Annotation <IResourceTypeSupplier>()?.ResourceType);

            XElement containedResource = null;

            if (containedResourceType != null)
            {
                containedResource = new XElement(XName.Get(containedResourceType, ns));
            }

            var childParent = containedResource ?? me;

            // Now, do the same for the children
            // xml requires a certain order, so let's make sure we serialize in the right order
            var orderedChildren = source.Children().OrderBy(c => c.Definition?.Order ?? 0);

            foreach (var child in orderedChildren)
            {
                build(child, childParent);
            }

            if (serializationInfo?.Representation == XmlRepresentation.XmlText || xmlDetails?.NodeText != null)
            {
                childParent.Add(new XText(value ?? xmlDetails.NodeText));
            }

            if (sourceComments?.ClosingComments != null)
            {
                writeComments(sourceComments.ClosingComments, me);
            }

            // Only really add this contained resource to me when it has contents
            if (containedResource != null && (containedResource.HasAttributes || containedResource.HasElements))
            {
                me.Add(containedResource);
            }

            // Only add myself to my parent if I have content, or I am the root
            if (value != null || me.HasElements || atRoot)
            {
                if (sourceComments?.CommentsBefore != null)
                {
                    writeComments(sourceComments.CommentsBefore, parent);
                }

                parent.Add(me);
            }

            if (atRoot && parent.Elements().Any() && sourceComments?.DocumentEndComments != null)
            {
                writeComments(sourceComments.DocumentEndComments, parent);
            }
        }
Esempio n. 6
0
 private ScopedNode getScope(ITypedElement node) =>
 node.Annotation <ScopedNode>();