- goalbook.zip
- 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
- GoalBook.Goals
- GoalBook.Infrastructure
- GoalBook.Notes
- GoalBook.Public
- GoalBook.Shell
- App.ico
- App.xaml
- App.xaml.cs
- Bootstrapper.cs
- Commands
- GoalBook.Shell.csproj
- GoalBook.Shell.csproj.user
- Journal.ico
- Journal48.ico
- Misc
- Modules
- Properties
- 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
- Splash.png
- Views
- vssver2.scc
- Windows
- GoalBook.sln
- GoalBook.snk
- GoalBook.Synchronisation
- GoalBook.Tasks
- License.txt
- ReadMe.txt
- SolutionInfo.cs
- vssver2.scc
|
//===============================================================================
// Goal Book.
// Copyright © 2009 Mark Brownsword.
//===============================================================================
#region Using Statements
using System;
using System.Linq;
using System.Xml.Linq;
using GoalBook.Infrastructure.ObjectModel;
#endregion
namespace GoalBook.Synchronisation.ToodleDo
{
internal class GoalSynchronisor : Synchronisor<GoalList>
{
#region Constants and Enums
//Goal constants
private const string GOAL = "goal";
private const string GOAL_ID = "id";
private const string GOAL_LEVEL = "level";
private const string GOAL_CONTRIBUTES = "contributes";
private const string GOAL_ARCHIVED = "archived";
//URL constants
private const string GET_GOALS_URL = @"http://api.toodledo.com/api.php?method=getGoals;key={0}";
private const string ADD_GOAL_URL = @"http://api.toodledo.com/api.php?method=addGoal;key={0};title={1};level={2}";
private const string DELETE_GOAL_URL = @"http://api.toodledo.com/api.php?method=deleteGoal;key={0};id={1}";
private const string EDIT_GOAL_URL = @"http://api.toodledo.com/api.php?method=editGoal;key={0};id={1};title={2};level={3}";
private const string APPEND_CONTRIBUTES = @";contributes={0}";
#endregion
#region Inner Classes and Structures
#endregion
#region Delegates and Events
#endregion
#region Instance and Shared Fields
#endregion
#region Constructors
/// <summary>
/// Constructor.
/// </summary>
internal GoalSynchronisor(ToodledoConnector connector)
: base(connector)
{
}
#endregion
#region Properties
#endregion
#region Private and Protected Methods
/// <summary>
/// Get ExternalIdentifier. Swap internal identifier with external identifier.
/// </summary>
private int GetExternalIdentifier(Guid contributesID, GoalList goalList)
{
var targetList = from g in goalList where g.GoalID == contributesID select g;
foreach (Goal goal in targetList)
{
return goal.ExternalIdentifier; //One only can exist.
}
return 0;
}
/// <summary>
/// Get Goal with the specified id.
/// </summary>
private Goal GetGoal(GoalList goalList, int id)
{
var targetList = from g in goalList where g.ExternalIdentifier == id select g;
foreach (Goal goal in targetList)
{
return goal; //One only can exist.
}
return null;
}
/// <summary>
/// SyncGoals ServerChanges.
/// </summary>
/// <param name="goalList">GoalList</param>
private void SyncGoalsServer(GoalList goalList)
{
//Get Toodledo goals.
string goalsURL = string.Format(GET_GOALS_URL, Connector.GetSessionKey());
XDocument serverList = Connector.MakeServerCall(goalsURL);
//Delete.
var clientList = from g in goalList where g.ExternalIdentifier > 0 orderby g.LevelID select g;
foreach (Goal goal in clientList)
{
bool found = false;
var targetList = from s in serverList.Descendants(GOAL)
where int.Parse(s.Attribute(GOAL_ID).Value) == goal.ExternalIdentifier && int.Parse(s.Attribute(GOAL_ARCHIVED).Value) == 0
select s;
foreach (XElement element in targetList)
{
//Only one goal can exist with the specified id, so move on.
found = true;
break;
}
//If not found then it has been deleted on the server. Remove the goal.
//NOTE: Goal is moved to the Deleted list.
if (!found)
{
goalList.Remove(goal);
}
}
//Add, Edit.
var orderedServerList = from s in serverList.Descendants(GOAL)
where int.Parse(s.Attribute(GOAL_ARCHIVED).Value) == 0
orderby s.Attribute(GOAL_LEVEL).Value
select s;
foreach (XElement element in orderedServerList)
{
Goal target = GetGoal(goalList, int.Parse(element.Attribute(GOAL_ID).Value));
if (target == null)
{
//Add
int levelID = int.Parse(element.Attribute(GOAL_LEVEL).Value);
Guid contributesID = Guid.Empty;
Goal contributesGoal = GetGoal(goalList, int.Parse(element.Attribute(GOAL_CONTRIBUTES).Value));
if (contributesGoal == null) { contributesID = Guid.Empty; }
else { contributesID = contributesGoal.GoalID; }
bool archived = element.Attribute(GOAL_ARCHIVED).Value == NUMERIC_TRUE;
string title = element.Value;
Goal addGoal = new Goal(Guid.NewGuid(), levelID, contributesID, archived, title);
addGoal.ExternalIdentifier = int.Parse(element.Attribute(GOAL_ID).Value);
addGoal.SyncRequired = false;
goalList.Add(addGoal);
goalList.EndNew(goalList.IndexOf(addGoal));
}
else
{
//Edit
Goal editGoal = target.Clone();
Goal contributesGoal = GetGoal(goalList, int.Parse(element.Attribute(GOAL_CONTRIBUTES).Value));
editGoal.LevelID = int.Parse(element.Attribute(GOAL_LEVEL).Value);
if (contributesGoal == null) { editGoal.ContributesID = Guid.Empty; }
else { editGoal.ContributesID = contributesGoal.GoalID; }
editGoal.Archived = element.Attribute(GOAL_ARCHIVED).Value == NUMERIC_TRUE;
editGoal.Title = element.Value;
goalList[goalList.IndexOf(target)].MapFields(editGoal);
goalList[goalList.IndexOf(target)].SyncRequired = false;
}
}
}
/// <summary>
/// SyncGoals ClientChanges.
/// </summary>
private void SyncGoalsClient(GoalList goalList)
{
//Delete.
var deleteList = from g in goalList.DeletedPendingSync orderby g.LevelID descending select g;
foreach (Goal goal in deleteList.ToArray())
{
string deleteGoalURL = string.Format(DELETE_GOAL_URL, Connector.GetSessionKey(), goal.ExternalIdentifier);
XDocument result = Connector.MakeServerCall(deleteGoalURL, ToodledoConnector.SyncMethod.Post);
if (result.Element(SUCCESS) != null)
{
int deleteResult = 0;
if (int.TryParse(result.Element(SUCCESS).Value, out deleteResult) && deleteResult == 1)
{
goalList.DeletedPendingSync.Remove(goal);
}
}
else
{
/*<error>Invalid ID number</error>*/
}
}
//Add. Sort the Goals by Level (this ensures that top level goals are added before subsequent goals specify contributesID).
var addList = from g in goalList where g.ExternalIdentifier == 0 orderby g.LevelID select g;
foreach (Goal goal in addList)
{
string addGoalURL = string.Format(ADD_GOAL_URL, Connector.GetSessionKey(), Connector.UrlEncodeParameterValue(goal.Title), goal.LevelID);
if (goal.ContributesID != Guid.Empty)
{
addGoalURL = string.Concat(addGoalURL, string.Format(APPEND_CONTRIBUTES,
Connector.UrlEncodeParameterValue(GetExternalIdentifier(goal.ContributesID, goalList))));
}
XDocument result = Connector.MakeServerCall(addGoalURL, ToodledoConnector.SyncMethod.Post);
if (result.Element(ADDED) != null)
{
int addResult = 0;
if (int.TryParse(result.Element(ADDED).Value, out addResult) && addResult > 0)
{
goal.ExternalIdentifier = addResult;
goal.SyncRequired = false;
}
}
}
//Edit
var editList = from g in goalList where g.ExternalIdentifier > 0 && g.SyncRequired orderby g.LevelID select g;
foreach (Goal goal in editList)
{
string editGoalURL = string.Format(EDIT_GOAL_URL, Connector.GetSessionKey(), goal.ExternalIdentifier, Connector.UrlEncodeParameterValue(goal.Title), goal.LevelID);
XDocument result = Connector.MakeServerCall(editGoalURL, ToodledoConnector.SyncMethod.Post);
if (result.Element(SUCCESS) != null)
{
int editResult = 0;
if (int.TryParse(result.Element(SUCCESS).Value, out editResult) && editResult == 1)
{
goal.SyncRequired = false;
}
}
}
}
#endregion
#region Public and internal Methods
/// <summary>
/// Sync the GoalList.
/// </summary>
/// <param name="list">GoalList</param>
internal override void Sync(GoalList goalList)
{
DateTime savedLastServerGoalEdit = goalList.LastServerGoalEdit;
if (Connector.LastGoalEdit > savedLastServerGoalEdit && goalList.SyncRequired)
{
//Server and Client both have changes.
SyncGoalsClient(goalList);
SyncGoalsServer(goalList);
}
else if (Connector.LastGoalEdit > savedLastServerGoalEdit)
{
//Server only has changes.
SyncGoalsServer(goalList);
}
else if (goalList.SyncRequired)
{
//Client only has changes.
SyncGoalsClient(goalList);
}
}
#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.
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.