Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / System.Data.Entity / System / Data / Mapping / ViewGeneration / Structures / ErrorLog.cs
1 //---------------------------------------------------------------------
2 // <copyright file="ErrorLog.cs" company="Microsoft">
3 //      Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //
6 // @owner Microsoft
7 // @backupOwner Microsoft
8 //---------------------------------------------------------------------
9
10 namespace System.Data.Mapping.ViewGeneration.Structures
11 {
12     using System.Collections.Generic;
13     using System.Data.Common.Utils;
14     using System.Data.Entity;
15     using System.Data.Mapping.ViewGeneration.Utils;
16     using System.Data.Metadata.Edm;
17     using System.Diagnostics;
18     using System.Globalization;
19     using System.Linq;
20     using System.Text;
21
22     internal class ErrorLog : InternalBase
23     {
24
25         #region Constructors
26         internal ErrorLog()
27         {
28             m_log = new List<Record>();
29         }
30         #endregion
31
32         #region Fields
33         private List<Record> m_log;
34         #endregion
35
36         #region Properties
37         internal int Count
38         {
39             get { return m_log.Count; }
40         }
41
42         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] // referenced (indirectly) by System.Data.Entity.Design.dll
43         internal IEnumerable<EdmSchemaError> Errors
44         {
45             get
46             {
47                 foreach (Record record in m_log)
48                 {
49                     yield return record.Error;
50                 }
51             }
52         }
53         #endregion
54
55         #region Methods
56         internal void AddEntry(Record record)
57         {
58             EntityUtil.CheckArgumentNull(record, "record");
59             m_log.Add(record);
60         }
61
62         internal void Merge(ErrorLog log)
63         {
64             foreach (Record record in log.m_log)
65             {
66                 m_log.Add(record);
67             }
68         }
69
70         internal void PrintTrace()
71         {
72             StringBuilder builder = new StringBuilder();
73             ToCompactString(builder);
74             Helpers.StringTraceLine(builder.ToString());
75         }
76
77         internal override void ToCompactString(StringBuilder builder)
78         {
79             foreach (Record record in m_log)
80             {
81                 record.ToCompactString(builder);
82             }
83         }
84
85         internal string ToUserString()
86         {
87             StringBuilder builder = new StringBuilder();
88             foreach (Record record in m_log)
89             {
90                 string recordString = record.ToUserString();
91                 builder.AppendLine(recordString);
92             }
93             return builder.ToString();
94         }
95         #endregion
96
97         #region Nested classes/struct
98         internal class Record : InternalBase
99         {
100             #region Constructor
101             // effects: Creates an error record for wrappers, a debug message
102             // and an error message given by "message". Note: wrappers cannot
103             // be null
104             internal Record(bool isError, ViewGenErrorCode errorCode, string message,
105                             IEnumerable<LeftCellWrapper> wrappers, string debugMessage)
106             {
107                 Debug.Assert(wrappers != null);
108                 IEnumerable<Cell> cells = LeftCellWrapper.GetInputCellsForWrappers(wrappers);
109                 Init(isError, errorCode, message, cells, debugMessage);
110             }
111
112             internal Record(bool isError, ViewGenErrorCode errorCode, string message, Cell sourceCell, string debugMessage)
113             {
114                 Init(isError, errorCode, message, new Cell[] { sourceCell }, debugMessage);
115             }
116
117             internal Record(bool isError, ViewGenErrorCode errorCode, string message, IEnumerable<Cell> sourceCells,
118                             string debugMessage)
119             {
120                 Init(isError, errorCode, message, sourceCells, debugMessage);
121             }
122
123             //There are cases when we want to create a ViewGen error that is not specific to any mapping fragment
124             //In this case, it is better to just create the EdmSchemaError directly and hold on to it.
125             internal Record(EdmSchemaError error)
126             {
127                 m_debugMessage = error.ToString();
128                 m_mappingError = error;
129             }
130
131
132             private void Init(bool isError, ViewGenErrorCode errorCode, string message,
133                               IEnumerable<Cell> sourceCells, string debugMessage)
134             {
135                 m_sourceCells = new List<Cell>(sourceCells);
136
137                 Debug.Assert(m_sourceCells.Count > 0, "Error record must have at least one cell");
138
139                 // For certain foreign key messages, we may need the SSDL line numbers and file names
140                 CellLabel label = m_sourceCells[0].CellLabel;
141                 string sourceLocation = label.SourceLocation;
142                 int lineNumber = label.StartLineNumber;
143                 int columnNumber = label.StartLinePosition;
144
145                 string userMessage = InternalToString(message, debugMessage, m_sourceCells, sourceLocation, errorCode, isError, false);
146                 m_debugMessage = InternalToString(message, debugMessage, m_sourceCells, sourceLocation, errorCode, isError, true);
147                 m_mappingError = new EdmSchemaError(userMessage, (int)errorCode, EdmSchemaErrorSeverity.Error, sourceLocation,
148                                                       lineNumber, columnNumber);
149             }
150             #endregion
151
152             #region Fields
153             private EdmSchemaError m_mappingError;
154             private List<Cell> m_sourceCells;
155             private string m_debugMessage;
156             #endregion
157
158             #region Properties
159             [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] // referenced (indirectly) by System.Data.Entity.Design.dll
160             internal EdmSchemaError Error
161             {
162                 get { return m_mappingError; }
163             }
164             #endregion
165
166             #region Methods
167             internal override void ToCompactString(StringBuilder builder)
168             {
169                 builder.Append(m_debugMessage);
170             }
171
172             // effects: adds a comma-separated list of line numbers to the string builder
173             private static void GetUserLinesFromCells(IEnumerable<Cell> sourceCells, StringBuilder lineBuilder, bool isInvariant)
174             {
175                 var orderedCells = sourceCells.OrderBy<Cell, int>(cell => cell.CellLabel.StartLineNumber, Comparer<int>.Default);
176
177                 bool isFirst = true;
178                 // Get the line numbers
179                 foreach (Cell cell in orderedCells)
180                 {
181                     if (isFirst == false)
182                     {
183                         lineBuilder.Append(isInvariant ? EntityRes.GetString(EntityRes.ViewGen_CommaBlank) : ", ");
184                     }
185                     isFirst = false;
186                     lineBuilder.AppendFormat(CultureInfo.InvariantCulture, "{0}", cell.CellLabel.StartLineNumber);
187                 }
188                 Debug.Assert(isFirst == false, "No cells");
189             }
190
191             // effects: Converts the message/debugMessage to a user-readable
192             // message using resources (if isInvariant is false) or a test
193             // message (if isInvariant is true)
194             static private string InternalToString(string message, string debugMessage,
195                                                    List<Cell> sourceCells, string sourceLocation, ViewGenErrorCode errorCode,
196                                                    bool isError, bool isInvariant)
197             {
198                 StringBuilder builder = new StringBuilder();
199
200                 if (isInvariant)
201                 {
202                     builder.AppendLine(debugMessage);
203
204                     builder.Append(isInvariant ? "ERROR" : System.Data.Entity.Strings.ViewGen_Error);
205                     StringUtil.FormatStringBuilder(builder, " ({0}): ", (int)errorCode);
206                 }
207
208                 StringBuilder lineBuilder = new StringBuilder();
209                 GetUserLinesFromCells(sourceCells, lineBuilder, isInvariant);
210
211                 if (isInvariant)
212                 {
213                     if (sourceCells.Count > 1)
214                     {
215                         StringUtil.FormatStringBuilder(builder, "Problem in Mapping Fragments starting at lines {0}: ", lineBuilder.ToString());
216                     }
217                     else
218                     {
219                         StringUtil.FormatStringBuilder(builder, "Problem in Mapping Fragment starting at line {0}: ", lineBuilder.ToString());
220                     }
221                 }
222                 else
223                 {
224                     if (sourceCells.Count > 1)
225                     {
226                         builder.Append(Strings.ViewGen_ErrorLog2(lineBuilder.ToString()));
227                     }
228                     else
229                     {
230                         builder.Append(Strings.ViewGen_ErrorLog(lineBuilder.ToString()));
231                     }
232                 }
233                 builder.AppendLine(message);
234                 return builder.ToString();
235             }
236
237             internal string ToUserString()
238             {
239                 return m_mappingError.ToString();
240             }
241             #endregion
242         }
243         #endregion
244     }
245 }