/// <summary>
        /// Resolves the replication collision.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="collisionType">Type of the collision.</param>
        /// <param name="args">The args.</param>
        /// <returns></returns>
        private CollisionResult resolveReplicationCollision(LoadPackageRecordContext context,
                                                            CollisionType collisionType, params object[] args)
        {
            var e = new ResolveReplicationCollisionArgs(context, collisionType, args);
            Owner.DoResolveReplicationCollision(e);
            if (e.ResolveResult == CollisionResult.Error)
                throw new ReplicationCollisionException(collisionType);

            context.Worker.ReportProgress(Color.Goldenrod,
                Localizer.CollisionDetected,
                collisionType, context.PackageRecord, e.ResolveResult);

            return e.ResolveResult;
        }
        /// <summary>
        /// Loads the package record.
        /// </summary>
        /// <param name="context">The context.</param>
        private void loadPackageRecord(LoadPackageRecordContext context)
        {
            var args = new LoadRecordArgs(context);
            var objectSpace = getPlaybackObjectSpace(context.PackageSession, context.ActiveObjectSpaces);
            if (!Owner.DoBeforeLoadRecord(args))
            {
                var operationType =
                    (ProtocolEventType) Enum.Parse(typeof (ProtocolEventType), context.PackageRecord.OperationType);

                if (operationType == ProtocolEventType.CommitSession)
                {
                    commitObjectSpaceOnLoad(objectSpace, context.ActiveObjectSpaces);
                }
                else
                {
                    var senderNodeId = context.Package.SenderNodeId;
                    var targetObject = OidMap.FindApplicationObject(objectSpace,
                                                                    context.PackageRecord.AuditedObject, senderNodeId);

                    ITypeInfo targetTypeInfo = null;
                    if (targetObject != null)
                        targetTypeInfo = objectSpace.TypesInfo.FindTypeInfo(targetObject.GetType());

                    XPMemberInfo memberInfo = null;
                    var propertyIsEmpty = string.IsNullOrEmpty(context.PackageRecord.PropertyName);
                    if (!propertyIsEmpty && targetObject != null && targetTypeInfo != null)
                    {
                        memberInfo = ((ISessionProvider)targetObject).Session.GetClassInfo(targetObject)
                            .GetMember(context.PackageRecord.PropertyName);
                    }

                    bool oldObjectShouldExists;
                    var oldObject = restoreObjectFromRef(objectSpace, senderNodeId,
                                                         context.PackageRecord.OldObject, out oldObjectShouldExists);

                    bool newObjectShouldExists;
                    var newObject = restoreObjectFromRef(objectSpace, senderNodeId,
                                                         context.PackageRecord.NewObject, out newObjectShouldExists);

                    // collision resolving
                    var replres = resolveCollisions(context, oldObject, newObjectShouldExists,
                                                    newObject, operationType, oldObjectShouldExists, targetObject,
                                                    memberInfo, propertyIsEmpty);

                    if (replres == CollisionResult.Default)
                    {
                        switch (operationType)
                        {
                            case ProtocolEventType.MethodCall:
                                if(targetObject != null)
                                {
                                    if (targetTypeInfo != null)
                                    {
                                        var classType = targetTypeInfo.Type;
                                        if (context.PackageRecord != null
                                            && !string.IsNullOrEmpty(context.PackageRecord.PropertyName))
                                        {
                                            var callParameters = (MethodCallParams)oldObject;

                                            var methodInfo = (from m in classType.GetMethods()
                                                              where m.Name == context.PackageRecord.PropertyName
                                                              && m.GetParameters().Count() == callParameters.MethodParamValues.Count
                                                              select m).FirstOrDefault();

                                            if (methodInfo != null)
                                            {
                                                var paramValues = callParameters.GetParamValues();
                                                methodInfo.Invoke(targetObject, paramValues);
                                            }
                                        }
                                    }
                                }
                                break;

                            case ProtocolEventType.AddedToCollection:
                                if (memberInfo != null && memberInfo.IsAssociationList && oldObject != null)
                                {
                                    var collObj = memberInfo.GetValue(targetObject);
                                    if (collObj != null)
                                    {
                                        if(collObj.GetType().GetInterface("IList") != null)
                                        {
                                            var list = (IList) collObj;
                                            if(!list.Contains(oldObject))
                                                list.Add(oldObject);
                                        }
                                    }
                                }
                                break;

                            case ProtocolEventType.AggregatedObjectChanged:
                                break;

                            case ProtocolEventType.CollectionObjectChanged:
                                break;

                            case ProtocolEventType.InitialValueAssigned:
                            case ProtocolEventType.ObjectChanged:
                                if (memberInfo != null)
                                {
                                    object newValue = null;
                                    if (context.PackageRecord.NewBlobValue != null)
                                    {
                                        newValue = ValueTransform.RestoreFromBlob(context.PackageRecord.NewBlobValue);
                                    }
                                    else
                                    {
                                        // NewBlobValue is empty - restore value from context.PackageRecord.NewValue
                                        if (context.PackageRecord.NewValue != null)
                                        {
                                            if (memberInfo.ReferenceType == null)
                                            {
                                                if (!string.IsNullOrEmpty(context.PackageRecord.NewValue))
                                                    newValue = ValueTransform.StringToObject(context.PackageRecord.NewValue,
                                                        memberInfo.MemberType);
                                                else
                                                    newValue = memberInfo.MemberType.IsValueType ?
                                                        Activator.CreateInstance(memberInfo.MemberType) : null;
                                            }
                                            else
                                                newValue = newObject;
                                        }
                                    }

                                    // replace aggregated members initialization with oidmap redirection
                                    if (operationType == ProtocolEventType.InitialValueAssigned
                                        && memberInfo.IsAggregated && !memberInfo.IsAssociationList && newValue != null)
                                    {
                                        var oldAggregatedObj = memberInfo.GetValue(targetObject);
                                        if (oldAggregatedObj != null)
                                        {
                                            var mapItem = OidMap.GetOidMap(newValue, context.Package.SenderNodeId);
                                            if (mapItem != null)
                                            {
                                                // redirect aggregated object reference to oldAggregatedObj
                                                if (mapItem.Target == null)
                                                    mapItem.NewObject = oldAggregatedObj;
                                                else
                                                    mapItem.Target.Target = oldAggregatedObj;
                                            }
                                        }
                                        else
                                            memberInfo.SetValue(targetObject, newValue);
                                    }

                                    // skip object initialization for objects already exists in app database
                                    if (operationType == ProtocolEventType.InitialValueAssigned
                                        && !((ISessionProvider)targetObject).Session.IsNewObject(targetObject))
                                        break;

                                    memberInfo.SetValue(targetObject, newValue);
                                }
                                break;

                            case ProtocolEventType.ObjectCreated:
                                if (targetObject == null)
                                {
                                    var reference = context.PackageRecord.AuditedObject;
                                    var className = reference.ClassName;
                                    var classType = objectSpace.TypesInfo.FindTypeInfo(className).Type;

                                    targetObject = objectSpace.CreateObject(classType);
                                    OidMap.CreateOidMap(objectSpace, reference, senderNodeId, targetObject);
                                }
                                break;

                            case ProtocolEventType.ObjectDeleted:
                                if (targetObject != null)
                                    objectSpace.Delete(targetObject);
                                break;

                            case ProtocolEventType.RemovedFromCollection:
                                if (memberInfo != null && memberInfo.IsAssociationList && oldObject != null)
                                {
                                    var collObj = memberInfo.GetValue(targetObject);
                                    if (collObj != null)
                                    {
                                        if(collObj is XPBaseCollection)
                                        {
                                            var collection = (XPBaseCollection) collObj;
                                            if (collection.Cast<object>().Contains(oldObject))
                                                collection.BaseRemove(oldObject);
                                        }
                                        else if(collObj.GetType().GetInterface("IList") != null)
                                        {
                                            var list = (IList) collObj;
                                            if(list.Contains(oldObject))
                                                list.Remove(oldObject);
                                        }
                                    }
                                }
                                break;
                        }
                    }
                }
            }

            Owner.DoAfterLoadRecord(args);
        }
        /// <summary>
        /// Resolves the collisions.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="oldObject">The old object.</param>
        /// <param name="newObjectShouldExists">if set to <c>true</c> [new object should exists].</param>
        /// <param name="newObject">The new object.</param>
        /// <param name="operationType">Type of the operation.</param>
        /// <param name="oldObjectShouldExists">if set to <c>true</c> [old object should exists].</param>
        /// <param name="targetObject">The target object.</param>
        /// <param name="memberInfo">The member info.</param>
        /// <param name="propertyIsEmpty">if set to <c>true</c> [property is empty].</param>
        /// <returns></returns>
        private CollisionResult resolveCollisions(LoadPackageRecordContext context, object oldObject,
                                                  bool newObjectShouldExists, object newObject,
                                                  ProtocolEventType operationType,
                                                  bool oldObjectShouldExists, object targetObject,
                                                  XPMemberInfo memberInfo, bool propertyIsEmpty)
        {
            var replres = CollisionResult.Default;

            if (operationType == ProtocolEventType.ObjectCreated && targetObject != null)
                replres = resolveReplicationCollision(context,
                                                      CollisionType.TargetObjectAlreadyExists, targetObject);

            if (operationType != ProtocolEventType.ObjectCreated && targetObject == null)
                replres = resolveReplicationCollision(context,
                                                      CollisionType.TargetObjectIsNotFound);

            if (!propertyIsEmpty && memberInfo == null)
                replres = resolveReplicationCollision(context,
                                                      CollisionType.MemberIsNotFound, targetObject);

            if (!propertyIsEmpty && memberInfo != null && !memberInfo.IsAssociationList && memberInfo.IsReadOnly)
                replres = resolveReplicationCollision(context,
                                                      CollisionType.ChangeReadOnlyMember, targetObject);

            if (oldObjectShouldExists && oldObject == null)
                replres = resolveReplicationCollision(context,
                                                      CollisionType.OldObjectIsNotFound, targetObject);

            if (newObjectShouldExists && newObject == null)
                replres = resolveReplicationCollision(context,
                                                      CollisionType.NewObjectIsNotFound, targetObject);
            return replres;
        }