/// <summary>
        /// Gets the join queries.
        /// </summary>
        /// <param name="dependency">The dependency.</param>
        /// <param name="aliasCollection">The alias collection.</param>
        /// <returns>List{System.String}.</returns>
        private List<string> GetJoinQueries(ExpressionDependency dependency, TableAliasCollection aliasCollection)
        {
            var queries = new List<string>();

            foreach (var joinField in dependency.JoinFields)
            {
                var singleReverseCrossReference = joinField as SingleReverseCrossReferenceFieldDefinition;
                if (singleReverseCrossReference != null)
                    queries.Add(GetReverseCrossReferenceItemsQuery(singleReverseCrossReference, aliasCollection));

                var multiReverseCrossReference = joinField as MultiReverseCrossReferenceFieldDefinition;
                if (multiReverseCrossReference != null)
                    queries.Add(GetReverseCrossReferenceItemsQuery(multiReverseCrossReference, aliasCollection));
            }

            return queries;
        }
        /// <summary>
        /// Generates the expression affected items query.
        /// </summary>
        /// <param name="dependency">The dependency.</param>
        /// <returns>System.String.</returns>
        private string GenerateExpressionAffectedItemsQuery(ExpressionDependency dependency)
        {
            var sql = new StringBuilder();
            var aliasCollection = new TableAliasCollection();
            var queries = GetJoinQueries(dependency, aliasCollection);

            if (queries.Count > 0)
            {
                sql.AppendLine("WITH");
                sql.AppendLine(string.Join(Environment.NewLine + ",", queries));
            }

            sql.AppendFormat(@"SELECT DISTINCT {0}.""Id""
FROM
    ""{1}"" {0}", aliasCollection.GetTableAlias(dependency.DependentProcess), OracleNamesTranslator.Translate(dependency.DependentProcess.SystemName));

            var currentProcess = dependency.DependentProcess;

            foreach (var @join in dependency.JoinFields)
            {
                AddBaseTableJoins(sql, currentProcess, @join.DeclaringProcess, aliasCollection);
                AddJoin(sql, @join, aliasCollection);

                currentProcess = @join.ReferencedProcess;
            }

            sql.AppendLine()
               .AppendFormat(
                   "WHERE {0}.\"{1}\" = 0 AND {2}.\"{3}\" = :id",
                   aliasCollection.GetTableAlias(dependency.DependentProcess),
                   Constants.IsRemovedColumnName,
                   aliasCollection.GetTableAlias(dependency.JoinFields.Last().ReferencedProcess),
                   Constants.IdColumnName);

            return sql.ToString();
        }
        /// <summary>
        /// Determines whether this instance [can generate query] the specified dependency.
        /// </summary>
        /// <param name="dependency">The dependency.</param>
        /// <returns><c>true</c> if this instance [can generate query] the specified dependency; otherwise, <c>false</c>.</returns>
        protected virtual bool CanGenerateQuery(ExpressionDependency dependency)
        {
            foreach (var joinField in dependency.JoinFields)
            {
                if (joinField is SingleCrossReferenceFieldDefinition)
                    continue;

                if (joinField is MultiCrossReferenceFieldDefinition)
                    continue;

                if (joinField is ChecklistFieldDefinition)
                    continue;

                if (joinField is ReverseCrossReferenceFieldDefinition)
                    continue;

                return false;
            }

            return dependency.JoinFields.Any();
        }
        /// <summary>
        /// Adds the get affected items method.
        /// </summary>
        /// <param name="assemblyCode">The assembly code.</param>
        /// <param name="dependency">The dependency.</param>
        /// <param name="index">The index.</param>
        protected override void AddGetAffectedItemsMethod(
            StringBuilder assemblyCode, ExpressionDependency dependency, int index)
        {
            assemblyCode.AppendFormat(@"
        public System.Collections.Generic.IEnumerable<int> GetAffectedItems{0}(int itemId)
        {{
            var result = new System.Collections.Generic.HashSet<int>();
", index);

            var databaseGeneratedFields = new[] { Constants.IdColumnName };

            if (dependency.JoinFields.Count == 0 && dependency.ProcessName == dependency.DependentProcess.SystemName
                && databaseGeneratedFields.Contains(dependency.FieldName))
            {
                assemblyCode.AppendFormat(@"
            result.Add(itemId);");
            }

            if (CanGenerateQuery(dependency))
            {
                var sql = GenerateExpressionAffectedItemsQuery(dependency);

                assemblyCode.AppendFormat(@"
            const string sql = {0};
        
            using (var ctx = Csla.Data.ConnectionManager<Oracle.DataAccess.Client.OracleConnection>.GetManager(
                Cebos.Veyron.SharedTypes.ServerSettings.ConnectionString, false))
            {{
                using (var cmd = new Oracle.DataAccess.Client.OracleCommand(sql, ctx.Connection))
                {{
                    cmd.BindByName = true;
                    cmd.Parameters.Add(""id"", itemId);
        
                    using (var reader = cmd.ExecuteReader())
                    {{
                        while (reader.Read())
                        {{
                            result.Add(Cebos.Veyron.SharedTypes.SafeTypeConverter.Convert<int>(reader.GetValue(0)));
                        }}
                    }}
                }}
            }}", sql.ToLiteral());
            }
            
            assemblyCode.AppendFormat(@"

            return result;
        }}
");
        }
        /// <summary>
        /// Adds the get affected items method.
        /// </summary>
        /// <param name="assemblyCode">The assembly code.</param>
        /// <param name="dependency">The dependency.</param>
        /// <param name="index">The index.</param>
        protected virtual void AddGetAffectedItemsMethod(
            StringBuilder assemblyCode, ExpressionDependency dependency, int index)
        {
            assemblyCode.AppendFormat(@"
        public System.Collections.Generic.IEnumerable<int> GetAffectedItems{0}(int itemId)
        {{
            return System.Linq.Enumerable.Empty<int>();
        }}
", index);
        }