1 //---------------------------------------------------------------------
2 // <copyright file="ErrorLog.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
7 // @backupOwner Microsoft
8 //---------------------------------------------------------------------
10 namespace System.Data.Mapping.ViewGeneration.Structures
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;
22 internal class ErrorLog : InternalBase
28 m_log = new List<Record>();
33 private List<Record> m_log;
39 get { return m_log.Count; }
42 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] // referenced (indirectly) by System.Data.Entity.Design.dll
43 internal IEnumerable<EdmSchemaError> Errors
47 foreach (Record record in m_log)
49 yield return record.Error;
56 internal void AddEntry(Record record)
58 EntityUtil.CheckArgumentNull(record, "record");
62 internal void Merge(ErrorLog log)
64 foreach (Record record in log.m_log)
70 internal void PrintTrace()
72 StringBuilder builder = new StringBuilder();
73 ToCompactString(builder);
74 Helpers.StringTraceLine(builder.ToString());
77 internal override void ToCompactString(StringBuilder builder)
79 foreach (Record record in m_log)
81 record.ToCompactString(builder);
85 internal string ToUserString()
87 StringBuilder builder = new StringBuilder();
88 foreach (Record record in m_log)
90 string recordString = record.ToUserString();
91 builder.AppendLine(recordString);
93 return builder.ToString();
97 #region Nested classes/struct
98 internal class Record : InternalBase
101 // effects: Creates an error record for wrappers, a debug message
102 // and an error message given by "message". Note: wrappers cannot
104 internal Record(bool isError, ViewGenErrorCode errorCode, string message,
105 IEnumerable<LeftCellWrapper> wrappers, string debugMessage)
107 Debug.Assert(wrappers != null);
108 IEnumerable<Cell> cells = LeftCellWrapper.GetInputCellsForWrappers(wrappers);
109 Init(isError, errorCode, message, cells, debugMessage);
112 internal Record(bool isError, ViewGenErrorCode errorCode, string message, Cell sourceCell, string debugMessage)
114 Init(isError, errorCode, message, new Cell[] { sourceCell }, debugMessage);
117 internal Record(bool isError, ViewGenErrorCode errorCode, string message, IEnumerable<Cell> sourceCells,
120 Init(isError, errorCode, message, sourceCells, debugMessage);
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)
127 m_debugMessage = error.ToString();
128 m_mappingError = error;
132 private void Init(bool isError, ViewGenErrorCode errorCode, string message,
133 IEnumerable<Cell> sourceCells, string debugMessage)
135 m_sourceCells = new List<Cell>(sourceCells);
137 Debug.Assert(m_sourceCells.Count > 0, "Error record must have at least one cell");
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;
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);
153 private EdmSchemaError m_mappingError;
154 private List<Cell> m_sourceCells;
155 private string m_debugMessage;
159 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] // referenced (indirectly) by System.Data.Entity.Design.dll
160 internal EdmSchemaError Error
162 get { return m_mappingError; }
167 internal override void ToCompactString(StringBuilder builder)
169 builder.Append(m_debugMessage);
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)
175 var orderedCells = sourceCells.OrderBy<Cell, int>(cell => cell.CellLabel.StartLineNumber, Comparer<int>.Default);
178 // Get the line numbers
179 foreach (Cell cell in orderedCells)
181 if (isFirst == false)
183 lineBuilder.Append(isInvariant ? EntityRes.GetString(EntityRes.ViewGen_CommaBlank) : ", ");
186 lineBuilder.AppendFormat(CultureInfo.InvariantCulture, "{0}", cell.CellLabel.StartLineNumber);
188 Debug.Assert(isFirst == false, "No cells");
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)
198 StringBuilder builder = new StringBuilder();
202 builder.AppendLine(debugMessage);
204 builder.Append(isInvariant ? "ERROR" : System.Data.Entity.Strings.ViewGen_Error);
205 StringUtil.FormatStringBuilder(builder, " ({0}): ", (int)errorCode);
208 StringBuilder lineBuilder = new StringBuilder();
209 GetUserLinesFromCells(sourceCells, lineBuilder, isInvariant);
213 if (sourceCells.Count > 1)
215 StringUtil.FormatStringBuilder(builder, "Problem in Mapping Fragments starting at lines {0}: ", lineBuilder.ToString());
219 StringUtil.FormatStringBuilder(builder, "Problem in Mapping Fragment starting at line {0}: ", lineBuilder.ToString());
224 if (sourceCells.Count > 1)
226 builder.Append(Strings.ViewGen_ErrorLog2(lineBuilder.ToString()));
230 builder.Append(Strings.ViewGen_ErrorLog(lineBuilder.ToString()));
233 builder.AppendLine(message);
234 return builder.ToString();
237 internal string ToUserString()
239 return m_mappingError.ToString();