source: trunk/CrypPlugins/StreamComparator/StreamComparator.cs @ 2527

Last change on this file since 2527 was 2334, checked in by Matthäus Wander, 11 years ago

removed 1006 occurences of DisplayLevel in 218 files (see #122)

File size: 17.4 KB
Line 
1using System.ComponentModel;
2using System.IO;
3using System.Windows.Controls;
4using Cryptool.PluginBase;
5using System;
6using System.Windows.Media.Imaging;
7using System.Text;
8using System.Web;
9using System.Xml;
10using System.Windows.Markup;
11using Cryptool.PluginBase.Analysis;
12using Cryptool.PluginBase.IO;
13using System.Collections.Generic;
14using System.Runtime.Remoting.Contexts;
15using Cryptool.PluginBase.Miscellaneous;
16
17namespace Cryptool.StreamComparator
18{
19  [Author("Thomas Schmid", "thomas.schmid@cryptool.org", "Uni Siegen", "http://www.uni-siegen.de")]
20  [PluginInfo(false, "Stream Comparator", "Compares two inputs Streams and decides if they are equal.", null, "StreamComparator/icon.png", "StreamComparator/Images/equal.png", "StreamComparator/Images/unequal.png", "StreamComparator/Images/contextmenu.png")]
21  public class StreamComparator : IDifferential
22  {
23    #region Private variables
24    private bool isBinary;
25    private bool stop;
26    private CryptoolStream streamOne;
27    private CryptoolStream streamTwo;
28    private List<CryptoolStream> listCryptoolStreams = new List<CryptoolStream>();
29    private StreamComparatorPresentation streamComparatorPresentation;
30    #endregion
31
32    private StreamComparatorSettings settings;
33    public ISettings Settings
34    {
35      get { return settings; }
36      set { settings = (StreamComparatorSettings)value; }
37    }
38
39    # region ctor
40
41    public StreamComparator()
42    {
43      streamComparatorPresentation = new StreamComparatorPresentation();
44      settings = new StreamComparatorSettings();
45    }
46
47    # endregion
48
49    #region Properties
50
51    [PropertyInfo(Direction.InputData, "Stream one", "First stream to compare", "", true, false, QuickWatchFormat.None, null)]
52    public CryptoolStream InputOne
53    {
54      get 
55      {
56        CryptoolStream cryptoolStream = null;
57        if (streamOne != null)
58        {
59          cryptoolStream = new CryptoolStream();
60          cryptoolStream.OpenRead(streamOne.FileName);
61          listCryptoolStreams.Add(cryptoolStream);
62        }
63        return cryptoolStream; 
64      }
65      set { streamOne = value; }
66    }
67
68    [PropertyInfo(Direction.InputData, "Stream two", "Second stream to compare", "", true, false, QuickWatchFormat.None, null)]
69    public CryptoolStream InputTwo
70    {
71      get 
72      {
73        CryptoolStream cryptoolStream = null;
74        if (streamTwo != null)
75        {
76          cryptoolStream = new CryptoolStream();
77          cryptoolStream.OpenRead(streamTwo.FileName);
78          listCryptoolStreams.Add(cryptoolStream);
79        }
80        return cryptoolStream; 
81      }
82      set { streamTwo = value; }
83    }
84
85    private bool inputsAreEqual;
86    [PropertyInfo(Direction.OutputData, "Comparator achievement", "Ture if streams are equal, otherwise false.", "", false, false, QuickWatchFormat.Text, null)]
87    public bool InputsAreEqual
88    {
89      get { return inputsAreEqual; }
90      set
91      {
92        inputsAreEqual = value;
93        OnPropertyChanged("InputsAreEqual");
94      }
95    }
96
97    #endregion
98
99    #region IPlugin Members
100
101    public void Execute()
102    {
103      stop = false;
104      isBinary = false;
105
106      // this would result in one extra message on each comparison so just set it to false on
107      // pre-execution
108      // InputsAreEqual = false;
109
110      int streamOneByte;
111      int streamTwoByte;
112
113      CryptoolStream workingStreamOne = InputOne;
114      CryptoolStream workingStreamTwo = InputTwo;
115
116      if (workingStreamOne != null && workingStreamTwo != null)
117      {
118        if (workingStreamOne == workingStreamTwo || workingStreamOne.FileName == workingStreamTwo.FileName && settings.Diff)
119        {
120          GuiTextChanged("Inputs are equal: same file was referenced two times.", NotificationLevel.Info);
121          InputsAreEqual = true;
122          if (OnPluginProgressChanged != null) OnPluginProgressChanged(this, new PluginProgressEventArgs(1, 1));
123          if (settings.Diff) CreateDiffView();         
124        }
125        else if (workingStreamOne.Length != workingStreamTwo.Length && !settings.Diff)
126        {
127          GuiTextChanged("Inputs are not equal, because the filesize is different.", NotificationLevel.Info);
128          InputsAreEqual = false;
129          if (OnPluginProgressChanged != null) OnPluginProgressChanged(this, new PluginProgressEventArgs(1, 1));
130          if (settings.Diff) CreateDiffView();
131        }
132        else
133        {
134          workingStreamOne.Position = 0;
135          workingStreamTwo.Position = 0;
136          DateTime startTime = DateTime.Now;
137          int position = 0;
138          GuiTextChanged("Starting byte comparison of files now...", NotificationLevel.Info);
139          // Read and compare a byte from each file until either a
140          // non-matching set of bytes is found or until the end of
141          // file1 is reached.
142          do
143          {
144            // Read one byte from each file.
145            streamOneByte = workingStreamOne.ReadByte();
146            streamTwoByte = workingStreamTwo.ReadByte();
147
148            if (streamOneByte == 0) isBinary = true;
149
150            if (OnPluginProgressChanged != null && workingStreamOne.Length > 0 &&
151                (int)(workingStreamOne.Position * 100 / workingStreamOne.Length) > position)
152            {
153              position = (int)(workingStreamOne.Position * 100 / workingStreamOne.Length);
154              OnPluginProgressChanged(this,
155                new PluginProgressEventArgs(workingStreamOne.Position, workingStreamOne.Length));
156            }
157          } while ((streamOneByte == streamTwoByte) && (streamOneByte != -1));
158
159          // Return the success of the comparison. "file1byte" is
160          // equal to "file2byte" at this point only if the files are
161          // the same.
162          InputsAreEqual = ((streamOneByte - streamTwoByte) == 0);
163          DateTime stopTime = DateTime.Now;
164          TimeSpan duration = stopTime - startTime;
165          GuiTextChanged(
166            "Comparison complete. Files are " + (InputsAreEqual ? "equal" : "unequal") + ".", NotificationLevel.Info);
167          if (!InputsAreEqual)
168            GuiTextChanged("First position a different byte: " + workingStreamOne.Position, NotificationLevel.Info);
169
170          if (OnPluginProgressChanged != null) OnPluginProgressChanged(this, new PluginProgressEventArgs(1, 1));
171            GuiTextChanged("Duration: " + duration, NotificationLevel.Info);
172
173          if (settings.Diff) CreateDiffView();
174        }
175
176        if (InputsAreEqual)
177        {
178          // QuickWatchInfo = "Inputs are equal";
179          StatusChanged((int)StreamComparatorImage.Equal);
180        }
181        else
182        {
183          // QuickWatchInfo = "Inputs are unequal";
184          StatusChanged((int)StreamComparatorImage.Unequal);
185        }
186      }
187      if (workingStreamOne == null)
188        GuiTextChanged("Stream one is null, no comparison done.", NotificationLevel.Warning);
189      if (workingStreamTwo == null)
190        GuiTextChanged("Stream two is null, no comparison done.", NotificationLevel.Warning);
191    }
192
193    private StringBuilder result;
194
195    /// <summary>
196    /// Creates the diff view.
197    /// </summary>
198    public void CreateDiffView()
199    {     
200      if (!isBinary || true)
201      {
202        int maxLength = 65536;
203        GuiTextChanged("Generating diff now...", NotificationLevel.Info);
204        result = new StringBuilder();
205        try
206        {
207          CryptoolStream cryptoolStream = InputOne;
208          CryptoolStream cryptoolStream2 = InputTwo;
209
210          if (cryptoolStream.Length > maxLength || cryptoolStream2.Length > maxLength)
211            GuiTextChanged("Streams too big for complete diff, reading end of files only.", NotificationLevel.Warning);
212
213          long startIndex = Math.Max(
214            cryptoolStream.Length - maxLength, 
215            cryptoolStream2.Length - maxLength);
216
217          StreamReader sr = new StreamReader(cryptoolStream, Encoding.ASCII);         
218          StringBuilder strTxt1 = new StringBuilder();
219
220          int size = startIndex > 0 ? (int)(cryptoolStream.Length - startIndex) : (int)cryptoolStream.Length;
221          char[] bArr = new char[size];
222
223          if (startIndex > 0) sr.BaseStream.Seek(startIndex, SeekOrigin.Begin);
224          sr.Read(bArr, 0, bArr.Length);
225          bool test = sr.EndOfStream;
226          cryptoolStream.Close();
227
228          for (int i = 0; i < bArr.Length; i++)
229            strTxt1.Append(bArr[i]);         
230
231          sr = new StreamReader(cryptoolStream2, Encoding.ASCII);
232          if (startIndex > 0) sr.BaseStream.Seek(startIndex, SeekOrigin.Begin);
233          StringBuilder strTxt2 = new StringBuilder();
234
235          size = startIndex > 0 ? (int)(cryptoolStream2.Length - startIndex) : (int)cryptoolStream2.Length;
236          bArr = new char[size];
237          sr.Read(bArr, 0, bArr.Length);
238          test = sr.EndOfStream;
239          cryptoolStream2.Close();
240
241          for (int i = 0; i < bArr.Length; i++)
242            strTxt2.Append(bArr[i]);
243         
244
245          string[] aLines = strTxt1.ToString().Split('\n');
246          string[] bLines = strTxt2.ToString().Split('\n');
247
248          Diff diff = new Diff();
249          Diff.Item[] diffItem = diff.DiffText(strTxt1.ToString(), strTxt2.ToString());
250
251          result.AppendLine("<FlowDocument xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\">");
252          result.AppendLine("<Table CellSpacing=\"0\" FontFamily=\"Tahoma\" FontSize=\"12\" Background=\"White\">");
253          result.AppendLine("<Table.Columns><TableColumn Width=\"40\" /><TableColumn/></Table.Columns>");
254          result.AppendLine("<TableRowGroup>");
255
256
257          string color = InputsAreEqual ? "#80FF80" : "#FF8080";
258
259          result.AppendLine("<TableRow Background=\"" + color + "\"><TableCell ColumnSpan=\"2\" TextAlignment=\"Left\">");
260          result.AppendLine("<Paragraph FontSize=\"9pt\" FontWeight=\"Bold\">");
261          if (InputsAreEqual) result.AppendLine("Input streams are equal.");
262          else result.AppendLine("Input streams are unequal.");
263          result.AppendLine("</Paragraph></TableCell></TableRow>");
264         
265          result.AppendLine("<TableRow Background=\"SkyBlue\"><TableCell ColumnSpan=\"2\" TextAlignment=\"Left\">");
266          result.AppendLine("<Paragraph FontSize=\"9pt\" FontWeight=\"Bold\">");
267          result.AppendLine(streamOne.FileName);
268          result.AppendLine("</Paragraph></TableCell></TableRow>");
269
270          result.AppendLine("<TableRow Background=\"SkyBlue\"><TableCell ColumnSpan=\"2\" TextAlignment=\"Left\">");
271          result.AppendLine("<Paragraph FontSize=\"9pt\" FontWeight=\"Bold\">");
272          result.AppendLine(streamTwo.FileName);
273          result.AppendLine("</Paragraph></TableCell></TableRow>");
274
275
276          int n = 0;
277          for (int fdx = 0; fdx < diffItem.Length; fdx++)
278          {
279            if (stop) break;
280            Diff.Item aItem = diffItem[fdx];
281
282            // write unchanged lines
283            while ((n < aItem.StartB) && (n < bLines.Length))
284            {
285              StatusBarProgressbarValueChanged(n, bLines.Length);
286              WriteLine(n, DiffMode.NoChange, bLines[n]);
287              n++;
288            } // while
289
290            // write deleted lines
291            for (int m = 0; m < aItem.deletedA; m++)
292            {
293              StatusBarProgressbarValueChanged(n, bLines.Length);
294              WriteLine(-1, DiffMode.Remove, aLines[aItem.StartA + m]);
295            } // for
296
297            // write inserted lines
298            while (n < aItem.StartB + aItem.insertedB)
299            {
300              StatusBarProgressbarValueChanged(n, bLines.Length);
301              WriteLine(n, DiffMode.Add, bLines[n]);
302              n++;
303            } // while
304          } // while
305
306          // write rest of unchanged lines
307          while (n < bLines.Length && !stop)
308          {
309            StatusBarProgressbarValueChanged(n, bLines.Length);
310            WriteLine(n, DiffMode.NoChange, bLines[n]);
311            n++;
312          } // while
313          result.AppendLine("</TableRowGroup></Table></FlowDocument>");
314          StatusBarProgressbarValueChanged(1, 2);
315          CryptoolStream cs = new CryptoolStream();
316          cs.OpenRead(this.GetPluginInfoAttribute().Caption, Encoding.Default.GetBytes(result.ToString()));
317          streamComparatorPresentation.SetContent(cs);
318          cs.Close();
319          StatusBarProgressbarValueChanged(1, 1);
320        }
321        catch (Exception exception)
322        {
323          GuiTextChanged(exception.Message, NotificationLevel.Error);
324          GuiTextChanged("There were erros while creating the diff. Is this really text input?", NotificationLevel.Error);
325        }
326      }
327      else
328      {
329        GuiTextChanged("BinaryInput, no comparison done.", NotificationLevel.Warning);
330        streamComparatorPresentation.SetBinaryDocument();
331      }
332    }
333
334    // public string Xaml;
335
336    private enum DiffMode
337    {
338      Add, Remove, NoChange
339    }
340
341
342    /// <summary>
343    /// Writes the line.
344    /// </summary>
345    /// <param name="lineNumber">The line number.</param>
346    /// <param name="dm">The DiffMode.</param>
347    /// <param name="aText">A text.</param>
348    private void WriteLine(int lineNumber, DiffMode dm, string aText)
349    {
350      result.Append("<TableRow><TableCell Background=\"lightgray\"><Paragraph>");
351      if (lineNumber != -1) result.Append((lineNumber + 1).ToString("0000"));
352      else result.Append(" ");
353
354      result.Append("</Paragraph></TableCell><TableCell>");
355
356      if (dm == DiffMode.Add)
357        result.Append("<Paragraph Background=\"#80FF80\">");
358      else if (dm == DiffMode.Remove)
359        result.Append("<Paragraph Background=\"#FF8080\">");
360      else
361        result.Append("<Paragraph>");
362
363      // result.Append("<TextBlock TextWrapping=\"NoWrap\">");
364
365      StringBuilder sb = new StringBuilder();
366      StringWriter sw = new StringWriter(sb);     
367      XmlTextWriter xtw = new XmlTextWriter(sw);     
368      xtw.WriteString(removeUnprintablesAndUnicode(aText));
369      // xtw.WriteString(aText);
370      xtw.Flush();
371      xtw.Close();
372
373      result.AppendLine(sb.ToString() + "</Paragraph></TableCell></TableRow>\n");
374    }
375
376    /// <summary>
377    /// Removes the unprintables and unicode.
378    /// </summary>
379    /// <param name="text">The text.</param>
380    /// <returns></returns>
381    public string removeUnprintablesAndUnicode(string text)
382    {
383      text = text.Replace("\r", "");
384      string outputs = String.Empty;
385      for (int jj = 0; jj < text.Length; jj++)
386      {
387        char ch = text[jj];       
388        if (((int)(byte)ch) >= 32 & ((int)(byte)ch) <= 128)
389        {
390          outputs += ch;
391        }
392        else
393        {
394          outputs += ".";
395        }
396      }
397      return outputs;
398    }
399
400    public event GuiLogNotificationEventHandler OnGuiLogNotificationOccured;
401
402    public event PluginProgressChangedEventHandler OnPluginProgressChanged;
403
404    public event StatusChangedEventHandler OnPluginStatusChanged;
405
406    public string Title { get; set; }
407
408    public bool HasChanges
409    {
410      get { return settings.HasChanges; }
411      set { settings.HasChanges = value; }
412    }
413
414    public UserControl Presentation
415    {
416      get { return (UserControl)streamComparatorPresentation; }
417      set { }
418    }
419
420    public UserControl QuickWatchPresentation
421    {
422      get { return null; }
423    }   
424
425    public void Initialize()
426    {
427    }
428
429    public void Dispose()
430    {
431      foreach (CryptoolStream stream in listCryptoolStreams)
432      {
433        if (stream != null) stream.Close();
434      }
435      listCryptoolStreams.Clear();
436      if (streamOne != null)
437      {
438        this.streamOne.Close();
439        this.streamOne = null;
440      }
441      if (streamTwo != null)
442      {
443        this.streamTwo.Close();
444        this.streamTwo = null;
445      }
446    }
447
448    public void Stop()
449    {
450      stop = true;
451    }
452
453    #endregion
454
455    #region INotifyPropertyChanged Members
456
457    public event PropertyChangedEventHandler PropertyChanged;
458
459    protected void OnPropertyChanged(string name)
460    {
461      EventsHelper.PropertyChanged(PropertyChanged, this, new PropertyChangedEventArgs(name));
462    }
463
464    #endregion
465
466    # region methods
467    private void GuiTextChanged(string message, NotificationLevel logLevel)
468    {
469      EventsHelper.GuiLogMessage(OnGuiLogNotificationOccured, this, new GuiLogEventArgs(message, this, logLevel));
470    }
471
472    private void StatusBarProgressbarValueChanged(double value, double maxValue)
473    {
474      EventsHelper.ProgressChanged(OnPluginProgressChanged, this, new PluginProgressEventArgs(value, maxValue));
475    }
476
477    private void StatusChanged(int imageIndex)
478    {
479      EventsHelper.StatusChanged(OnPluginStatusChanged, this, new StatusEventArgs(StatusChangedMode.ImageUpdate, imageIndex));
480    }
481    #endregion
482
483    #region IPlugin Members
484
485
486    public void PreExecution()
487    {
488      // QuickWatchInfo = null;
489      streamComparatorPresentation.SetNoComparisonYetDocument();
490      // InputsAreEqual = false;
491    }
492
493    public void PostExecution()
494    {
495      Dispose(); 
496    }
497
498    #endregion
499
500    #region IPlugin Members
501
502    public void Pause()
503    {
504     
505    }
506
507    #endregion
508  }
509
510  enum StreamComparatorImage
511  {
512    Default, 
513    Equal, 
514    Unequal
515  }
516}
Note: See TracBrowser for help on using the repository browser.