public object Translate(Artifact source)
		{
			var result = new CREFModel.DynamicRule();

			var context = new TranslationContext(this);

			// Metadata
			var identifier = source.MetaData.Children.First(c => c.Name == "identifiers").Children.First(c => c.Name == "identifier");
			result.Name = identifier.GetAttribute<string>("root");
			result.Description = source.MetaData.Children.First(c => c.Name == "title").GetAttribute<string>("value");
			result.SeverityID = "MED"; // TODO: HeD does not have an artifact level severity indicator.

			// Named Expressions
			result.DynamicRuleNamedExpressions = 
				(
					from expression in source.Expressions
						select TranslateNamedExpression(context, expression)
				).ToList();

			// Criteria
			result.DynamicRuleCriteria = TranslateCriteria(context, source.Conditions.First());

			// TODO: Assertion
			result.DynamicRuleAssertion = TranslateAssertion(context, source.ActionGroup);

			return result;
		}
Пример #2
0
		public object Translate(TranslationContext context, ASTNode node)
		{
			var result = new SQLModel.TableExpression();
			var sqlContext = (SQLTranslationContext)context;
			result.TableName = sqlContext.GetExpressionObjectName(String.Format("{0}.{1}", node.GetAttribute<string>("libraryName", sqlContext.ArtifactName), node.GetAttribute<string>("name")));

			// If the expression being referenced is scalar, it will be automatically promoted to a query by the expression def translation
			// In this case, it must be demoted back to a scalar expression with a subquery access.
			if (!(node.ResultType is ListType) && !(node.ResultType is ObjectType))
			{
				var selectExpression = new SQLModel.SelectExpression();
				selectExpression.SelectClause = new SQLModel.SelectClause();
				selectExpression.SelectClause.Columns.Add(new SQLModel.ColumnExpression(new SQLModel.QualifiedFieldExpression("value")));
				selectExpression.FromClause = new SQLModel.CalculusFromClause(new SQLModel.TableSpecifier(result));

				// If the result type is also boolean, the expression will be converted to a 1 or 0, so it must be demoted back to an actual boolean-valued expression
				if (DataTypes.Equal(node.ResultType, DataTypes.Boolean))
				{
					return SQLTranslationUtilities.DemoteBooleanValuedExpression(selectExpression);
				}

				return selectExpression;
			}

			return result;
		}
		private CREFModel.ClinicalAssertion TranslateClinicalAssertion(TranslationContext context, Node node)
		{
			// node is expected to be an ActionGroup
			// Action types determine the assertion to be created
				// CreateAction - MissingDataAssertion
				// UpdateAction - MissingDataAssertion
				// MessageAction - OutOfRangeAssertion
				// CollectInformationAction - MissingDataAssertion
				// Any other action cannot be represented

			var assertions = new List<CREFModel.ClinicalAssertion>();

			var subElements = node.Children.FirstOrDefault(c => c.Name == "subElements");

			if (subElements != null)
			{
				foreach (var element in subElements.Children)
				{
					if (element.Name == "simpleAction")
					{
						switch (element.NodeType.GetLocalName())
						{
							case "CreateAction" : assertions.Add(TranslateCreateAction(context, element)); break;
							case "UpdateAction" : assertions.Add(TranslateUpdateAction(context, element)); break;
							case "MessageAction" : assertions.Add(TranslateMessageAction(context, element)); break;
							case "CollectInformationAction" : assertions.Add(TranslateCollectInformationAction(context, element)); break;
							default: throw new NotSupportedException(String.Format("Translation of {0} actions is not supported.", element.NodeType.GetLocalName()));
						}
					}
					else if (element.Name == "actionGroup")
					{
						assertions.Add(TranslateClinicalAssertion(context, element));
					}
					else if (element.Name == "actionGroupReference")
					{
						throw new NotSupportedException("Translation of action group references is not supported.");
					}
				}
			}

			if (assertions.Count > 1)
			{
				var compositeAssertion = new CREFModel.CompositeAssertion();

				compositeAssertion.CompositionType = GetCompositionType(GetGroupSelectionBehavior(node));

				var descriptionNode = node.Children.FirstOrDefault(c => c.Name == "Description");
				if (descriptionNode != null)
				{
					compositeAssertion.Description = descriptionNode.GetAttribute<string>("value");
				}

				compositeAssertion.CompositeAssertionAssertions.AddRange(assertions);

				return compositeAssertion;
			}

			return assertions[0];
		}
		private CREFModel.DynamicRuleDynamicRuleAssertion TranslateAssertion(TranslationContext context, Node node)
		{
			var result = new CREFModel.DynamicRuleDynamicRuleAssertion();

			result.Item = TranslateClinicalAssertion(context, node);

			return result;
		}
		private CREFModel.DynamicRuleDynamicRuleCriteria TranslateCriteria(TranslationContext context, ASTNode condition)
		{
			var result = new CREFModel.DynamicRuleDynamicRuleCriteria();

			result.Item = context.TranslateNode(condition);

			return result;
		}
Пример #6
0
		public object Translate(TranslationContext context, ASTNode node)
		{
			var result = new CREFModel.ExpressionReference();

			result.Name = node.GetAttribute<string>("name");

			return result;
		}
		private CREFModel.NamedExpression TranslateNamedExpression(TranslationContext context, ExpressionDef expression)
		{
			var result = new CREFModel.NamedExpression();

			result.Name = expression.Name;
			result.Item = context.TranslateNode(expression.Expression);

			return result;
		}
		protected object GetFirstExpression(TranslationContext context, object source)
		{
			var first = new SQLModel.UnaryExpression();

			first.Item = source;
			first.Operator = SQLModel.UnaryOperator.opFirst;
			first.OperatorSpecified = true;

			return first;
		}
Пример #9
0
		public object Translate(TranslationContext context, ASTNode node)
		{
			var result = new CREFModel.ParameterExpression();

			result.Name = node.GetAttribute<string>("name");

			// TODO: Default value?

			return result;
		}
Пример #10
0
		public object Translate(TranslationContext context, ASTNode node)
		{
			var result = new SQLModel.TableExpression();

			// TODO: Handle Cardinality
			// TODO: Handle whether we are in a FromClause context.
			var sqlContext = (SQLTranslationContext)context;
			result.TableName = sqlContext.GetExpressionObjectName(String.Format("{0}.{1}", node.GetAttribute<string>("libraryName", sqlContext.ArtifactName), node.GetAttribute<string>("name")));

			return result;
		}
		protected object TranslateCodeReference(TranslationContext context, ObjectType sourceType, ASTNode node, string path)
		{
			// Reference the Codes property with a First expression
			var result = GetPropertyExpression(context, node, "Codes");

			result = GetFirstExpression(context, result);

			// TODO: Issue a warning that an arbitrary Code is being selected

			return result;
		}
		protected object GetPropertyExpression(TranslationContext context, ASTNode node, string path)
		{
			var result = new SQLModel.PropertyExpression();
			result.Path = path;

			if (node.Children.Count > 0)
			{
				result.Item = context.TranslateNode(node.Children[0]);
			}

			return result;
		}
Пример #13
0
        public object Translate(TranslationContext context, ASTNode node)
        {
            var result = new CREFModel.BinaryExpression();
            result.Operator = GetOperator();
            result.OperatorSpecified = true;

            foreach (var child in node.Children)
            {
                result.Items.Add(context.TranslateNode(child));
            }

            return result;
        }
Пример #14
0
		public object Translate(TranslationContext context, ASTNode node)
		{
			var result = new CREFModel.ValueExpression();

			if (DataTypes.Equal(node.ResultType, DataTypes.String))
			{
				result.Type = Model.ValueType.String;
				result.TypeSpecified = true;
				result.Value = node.GetAttribute<string>("value");
			}
			else if (DataTypes.Equal(node.ResultType, DataTypes.Integer))
			{
				result.Type = Model.ValueType.Int32;
				result.TypeSpecified = true;
				result.Value = node.GetAttribute<string>("value");
			}
			else if (DataTypes.Equal(node.ResultType, DataTypes.Boolean))
			{
				result.Type = Model.ValueType.Boolean;
				result.TypeSpecified = true;
				result.Value = node.GetAttribute<string>("value");
			}
			else if (DataTypes.Equal(node.ResultType, DataTypes.Decimal))
			{
				result.Type = Model.ValueType.Decimal;
				result.TypeSpecified = true;
				result.Value = node.GetAttribute<string>("value");
			}
			else if (DataTypes.Equal(node.ResultType, DataTypes.DateTime))
			{
				result.Type = Model.ValueType.Date;
				result.TypeSpecified = true;
				result.Value = node.GetAttribute<string>("value"); // TODO: Convert to format expected by CREF
			}
			else
			{
				throw new NotSupportedException(String.Format("Unsupported literal type: {0}.", node.ResultType.Name));
			}

			return result;
		}
		protected object GetCalculateAgeExpression(TranslationContext context, object result)
		{
			var calculateAge = new SQLModel.CalculateAge();

			calculateAge.Items.Add(result);

			var binaryExpression = new SQLModel.BinaryExpression();

			// Returns as years, so multiply by days/year to get consistent results with the physical quantity translator
			binaryExpression.Operator = SQLModel.BinaryOperator.opMultiply;
			binaryExpression.OperatorSpecified = true;
			binaryExpression.Items.Add(calculateAge);

			var multiplier = new SQLModel.ValueExpression();
			multiplier.Type = SQLModel.ValueType.Decimal;
			multiplier.TypeSpecified = true;
			multiplier.Value = Convert.ToString(365.25m);

			binaryExpression.Items.Add(multiplier);

			return binaryExpression;
		}
Пример #16
0
		public object Translate(TranslationContext context, ASTNode node)
		{
			if (DataTypes.Equal(node.ResultType, DataTypes.Boolean))
			{
				return new Model.BinaryExpression(new Model.ValueExpression(1), "iEqual", new Model.ValueExpression(Boolean.Parse(node.GetAttribute<string>("value")) ? 1 : 0));
			}
			else if (DataTypes.Equal(node.ResultType, DataTypes.DateTime))
			{
				// TODO: Convert to format expected by T-SQL
				return new Model.CallExpression("convert", new Model.Expression[] { new Model.IdentifierExpression("datetime"), new Model.ValueExpression(node.GetAttribute<string>("value")) }); 
			}
			else
			{
				var result = new Model.ValueExpression();

				if (DataTypes.Equal(node.ResultType, DataTypes.String))
				{
					result.Token = Model.TokenType.String;
					result.Value = node.GetAttribute<string>("value");
				}
				else if (DataTypes.Equal(node.ResultType, DataTypes.Integer))
				{
					result.Token = Model.TokenType.Integer;
					result.Value = Int32.Parse(node.GetAttribute<string>("value"));
				}
				else if (DataTypes.Equal(node.ResultType, DataTypes.Decimal))
				{
					result.Token = Model.TokenType.Decimal;
					result.Value = Decimal.Parse(node.GetAttribute<string>("value"));
				}
				else
				{
					throw new NotSupportedException(String.Format("Unsupported literal type: {0}.", node.ResultType.Name));
				}

				return result;
			}
		}
Пример #17
0
        public object Translate(TranslationContext context, ASTNode node)
        {
            var result = new CREFModel.ListExpression();

            foreach (var child in node.Children)
            {
                result.Items.Add(context.TranslateNode(child));
            }

            return result;
        }
Пример #18
0
        public object Translate(TranslationContext context, ASTNode node)
        {
            // Ideally, this would be expressed as an InValueSet expression within CREF, but in the absence of such an operator, the translation
            // Can be supporting using: Exists(Filter(ValueSet(ValueSetId), Condition(Current = Operand)))
            var valueSetId = node.GetAttribute<string>("id");
            var valueSetVersion = node.GetAttribute<string>("version");
            var valueSetAuthority = node.GetAttribute<string>("authority"); // TODO: Authority resolution?

            var operand = node.Children.FirstOrDefault(c => c.Name == "operand");

            var valueSetExpression = new CREFModel.ValueSetExpression();
            valueSetExpression.ValueSetID = valueSetId;
            if (!String.IsNullOrEmpty(valueSetVersion))
            {
                valueSetExpression.Version = Convert.ToInt32(valueSetVersion);
                valueSetExpression.VersionSpecified = true;
            }

            var filter = new CREFModel.FilterExpression();

            filter.Items.Add(valueSetExpression);

            var condition = new CREFModel.BinaryExpression();
            condition.Operator = CREFModel.BinaryOperator.opEqual;
            condition.OperatorSpecified = true;

            // Assumption: A property expression with no path specified is equivalent to a "current" reference
            var property = new CREFModel.PropertyExpression();

            condition.Items.Add(property);
            condition.Items.Add(context.TranslateNode(operand));

            var exists = new CREFModel.UnaryExpression();
            exists.Operator = CREFModel.UnaryOperator.opExists;
            exists.OperatorSpecified = true;
            exists.Item = filter;

            return exists;
        }
Пример #19
0
        public object Translate(TranslationContext context, ASTNode node)
        {
            var unaryExpression = new CREFModel.UnaryExpression();
            unaryExpression.Operator = CREFModel.UnaryOperator.opExists;
            unaryExpression.OperatorSpecified = true;
            unaryExpression.Item = context.TranslateNode(node.Children[0]);

            return unaryExpression;
        }
Пример #20
0
        public object Translate(TranslationContext context, ASTNode node)
        {
            // As long as this is list containment, it can be translated using an Exists(Filter(Collection, Condition(Current = Element)));
            var collectionNode = node.Children.FirstOrDefault(c => c.Name == "collection");
            var elementNode = node.Children.FirstOrDefault(c => c.Name == "element");

            if (elementNode.ResultType is ListType)
            {
                throw new NotSupportedException("In translation with an element of type list is not supported because there is no equivalent CREF representation.");
            }

            var filter = new CREFModel.FilterExpression();

            filter.Items.Add(context.TranslateNode(collectionNode));

            var condition = new CREFModel.BinaryExpression();
            condition.Operator = CREFModel.BinaryOperator.opEqual;
            condition.OperatorSpecified = true;

            // Assumption: A property expression with no path specified is equivalent to a "current" reference
            var property = new CREFModel.PropertyExpression();

            condition.Items.Add(property);
            condition.Items.Add(context.TranslateNode(elementNode));

            var exists = new CREFModel.UnaryExpression();
            exists.Operator = CREFModel.UnaryOperator.opExists;
            exists.OperatorSpecified = true;
            exists.Item = filter;

            return exists;
        }
Пример #21
0
        public object Translate(TranslationContext context, ASTNode node)
        {
            // Use LogicalConnective
            var result = new CREFModel.LogicalConnective();

            result.Operator = GetOperator();
            result.OperatorSpecified = true;

            foreach (var child in node.Children)
            {
                var childResult = context.TranslateNode(child);
                result.Items.Add(childResult);
            }

            return result;
        }
Пример #22
0
 public object Translate(TranslationContext context, ASTNode node)
 {
     var child = node.Children[0];
     return context.TranslateNode(child);
 }
Пример #23
0
        public object Translate(TranslationContext context, ASTNode node)
        {
            if (DataTypes.Equal(node.ResultType, DataTypes.TimestampInterval))
            {
                var result = new CREFModel.DateRange();

                var beginOpen = Convert.ToBoolean(node.GetAttribute<string>("beginOpen"));
                var endOpen = Convert.ToBoolean(node.GetAttribute<string>("endOpen"));
                if (beginOpen || endOpen)
                {
                    throw new NotSupportedException("Translation for open intervals is not supported because CREF only supports closed interval values.");
                }

                foreach (var child in node.Children)
                {
                    result.Items.Add(context.TranslateNode(child));
                }

                return result;
            }
            else
            {
                throw new NotSupportedException("Translation for intervals with point types other than Timestamp is not supported because CREF does not support generic interval values.");
            }
        }
Пример #24
0
        public object Translate(TranslationContext context, ASTNode node)
        {
            var scope = node.GetAttribute<string>("scope", VerificationContext.Current);
            if (scope != VerificationContext.Current)
            {
                throw new NotSupportedException("Translation of filter expression is not supported because it involves a named scope reference, which is not supported in CREF.");
            }

            var source = node.Children[0];
            var condition = node.Children[1];

            var result = new CREFModel.FilterExpression();
            result.Items.Add(context.TranslateNode(source));
            result.Items.Add(context.TranslateNode(condition));

            return result;
        }
Пример #25
0
        // Children
        // date
        // granularity
        // numberOfPeriods
        public object Translate(TranslationContext context, ASTNode node)
        {
            var result = new CREFModel.DateAdd();

            var date = node.Children[0];
            result.Items.Add(context.TranslateNode(date));

            var granularity = node.Children[1];
            if (granularity.NodeType == "urn:hl7-org:v3:knowledgeartifact:r1:Literal") // TODO: Better story for this type of thing....
            {
                result.Granularity = (CREFModel.DateGranularity)Enum.Parse(typeof(CREFModel.DateGranularity), granularity.GetAttribute<string>("value"));
                result.GranularitySpecified = true;
            }
            else
            {
                throw new NotSupportedException("Date granularity argument to a DateAdd expression must be a literal because CREF does not support granularity as an argument, only as an attribute of the target DateAdd expression.");
            }

            var numberOfPeriods = node.Children[2];
            result.Items.Add(context.TranslateNode(numberOfPeriods));

            return result;
        }
Пример #26
0
        public object Translate(TranslationContext context, ASTNode node)
        {
            // As long as this is list containment, it can be translated using an Exists(Filter(Source, Condition(Current = Value)));
            // TODO: Contains on a date interval could be translated as well
            var sourceNode = node.Children.FirstOrDefault(c => c.Name == "source");
            var elementNode = node.Children.FirstOrDefault(c => c.Name == "element");

            if (sourceNode.ResultType is IntervalType)
            {
                throw new NotImplementedException("Contains translation with Interval source is not yet supported.");
            }

            var filter = new CREFModel.FilterExpression();

            filter.Items.Add(context.TranslateNode(sourceNode));

            var condition = new CREFModel.BinaryExpression();
            condition.Operator = CREFModel.BinaryOperator.opEqual;
            condition.OperatorSpecified = true;

            // Assumption: A property expression with no path specified is equivalent to a "current" reference
            var property = new CREFModel.PropertyExpression();

            condition.Items.Add(property);
            condition.Items.Add(context.TranslateNode(elementNode));

            var exists = new CREFModel.UnaryExpression();
            exists.Operator = CREFModel.UnaryOperator.opExists;
            exists.OperatorSpecified = true;
            exists.Item = filter;

            return exists;
        }
Пример #27
0
        public object Translate(TranslationContext context, ASTNode node)
        {
            var result = new CREFModel.Code();

            result.CodeValue = node.GetAttribute<string>("code");
            result.CodingSystem = node.GetAttribute<string>("codeSystemName");
            result.CodeType = node.GetAttribute<string>("codeSystem"); // TODO: Verify w/ Allscripts
            result.CodeDescription = node.GetAttribute<string>("displayName");

            return result;
        }
Пример #28
0
        public object Translate(TranslationContext context, ASTNode node)
        {
            // Model mapping
            var result = new CREFModel.RequestExpression();

            if (node.ResultType == null)
            {
                throw new InvalidOperationException("Clinical request expression has no result type.");
            }

            var cardinality = (RequestCardinality)Enum.Parse(typeof(RequestCardinality), node.Attributes["cardinality"].ToString(), true);
            result.Cardinality = cardinality == RequestCardinality.Single ? CREFModel.RequestCardinality.Single : CREFModel.RequestCardinality.Multiple;
            result.CardinalitySpecified = true;

            var requestListType = node.ResultType as ListType;
            var requestType = (requestListType == null ? node.ResultType : requestListType.ElementType) as ObjectType;
            if (requestType == null)
            {
                throw new InvalidOperationException(String.Format("Unable to determine request type from source type: '{0}'.", node.ResultType.Name));
            }

            result.Type = GetQueryType(context.TransformModelType(requestType));
            result.TypeSpecified = true;

            // Translate Codes
            var codes = node.Children.Where(n => n.Name == "codes").FirstOrDefault();
            if (codes != null)
            {
                var codesResult = context.TranslateNode(codes);
                result.Items.Add(codesResult);
            }

            // Translate DateRange
            var dateRange = node.Children.Where(n => n.Name == "dateRange").FirstOrDefault();
            if (dateRange != null)
            {
                var dateRangeResult = context.TranslateNode(dateRange);
                result.Items.Add(dateRangeResult);
            }

            // Validate idProperty, dateProperty, and codeProperty
            ValidateIdProperty(requestType, node.GetAttribute<string>("idProperty"));
            ValidateDateProperty(requestType, node.GetAttribute<string>("dateProperty"));
            ValidateCodeProperty(requestType, node.GetAttribute<string>("codeProperty"));

            // Add status filters if necessary
            var filterValue = GetStatusFilterValue(requestType);
            if (!String.IsNullOrEmpty(filterValue))
            {
                var filter = new CREFModel.FilterExpression();

                filter.Items.Add(result);

                var condition = new CREFModel.BinaryExpression();
                condition.Operator = CREFModel.BinaryOperator.opEqual;
                condition.OperatorSpecified = true;

                condition.Items.Add(new CREFModel.PropertyExpression() { Path = "Status" });
                condition.Items.Add(new CREFModel.ValueExpression() { Type = CREFModel.ValueType.String, TypeSpecified = true, Value = filterValue });

                filter.Items.Add(condition);

                return filter;
            }

            return result;
        }
Пример #29
0
        public object Translate(TranslationContext context, ASTNode node)
        {
            var result = new CREFModel.ValueExpression();

            result.Type = CREFModel.ValueType.Boolean;
            result.TypeSpecified = true;

            result.Value = node.GetAttribute<string>("value"); // TODO: This assumes boolean representation will translate...

            return result;
        }
Пример #30
0
        public object Translate(TranslationContext context, ASTNode node)
        {
            var result = new CREFModel.ValueSetExpression();

            // TODO: Handle Value Set Mapping
            result.ValueSetID = node.GetAttribute<string>("id");

            var version = node.GetAttribute<string>("version");
            if (!String.IsNullOrEmpty(version))
            {
                result.Version = Int32.Parse(version);
                result.VersionSpecified = true;
            }

            // TODO: Value Set Authority

            return result;
        }