Merge pull request #2250 from esdrubal/master
[mono.git] / mcs / class / referencesource / System.Data.Entity / System / Data / Common / Utils / Boolean / Clause.cs
1 //---------------------------------------------------------------------
2 // <copyright file="Clause.cs" company="Microsoft">
3 //      Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //
6 // @owner [....]
7 // @backupOwner [....]
8 //---------------------------------------------------------------------
9
10 using System;
11 using System.Collections.Generic;
12 using System.Text;
13 using System.Globalization;
14 using System.Collections.ObjectModel;
15 using System.Diagnostics;
16 using System.Linq;
17
18 namespace System.Data.Common.Utils.Boolean
19 {
20     /// <summary>
21     /// Base class for clauses, which are (constrained) combinations of literals.
22     /// </summary>
23     /// <typeparam name="T_Identifier">Type of normal form literal.</typeparam>
24     internal abstract class Clause<T_Identifier> : NormalFormNode<T_Identifier>
25     {
26         private readonly Set<Literal<T_Identifier>> _literals;
27         private readonly int _hashCode;
28
29         /// <summary>
30         /// Initialize a new clause.
31         /// </summary>
32         /// <param name="literals">Literals contained in the clause.</param>
33         /// <param name="treeType">Type of expression tree to produce from literals.</param>
34         protected Clause(Set<Literal<T_Identifier>> literals, ExprType treeType)
35             : base(ConvertLiteralsToExpr(literals, treeType))
36         {
37             _literals = literals.AsReadOnly();
38             _hashCode = _literals.GetElementsHashCode();
39         }
40
41         /// <summary>
42         /// Gets the literals contained in this clause.
43         /// </summary>
44         internal Set<Literal<T_Identifier>> Literals
45         {
46             get { return _literals; }
47         }
48
49         // Given a collection of literals and a tree type, returns an expression of the given type.
50         private static BoolExpr<T_Identifier> ConvertLiteralsToExpr(Set<Literal<T_Identifier>> literals, ExprType treeType)
51         {
52             bool isAnd = ExprType.And == treeType;
53             Debug.Assert(isAnd || ExprType.Or == treeType);
54
55             IEnumerable<BoolExpr<T_Identifier>> literalExpressions = literals.Select(
56                 new Func<Literal<T_Identifier>, BoolExpr<T_Identifier>>(ConvertLiteralToExpression));
57
58             if (isAnd)
59             {
60                 return new AndExpr<T_Identifier>(literalExpressions);
61             }
62             else
63             {
64                 return new OrExpr<T_Identifier>(literalExpressions);
65             }
66         }
67
68         // Given a literal, returns its logical equivalent expression.
69         private static BoolExpr<T_Identifier> ConvertLiteralToExpression(Literal<T_Identifier> literal)
70         {
71             return literal.Expr;
72         }
73
74         public override string ToString()
75         {
76             StringBuilder builder = new StringBuilder();
77             builder.Append("Clause{");
78             builder.Append(_literals);
79             return builder.Append("}").ToString();
80         }
81
82         public override int GetHashCode()
83         {
84             return _hashCode;
85         }
86
87         public override bool Equals(object obj)
88         {
89             Debug.Fail("call typed Equals");
90             return base.Equals(obj);
91         }
92     }
93
94     /// <summary>
95     /// A DNF clause is of the form:
96     /// 
97     ///     Literal1 . Literal2 . ...
98     /// 
99     /// Each literal is of the form:
100     /// 
101     ///     Term
102     /// 
103     /// or
104     /// 
105     ///     !Term
106     /// </summary>
107     /// <typeparam name="T_Identifier">Type of normal form literal.</typeparam>
108     internal sealed class DnfClause<T_Identifier> : Clause<T_Identifier>,
109         IEquatable<DnfClause<T_Identifier>>
110     {
111         /// <summary>
112         /// Initialize a DNF clause.
113         /// </summary>
114         /// <param name="literals">Literals in clause.</param>
115         internal DnfClause(Set<Literal<T_Identifier>> literals)
116             : base(literals, ExprType.And)
117         {
118         }
119
120         public bool Equals(DnfClause<T_Identifier> other)
121         {
122             return null != other &&
123                 other.Literals.SetEquals(Literals);
124         }
125     }
126
127     /// <summary>
128     /// A CNF clause is of the form:
129     /// 
130     ///     Literal1 + Literal2 . ...
131     /// 
132     /// Each literal is of the form:
133     /// 
134     ///     Term
135     /// 
136     /// or
137     /// 
138     ///     !Term
139     /// </summary>
140     /// <typeparam name="T_Identifier">Type of normal form literal.</typeparam>
141     internal sealed class CnfClause<T_Identifier> : Clause<T_Identifier>,
142         IEquatable<CnfClause<T_Identifier>>
143     {
144         /// <summary>
145         /// Initialize a CNF clause.
146         /// </summary>
147         /// <param name="literals">Literals in clause.</param>
148         internal CnfClause(Set<Literal<T_Identifier>> literals)
149             : base(literals, ExprType.Or)
150         {
151         }
152
153         public bool Equals(CnfClause<T_Identifier> other)
154         {
155             return null != other &&
156                 other.Literals.SetEquals(Literals);
157         }
158     }
159 }