public void GenerateSchematronAssertion_Element_ValueSet_SVS_ConformanceSHALL_CardinalityOneToOne() { var element = new DocumentTemplateElement("administrativeGenderCode"); //create schematron assertion line builder, build one at a time (regular interface, see above for fluent interface) var builder = new AssertionLineBuilder(element, 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); builder.WithinValueSet("4.3.2.1", VocabularyOutputType.SVS_SingleValueSet); //generate string string assertion = builder.ToString(); //did we generate the correct string? string expected = @"count(administrativeGenderCode[@code=document('4.3.2.1.xml')/svs:RetrieveValueSetResponse/svs:ValueSet[@id='4.3.2.1']/svs:ConceptList/svs:Concept/@code])=1"; Assert.IsTrue(assertion == expected, "Assertion string was not correct. Expected '{0}', Actual '{1}'.", expected, assertion); }
public void GenerateSchematronAssertion_Element_ConformanceSHALL_CardinalityOneToOne() { //create cda doc var cdaDocumentTemplate = new DocumentTemplate("urn:hl7-org:v3"); //create code element var element = new DocumentTemplateElement("code"); //add element to doc cdaDocumentTemplate.AddElement(element); //create schematron assertion line builder var builder = new AssertionLineBuilder(this.tdb, element, this.igType, this.igTypeSchema); //define cardinality and conformance var cardinality = CardinalityParser.Parse("1..1"); var conformance = ConformanceParser.Parse("SHALL"); //add element (context comes from doc), conformance, cardinality through fluent interface builder.ConformsTo(conformance).WithCardinality(cardinality); //generate string string assertion = builder.ToString(); //did we generate the correct string? Assert.IsTrue(assertion == @"count(cda:code)=1", "The generated assertion was not correct. Expected 'count(cda:code)=1', Actual '{0}'.", assertion); }
public void GenerateSchematronAssertion_Element_With_Value_ConformanceSHALL_CardinalityOneToOne() { //create cda doc var cdaDocumentTemplate = new DocumentTemplate("urn:hl7-org:v3"); //create code element var element = new DocumentTemplateElement("code", "Test"); //add element to doc cdaDocumentTemplate.AddElement(element); //create schematron assertion line builder var builder = new AssertionLineBuilder(element, templateIdentifierXpath, templateVersionIdentifierXpath, "cda"); //define cardinality and conformance var cardinality = CardinalityParser.Parse("1..1"); var conformance = ConformanceParser.Parse("SHALL"); //add element (context comes from doc), conformance, cardinality through fluent interface builder.ConformsTo(conformance).WithCardinality(cardinality); //generate string string assertion = builder.ToString(); //did we generate the correct string? Assert.IsTrue(assertion == @"count(cda:code[translate(text(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')='test'])=1", "The generated assertion was not correct. Expected 'count(cda:code[text()='Test'])=1', Actual '{0}'.", assertion); }
public void GenerateSchematronAssertion_NamespaceEMA_Element_Template_ConformanceSHALL_CardinalityOneToOne() { //create cda doc var cdaDocumentTemplate = new DocumentTemplate("urn:hl7-org:v3"); //create code element var element = new DocumentTemplateElement("encounter"); //add element to doc cdaDocumentTemplate.AddElement(element); //create schematron assertion line builder var builder = new AssertionLineBuilder(this.tdb, element, this.igType, this.igTypeSchema, "ema"); //define cardinality and conformance var cardinality = CardinalityParser.Parse("1..1"); var conformance = ConformanceParser.Parse("SHALL"); //add element (context comes from doc), conformance, cardinality through fluent interface builder.ConformsTo(conformance).WithCardinality(cardinality).ContainsTemplate("urn:oid:4.3.2.1", "Section"); //generate string string assertion = builder.ToString(); string expected = @"count(ema:encounter[ema:templateId[@root='4.3.2.1']])=1"; //did we generate the correct string? Assert.IsTrue(assertion == expected, "The generated assertion was not correct. Expected '{0}', Actual '{1}'.", expected, assertion); }
public void GenerateSchematronAssertion_Attribute_Valueset_ConformanceMAY_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 = ConformanceParser.Parse("MAY"); //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 = "@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 void GenerateSchematronAssertion_Element_ConformanceSHALL_CardinalityZeroToMany() { //create cda doc var cdaDocumentTemplate = new DocumentTemplate("urn:hl7-org:v3"); //create code element var element = new DocumentTemplateElement("code"); //add element to doc cdaDocumentTemplate.AddElement(element); //create schematron assertion line builder var builder = new AssertionLineBuilder(element, templateIdentifierXpath, templateVersionIdentifierXpath); //define cardinality and conformance var cardinality = CardinalityParser.Parse("0..*"); var conformance = ConformanceParser.Parse("SHALL"); //add element (context comes from doc), conformance, cardinality through fluent interface builder.ConformsTo(conformance).WithCardinality(cardinality); //generate string string assertion = builder.ToString(); string expected = "not(code) or code"; //did we generate the correct string? Assert.IsTrue(assertion == expected, "The generated assertion was not correct. Expected '{0}', Actual '{1}'.", expected, assertion); }
public ConstraintParser(IObjectRepository tdb, IConstraint constraint, ImplementationGuideType igType, string valueSetFile = "voc.xml", VocabularyOutputType vocabularyOutputType = VocabularyOutputType.Default) { this.tdb = tdb; this.constraint = constraint; this.valueSetFile = valueSetFile; this.igTypePlugin = igType.GetPlugin(); if (this.constraint.ValueSetId != null) { this.constraintValueSet = this.tdb.ValueSets.Single(y => y.Id == constraint.ValueSetId); } if (this.constraint.ValueCodeSystemId != null) { this.constraintCodeSystem = this.tdb.CodeSystems.Single(y => y.Id == constraint.ValueCodeSystemId); } if (!string.IsNullOrEmpty(this.constraint.Cardinality)) { this.constraintCardinalityType = CardinalityParser.Parse(this.constraint.Cardinality); } if (!string.IsNullOrEmpty(this.constraint.Conformance)) { this.constraintConformanceType = ConformanceParser.Parse(this.constraint.Conformance); } if (this.constraint.ContainedTemplateId != null) { this.containedTemplate = this.tdb.Templates.Single(y => y.Id == this.constraint.ContainedTemplateId.Value); } this.prefix = igType.SchemaPrefix; this.vocabularyOutputType = vocabularyOutputType; }
/// <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); }