using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Technewlogic.ObjectLounge.Framework.Proxy;
using Technewlogic.ObjectLounge.Framework.MetaModel;
using Technewlogic.ObjectLounge.Framework.Transactions;
namespace Technewlogic.ObjectLounge.Framework.BaseConcerns
{
public class ChangeTrackingConcern : ConcernBase<IUnitOfWorkConcern>
{
internal ChangeTrackingConcern(
EntitySpec entitySpec,
IUnitOfWorkConcern parent,
SynchronizationOperation initialSynchronizationOperation,
ShadowStorageTransactionMapper shadowStorageTransactionMapper)
{
_entitySpec = entitySpec;
_synchronizationOperation = initialSynchronizationOperation;
_shadowStorageTransactionMapper = shadowStorageTransactionMapper;
_shadowStorageTransactionMapper.RegisterRollbackAction(
_synchronizationOperationPropertyKey,
(o) => SynchronizationOperation = (SynchronizationOperation)o);
Parent = parent;
}
private readonly string _synchronizationOperationPropertyKey
= "SynchronizationOperationProperty" + "_" + Guid.NewGuid().ToString();
private readonly EntitySpec _entitySpec;
private readonly ShadowStorageTransactionMapper _shadowStorageTransactionMapper;
private SynchronizationOperation _synchronizationOperation;
public SynchronizationOperation SynchronizationOperation
{
get
{
SynchronizationOperation backupValue;
if (_shadowStorageTransactionMapper.TryGetCommittedValue(
_synchronizationOperationPropertyKey, out backupValue))
{
return backupValue;
}
else
return _synchronizationOperation;
}
internal set
{
var oldValue = _synchronizationOperation;
_shadowStorageTransactionMapper.OnPropertyChanging(
_synchronizationOperationPropertyKey, value, oldValue);
_synchronizationOperation = value;
_shadowStorageTransactionMapper.OnPropertyChanged(
_synchronizationOperationPropertyKey, value, oldValue);
}
}
public bool IsCurrentlyInDB
{
get
{
return SynchronizationOperation == SynchronizationOperation.Nothing
|| SynchronizationOperation == SynchronizationOperation.Deleted
|| SynchronizationOperation == SynchronizationOperation.Updated;
}
}
public bool WillBeInDB
{
get
{
return SynchronizationOperation == SynchronizationOperation.Inserted
|| SynchronizationOperation == SynchronizationOperation.Updated
|| SynchronizationOperation == SynchronizationOperation.Nothing;
}
}
#region Mark Functionality
internal void MarkForInsert()
{
switch (SynchronizationOperation)
{
case SynchronizationOperation.Unknown:
SetState(SynchronizationOperation.Inserted);
break;
case SynchronizationOperation.Nothing:
case SynchronizationOperation.Updated:
throw Error.InvalidEntityStateOperation(
this.Parent,
Error.EntityStateOperation.Insert,
SynchronizationOperation);
case SynchronizationOperation.Inserted:
break;
case SynchronizationOperation.Deleted:
SetState(SynchronizationOperation.Updated);
break;
default:
throw Error.EntityStateUnknown(
this.Parent,
Error.EntityStateOperation.Insert,
SynchronizationOperation);
}
}
internal void MarkForUpdate()
{
switch (SynchronizationOperation)
{
case SynchronizationOperation.Unknown:
throw Error.InvalidEntityStateOperation(
this.Parent,
Error.EntityStateOperation.Update,
SynchronizationOperation);
case SynchronizationOperation.Nothing:
SetState(SynchronizationOperation.Updated);
break;
case SynchronizationOperation.Inserted:
case SynchronizationOperation.Updated:
case SynchronizationOperation.Deleted:
break;
default:
throw Error.EntityStateUnknown(
this.Parent,
Error.EntityStateOperation.Update,
SynchronizationOperation);
}
}
internal void MarkForDelete()
{
switch (SynchronizationOperation)
{
case SynchronizationOperation.Unknown:
throw Error.InvalidEntityStateOperation(
this.Parent,
Error.EntityStateOperation.Delete,
SynchronizationOperation);
case SynchronizationOperation.Nothing:
case SynchronizationOperation.Updated:
SetState(SynchronizationOperation.Deleted);
break;
case SynchronizationOperation.Inserted:
SetState(SynchronizationOperation.Unknown);
break;
case SynchronizationOperation.Deleted:
break;
default:
throw Error.EntityStateUnknown(
this.Parent,
Error.EntityStateOperation.Delete,
SynchronizationOperation);
}
}
// IMP: Ist das nach der Zusammenführung von ChangeTrackingState mit ChangeTrackingConcern noch gut?
private void SetState(SynchronizationOperation synchronizationOperation)
{
SynchronizationOperation = synchronizationOperation;
foreach (var it in Parent.NavigationConcern.EntitySyncs.Values)
it.InformDBStateChanged();
}
#endregion
internal void OnPropertyChanging(string propertyName, object newValue, object oldVvalue)
{
// IMP: prüfen?
_shadowStorageTransactionMapper.OnPropertyChanging(
propertyName, newValue, oldVvalue);
}
internal void OnPropertyChanged(string propertyName, object newValue, object oldVvalue)
{
if (SynchronizationOperation != SynchronizationOperation.Unknown
&& _entitySpec.UpdateTriggerPropertyNames.Contains(propertyName))
{
MarkForUpdate();
}
_shadowStorageTransactionMapper.OnPropertyChanged(
propertyName, newValue, oldVvalue);
// OPT: Das hier einbauen
//// IMP: es MUSS immer eine Transaktion geben!
//if (_transactionManager.HasTransaction)
//{
// _transactionManager.CurrentTransaction.ChangeTrackingTransactionService
// .RegisterChangedEntity(_parent);
//}
}
}
}