/// <summary>
        /// Gets the protocol record recipients.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <returns></returns>
        private List<ReplicationNode> getProtocolRecordRecipients(SaveProtocolRecordParams context)
        {
            var result = new List<ReplicationNode>();
            var reference = context.ProtocolRecord.AuditedObject;
            if (reference != null && reference.Target != null)
            {
                // target object type
                var ti = context.ObjectSpace.TypesInfo.FindTypeInfo(reference.Target.GetType());
                var objType = ti.Type;

                var modelClass = XafDeltaModule.XafApp.Model.Application.BOModel.GetClass(objType);

                // prepare context list for select recipients
                var genType = typeof (RecipientsContext<>).MakeGenericType(objType);

                var sourceNodes = context.AllNodes;
                // for broadcast routing type assume the only recipient node is current (sender) node
                if (Owner.RoutingType == RoutingType.BroadcastRouting)
                    sourceNodes = new List<ReplicationNode> {context.CurrentNode};

                var allContext = (from c in sourceNodes
                                  select createRecipientContext(context, c, genType)).ToList();

                result = selectRecipients(modelClass, allContext).ToList();

                // if protocol record's target object is IReplicable then call it's GetRecipients method
                if (reference.Target is IReplicable)
                    ((IReplicable) reference.Target).GetRecipients(
                        new GetRecipientsEventArgs(context.ProtocolRecord, context.ObjectSpace, result));
            }
            else
            {
                if (Owner.RoutingType == RoutingType.BroadcastRouting)
                    result.Add(context.CurrentNode);
                else
                    result.AddRange(context.AllNodes);
            }

            // raise module's GetRecipients event
            Owner.OnGetRecipients(new GetRecipientsEventArgs(context.ProtocolRecord,
                                                                  context.ObjectSpace, result));
            // remove invalid recipients
            if (Owner.RoutingType != RoutingType.BroadcastRouting)
            {
                result.Remove(context.CurrentNode);
                var disabledNodes = from n in result where n.Disabled select n;
                result = result.Except(disabledNodes).ToList();
            }

            if (context.ProtocolSession is ExternalProtocolSession)
            {
                // prevent package 'reflection' - don't replicate it to nodes already specified in route
                var externalSession = (ExternalProtocolSession) context.ProtocolSession;
                var passedNodes = externalSession.Route.Split('\n');
                result = (from c in result where !passedNodes.Contains(c.NodeId) select c).ToList();
            }

            return result;
        }
 /// <summary>
 /// Creates the recipient context.
 /// </summary>
 /// <param name="context">The context.</param>
 /// <param name="recipient">The recipient.</param>
 /// <param name="genType">Type of the gen.</param>
 /// <returns></returns>
 private RecipientsContextBase createRecipientContext(SaveProtocolRecordParams context,
     ReplicationNode recipient, Type genType)
 {
     var result = (RecipientsContextBase)context.ObjectSpace.CreateObject(genType);
     result.RecipientNode = recipient;
     result.SenderNode = ReplicationNode.GetCurrentNode(context.ObjectSpace);
     result.ProtocolRecord = context.ProtocolRecord;
     /* 11.2.7 */
     result.RoutingType =
         ((IModelReplicationNode)XafDeltaModule.XafApp.Model.GetNode("Replication")).RoutingType;
     return result;
 }
        /// <summary>
        /// Creates the package record.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="recipient">The recipient.</param>
        private void createPackageRecord(SaveProtocolRecordParams context, ReplicationNode recipient)
        {
            // skip protocol records registered before last snapshot
            if (context.ProtocolRecord.ModifiedOn <= recipient.SnapshotDateTime) return;

            // look for recipient package in context.CreatedPackages dictionary.
            // if not found then create new one.
            if(!context.CreatedPackages.ContainsKey(recipient))
            {
                var package = Owner.MessagingService.CreateOutputPackage(context.ObjectSpace,
                    recipient, PackageType.Protocol);
                package.CreateLogRecord(PackageEventType.Created);

                context.CreatedPackages.Add(recipient, new PackageSaveInfo { Package = package });
                context.Worker.ReportProgress(Color.Green, Localizer.PackageCreated, package.FileName);
            }

            // create PackageSession if needed
            var saveInfo = context.CreatedPackages[recipient];

            var packageSession = PackageSession.CreateForProtocolSession(saveInfo.Package.UnitOfWork,
                context.ProtocolSession, context.CurrentNode.NodeId);

            saveInfo.CurrentSession = packageSession;

            // create package protocol record
            PackageRecord.CreateForProtocolRecord(saveInfo.CurrentSession, context.ProtocolRecord, recipient);
        }
 /// <summary>
 /// Creates the packages for prepared data.
 /// </summary>
 /// <param name="rootContext">The root context.</param>
 private void createPackages(SaveProtocolParams rootContext)
 {
     if (rootContext.Worker.CancellationPending) return;
     removeEmptySessions();
     var i = 0;
     foreach (var sessionList in BuildSessionInfo.PacketTargets.Values)
     {
         rootContext.Worker.ReportPercent((double)i++ / (double)BuildSessionInfo.PacketTargets.Values.Count());
         if (rootContext.Worker.CancellationPending) break;
         foreach (var saveSessionInfo in sessionList)
         {
             if (rootContext.Worker.CancellationPending) break;
             var sessionParams = new SaveProtocolSessionParams(rootContext, saveSessionInfo.ProtocolSession);
             foreach (var protocolRecord in saveSessionInfo.ProtocolRecords)
             {
                 if (rootContext.Worker.CancellationPending) break;
                 var recordParams = new SaveProtocolRecordParams(sessionParams, protocolRecord);
                 createPackageRecord(recordParams, saveSessionInfo.TargetNode);
             }
         }
     }
     BuildSessionInfo.PacketTargets.Clear();
 }
 /// <summary>
 /// Specify protocol record recipients.
 /// </summary>
 /// <param name="context">The context.</param>
 private void routeProtocolRecord(SaveProtocolRecordParams context)
 {
     var recipients = getProtocolRecordRecipients(context);
     recipients.ForEach(x => BuildSessionInfo.GetInstance(x,
         context.ProtocolSession).ProtocolRecords.Add(context.ProtocolRecord));
 }