OSDN Git Service

Ver.1.0.0.185 Task187 Interface based design
[simplebackup/SBTGitRepository.git] / Main / Services / BackupSettingService.cs
1 //-----------------------------------------------------------------------
2 // <copyright file="BackupSettingService.cs" company="Takayoshi Matsuyama">
3 //     Copyright (c) Takayoshi Matsuyama. All rights reserved.
4 // </copyright>
5 //-----------------------------------------------------------------------
6
7 // This file is part of Simple Backup.
8 //
9 // Simple Backup is free software: you can redistribute it and/or modify
10 // it under the terms of the GNU General Public License as published by
11 // the Free Software Foundation, either version 3 of the License, or
12 // (at your option) any later version.
13 //
14 // Simple Backup is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 // GNU General Public License for more details.
18 //
19 // You should have received a copy of the GNU General Public License
20 // along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
21
22 using System;
23 using System.IO;
24 using System.Linq;
25 using System.Windows;
26 using System.Windows.Input;
27 using System.Xml.Linq;
28 using SimpleBackup.Core.Models;
29 using SimpleBackup.Core.Services;
30 using SimpleBackup.Core.Utilities;
31 using SimpleBackup.Models;
32
33 namespace SimpleBackup.Services
34 {
35     using SimpleBackup.Resources;
36
37     using Application = System.Windows.Application;
38     using Cursors = System.Windows.Input.Cursors;
39     using MessageBox = System.Windows.MessageBox;
40     using OpenFileDialog = Microsoft.Win32.OpenFileDialog;
41     using SaveFileDialog = Microsoft.Win32.SaveFileDialog;
42
43     /// <summary>
44     /// Backup Setting service.
45     /// </summary>
46     public class BackupSettingService : IBackupSettingService
47     {
48         /// <summary>
49         /// The supported major version
50         /// </summary>
51         private const int SupportedMajorVersion = 1;
52
53         /// <summary>
54         /// The supported minor version
55         /// </summary>
56         private const int SupportedMinorVersion = 0;
57
58         /// <summary>
59         /// The synchronize root
60         /// </summary>
61         private static readonly object SyncRoot = new object();
62
63         /// <summary>
64         /// The instance of SettingFileService.
65         /// </summary>
66         private static volatile BackupSettingService instance;
67
68         /// <summary>
69         /// Prevents a default instance of the <see cref="BackupSettingService"/> class from being created.
70         /// </summary>
71         private BackupSettingService()
72         {
73         }
74
75         /// <summary>
76         /// Occurs when backup setting is created.
77         /// </summary>
78         public event EventHandler<SettingFileEventArgs> BackupSettingCreated;
79
80         /// <summary>
81         /// Occurs when backup setting is opened.
82         /// </summary>
83         public event EventHandler<SettingFileEventArgs> BackupSettingOpened;
84
85         /// <summary>
86         /// Occurs when backup setting is modified.
87         /// </summary>
88         public event EventHandler<SettingFileEventArgs> BackupSettingModified;
89
90         /// <summary>
91         /// Occurs when backup setting is saved.
92         /// </summary>
93         public event EventHandler<SettingFileEventArgs> BackupSettingSaved;
94
95         /// <summary>
96         /// Occurs when backup setting is closed.
97         /// </summary>
98         public event EventHandler<SettingFileEventArgs> BackupSettingClosed;
99
100         /// <summary>
101         /// Gets the instance.
102         /// </summary>
103         public static IBackupSettingService Instance
104         {
105             get
106             {
107                 if (instance == null)
108                 {
109                     lock (SyncRoot)
110                     {
111                         if (instance == null)
112                         {
113                             instance = new BackupSettingService();
114                         }
115                     }
116                 }
117
118                 return instance;
119             }
120         }
121
122         /// <summary>
123         /// Gets the current setting.
124         /// </summary>
125         public IBackupSetting CurrentSetting { get; private set; }
126
127         /// <summary>
128         /// Creates the backup setting.
129         /// </summary>
130         /// <returns><c>true</c> if the new backup setting is created; otherwise, <c>false</c>.</returns>
131         public bool CreateBackupSetting()
132         {
133             if ((this.CurrentSetting != null) && this.CurrentSetting.Modified)
134             {
135                 MessageBoxResult confirmationResult = MessageBox.Show(
136                     Application.Current.MainWindow,
137                     Resources.Views_SaveConfirmationMessage,
138                     Resources.Views_ConfirmationDialogTitle,
139                     MessageBoxButton.YesNoCancel);
140                 if (confirmationResult == MessageBoxResult.Yes)
141                 {
142                     this.SaveCurrentBackupSetting();
143                 }
144                 else if (confirmationResult == MessageBoxResult.Cancel)
145                 {
146                     return false;
147                 }
148             }
149
150             if (this.CurrentSetting != null)
151             {
152                 this.CloseCurrentBackupSetting();
153             }
154
155             var backupSetting = new BackupSetting { Modified = true };
156             this.CurrentSetting = backupSetting;
157             this.CurrentSetting.SettingModified += this.OnCurrentSettingModified;
158
159             if (this.BackupSettingCreated != null)
160             {
161                 this.BackupSettingCreated(this, new SettingFileEventArgs(this.CurrentSetting.SettingName));
162             }
163
164             return true;
165         }
166
167         /// <summary>
168         /// Opens the backup setting.
169         /// </summary>
170         /// <param name="resultMessage">The result message.</param>
171         /// <returns>
172         ///   <c>true</c> if backup setting is successfully loaded; otherwise, <c>false</c>.
173         /// </returns>
174         public bool OpenBackupSetting(out string resultMessage)
175         {
176             if ((this.CurrentSetting != null) && this.CurrentSetting.Modified)
177             {
178                 MessageBoxResult confirmationResult = MessageBox.Show(
179                     Application.Current.MainWindow,
180                     Resources.Views_SaveConfirmationMessage,
181                     Resources.Views_ConfirmationDialogTitle,
182                     MessageBoxButton.YesNoCancel);
183                 if (confirmationResult == MessageBoxResult.Yes)
184                 {
185                     this.SaveCurrentBackupSetting();
186                 }
187                 else if (confirmationResult == MessageBoxResult.Cancel)
188                 {
189                     resultMessage = string.Empty;
190                     return false;
191                 }
192             }
193
194             string initialDirectory = AppDomain.CurrentDomain.BaseDirectory;
195             if ((this.CurrentSetting != null) &&
196                 this.CurrentSetting.SettingFileName.IsValidFilePath())
197             {
198                 initialDirectory = Path.GetDirectoryName(this.CurrentSetting.SettingFileName);
199                 this.CloseBackupSetting();
200             }
201
202             var openFileDialog = new OpenFileDialog
203             {
204                 Title = Resources.Views_OpenFileDialogTitle,
205                 DefaultExt = ".xml",
206                 Filter = "Backup Setting File|*.xml",
207                 InitialDirectory = initialDirectory,
208                 Multiselect = false
209             };
210
211             if (openFileDialog.ShowDialog(Application.Current.MainWindow) != true)
212             {
213                 resultMessage = string.Empty;
214                 return false;
215             }
216
217             var fileName = openFileDialog.FileName;
218             try
219             {
220                 Mouse.OverrideCursor = Cursors.Wait;
221                 return this.OpenBackupSetting(fileName, out resultMessage);
222             }
223             finally
224             {
225                 Mouse.OverrideCursor = null;
226             }
227         }
228
229         /// <summary>
230         /// Closes the backup setting.
231         /// </summary>
232         public void CloseBackupSetting()
233         {
234             if (this.CurrentSetting == null)
235             {
236                 return;
237             }
238
239             if (this.CurrentSetting.Modified)
240             {
241                 MessageBoxResult confirmationResult = MessageBox.Show(
242                     Application.Current.MainWindow,
243                     Resources.Views_SaveConfirmationMessage,
244                     Resources.Views_ConfirmationDialogTitle,
245                     MessageBoxButton.YesNoCancel);
246                 if (confirmationResult == MessageBoxResult.Yes)
247                 {
248                     this.SaveCurrentBackupSetting();
249                 }
250                 else if (confirmationResult == MessageBoxResult.Cancel)
251                 {
252                     return;
253                 }
254             }
255
256             this.CloseCurrentBackupSetting();
257         }
258
259         /// <summary>
260         /// Overwrites the currnt backup setting.
261         /// </summary>
262         /// <returns><c>true</c> if the backup setting is saved; otherwise, <c>false</c>.</returns>
263         public bool OverWriteCurrntBackupSetting()
264         {
265             if (this.CurrentSetting == null)
266             {
267                 return false;
268             }
269
270             if (string.IsNullOrEmpty(this.CurrentSetting.SettingFileName) ||
271                 (File.Exists(this.CurrentSetting.SettingFileName) == false))
272             {
273                 var saveFileDialog = new SaveFileDialog
274                 {
275                     Title = Resources.Views_SaveFileDialogTitle,
276                     DefaultExt = ".xml",
277                     Filter = "Backup Setting File|*.xml"
278                 };
279
280                 if (saveFileDialog.ShowDialog(Application.Current.MainWindow) != true)
281                 {
282                     return false;
283                 }
284
285                 this.CurrentSetting.SettingFileName = saveFileDialog.FileName;
286             }
287
288             this.SaveCurrentBackupSetting();
289             return true;
290         }
291
292         /// <summary>
293         /// Saves the current backup setting as a new file.
294         /// </summary>
295         /// <returns><c>true</c> if the backup setting is saved; otherwise, <c>false</c>.</returns>
296         public bool SaveCurrentBackupSettingAsNewFile()
297         {
298             if (this.CurrentSetting == null)
299             {
300                 return false;
301             }
302
303             var saveFileDialog = new SaveFileDialog
304             {
305                 Title = Resources.Views_SaveFileDialogTitle,
306                 DefaultExt = ".xml",
307                 Filter = "Backup Setting File|*.xml"
308             };
309
310             if (saveFileDialog.ShowDialog(Application.Current.MainWindow) != true)
311             {
312                 return false;
313             }
314
315             this.CurrentSetting.SettingFileName = saveFileDialog.FileName;
316
317             this.SaveCurrentBackupSetting();
318             return true;
319         }
320
321         /// <summary>
322         /// Opens the default backup setting.
323         /// </summary>
324         /// <param name="resultMessage">The result message.</param>
325         /// <returns>
326         ///   <c>true</c> if succeeded, otherwise; <c>false</c>.
327         /// </returns>
328         public bool OpenDefaultBackupSetting(out string resultMessage)
329         {
330             return this.OpenBackupSetting(
331                 Properties.Settings.Default.DefaultSettingFileName,
332                 out resultMessage);
333         }
334
335         /// <summary>
336         /// Creates the backup information.
337         /// </summary>
338         /// <param name="index">The index.</param>
339         /// <returns>The created backup information.</returns>
340         /// <exception cref="System.ArgumentOutOfRangeException"><paramref name="index"/></exception>
341         public IBackupInfo CreateBackupInfo(int index)
342         {
343             if (index < 0)
344             {
345                 throw new ArgumentOutOfRangeException("index");
346             }
347
348             var backupInfo = new BackupInfo();
349             this.CurrentSetting.Insert(index, backupInfo);
350             return backupInfo;
351         }
352
353         /// <summary>
354         /// Copies the backup information.
355         /// </summary>
356         /// <param name="sourceBackupInfo">The source backup information.</param>
357         /// <returns>A copied BackupInfo.</returns>
358         /// <exception cref="System.ArgumentNullException"><paramref name="sourceBackupInfo"/></exception>
359         public IBackupInfo CopyBackupInfo(IBackupInfo sourceBackupInfo)
360         {
361             sourceBackupInfo.ThrowsArgumentNullException("sourceBackupInfo");
362
363             var backupInfo = new BackupInfo(sourceBackupInfo);
364             return backupInfo;
365         }
366
367         /// <summary>
368         /// Inserts the backup information.
369         /// </summary>
370         /// <param name="index">The index.</param>
371         /// <param name="backupInfo">The backup information.</param>
372         /// <exception cref="System.ArgumentOutOfRangeException"><paramref name="index"/></exception>
373         /// <exception cref="System.ArgumentNullException"><paramref name="backupInfo"/></exception>
374         public void InsertBackupInfo(int index, IBackupInfo backupInfo)
375         {
376             if (index > this.CurrentSetting.Count)
377             {
378                 throw new ArgumentOutOfRangeException("index");
379             }
380
381             backupInfo.ThrowsArgumentNullException("backupInfo");
382
383             this.CurrentSetting.Insert(index, backupInfo);
384         }
385
386         /// <summary>
387         /// Removes the backup information.
388         /// </summary>
389         /// <param name="backupInfoId">The backup information identifier.</param>
390         public void RemoveBackupInfo(Guid backupInfoId)
391         {
392             IBackupInfo removingBackupInfo =
393                 this.CurrentSetting.FirstOrDefault(backupInfoId);
394             if (removingBackupInfo == null)
395             {
396                 return;
397             }
398
399             this.CurrentSetting.Remove(removingBackupInfo);
400         }
401
402         /// <summary>
403         /// Saves the backup setting.
404         /// </summary>
405         /// <param name="backupSetting">The backup setting.</param>
406         private static void SaveBackupSetting(IBackupSetting backupSetting)
407         {
408             var xdoc = new XDocument { Declaration = new XDeclaration("1.0", "utf-8", "yes") };
409             xdoc.Add(backupSetting.ToXml());
410
411             xdoc.Save(backupSetting.SettingFileName, SaveOptions.None);
412         }
413
414         /// <summary>
415         /// Opens the backup setting.
416         /// </summary>
417         /// <param name="fileName">Name of the file.</param>
418         /// <param name="resultMessage">The result message.</param>
419         /// <returns>
420         ///   <c>true</c> if succeeded; otherwise, <c>false</c>.
421         /// </returns>
422         private bool OpenBackupSetting(string fileName, out string resultMessage)
423         {
424             resultMessage = string.Empty;
425
426             if (string.IsNullOrEmpty(fileName))
427             {
428                 resultMessage = string.Format(
429                     Resources.BackupSetting_FailedToOpenSetting_EmptyFileNameFormat,
430                     fileName);
431                 return false;
432             }
433
434             XDocument xml = XDocument.Load(fileName, LoadOptions.None);
435             XElement backupSettingElement = xml.Elements("BackupSetting").FirstOrDefault();
436             if (backupSettingElement == null)
437             {
438                 resultMessage = string.Format(
439                     Resources.BackupSetting_FailedToOpenSetting_NoBackupSettingElementFormat,
440                     fileName);
441                 return false;
442             }
443
444             XAttribute versionAttribute = backupSettingElement.Attributes().FirstOrDefault(p => p.Name == "Version");
445             if (versionAttribute == null)
446             {
447                 resultMessage = string.Format(
448                     Resources.BackupSetting_FailedToOpenSetting_NoVersionElementFormat,
449                     fileName);
450                 return false;
451             }
452
453             string[] versionTextFlagments = versionAttribute.Value.Split('.');
454             if (versionTextFlagments.Length != 2)
455             {
456                 resultMessage = string.Format(
457                     Resources.BackupSetting_FailedToOpenSetting_InvalidVersionFormat,
458                     fileName);
459                 return false;
460             }
461
462             int majorVersion;
463             if (int.TryParse(versionTextFlagments[0], out majorVersion) == false)
464             {
465                 resultMessage = string.Format(
466                     Resources.BackupSetting_FailedToOpenSetting_InvalidMajorVersionFormat,
467                     fileName);
468                 return false;
469             }
470
471             int minorVersion;
472             if (int.TryParse(versionTextFlagments[1], out minorVersion) == false)
473             {
474                 resultMessage = string.Format(
475                     Resources.BackupSetting_FailedToOpenSetting_InvalidMinorVersionFormat,
476                     fileName);
477                 return false;
478             }
479
480             XAttribute requiredToolVersionAttribute = backupSettingElement.Attributes().FirstOrDefault(p => p.Name == "RequiredToolVersion");
481             if (requiredToolVersionAttribute == null)
482             {
483                 resultMessage = string.Format(
484                     Resources.BackupSetting_FailedToOpenSetting_InvalidRequiredToolVersionFormat,
485                     fileName);
486                 return false;
487             }
488
489             if (majorVersion > SupportedMajorVersion)
490             {
491                 string message = string.Format(
492                     Resources.BackupSetting_IncompatibleMajorVersionFormat,
493                     requiredToolVersionAttribute.Value);
494                 MessageBox.Show(
495                     Application.Current.MainWindow,
496                     message,
497                     Resources.Views_DefaultWindowTitle,
498                     MessageBoxButton.OK,
499                     MessageBoxImage.Error);
500                 resultMessage = message;
501                 return false;
502             }
503
504             if (minorVersion > SupportedMinorVersion)
505             {
506                 string message = string.Format(
507                     Resources.BackupSetting_IncompatibleMinorVersionFormat,
508                     requiredToolVersionAttribute.Value);
509                 MessageBox.Show(
510                     Application.Current.MainWindow,
511                     message,
512                     Resources.Views_DefaultWindowTitle,
513                     MessageBoxButton.OK,
514                     MessageBoxImage.Warning);
515                 resultMessage = message + "\r\n";
516             }
517
518             BackupSetting backupSetting = ModelHelper.RestoreBackupSettingFromXml(backupSettingElement, fileName);
519             this.CurrentSetting = backupSetting;
520             this.CurrentSetting.SettingModified += this.OnCurrentSettingModified;
521             if (this.BackupSettingOpened != null)
522             {
523                 this.BackupSettingOpened(this, new SettingFileEventArgs(backupSetting.SettingFileName));
524             }
525
526             resultMessage += string.Format(Resources.BackupSetting_SettingOpenedFormat, fileName);
527             return true;
528         }
529
530         /// <summary>
531         /// Saves the current backup setting.
532         /// </summary>
533         private void SaveCurrentBackupSetting()
534         {
535             try
536             {
537                 Mouse.OverrideCursor = Cursors.Wait;
538
539                 SaveBackupSetting(this.CurrentSetting);
540
541                 this.CurrentSetting.Modified = false;
542             }
543             finally
544             {
545                 Mouse.OverrideCursor = null;
546             }
547
548             if (this.BackupSettingSaved != null)
549             {
550                 this.BackupSettingSaved(this, new SettingFileEventArgs(this.CurrentSetting.SettingFileName));
551             }
552         }
553
554         private void CloseCurrentBackupSetting()
555         {
556             UndoRedoService.Instance.ClearUndoRedoBuffer();
557             string settingName = this.CurrentSetting.SettingFileName;
558             this.CurrentSetting.SettingModified -= this.OnCurrentSettingModified;
559             this.CurrentSetting = null;
560
561             if (this.BackupSettingClosed != null)
562             {
563                 this.BackupSettingClosed(this, new SettingFileEventArgs(settingName));
564             }
565         }
566
567         /// <summary>
568         /// Called when current setting is modified.
569         /// </summary>
570         /// <param name="sender">The sender.</param>
571         /// <param name="eventArgs">The <see cref="EventArgs"/> instance containing the event data.</param>
572         private void OnCurrentSettingModified(object sender, EventArgs eventArgs)
573         {
574             if (this.BackupSettingModified != null)
575             {
576                 this.BackupSettingModified(this, new SettingFileEventArgs(this.CurrentSetting.SettingName));
577             }
578         }
579     }
580 }