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; }
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; }
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; }
public object Translate(TranslationContext context, ASTNode node) { var result = new CREFModel.ParameterExpression(); result.Name = node.GetAttribute<string>("name"); // TODO: Default value? return result; }
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; }
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; }
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; }
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; } }
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; }
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; }
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; }
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; }
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; }
public object Translate(TranslationContext context, ASTNode node) { var child = node.Children[0]; return context.TranslateNode(child); }
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."); } }
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; }
// 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; }
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; }
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; }
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; }
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; }
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; }