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); }
/// <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); }
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); }