コード例 #1
0
        public void GenerateSchematronAssertion_Attribute_Value_DataType_ConformanceSHALL_CardinalityOneToOne()
        {
            var attr = new DocumentTemplateElementAttribute("code", "57024-2")
            {
                DataType = "CE"
            };
            //create schematron assertion line builder, build one at a time (regular interface, see above for fluent interface)
            var builder = new AssertionLineBuilder(attr, templateIdentifierXpath, templateVersionIdentifierXpath);
            //define cardinality
            var cardinality = CardinalityParser.Parse("1..1");

            //add cardinality for the element
            builder.WithCardinality(cardinality);
            //define conformance
            var conformance = ConformanceParser.Parse("SHALL");

            //add conformance for the element
            builder.ConformsTo(conformance);
            //generate string
            string assertion = builder.ToString();
            //did we generate the correct string?
            string expected = @"count(self::node()[@code='57024-2'])=1";

            Assert.IsTrue(assertion == expected, "Assertion string was not correct. Expected '{0}', Actual '{1}'.", expected, assertion);
        }
コード例 #2
0
 static public void AddElementValueAndDataType(string aPrefix, DocumentTemplateElement aElement, IConstraint aTemplateConstraint)
 {
     if (!string.IsNullOrEmpty(aTemplateConstraint.Value))
     {
         if (!string.IsNullOrEmpty(aTemplateConstraint.ValueConformance))
         {
             var valueConformanceType = ConformanceParser.Parse(aTemplateConstraint.ValueConformance);
             var conformanceType      = ConformanceParser.Parse(aTemplateConstraint.Conformance);
             if (valueConformanceType == conformanceType)
             {
                 aElement.Value = !string.IsNullOrEmpty(aTemplateConstraint.Value) ? aTemplateConstraint.Value.Trim() : aTemplateConstraint.Value;
             }
         }
         else
         {
             aElement.Value = !string.IsNullOrEmpty(aTemplateConstraint.Value) ? aTemplateConstraint.Value.Trim() : aTemplateConstraint.Value;
         }
     }
     // Add the data type attribute if one is present on the constraint
     if (!string.IsNullOrEmpty(aTemplateConstraint.DataType))
     {
         if (aPrefix == "cda")
         {
             if (aElement.ElementName != "code")
             {
                 DocumentTemplateElementAttribute dataTypeAttr = new DocumentTemplateElementAttribute("xsi:type");
                 dataTypeAttr.SingleValue = aTemplateConstraint.DataType;
                 aElement.AddAttribute(dataTypeAttr);
             }
         }
     }
 }
コード例 #3
0
        public void GenerateSchematronAssertion_NestedElement_WithAttribute_ConformanceSHALL_CardinalityOneToOne()
        {
            var addrElement = new DocumentTemplateElement("addr");
            var useAttr     = new DocumentTemplateElementAttribute("use", "HP");

            addrElement.AddAttribute(useAttr);
            var element             = new DocumentTemplateElement("state");
            var cdaDocumentTemplate = new DocumentTemplate("urn:hl7-org:v3")
                                      .AddElement(new DocumentTemplateElement("recordTarget")
                                                  .AddElement(new DocumentTemplateElement("patientRole")
                                                              .AddElement(addrElement)
                                                              .AddElement(element)));
            //need to have cardinality on both parent and child elements?
            //how do we tell it to generate cda: on context as in below?
            var cardinality       = CardinalityParser.Parse("1..1");
            var builder           = new AssertionLineBuilder(this.tdb, element, this.igType, this.igTypeSchema).WithCardinality(cardinality).ConformsTo(Conformance.SHALL).WithinContext(@"cda:");
            var assertion         = builder.ToString();
            var expectedAssertion = @"count(cda:state)=1";

            Assert.IsTrue(assertion == expectedAssertion,
                          "Assertion string was not correct. Expected '{0}', Actual '{1}'.", expectedAssertion, assertion);
            var contextBuilder  = new ContextBuilder(useAttr, "cda");
            var context         = contextBuilder.GetRelativeContextString();
            var expectedContext = "cda:addr[@use='HP']";

            Assert.IsTrue(context == expectedContext, "Context is not correct. Expected '{0}', Actual '{1}'", expectedContext, context);
        }
コード例 #4
0
        public void GenerateSchematronAssertion_Attribute_TwoAttributes_No_Element_ConformanceSHALL_CardinalityOneToOne()
        {
            var attr = new DocumentTemplateElementAttribute("code");

            attr.SingleValue = "OBS";
            attr.DataType    = "CD";
            //create schematron assertion line builder, build one at a time (regular interface, see above for fluent interface)
            var builder = new AssertionLineBuilder(this.tdb, attr, this.igType, this.igTypeSchema);
            //define cardinality
            var cardinality = CardinalityParser.Parse("1..1");

            //add cardinality for the element
            builder.WithCardinality(cardinality);
            //define conformance
            var conformance = ConformanceParser.Parse("SHALL");

            //add conformance for the element
            builder.ConformsTo(conformance);
            //generate string
            string assertion = builder.ToString();
            //did we generate the correct string?
            string expected = @"count(self::node()[@code='OBS'])=1";

            Assert.IsTrue(assertion == expected, "Assertion string was not correct. Expected '{0}', Actual '{1}'.", expected, assertion);
        }
コード例 #5
0
        public void GenerateSchematronAssertion_NestedElement_WithAttribute_NULLFlavor_ConformanceSHALL_CardinalityOneToOne()
        {
            var idElement           = new DocumentTemplateElement("id");
            var nullFlavorAttribute = new DocumentTemplateElementAttribute("nullFlavor", "NI");

            idElement.AddAttribute(nullFlavorAttribute);
            var cdaDocumentTemplate = new DocumentTemplate("urn:hl7-org:v3");

            cdaDocumentTemplate.AddElement(new DocumentTemplateElement("component")
                                           .AddElement(new DocumentTemplateElement("section")
                                                       .AddElement(new DocumentTemplateElement("entry")
                                                                   .AddElement(new DocumentTemplateElement("organizer")
                                                                               .AddElement(new DocumentTemplateElement("performer")
                                                                                           .AddElement(new DocumentTemplateElement("assignedEntity")
                                                                                                       .AddElement(idElement)))))));
            var builder = new AssertionLineBuilder(this.tdb, nullFlavorAttribute, this.igType, this.igTypeSchema);

            builder.ConformsTo(ConformanceParser.Parse("SHALL")).WithCardinality(CardinalityParser.Parse("1..1")).WithinContext("cda:");
            var assertion         = builder.ToString();
            var expectedAssertion = @"cda:id[@nullFlavor='NI']";

            Assert.IsTrue(assertion == expectedAssertion,
                          "Assertion string was not correct. Expected '{0}', Actual '{1}'.", expectedAssertion, assertion);
            var contextBuilder  = new ContextBuilder(idElement.ParentElement, "cda");
            var context         = contextBuilder.GetRelativeContextString();
            var expectedContext = "cda:assignedEntity";

            Assert.IsTrue(context == expectedContext, "Context is not correct. Expected '{0}', Actual '{1}'", expectedContext, context);
        }
コード例 #6
0
ファイル: BranchHelper.cs プロジェクト: BOBO41/trifolia
 /// <summary>
 /// Takes a given child element (aChildElement) and parent constraint (aParentTemplateConstraint) and steps through the Children of the parent constraint
 /// to determine if any siblings of the child element exist.
 /// </summary>
 /// <param name="aChildElement">Target element that we need to locate siblings for</param>
 /// <param name="aParentTemplateConstraint">Parent Constraint of the aChildElement</param>
 /// <param name="aParentElement">Parent Element for the aChildElement</param>
 /// <param name="aAddedConstraints">Constraints that have already been added to the child collection, we don't need to parse these.</param>
 static private void AddSiblingElements(DocumentTemplateElement aChildElement, IConstraint aParentTemplateConstraint, DocumentTemplateElement aParentElement, Dictionary <DocumentTemplateElement, IConstraint> aConstraintMap)
 {
     //look at parent to get the siblings
     if (aParentTemplateConstraint.Children != null)
     {
         DocumentTemplateElement          parsedElement   = null;
         DocumentTemplateElementAttribute parsedAttribute = null;
         //walk through the siblings
         foreach (var sibling in aParentTemplateConstraint.Children)
         {
             //have we already added this constraint in a previous iteration (e.g. it's on the main path from the leaf to the root)
             if (sibling.IsBranchIdentifier && !aConstraintMap.ContainsValue(sibling))
             {
                 //parse the context
                 var cp = new ContextParser(sibling.Context);
                 cp.Parse(out parsedElement, out parsedAttribute);
                 //is this an element or an attribute?
                 if ((parsedElement != null) && (!string.IsNullOrEmpty(parsedElement.ElementName)))
                 {
                     parsedElement.IsBranchIdentifier = sibling.IsBranchIdentifier;
                     parsedElement.IsBranch           = sibling.IsBranch;
                     //element, let's add it to the parent element's children so it becomes a sibling of aChildElement
                     parsedElement.Value = sibling.Value;
                     aParentElement.AddElement(parsedElement);
                     AddBranchedAttributes(parsedElement, sibling);
                     aConstraintMap.Add(parsedElement, sibling);
                 }
             }
         }
     }
 }
コード例 #7
0
        private void DecorateAttributeFromConstraint(string aParentContext, DocumentTemplateElementAttribute aAttribute, IConstraint aConstraint, ValueSet aConstraintValueSet)
        {
            // Set the attribute's value if the constraint indicates one
            if (!string.IsNullOrEmpty(aConstraint.Value))
            {
                aAttribute.SingleValue = !string.IsNullOrEmpty(aConstraint.Value) ? aConstraint.Value.Trim() : string.Empty;
            }

            // Set the data-type for the attribute if one is present in the constraint
            if (!string.IsNullOrEmpty(aConstraint.DataType))
            {
                aAttribute.DataType = aConstraint.DataType;
            }

            // Do we have a valueset on this attribute?
            if (aConstraintValueSet != null)
            {
                aAttribute.ValueSet = this.igTypePlugin.ParseIdentifier(this.valueSet.GetIdentifier(this.igTypePlugin));
            }

            if (this.codeSystem != null)
            {
                //TODO: CDA specific logic, need to refactor this out to make more dynamic
                if ((aAttribute.AttributeName == "code" || aAttribute.AttributeName == "value") && (aParentContext.EndsWith(this.prefix + ":code") || aParentContext.EndsWith(this.prefix + ":value")))
                {
                    aAttribute.CodeSystemOid = this.igTypePlugin.ParseIdentifier(this.codeSystem.Oid);
                }
            }
        }
コード例 #8
0
        /// <summary>
        /// Builds the full context from the given aTemplateConstraint forward. If the given aTemplateConstraint has a parent context then this will be built also,
        /// using the aPerspectiveConstraint. aPerspectiveConstraint is always the constraint we are requesting the context for. This ensures that we only traverse
        /// the perspective's children 1 time.
        /// </summary>
        /// <param name="aPrefix"></param>
        /// <param name="aTemplateConstraint"></param>
        /// <param name="aPerspectiveConstraint"></param>
        /// <param name="aIgnoreParent">Specifies whether to walk the the parent tree</param>
        /// <returns></returns>
        private string CreateFullBranchedParentContext(TemplateConstraint aTemplateConstraint, TemplateConstraint aPerspectiveConstraint = null, bool aIgnoreParent = false, bool isTarget = false)
        {
            string constraintParentContext = string.Empty;

            if (aTemplateConstraint.Parent != null && !aIgnoreParent)
            {
                constraintParentContext = CreateFullBranchedParentContext(aTemplateConstraint.ParentConstraint, aTemplateConstraint);
            }

            DocumentTemplateElement          element   = null;
            DocumentTemplateElementAttribute attribute = null;
            ContextParser parser = new ContextParser(aTemplateConstraint.Context);

            parser.Parse(out element, out attribute);

            if (attribute != null) //we are only looking for attributes
            {
                attribute.SingleValue = aTemplateConstraint.Value;
            }

            if (element != null)
            {
                element.IsBranch           = aTemplateConstraint.IsBranch;
                element.IsBranchIdentifier = aTemplateConstraint.IsBranchIdentifier;
                ConstraintToDocumentElementHelper.AddElementValueAndDataType(this.prefix, element, aTemplateConstraint);
            }

            ContextBuilder builder      = ContextBuilder.CreateFromElementAndAttribute(element, attribute, this.prefix);
            StringBuilder  childStrings = new StringBuilder();

            foreach (var child in aTemplateConstraint.ChildConstraints)
            {
                if (aPerspectiveConstraint == null || aPerspectiveConstraint.Id != child.Id) //since we call ourselves recursively, this ensures we only go down the path of the original caller once.
                {
                    if (child.IsBranchIdentifier == true)
                    {
                        childStrings.Append(CreateFullBranchedParentContext(child, aIgnoreParent: true));
                    }
                }
            }

            string context = builder.GetFullyQualifiedContextString() + childStrings;

            if (element != null && aTemplateConstraint.Parent != null)
            {
                if (element.IsBranchIdentifier)
                {
                    context = "[" + context + "]";
                }
                else
                {
                    context = "/" + context;
                }
            }

            return(constraintParentContext + context);
        }
コード例 #9
0
        public AssertionLineBuilder(IObjectRepository tdb, DocumentTemplateElementAttribute aAttribute, ImplementationGuideType igType, SimpleSchema igTypeSchema, string prefix = null)
            : this(tdb, igType, igTypeSchema, igType.SchemaPrefix)
        {
            _attribute = aAttribute;
            _element   = _attribute.Element;

            if (!string.IsNullOrEmpty(prefix))
            {
                this._prefix = prefix;
            }
        }
コード例 #10
0
 private string BuildSingleAttributeString(DocumentTemplateElementAttribute aAttribute)
 {
     if (string.IsNullOrEmpty(aAttribute.SingleValue))
     {
         return(string.Format("[@{0}]", aAttribute.AttributeName));
     }
     else
     {
         return(string.Format("[@{0}='{1}']", aAttribute.AttributeName, aAttribute.SingleValue));
     }
 }
コード例 #11
0
        /// <summary>
        /// Uses back-tracing algorithm to go backwards through the tree
        /// Helper function which builds the full parent context for a given template constraint. For example, for the template constraint @code with cda:entryRelationship/cda:observation/cda:code[@code]
        /// this function returns the cda:entryRelationship/cda:observation/cda:code.
        /// </summary>
        /// <param name="aElement">current element to start from</param>
        /// <param name="aTemplateConstraint">constraint which will have its parent chain walked to form path</param>
        /// <param name="aIncludeElementInPath">determines whether we start the path with the element passed in (true) or its parent (false)</param>
        /// <returns>full context string</returns>
        public static string CreateFullParentContext(string aPrefix, IConstraint aTemplateConstraint)
        {
            if (aTemplateConstraint == null)
            {
                return(string.Empty);
            }

            DocumentTemplateElement          firstElement    = null;
            DocumentTemplateElement          newElement      = null;
            DocumentTemplateElement          previousElement = null;
            DocumentTemplateElementAttribute newAttribute    = null;
            IConstraint currentConstraint = aTemplateConstraint.Parent;

            while (currentConstraint != null)
            {
                //parse the context to determine whether this is element or attribute
                var contextParser = new ContextParser(currentConstraint.Context);
                contextParser.Parse(out newElement, out newAttribute);
                newElement.Attributes.Clear();
                if (currentConstraint.IsBranch) //if we hit a branch then we stop b/c we are in the branch's context
                {
                    break;
                }
                if (newElement == null)
                {
                    break;  //there is a broken chain, we have null parent
                }
                //add value and data type (if present)
                ConstraintToDocumentElementHelper.AddElementValueAndDataType(aPrefix, newElement, currentConstraint);
                //chain the previous element to the child collection of this new one
                if (previousElement != null)
                {
                    newElement.AddElement(previousElement);
                }
                //get the leaf node
                if (firstElement == null)
                {
                    firstElement = newElement;
                }
                previousElement = newElement;
                //walk the parent chain
                currentConstraint = currentConstraint.Parent;
            }
            if (firstElement == null)
            {
                return(string.Empty);
            }
            else
            {
                var contextBuilder = new ContextBuilder(firstElement, aPrefix);
                return(contextBuilder.GetFullyQualifiedContextString());
            }
        }
コード例 #12
0
        public void ParseElementAndAttribute()
        {
            string context = "code/@code";
            DocumentTemplateElement          element   = null;
            DocumentTemplateElementAttribute attribute = null;
            var parser = new ContextParser(context);

            parser.Parse(out element, out attribute);
            Assert.IsNotNull(element, "No element was passed back from the parser.");
            Assert.IsTrue(element.ElementName == "code", "Element name was incorrect. Expected 'code', Actual '{0}'", element.ElementName);
            Assert.IsNotNull(attribute, "No attribute was passed back from the parser.");
            Assert.IsTrue(attribute.AttributeName == "code", "Element name was incorrect. Expected 'code', Actual '{0}'", attribute.AttributeName);
        }
コード例 #13
0
        public void ParseMultipleElements()
        {
            string context = "entry/observation";
            DocumentTemplateElement          element   = null;
            DocumentTemplateElementAttribute attribute = null;
            var parser = new ContextParser(context);

            parser.Parse(out element, out attribute);
            Assert.IsNotNull(element, "No element was passed back from the parser.");
            Assert.IsTrue(element.ElementName == "observation", "Element name was incorrect. Expected 'observation', Actual '{0}'", element.ElementName);

            Assert.IsNotNull(element.ParentElement, "No parent element was passed back from the parser.");
            Assert.IsTrue(element.ParentElement.ElementName == "entry", "Element name was incorrect. Expected 'entry', Actual '{0}'", element.ElementName);

            Assert.IsNull(attribute, "An attribute was passed back from the parser. Exected null.");
        }
コード例 #14
0
        public void GenerateContext_SingleElementChildElement_2Levels_SingleAttribute()
        {
            var element   = new DocumentTemplateElement("assignedPerson");
            var attribute = new DocumentTemplateElementAttribute("classCode", "ASSIGNED");

            element.AddAttribute(attribute);
            var cdaDocumentTemplate = new DocumentTemplate("urn:hl7-org:v3");

            cdaDocumentTemplate.AddElement(new DocumentTemplateElement("custodian")
                                           .AddElement(element));
            var contextBuilder = new ContextBuilder(attribute, "cda");
            var context        = contextBuilder.GetRelativeContextString();
            var expected       = "cda:assignedPerson[@classCode='ASSIGNED']";

            Assert.IsFalse(string.IsNullOrEmpty(context), "Null or empty string returned by context builder");
            Assert.IsTrue(context == expected, "Context string was not correct, expected '{0}', actual '{1}'", expected, context);
        }
コード例 #15
0
        public void Parse(out DocumentTemplateElement aContextElement, out DocumentTemplateElementAttribute aAttribute)
        {
            aContextElement = null; //default
            aAttribute      = null; //default

            var parsedContext = _context.Split('/');

            if (parsedContext.Length > 1)   //does the context contain a complex element structure (e.g. code/@code)
            {
                DocumentTemplateElement parentContextElement = null;
                for (int i = 0; i < parsedContext.Length; i++)
                {
                    if (IsAttribute(parsedContext[i]))
                    {
                        aAttribute = new DocumentTemplateElementAttribute(parsedContext[i].Replace("@", ""));
                        aContextElement.AddAttribute(aAttribute);
                    }
                    else
                    {
                        aContextElement = new DocumentTemplateElement(parsedContext[i]);
                        if (parentContextElement != null)
                        {
                            parentContextElement.AddElement(aContextElement);
                        }
                    }
                    parentContextElement = aContextElement;
                }
            }
            else
            {
                if (IsAttribute(_context))
                {
                    aAttribute = new DocumentTemplateElementAttribute(_context.Replace("@", ""));
                }
                else
                {
                    aContextElement = new DocumentTemplateElement(_context);
                }
            }
        }
コード例 #16
0
ファイル: BranchHelper.cs プロジェクト: BOBO41/trifolia
 /// <summary>
 /// Helper method which steps through the children for a given constraint (aTemplateConstraint) and attaches any attributes to the
 /// given element (aElement)).
 /// </summary>
 /// <param name="aElement">Element to add the attributes to</param>
 /// <param name="aTemplateConstraint">Constraint to walk the children to find attributes</param>
 static private void AddBranchedAttributes(DocumentTemplateElement aElement, IConstraint aTemplateConstraint)
 {
     if (aTemplateConstraint.Children != null)
     {
         DocumentTemplateElement          parsedElement   = null;
         DocumentTemplateElementAttribute parsedAttribute = null;
         foreach (var child in aTemplateConstraint.Children)
         {
             var cp = new ContextParser(child.Context);
             cp.Parse(out parsedElement, out parsedAttribute);
             if (parsedElement != null)
             {
                 parsedElement.IsBranch           = child.IsBranch;
                 parsedElement.IsBranchIdentifier = child.IsBranchIdentifier;
             }
             if (parsedAttribute != null) //we are only looking for attributes
             {
                 parsedAttribute.SingleValue = child.Value;
                 aElement.AddAttribute(parsedAttribute);
             }
         }
     }
 }
コード例 #17
0
        public void GenerateSchematronAssertion_Attribute_Valueset_ConformanceMAYNOT_CardinalityOneToOne()
        {
            var attr = new DocumentTemplateElementAttribute("moodCode", "EVN");
            //create schematron assertion line builder, build one at a time (regular interface, see above for fluent interface)
            var builder = new AssertionLineBuilder(this.tdb, attr, this.igType, this.igTypeSchema);
            //define cardinality
            var cardinality = CardinalityParser.Parse("1..1");

            //add cardinality for the element
            builder.WithCardinality(cardinality);
            //define conformance
            var conformance = Conformance.MAY_NOT;

            //add conformance for the element
            builder.ConformsTo(conformance);
            //add valueset
            builder.WithinValueSet("2.16.840.1.113883.1.11.20.2");
            //generate string
            string assertion = builder.ToString();
            //did we generate the correct string?
            string expected = "not(@moodCode='EVN' and @moodCode=document('the_voc.xml')/voc:systems/voc:system[@valueSetOid='2.16.840.1.113883.1.11.20.2']/voc:code/@value)";

            Assert.IsTrue(assertion == expected, "Assertion string was not correct. Expected empty string, Actual '{1}'.", expected, assertion);
        }
コード例 #18
0
 public AssertionLineBuilder(DocumentTemplateElementAttribute aAttribute, string templateIdentifierXpath, string templateVersionIdentifierXpath, string prefix = null)
     : this(prefix, templateIdentifierXpath, templateVersionIdentifierXpath)
 {
     _attribute = aAttribute;
     _element   = _attribute.Element;
 }
コード例 #19
0
        private AssertionLineBuilder CreateBranchedRootAssertionLineBuilderFromConstraint(IConstraint aConstraint)
        {
            AssertionLineBuilder             asb       = null;
            DocumentTemplateElement          element   = null;
            DocumentTemplateElementAttribute attribute = null;
            //parse the context
            ContextParser contextParser = new ContextParser(aConstraint.Context);

            contextParser.Parse(out element, out attribute);

            if (element != null)
            {
                if (!string.IsNullOrEmpty(aConstraint.Value))
                {
                    element.Value = aConstraint.Value;
                }

                asb = new AssertionLineBuilder(this.tdb, element, this.igType, this.igTypeSchema);

                var containedTemplates = (from tcr in aConstraint.References
                                          join t in this.allTemplates on tcr.ReferenceIdentifier equals t.Oid
                                          where tcr.ReferenceType == ConstraintReferenceTypes.Template
                                          select new { Identifier = t.Oid, t.PrimaryContextType }).ToList();

                foreach (var containedTemplate in containedTemplates)
                {
                    asb.ContainsTemplate(containedTemplate.Identifier, containedTemplate.PrimaryContextType);
                }
            }
            else if (attribute != null)
            {
                if (!string.IsNullOrEmpty(aConstraint.Value))
                {
                    attribute.SingleValue = aConstraint.Value;
                }

                asb = new AssertionLineBuilder(this.tdb, attribute, this.igType, this.igTypeSchema);
            }
            else
            {
                throw new Exception();
            }
            ConstraintToDocumentElementHelper.AddCardinality(aConstraint, asb);
            ConstraintToDocumentElementHelper.AddConformance(aConstraint, asb);

            foreach (var child in aConstraint.Children)
            {
                DocumentTemplateElement          childElement   = null;
                DocumentTemplateElementAttribute childAttribute = null;
                ContextParser childContextParser = new ContextParser(child.Context);
                childContextParser.Parse(out childElement, out childAttribute);

                if (child.IsBranchIdentifier)
                {
                    if (childElement != null)
                    {
                        asb.WithChildElementBuilder(CreateBranchedRootAssertionLineBuilderFromConstraint(child));
                    }
                    else if (childAttribute != null)
                    {
                        if (!string.IsNullOrEmpty(child.Value))
                        {
                            childAttribute.SingleValue = child.Value;
                        }
                        element.AddAttribute(childAttribute);
                    }
                }
            }

            if (aConstraint.IsBranch)
            {
                asb.MarkAsBranchRoot();
            }

            return(asb);
        }
コード例 #20
0
        private AssertionLineBuilder CreateAssertionLineBuilderForAttribute(DocumentTemplateElement aParentElement, DocumentTemplateElementAttribute aAttribute, ref string aParentContext, ref IConstraint aConstraint)
        {
            AssertionLineBuilder asb = null;

            if ((aParentElement != null) && (aConstraint.Parent.IsBranch))
            {
                asb         = CreateAssertionLineBuilderForElement(aParentElement, aConstraint.Parent, ref aParentContext);
                aConstraint = aConstraint.Parent;
            }
            else
            {
                asb = new AssertionLineBuilder(this.tdb, aAttribute, this.igType, this.igTypeSchema);

                if (aConstraint.Parent != null)
                {
                    Cardinality cardinality = CardinalityParser.Parse(aConstraint.Parent.Cardinality);
                    if (cardinality.Left == 0)
                    {
                        asb.HasOptionalParentContext();
                    }
                }
            }

            return(asb);
        }
コード例 #21
0
        /// <summary>
        /// This is the main public interface for constraint parser. Takes the given constraint and builds an AssertionLineBuilder, applying the values, attributes, context, etc as necessary.
        /// </summary>
        /// <returns>
        /// AssertionLineBuilder representing the values from the constraint given to the parser.
        /// </returns>
        public AssertionLineBuilder CreateAssertionLineBuilder()
        {
            if (this.valueSet == null && this.constraint.ValueSetId != null)
            {
                this.valueSet = this.tdb.ValueSets.Single(y => y.Id == constraint.ValueSetId);
            }

            if (this.codeSystem == null && this.constraint.ValueCodeSystemId != null)
            {
                this.codeSystem = this.tdb.CodeSystems.Single(y => y.Id == constraint.ValueCodeSystemId);
            }

            IConstraint currentConstraint  = this.constraint; //set current constraint, setting this as a variable allows us to move the current constraint to the parent when dealing with branches
            var         containedTemplates = currentConstraint.References.Where(y => y.ReferenceType == ConstraintReferenceTypes.Template);

            if (string.IsNullOrEmpty(currentConstraint.Context) && !containedTemplates.Any()) //we can have empty context but a contained template
            {
                return(null);
            }

            DocumentTemplateElement          element   = null;
            DocumentTemplateElementAttribute attribute = null;

            ConstraintToDocumentElementHelper.ParseContextForElementAndAttribute(currentConstraint, out element, out attribute);
            DocumentTemplateElement parentElement =
                ConstraintToDocumentElementHelper.CreateParentElementForAttribute(currentConstraint, attribute);

            string parentContext =
                CreateParentContextForElement(parentElement, element, currentConstraint);

            AssertionLineBuilder asb             = null;
            AssertionLineBuilder branchedRootAsb = null;

            // Determine if we should create the AssertionLineBuilder starting with an attribute or an element.
            if (attribute != null)
            {
                DecorateAttributeFromConstraint(parentContext, attribute, currentConstraint, this.valueSet);
                if (currentConstraint.Parent != null && currentConstraint.IsBranch)
                {
                    branchedRootAsb = CreateBranchedRootAssertionLineBuilderFromConstraint(currentConstraint);
                }
                else
                {
                    asb = CreateAssertionLineBuilderForAttribute(parentElement, attribute, ref parentContext, ref currentConstraint);
                }
            }
            else //this is an element
            {
                // Only add the code system constraints if there is no value conformance or the value conformance matches the element/attribute conformance
                // This is because in the SchematronGenerator class, a duplicate constraint is created when the value conformance is different from
                // the element/attribute conformance, where the duplicate constraint's conformance matches the value conformance.
                if (string.IsNullOrEmpty(currentConstraint.ValueConformance) || ConformanceParser.Parse(currentConstraint.Conformance) == ConformanceParser.Parse(currentConstraint.ValueConformance))
                {
                    ConstraintToDocumentElementHelper.AddCodeSystemToElement(this.tdb, this.igTypePlugin, element, currentConstraint);
                }

                if (currentConstraint.IsBranch)
                {
                    branchedRootAsb = CreateBranchedRootAssertionLineBuilderFromConstraint(currentConstraint);
                    branchedRootAsb.HasParentContext(parentContext);
                }
                else
                {
                    //if we have a context already then we will append it at end so pass in false, else go ahead and generate (pass in true)
                    asb = CreateAssertionLineBuilderForElement(element, this.constraint, ref parentContext, string.IsNullOrEmpty(parentContext));
                }
            }

            if (branchedRootAsb == null) //if this is a branched root then a separate builder was constructed
            {
                ConstraintToDocumentElementHelper.AddConformance(currentConstraint, asb);
                ConstraintToDocumentElementHelper.AddCardinality(currentConstraint, asb);
                // Determine if we have a valueset
                if (this.valueSet != null && currentConstraint.IsValueSetStatic)
                {
                    var requireValueset = true;

                    if (!string.IsNullOrEmpty(currentConstraint.ValueConformance))
                    {
                        if (ConformanceParser.Parse(currentConstraint.Conformance) != ConformanceParser.Parse(currentConstraint.ValueConformance))
                        {
                            requireValueset = false;
                        }
                    }

                    if (requireValueset)
                    {
                        //TODO: Move into CDA specific library
                        //are we bound directly to a code or value element?
                        bool includeNullFlavor = false;
                        if (element != null && attribute == null && (element.ElementName == "value" || element.ElementName == "code"))
                        {
                            includeNullFlavor = true;
                        }

                        string valueSetIdentifier = this.igTypePlugin.ParseIdentifier(this.valueSet.GetIdentifier(this.igTypePlugin));
                        asb.WithinValueSet(valueSetIdentifier, this.valueSetFile, this.vocabularyOutputType, includeNullFlavor);
                    }
                }

                //determine if we have a parent context
                if (!string.IsNullOrEmpty(parentContext))
                {
                    asb.HasParentContext(parentContext);
                    DecorateParentOptionality(asb, currentConstraint);
                }
            }
            else //branched root, use that one instead
            {
                //determine if we have a parent context
                if (!string.IsNullOrEmpty(parentContext))
                {
                    branchedRootAsb.HasParentContext(parentContext);
                    DecorateParentOptionality(branchedRootAsb, currentConstraint);
                }
            }

            return((branchedRootAsb == null) ? asb : branchedRootAsb);
        }
コード例 #22
0
        static public DocumentTemplateElement CreateParentElementForAttribute(IConstraint aConstraint, DocumentTemplateElementAttribute aAttribute)
        {
            DocumentTemplateElement parentElement = null;

            // Is there a parent constraint that should be used as a context
            if (aConstraint.Parent != null && !string.IsNullOrEmpty(aConstraint.Parent.Context) && !aConstraint.Parent.IsBranch)
            {
                if ((aAttribute != null) && (aAttribute.Element == null)) //we have an attribute, but no element attached. the parent constraint would then be the element.
                {
                    parentElement = new DocumentTemplateElement(aConstraint.Parent.Context);
                    if (aConstraint.Parent.IsBranch)
                    {
                        parentElement.AddAttribute(aAttribute);
                    }
                }
                else if ((aAttribute != null) && (aAttribute.Element != null) && (aConstraint.Parent.Context != aAttribute.Element.ElementName)) //we have an attribute, with an element attached, but the element does not match the parent context
                {
                    parentElement = new DocumentTemplateElement(aConstraint.Parent.Context);
                    parentElement.AddElement(aAttribute.Element);
                }
                else if (aAttribute != null && aAttribute.Element != null)
                {
                    parentElement = aAttribute.Element;
                }
            }
            return(parentElement);
        }
コード例 #23
0
        static public void ParseContextForElementAndAttribute(IConstraint aConstraint, out DocumentTemplateElement aElement, out DocumentTemplateElementAttribute aAttribute)
        {
            var cp = new ContextParser(aConstraint.Context);

            cp.Parse(out aElement, out aAttribute);
        }
コード例 #24
0
 public ContextBuilder(DocumentTemplateElementAttribute aAttribute, string aNamespace)
 {
     _attribute = aAttribute;
     _prefix    = aNamespace;
 }
コード例 #25
0
        public static ContextBuilder CreateFromElementAndAttribute(DocumentTemplateElement aElement, DocumentTemplateElementAttribute aAttribute, string aNameSpace)
        {
            if (aAttribute != null)
            {
                return(new ContextBuilder(aAttribute, aNameSpace));
            }
            if (aElement != null)
            {
                return(new ContextBuilder(aElement, aNameSpace));
            }

            throw new ArgumentException("Must provide a DocumentTemplate Element or an Attribute.");
        }
コード例 #26
0
        private AssertionLineBuilder CreateBranchedRootAssertionLineBuilderFromConstraint(IConstraint aConstraint)
        {
            AssertionLineBuilder             asb       = null;
            DocumentTemplateElement          element   = null;
            DocumentTemplateElementAttribute attribute = null;
            //parse the context
            ContextParser contextParser = new ContextParser(aConstraint.Context);

            contextParser.Parse(out element, out attribute);

            if (element != null)
            {
                asb = new AssertionLineBuilder(element, this.igTypePlugin.TemplateIdentifierXpath, this.igTypePlugin.TemplateVersionIdentifierXpath, this.prefix);
                if (aConstraint.ContainedTemplateId != null)
                {
                    var containedTemplate = this.tdb.Templates.Single(y => y.Id == aConstraint.ContainedTemplateId.Value);
                    if (containedTemplate != null)
                    {
                        asb.ContainsTemplate(containedTemplate.Oid);
                    }
                }
            }
            else if (attribute != null)
            {
                if (!string.IsNullOrEmpty(aConstraint.Value))
                {
                    attribute.SingleValue = aConstraint.Value;
                }
                asb = new AssertionLineBuilder(attribute, this.igTypePlugin.TemplateIdentifierXpath, this.igTypePlugin.TemplateVersionIdentifierXpath);
            }
            else
            {
                throw new Exception();
            }
            ConstraintToDocumentElementHelper.AddCardinality(aConstraint, asb);
            ConstraintToDocumentElementHelper.AddConformance(aConstraint, asb);

            foreach (var child in aConstraint.Children)
            {
                DocumentTemplateElement          childElement   = null;
                DocumentTemplateElementAttribute childAttribute = null;
                ContextParser childContextParser = new ContextParser(child.Context);
                childContextParser.Parse(out childElement, out childAttribute);

                if (child.IsBranchIdentifier)
                {
                    if (childElement != null)
                    {
                        asb.WithChildElementBuilder(CreateBranchedRootAssertionLineBuilderFromConstraint(child));
                    }
                    else if (childAttribute != null)
                    {
                        if (!string.IsNullOrEmpty(child.Value))
                        {
                            childAttribute.SingleValue = child.Value;
                        }
                        element.AddAttribute(childAttribute);
                    }
                }
            }

            if (aConstraint.IsBranch)
            {
                asb.MarkAsBranchRoot();
            }

            return(asb);
        }