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); }
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); } } } }
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); }
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); }
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); }
/// <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); } } } } }
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); } } }
/// <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); }
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; } }
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)); } }
/// <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()); } }
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); }
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."); }
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); }
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); } } }
/// <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); } } } }
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); }
public AssertionLineBuilder(DocumentTemplateElementAttribute aAttribute, string templateIdentifierXpath, string templateVersionIdentifierXpath, string prefix = null) : this(prefix, templateIdentifierXpath, templateVersionIdentifierXpath) { _attribute = aAttribute; _element = _attribute.Element; }
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); }
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); }
/// <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); }
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); }
static public void ParseContextForElementAndAttribute(IConstraint aConstraint, out DocumentTemplateElement aElement, out DocumentTemplateElementAttribute aAttribute) { var cp = new ContextParser(aConstraint.Context); cp.Parse(out aElement, out aAttribute); }
public ContextBuilder(DocumentTemplateElementAttribute aAttribute, string aNamespace) { _attribute = aAttribute; _prefix = aNamespace; }
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."); }
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); }