File: System\Data\Common\Utils\Boolean\Clause.cs
Project: ndp\fx\src\DataEntity\System.Data.Entity.csproj (System.Data.Entity)
//---------------------------------------------------------------------
// <copyright file="Clause.cs" company="Microsoft">
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
//
// @owner Microsoft
// @backupOwner Microsoft
//---------------------------------------------------------------------
 
using System;
using System.Collections.Generic;
using System.Text;
using System.Globalization;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
 
namespace System.Data.Common.Utils.Boolean
{
    /// <summary>
    /// Base class for clauses, which are (constrained) combinations of literals.
    /// </summary>
    /// <typeparam name="T_Identifier">Type of normal form literal.</typeparam>
    internal abstract class Clause<T_Identifier> : NormalFormNode<T_Identifier>
    {
        private readonly Set<Literal<T_Identifier>> _literals;
        private readonly int _hashCode;
 
        /// <summary>
        /// Initialize a new clause.
        /// </summary>
        /// <param name="literals">Literals contained in the clause.</param>
        /// <param name="treeType">Type of expression tree to produce from literals.</param>
        protected Clause(Set<Literal<T_Identifier>> literals, ExprType treeType)
            : base(ConvertLiteralsToExpr(literals, treeType))
        {
            _literals = literals.AsReadOnly();
            _hashCode = _literals.GetElementsHashCode();
        }
 
        /// <summary>
        /// Gets the literals contained in this clause.
        /// </summary>
        internal Set<Literal<T_Identifier>> Literals
        {
            get { return _literals; }
        }
 
        // Given a collection of literals and a tree type, returns an expression of the given type.
        private static BoolExpr<T_Identifier> ConvertLiteralsToExpr(Set<Literal<T_Identifier>> literals, ExprType treeType)
        {
            bool isAnd = ExprType.And == treeType;
            Debug.Assert(isAnd || ExprType.Or == treeType);
 
            IEnumerable<BoolExpr<T_Identifier>> literalExpressions = literals.Select(
                new Func<Literal<T_Identifier>, BoolExpr<T_Identifier>>(ConvertLiteralToExpression));
 
            if (isAnd)
            {
                return new AndExpr<T_Identifier>(literalExpressions);
            }
            else
            {
                return new OrExpr<T_Identifier>(literalExpressions);
            }
        }
 
        // Given a literal, returns its logical equivalent expression.
        private static BoolExpr<T_Identifier> ConvertLiteralToExpression(Literal<T_Identifier> literal)
        {
            return literal.Expr;
        }
 
        public override string ToString()
        {
            StringBuilder builder = new StringBuilder();
            builder.Append("Clause{");
            builder.Append(_literals);
            return builder.Append("}").ToString();
        }
 
        public override int GetHashCode()
        {
            return _hashCode;
        }
 
        public override bool Equals(object obj)
        {
            Debug.Fail("call typed Equals");
            return base.Equals(obj);
        }
    }
 
    /// <summary>
    /// A DNF clause is of the form:
    /// 
    ///     Literal1 . Literal2 . ...
    /// 
    /// Each literal is of the form:
    /// 
    ///     Term
    /// 
    /// or
    /// 
    ///     !Term
    /// </summary>
    /// <typeparam name="T_Identifier">Type of normal form literal.</typeparam>
    internal sealed class DnfClause<T_Identifier> : Clause<T_Identifier>,
        IEquatable<DnfClause<T_Identifier>>
    {
        /// <summary>
        /// Initialize a DNF clause.
        /// </summary>
        /// <param name="literals">Literals in clause.</param>
        internal DnfClause(Set<Literal<T_Identifier>> literals)
            : base(literals, ExprType.And)
        {
        }
 
        public bool Equals(DnfClause<T_Identifier> other)
        {
            return null != other &&
                other.Literals.SetEquals(Literals);
        }
    }
 
    /// <summary>
    /// A CNF clause is of the form:
    /// 
    ///     Literal1 + Literal2 . ...
    /// 
    /// Each literal is of the form:
    /// 
    ///     Term
    /// 
    /// or
    /// 
    ///     !Term
    /// </summary>
    /// <typeparam name="T_Identifier">Type of normal form literal.</typeparam>
    internal sealed class CnfClause<T_Identifier> : Clause<T_Identifier>,
        IEquatable<CnfClause<T_Identifier>>
    {
        /// <summary>
        /// Initialize a CNF clause.
        /// </summary>
        /// <param name="literals">Literals in clause.</param>
        internal CnfClause(Set<Literal<T_Identifier>> literals)
            : base(literals, ExprType.Or)
        {
        }
 
        public bool Equals(CnfClause<T_Identifier> other)
        {
            return null != other &&
                other.Literals.SetEquals(Literals);
        }
    }
}