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(Artifact source)
		{
            var result = new SQLModel.Batch();

			var context = new SQLTranslationContext(this);

			var identifier = source.MetaData.Children.First(c => c.Name == "identifiers").Children.First(c => c.Name == "identifier");
			context.StartArtifact(identifier.GetAttribute<string>("root"));
			try
			{
				// Libraries
				foreach (LibraryRef libraryRef in source.Libraries)
				{
					// Okay to pass null for the verification context here, each of the referenced libraries should already be verified at this point.
					result.Statements.AddRange(TranslateLibrary(context, libraryRef.Name, LibraryFactory.ResolveLibrary(libraryRef, null)));
				}

				// TODO: Parameters

				// ExpressionDefs
				foreach (ExpressionDef expression in source.Expressions) 
				{
					result.Statements.Add(TranslateExpressionDef(context, source.MetaData.Name, expression));
				}

				// Criteria
				// Criteria are translated as "create view <artifact name>_<condition><conditionNumber>"
				int conditionNumber = 0;
				foreach (ASTNode condition in source.Conditions) 
				{
					conditionNumber++;
					result.Statements.Add(TranslateCondition(context, source.MetaData.Name, String.Format("Condition{0}", conditionNumber), condition));
				}

				// TODO: Assertion

				return result;
			}
			finally
			{
				context.EndArtifact();
			}
		}
		public static Artifact Read(XDocument artifact, XmlSchemaSet schemas, string sourcePath)
		{
			artifact.Validate(schemas, onValidationEvent, true);

			if (artifact.Root.GetSchemaInfo().Validity != XmlSchemaValidity.Valid)
			{
				throw new InvalidOperationException("Artifact does not conform to the schema.");
			}

			var result = new Artifact();

			var ns = artifact.Root.GetDefaultNamespace();
			var elmns = XNamespace.Get("urn:hl7-org:elm:r1");

			var metaData = artifact.Root.Element(ns + "metadata");

			if (metaData != null)
			{
				result.MetaData = NodeReader.ReadNode(metaData);
			}

			// Pull models
			var dataModelsElement = artifact.Root.Element(ns + "metadata").Element(ns + "dataModels");
			if (dataModelsElement != null)
			{
				result.Models = ReadModels(ns, dataModelsElement.Elements(ns + "modelReference")).ToList();
			}
			else
			{
				result.Models = new List<ModelRef>();
			}

			// TODO: Add default model of HeDSchema?

			// Pull libraries
			var librariesElement = artifact.Root.Element(ns + "metadata").Element(ns + "libraries");
			if (librariesElement != null)
			{
				result.Libraries = ReadLibraries(ns, librariesElement.Elements(ns + "libraryReference"), sourcePath).ToList();
			}
			else
			{
				result.Libraries = new List<LibraryRef>();
			}

			var externalData = artifact.Root.Element(ns + "externalData");

			if (externalData != null)
			{
				// Pull Codesystems
				result.CodeSystems = ReadCodeSystems(ns, externalData.Elements(ns + "codesystem")).ToList();
				
				// Pull valuesets
				result.ValueSets = ReadValueSets(ns, externalData.Elements(ns + "valueset")).ToList();

				// Pull parameters
				result.Parameters = ReadParameters(ns, elmns, externalData.Elements(ns + "parameter")).ToList();

				// Pull external defs
				var externalDefs = ReadExpressionDefs(ns, elmns, externalData.Elements(ns + "def"));

				// Pull triggers
				var triggers = ReadTriggers(ns, elmns, externalData.Elements(ns + "trigger"));

                result.Expressions = externalDefs.Concat(triggers).ToList();
			}
			else
			{
				result.Parameters = new List<ParameterDef>();
				result.Expressions = new List<ExpressionDef>();
			}

			// Pull expressions
            var expressionsElement = artifact.Root.Element(ns + "expressions");
            if (expressionsElement != null)
            {
			    var expressions = ReadExpressionDefs(ns, elmns, expressionsElement.Elements(ns + "def"));

                result.Expressions = result.Expressions.Concat(expressions).ToList();
            }

			// Pull conditions
			var conditionsElement = artifact.Root.Element(ns + "conditions");
			if (conditionsElement != null)
			{
				result.Conditions = ReadConditions(ns, elmns, conditionsElement.Elements(ns + "condition")).ToList();
			}
			else
			{
				result.Conditions = new List<ASTNode>();
			}

			// Pull actions
			var actionGroupElement = artifact.Root.Element(ns + "actionGroup");
			if (actionGroupElement != null)
			{
				result.ActionGroup = NodeReader.ReadNode(actionGroupElement);
			}

			return result;
		}
        public IEnumerable<VerificationException> Verify(Artifact artifact)
        {
            // Parameters must be validated without access to parameter definitions, or expression definitions
            var initialContext = new VerificationContext(artifact.Models, null, null, null);

            // Resolve parameter types and verify default expressions
            foreach (var parameter in artifact.Parameters)
            {
                try
                {
                    parameter.ParameterType = initialContext.ResolveType(parameter.TypeName);

                    if (parameter.Default != null)
                    {
                        Verifier.Verify(initialContext, parameter.Default);
                        initialContext.VerifyType(parameter.Default.ResultType, parameter.ParameterType);
                    }
                }
                catch (Exception e)
                {
                    initialContext.ReportMessage(new VerificationException(String.Format("Exceptions occurred verifying parameter {0}.", parameter.Name), e), null);
                }
            }

            var context = new VerificationContext(artifact.Models, artifact.Parameters, artifact.Expressions, initialContext.Messages);

            // Verify expressions
            foreach (var expression in artifact.Expressions)
            {
                // If the result type is already set, this expression ref has already been resolved.
                if (expression.Expression.ResultType == null)
                {
                    Verifier.Verify(context, expression.Expression);
                }
            }

            // Verify conditions
            foreach (var condition in artifact.Conditions)
            {
                Verifier.Verify(context, condition);

                if (!DataTypes.Equal(condition.ResultType, DataTypes.Boolean))
                {
                    context.ReportMessage(new InvalidOperationException("Condition must evaluate to a value of type boolean."), condition);
                }
            }

            // Verify trigger expressions
            foreach (var trigger in artifact.Triggers)
            {
                VerifyExpressionNodes(context, trigger);
            }

            // Verify action conditions
            if (artifact.ActionGroup != null)
            {
                var containers = new Dictionary<string, ParameterDef>();

                // Verify documentation template conditions and binding expressions
                VerifyResponseBindings(context, artifact.ActionGroup, containers);

                foreach (var parameter in containers.Values)
                {
                    context.AddParameterDef(parameter);
                }

                VerifyExpressionNodes(context, artifact.ActionGroup);
            }

            return context.Messages;
        }