Click here to Skip to main content
12,758,014 members (33,076 online)
Click here to Skip to main content

Stats

48.8K views
765 downloads
69 bookmarked
Posted 26 Mar 2009

GoalBook - A Hybrid Smart Client

, 25 Sep 2009 CPOL
A WPF hybrid smart client that synchronises your goals with the Toodledo online To-do service.
GoalBook
Dependencies
CAG WPF 2
Microsoft.Practices.Composite.dll
Microsoft.Practices.Composite.Presentation.dll
Microsoft.Practices.Composite.UnityExtensions.dll
Microsoft.Practices.ObjectBuilder2.dll
Microsoft.Practices.ServiceLocation.dll
Microsoft.Practices.Unity.dll
vssver2.scc
CSLA
Csla.dll
Csla.XmlSerializers.dll
vssver2.scc
Infragistics
Infragistics3.Wpf.DataPresenter.v9.1.Express.dll
Infragistics3.Wpf.Editors.v9.1.Express.dll
Infragistics3.Wpf.v9.1.Express.dll
vssver2.scc
WPFToolkit
vssver2.scc
WPFToolkit.dll
GoalBook.Controls
CheckedList
vssver2.scc
Properties
vssver2.scc
vssver2.scc
GoalBook.Goals
GoalBook.Goals.csproj.user
Properties
vssver2.scc
Views
vssver2.scc
vssver2.scc
GoalBook.Infrastructure
Comparers
vssver2.scc
Constants
vssver2.scc
Controls
Converters
vssver2.scc
Enums
vssver2.scc
Events
vssver2.scc
GoalBook.Infrastructure.csproj.user
Helpers
vssver2.scc
Interfaces
vssver2.scc
ObjectModel
vssver2.scc
Printing
vssver2.scc
Properties
vssver2.scc
vssver2.scc
GoalBook.Notes
GoalBook.Notes.csproj.user
Properties
vssver2.scc
Resources
arrow_redo.png
arrow_undo.png
cut.png
page_copy.png
paste_plain.png
text_bold.png
text_indent.png
text_indent_remove.png
text_italic.png
text_list_bullets.png
text_list_numbers.png
vssver2.scc
world_link.png
Views
vssver2.scc
vssver2.scc
GoalBook.Public
Encryption
vssver2.scc
HtmlConverter
vssver2.scc
HtmlParser
vssver2.scc
Misc
vssver2.scc
Properties
vssver2.scc
vssver2.scc
GoalBook.Shell
App.ico
Commands
vssver2.scc
GoalBook.Shell.csproj.user
Journal.ico
Journal48.ico
Misc
vssver2.scc
Modules
vssver2.scc
Properties
licenses.licx
vssver2.scc
Resources
arrow_refresh.png
arrow_undo.png
checked.gif
cross.png
disk.png
email.png
erase.png
error.png
exclamation.png
flag_red.png
group.png
help.png
information.png
magnifier.png
page_red.png
pencil.png
printer.png
user.png
vssver2.scc
Wave.jpg
world.png
world_link.png
Services
vssver2.scc
Splash.png
Views
vssver2.scc
vssver2.scc
Windows
vssver2.scc
GoalBook.snk
GoalBook.Synchronisation
Events
vssver2.scc
Properties
vssver2.scc
ToodleDo
vssver2.scc
vssver2.scc
GoalBook.Tasks
Controls
vssver2.scc
Properties
vssver2.scc
Views
vssver2.scc
vssver2.scc
vssver2.scc
//===============================================================================
// Goal Book.
// Copyright © 2009 Mark Brownsword. 
//===============================================================================

#region Using Statements
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.IsolatedStorage;
using System.Linq;
using System.Security.Permissions;
using System.Xml.Linq;
using GoalBook.Infrastructure.Interfaces;
using GoalBook.Infrastructure.ObjectModel;
using GoalBook.Shell.Properties;
using GoalBook.Infrastructure;
#endregion

namespace GoalBook.Shell.Services
{
    /// <summary>
    /// Isolated Storage Service.
    /// </summary>
    [IsolatedStorageFilePermission(SecurityAction.Demand)]
    public sealed class IsolatedStorageService : IPersistenceService
    {                
        #region Constants and Enums
        #endregion

        #region Inner Classes and Structures
        #endregion

        #region Delegates and Events

        /// <summary>
        /// SaveOccured event.
        /// </summary>
        public event EventHandler SaveOccured;
        private void OnSaveOccured()
        {
            EventHandler saveOccured = SaveOccured;
            if (saveOccured != null)
            {
                EventArgs args = new EventArgs();
                saveOccured(this, args);
            }
        }  
     
        #endregion

        #region Instance and Shared Fields

        private static GoalList _goalList;
        private static NoteList _noteList;
        private static TaskList _taskList;
        private static FolderList _folderList;        
        private static string _goalFile;
        private static string _noteFile;
        private static string _taskFile;
        private static string _folderFile;        
        private Dictionary<int, string> _levelList;
        private Dictionary<Guid, string> _contributesList;
        private Dictionary<Guid, string> _filteredContributesList;
        private Dictionary<Guid, string> _folderReferenceList;        
        #endregion

        #region Constructors 

        /// <summary>
        /// Constructor.
        /// </summary>
        public IsolatedStorageService()
        {
            _goalFile = "Goals.xml";
            _noteFile = "Notes.xml";
            _taskFile = "Tasks.xml";
            _folderFile = "Folders.xml";
        }

        #endregion

        #region Properties

        /// <summary>
        /// Reference to Goals.
        /// </summary>
        public GoalList Goals 
        {
            get 
            {
                if (_goalList == null) InitialiseGoalList();
                return _goalList;
            }            
        }

        /// <summary>
        /// Reference to Notes.
        /// </summary>
        public NoteList Notes
        {
            get
            {
                if (_noteList == null) InitialiseNoteList();
                return _noteList;
            }            
        }

        /// <summary>
        /// Reference to Tasks.
        /// </summary>
        public TaskList Tasks
        {
            get
            {
                if (_taskList == null) InitialiseTaskList();
                return _taskList;
            }
        }

        /// <summary>
        /// Reference to Folders.
        /// </summary>
        public FolderList Folders
        {
            get
            {
                if (_folderList == null) InitialiseFolderList();
                return _folderList;
            }
        }                
        #endregion

        #region Private and Protected Methods

        /// <summary>
        /// Initialise GoalList.
        /// </summary>        
        private void InitialiseGoalList()
        {
            _goalList = new GoalList();
            _goalList.CreateFromXDocument(RetrieveFromIsolatedStorage(_goalFile));                                    
        }

        /// <summary>
        /// Initialise NoteList.
        /// </summary>        
        private void InitialiseNoteList()
        {
            _noteList = new NoteList();
            _noteList.CreateFromXDocument(RetrieveFromIsolatedStorage(_noteFile));                    
        }

        /// <summary>
        /// Initialise TaskList.
        /// </summary>
        private void InitialiseTaskList()
        {
            _taskList = new TaskList();
            _taskList.CreateFromXDocument(RetrieveFromIsolatedStorage(_taskFile));
        }

        /// <summary>
        /// Initialise FolderList.
        /// </summary>
        private void InitialiseFolderList()
        {
            _folderList = new FolderList();
            _folderList.CreateFromXDocument(RetrieveFromIsolatedStorage(_folderFile));            
        }

        /// <summary>
        /// Retrieve specified file from IsolatedStorage.
        /// </summary>
        /// <returns>XDocument</returns>
        private XDocument RetrieveFromIsolatedStorage(string file)
        {
            IsolatedStorageFile store = GetUserStore();
            XDocument result = null;

            if (store.GetFileNames(file).Length > 0)
            {
                // Read the stream from Isolated Storage.
                using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(file, FileMode.Open, store))
                {
                    using (StreamReader reader = new StreamReader(stream))
                    {
                        result = XDocument.Load(reader);
                    }
                }
            }

            return result;
        }

        /// <summary>
        /// Get a reference to the users Isolated Store.
        /// Saved location is under C:\Users\Mark\AppData\Local\IsolatedStorage.
        /// </summary>
        /// <returns>IsolatedStorageFile</returns>
        private IsolatedStorageFile GetUserStore()
        {
            return IsolatedStorageFile.GetStore(IsolatedStorageScope.User | IsolatedStorageScope.Assembly, null, null);
        }

        /// <summary>
        /// Save To IsolatedStorage.
        /// (e.g. C:\Users\[UserName]\AppData\Local\IsolatedStorage).
        /// </summary>
        /// <param name="document">XDocument to save</param>
        /// <param name="file">Name of file</param>
        private void SaveToIsolatedStorage(XDocument document, string file)
        {
            // Open the stream from IsolatedStorage.
            IsolatedStorageFileStream stream = new IsolatedStorageFileStream(
                file, FileMode.Create, GetUserStore());
            using (stream)
            {
                using (StreamWriter writer = new StreamWriter(stream))
                {
                    document.Save(writer);
                }
            }
        }

        #endregion

        #region Public Methods
        /// <summary>
        /// Clear all data.
        /// </summary>
        public void Clear()
        {
            if (_goalList != null)
            {
                _goalList.Clear();
                _goalList.MarkListOld();
                _goalList.DeletedPendingSync.Clear();
                _goalList.LastServerGoalEdit = DateTime.MinValue;
            }

            if (_folderList != null)
            {
                _folderList.Clear();
                _folderList.MarkListOld();
                _folderList.DeletedPendingSync.Clear();
                _folderList.LastServerFolderEdit = DateTime.MinValue;
            }

            if (_noteList != null)
            {
                _noteList.Clear();
                _noteList.MarkListOld();
                _noteList.DeletedPendingSync.Clear();
                _noteList.LastServerNoteEdit = DateTime.MinValue;
            }

            if (_taskList != null)
            {
                _taskList.Clear();
                _taskList.MarkListOld();
                _taskList.DeletedPendingSync.Clear();
                _taskList.LastServerTaskEdit = DateTime.MinValue;
            }
        }

        /// <summary>
        /// Save Data to Isolated Storage (e.g. C:\Users\[UserName]\AppData\Local\IsolatedStorage).
        /// </summary>
        public void Save()
        {            
            if (_goalList.IsSavable)
            {
                //Save Goals in clean state.
                IXDocSerializable cloneList = _goalList.Clone();
                cloneList.MarkListOld();
                SaveToIsolatedStorage(cloneList.GetXDocument(), _goalFile);
                _goalList.MarkListOld();
            }

            if (_folderList.IsSavable)
            {
                //Save the Folders in clean state.
                IXDocSerializable cloneList = _folderList.Clone();
                cloneList.MarkListOld();
                SaveToIsolatedStorage(cloneList.GetXDocument(), _folderFile);
                _folderList.MarkListOld();
            }

            if (_noteList.IsSavable)
            {
                //Save Notes in clean state.
                IXDocSerializable cloneList = _noteList.Clone();
                cloneList.MarkListOld();
                SaveToIsolatedStorage(cloneList.GetXDocument(), _noteFile);
                _noteList.MarkListOld();
            }

            if (_taskList.IsSavable)
            {
                //Save Tasks in clean state.
                IXDocSerializable cloneList = _taskList.Clone();
                cloneList.MarkListOld();
                SaveToIsolatedStorage(cloneList.GetXDocument(), _taskFile);
                _taskList.MarkListOld();
            }

            OnSaveOccured();
        }
               
        /// <summary>
        /// Fetch LevelList.
        /// </summary>
        /// <returns>Dictionary of levels</returns>
        public Dictionary<int, string> FetchLevelList()
        {
            if (_levelList == null)
            {
                _levelList = new Dictionary<int, string>();
                _levelList.Add(0, Resources.LevelLifetimeText);
                _levelList.Add(1, Resources.LevelLongtermText);
                _levelList.Add(2, Resources.LevelShorttermText);                
            }

            return _levelList;
        }

        /// <summary>
        /// Fetch ContributesList. Get all goals with level lower that specified value.
        /// </summary> 
        /// <returns>Dictionary</returns>
        public Dictionary<Guid, string> FetchContributesList(Guid currentGoal, int level)
        {
            if (_filteredContributesList == null)
            {
                _filteredContributesList = new Dictionary<Guid, string>();
            }

            _filteredContributesList.Clear();            
            foreach (Goal goal in _goalList)
            {
                if (goal.LevelID < level && goal.GoalID != currentGoal)
                {
                    if (_filteredContributesList.Count == 0) { _filteredContributesList.Add(Guid.Empty, null); }
                    _filteredContributesList.Add(goal.GoalID, goal.Title);                    
                }
            }

            return _filteredContributesList;
        }

        /// <summary>
        /// Fetch Contributes List.
        /// </summary>
        /// <returns>Dictionary</returns>
        public Dictionary<Guid, string> FetchContributesList()
        {
            if (_contributesList == null)
            {
                _contributesList = new Dictionary<Guid, string>();
                
                foreach (Goal goal in _goalList)
                {
                    _contributesList.Add(goal.GoalID, goal.Title);
                }
            }
            
            return _contributesList;
        }

        /// <summary>
        /// Fetch FolderList.
        /// </summary>
        /// <returns>Dictionary of folders</returns>
        public Dictionary<Guid, string> FetchFolderList()
        {
            if (_folderReferenceList == null)
            {
                _folderReferenceList = new Dictionary<Guid, string>();                          
            }

            _folderReferenceList.Clear();
            _folderReferenceList.Add(Guid.Empty, Resources.DefaultFolder);

            foreach (Folder folder in _folderList)
            {
                _folderReferenceList.Add(folder.FolderID, folder.Title);
            }

            return _folderReferenceList;
        }

        /// <summary>
        /// Update ContributesList. Add/Remove items as required.
        /// </summary>        
        public void UpdateContributesList(Guid goalID)
        {
            if (_contributesList.ContainsKey(goalID))
            {
                //Remove from contributesList
                _contributesList.Remove(goalID);
            }
            else
            {          
                foreach (Goal goal in _goalList)
                {
                    if (goal.GoalID == goalID)
                    {
                        //Add to contributesList
                        _contributesList.Add(goal.GoalID, goal.Title); break;
                    }
                }                                
            }
        }

        /// <summary>
        /// Update Folder List. 
        /// </summary>
        public void UpdateFolderList()
        {
            if (_folderReferenceList == null)
            {
                return;
            }

            // Check for deleted folders
            bool foundFolder = false;
            var checkDeleteList = from g in _folderReferenceList select g;
            foreach (KeyValuePair<Guid, string> folderItem in checkDeleteList.ToArray())
            {
                if (folderItem.Key == Guid.Empty)
                {
                    continue;
                }

                foreach (Folder folder in _folderList)
                {
                    if (folder.FolderID == folderItem.Key)
                    {
                        foundFolder = true;
                        break;
                    }
                }

                if (foundFolder)
                {
                    foundFolder = false;
                    continue;
                }
                else
                {
                    _folderReferenceList.Remove(folderItem.Key);

                    // Replace Note folderid with No Folder (Guid.Empty).
                    foreach (Note note in _noteList)
                    {
                        if (note.FolderID == folderItem.Key)
                        {
                            note.FolderID = Guid.Empty;
                        }
                    }

                    // Replace Task folderid with No Folder (Guid.Empty). 
                    foreach (Task task in _taskList)
                    {
                        if (task.TaskID == folderItem.Key)
                        {
                            task.TaskID = Guid.Empty;
                        }
                    }
                }
            }
                       
            // Check for Added folders.
            foreach (Folder folder in _folderList)
            {
                if (_folderReferenceList.ContainsKey(folder.FolderID))
                {
                    // Item exists, so just update Title.
                    _folderReferenceList[folder.FolderID] = folder.Title;
                }
                else
                {
                    // Add new item.
                    _folderReferenceList.Add(folder.FolderID, folder.Title);
                }
            }
        }

        /// <summary>
        /// Reference to SyncRequired. A flag indicating if synchronisation is required.
        /// </summary>        
        public bool SyncRequired
        {
            get
            {
                return Goals.SyncRequired || Notes.SyncRequired || Tasks.SyncRequired || Folders.SyncRequired;
            }
        }

        /// <summary>
        /// Get SaveRequired.
        /// </summary>
        public bool SaveRequired
        {
            get
            {
                return Goals.IsSavable || Notes.IsSavable || Tasks.IsSavable || Folders.IsSavable;
            }
        }

        #endregion

        #region Event Handlers
        #endregion

        #region Base Class Overrides
        #endregion        
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Mark Brownsword
Software Developer (Senior)
Australia Australia
I've been working as a software developer since 2000 and hold a Bachelor of Business degree from The Open Polytechnic of New Zealand. Computers are for people and I aim to build applications for people that they would want to use.

You may also be interested in...

Pro
Pro
Permalink | Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.170217.1 | Last Updated 25 Sep 2009
Article Copyright 2009 by Mark Brownsword
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid