private TemplateConstraint CloneTemplateConstraint(Template newTemplate, TemplateConstraint parentConstraint, TemplateConstraint constraint)
        {
            TemplateConstraint newConstraint = new TemplateConstraint()
            {
                Template           = newTemplate,
                Conformance        = constraint.Conformance,
                Cardinality        = constraint.Cardinality,
                Value              = constraint.Value,
                PrimitiveText      = constraint.PrimitiveText,
                DataType           = constraint.DataType,
                Context            = constraint.Context,
                CodeSystemId       = constraint.CodeSystemId,
                DisplayName        = constraint.DisplayName,
                IsBranch           = constraint.IsBranch,
                Order              = constraint.Order,
                Schematron         = constraint.Schematron,
                ValueConformance   = constraint.ValueConformance,
                ValueSetId         = constraint.ValueSetId,
                IsStatic           = constraint.IsStatic,
                IsBranchIdentifier = constraint.IsBranchIdentifier,
                IsSchRooted        = constraint.IsSchRooted,
                IsPrimitive        = constraint.IsPrimitive,
                IsInheritable      = constraint.IsInheritable,
                ValueSetDate       = constraint.ValueSetDate,
                Label              = constraint.Label,
                Notes              = constraint.Notes,
                Description        = constraint.Description,
                Number             = constraint.Number.Value,
                Category           = constraint.Category
            };

            if (parentConstraint != null)
            {
                newConstraint.ParentConstraintId = null;
                newConstraint.ParentConstraint   = parentConstraint;
            }

            if (constraint.ContainedTemplate != null)
            {
                newConstraint.ContainedTemplateId = null;
                newConstraint.ContainedTemplate   = constraint.ContainedTemplate;
            }

            // Clone each child constraint
            constraint.ChildConstraints.ToList().ForEach(y =>
            {
                newTemplate.ChildConstraints.Add(
                    CloneTemplateConstraint(newTemplate, newConstraint, y));
            });

            return(newConstraint);
        }
Example #2
0
        private void AddImportConstraint(TDBTemplate template, TDBTemplateConstraint parentConstraint, ImportConstraint importConstraint)
        {
            if (importConstraint.isVerbose)
            {
                return;
            }

            TDBTemplateConstraint constraint = null;

            if (importConstraint.numberSpecified)
            {
                constraint = template.ChildConstraints.SingleOrDefault(y => y.ParentConstraint == parentConstraint && y.Number == importConstraint.number);
            }
            else if (!string.IsNullOrEmpty(importConstraint.displayNumber))
            {
                constraint = template.ChildConstraints.SingleOrDefault(y => y.ParentConstraint == parentConstraint && y.DisplayNumber == importConstraint.displayNumber);
            }

            if (constraint == null)
            {
                constraint                  = new TDBTemplateConstraint();
                constraint.Number           = importConstraint.number;
                constraint.DisplayNumber    = importConstraint.displayNumber;
                constraint.Template         = template;
                constraint.ParentConstraint = parentConstraint;
                this.tdb.TemplateConstraints.Add(constraint);

                // TODO: Order the constraint? Or let the template re-order the constraints when it is edited?
            }

            this.UpdateConstraintProperties(constraint, importConstraint);

            this.UpdateConstraintContainedTemplate(constraint, importConstraint.ContainedTemplate);

            this.UpdateConstraintBinding(constraint, importConstraint);

            this.UpdateConstraintCodeSystem(constraint, importConstraint);

            this.UpdateConstraintCategories(constraint, importConstraint);

            this.UpdateConstraintSamples(constraint, importConstraint);

            // Add each of the constraint's child constraints
            if (importConstraint.Constraint != null)
            {
                importConstraint.Constraint.ToList().ForEach(y => AddImportConstraint(template, constraint, y));
            }
        }
        public object Clone()
        {
            TemplateConstraint clone = new TemplateConstraint();

            clone._Cardinality         = this._Cardinality;
            clone._CodeSystemId        = this._CodeSystemId;
            clone._Conformance         = this._Conformance;
            clone._ContainedTemplateId = this._ContainedTemplateId;
            clone._Context             = this._Context;
            clone._DataType            = this._DataType;
            clone._Description         = this._Description;
            clone._DisplayName         = this._DisplayName;
            clone._Id                 = this._Id;
            clone._IsBranch           = this._IsBranch;
            clone._IsBranchIdentifier = this._IsBranchIdentifier;
            clone._IsInheritable      = this._IsInheritable;
            clone._IsPrimitive        = this._IsPrimitive;
            clone._IsSchRooted        = this._IsSchRooted;
            clone._IsStatic           = this._IsStatic;
            clone._Label              = this._Label;
            clone._Notes              = this._Notes;
            clone._Order              = this._Order;
            clone._ParentConstraintId = this._ParentConstraintId;
            clone._PrimitiveText      = this._PrimitiveText;
            clone._Schematron         = this._Schematron;
            clone._TemplateId         = this._TemplateId;
            clone._Value              = this._Value;
            clone._ValueConformance   = this._ValueConformance;
            clone._ValueSetDate       = this._ValueSetDate;
            clone._ValueSetId         = this._ValueSetId;
            clone.Template            = this.Template;
            clone.ParentConstraint    = this.ParentConstraint;
            clone.CodeSystem          = this.CodeSystem;
            clone.ContainedTemplate   = this.ContainedTemplate;
            clone.ValueSet            = this.ValueSet;
            clone.Number              = this.Number;
            return(clone);
        }
        public string GetXpath()
        {
            if (this.IsPrimitive)
            {
                return(string.Empty);
            }

            StringBuilder      sb      = new StringBuilder();
            TemplateConstraint current = this;

            while (current != null && !string.IsNullOrEmpty(current.Context))
            {
                if (sb.Length > 0)
                {
                    sb.Insert(0, "/");
                }

                sb.Insert(0, current.Context);
                current = current.ParentConstraint;
            }

            return(sb.ToString());
        }
Example #5
0
        private TemplateConstraint CloneTemplateConstraint(Template newTemplate, TemplateConstraint parentConstraint, TemplateConstraint constraint)
        {
            TemplateConstraint newConstraint = new TemplateConstraint()
            {
                Template           = newTemplate,
                Conformance        = constraint.Conformance,
                Cardinality        = constraint.Cardinality,
                Value              = constraint.Value,
                PrimitiveText      = constraint.PrimitiveText,
                DataType           = constraint.DataType,
                Context            = constraint.Context,
                CodeSystemId       = constraint.CodeSystemId,
                DisplayName        = constraint.DisplayName,
                IsBranch           = constraint.IsBranch,
                Order              = constraint.Order,
                Schematron         = constraint.Schematron,
                ValueConformance   = constraint.ValueConformance,
                ValueSetId         = constraint.ValueSetId,
                IsStatic           = constraint.IsStatic,
                IsBranchIdentifier = constraint.IsBranchIdentifier,
                IsSchRooted        = constraint.IsSchRooted,
                IsPrimitive        = constraint.IsPrimitive,
                IsInheritable      = constraint.IsInheritable,
                ValueSetDate       = constraint.ValueSetDate,
                Label              = constraint.Label,
                Notes              = constraint.Notes,
                Description        = constraint.Description,
                Number             = constraint.Number.Value,
                Category           = constraint.Category,
                MustSupport        = constraint.MustSupport,
                IsModifier         = constraint.IsModifier,
                IsFixed            = constraint.IsFixed,
                IsChoice           = constraint.IsChoice,
                IsHeading          = constraint.IsHeading,
                HeadingDescription = constraint.HeadingDescription
            };

            if (parentConstraint != null)
            {
                newConstraint.ParentConstraintId = null;
                newConstraint.ParentConstraint   = parentConstraint;
            }

            constraint.References.ToList().ForEach(y =>
            {
                newConstraint.References.Add(new TemplateConstraintReference()
                {
                    Constraint          = newConstraint,
                    ReferenceIdentifier = y.ReferenceIdentifier,
                    ReferenceType       = y.ReferenceType
                });
            });

            // Clone each child constraint
            constraint.ChildConstraints.ToList().ForEach(y =>
            {
                newTemplate.ChildConstraints.Add(
                    CloneTemplateConstraint(newTemplate, newConstraint, y));
            });

            return(newConstraint);
        }
Example #6
0
 private void SetPropeties(TemplateConstraint constraint)
 {
 }
        /// <summary>
        /// Perform validations on a single constraint.
        /// </summary>
        /// <param name="errors">The list of errors that should be added to when a constraint has an error matching the schema</param>
        /// <param name="schemaObjects">The list of sibling-level schema objects that the constraint should be compared to</param>
        /// <param name="currentConstraint">The current constraint to match against the schema</param>
        public static void ValidateTemplateConstraint(this Template template, XPathNavigator xpathNavigator, List <TemplateValidationResult> errors, SimpleSchema schema, List <SimpleSchema.SchemaObject> schemaObjects, TemplateConstraint currentConstraint)
        {
            List <TemplateConstraint> childConstraints = currentConstraint.ChildConstraints.ToList();

            if (!string.IsNullOrEmpty(currentConstraint.Schematron))
            {
                try
                {
                    XPathExpression expr = xpathNavigator.Compile(currentConstraint.Schematron);
                }
                catch (XPathException ex)
                {
                    errors.Add(TemplateValidationResult.CreateResult(currentConstraint.Number, ValidationLevels.Error, "Custom schematron is not valid: " + ex.Message));
                }
            }

            if (currentConstraint.IsPrimitive && string.IsNullOrEmpty(currentConstraint.PrimitiveText))
            {
                errors.Add(TemplateValidationResult.CreateResult(currentConstraint.Number, ValidationLevels.Error, "Primitive does not have any narrative text."));
                return;
            }
            else if (!string.IsNullOrEmpty(currentConstraint.Context))
            {
                string context     = currentConstraint.Context;
                bool   isAttribute = context.StartsWith("@");

                // If it is an attribute, then we need to remove the @ from the context
                if (isAttribute)
                {
                    context = context.Substring(1);
                }

                SimpleSchema.SchemaObject foundSchemaObject = schemaObjects.SingleOrDefault(y => y.Name.ToLower() == context.ToLower() && y.IsAttribute == isAttribute);

                // Verify that the template (if specified) matches the datatype of the constraints
                if (currentConstraint.ContainedTemplate != null &&
                    currentConstraint.ContainedTemplate.PrimaryContextType != null &&
                    foundSchemaObject != null)
                {
                    string containedTemplateDataType = currentConstraint.ContainedTemplate.PrimaryContextType;
                    string constraintDataType        = !string.IsNullOrEmpty(currentConstraint.DataType) ? currentConstraint.DataType : foundSchemaObject.DataType;

                    bool isFhirResourceReference = schema.Schema.TargetNamespace == "http://hl7.org/fhir" && (constraintDataType == "ResourceReference" || constraintDataType == "Reference");

                    if (!isFhirResourceReference && containedTemplateDataType.ToLower() != constraintDataType.ToLower())
                    {
                        errors.Add(TemplateValidationResult.CreateResult(
                                       currentConstraint.Number,
                                       ValidationLevels.Error,
                                       "Contained template \"{0}\" has a type of \"{1}\" which does not match the containing element \"{2}\"",
                                       currentConstraint.ContainedTemplate.Oid,
                                       containedTemplateDataType,
                                       constraintDataType));
                    }
                }

                // Verify that branched elements have at least one identifier
                if (currentConstraint.IsBranch && childConstraints.Count(y => y.IsBranchIdentifier) == 0)
                {
                    errors.Add(TemplateValidationResult.CreateResult(currentConstraint.Number, ValidationLevels.Warning, "Branched constraint \"{0}\" does not have any identifiers associated with it.", currentConstraint.GetXpath()));
                }

                // Verify that a schema-object can be matched to this constraint
                if (foundSchemaObject == null)
                {
                    errors.Add(TemplateValidationResult.CreateResult(currentConstraint.Number, ValidationLevels.Error, "Constraint has context of \"{0}\" which is not found in the schema.", currentConstraint.GetXpath()));
                    return; // Do not process child constraints when the parent is not matched to the schema
                }
                else if (foundSchemaObject.Cardinality != null && currentConstraint.Cardinality != null)
                {
                    // Warn when a constraint that is associated with the schema that has multiple cardinality but is not branched
                    if (template.IsOpen &&
                        !foundSchemaObject.Cardinality.EndsWith("..1") &&
                        !foundSchemaObject.Cardinality.EndsWith("..0") &&
                        !currentConstraint.IsBranch)
                    {
                        var error = TemplateValidationResult.CreateResult(currentConstraint.Number, ValidationLevels.Warning, "Schema allows multiple for \"{0}\" but the constraint is not branched. Consider branching this constraint.", currentConstraint.GetXpath());
                        errors.Add(error);
                    }

                    if (foundSchemaObject.Cardinality.EndsWith("..1") && !(currentConstraint.Cardinality.EndsWith("..0") || currentConstraint.Cardinality.EndsWith("..1")))
                    {
                        var error = TemplateValidationResult.CreateResult(currentConstraint.Number, ValidationLevels.Error, "The cardinality for the element is loosened in the constraint from the underlying schema.");
                        errors.Add(error);
                    }
                }

                List <SimpleSchema.SchemaObject> childSchemaObjects = foundSchemaObject.Children;

                // If a data-type is specified, then we should find the data-type within the schema, since it is likely different than what
                // is specified by default.
                if (!string.IsNullOrEmpty(currentConstraint.DataType))
                {
                    SimpleSchema.SchemaObject foundSchemaTypeObject = schema.FindFromType(currentConstraint.DataType);

                    if (foundSchemaTypeObject != null)
                    {
                        childSchemaObjects = foundSchemaTypeObject.Children;
                    }
                }

                childConstraints.ForEach(y => template.ValidateTemplateConstraint(xpathNavigator, errors, schema, childSchemaObjects, y));
            }
        }