internal void GenerateUpdateCollectionMessage(int updateType, DataDestination dataDestination, Sequence sequence, int position, Identity identity)
		{
			UpdateCollectionMessage updateCollectionMessage = CreateUpdateCollectionMessage(dataDestination, sequence);
			updateCollectionMessage.AddItemIdentityChange(updateType, position, identity);
            if (updateCollectionMessage.collectionId != null)
                _updateCollectionMessages[updateCollectionMessage.collectionId] = updateCollectionMessage;
            else
            {
                //without fill parameters
                _updateCollectionMessages[new object[0]] = updateCollectionMessage;
            }
		}
		private UpdateCollectionMessage CreateUpdateCollectionMessage(DataDestination dataDestination, Sequence sequence)
		{
			UpdateCollectionMessage updateCollectionMessage = new UpdateCollectionMessage();
			updateCollectionMessage.clientId = this.ClientId;
			updateCollectionMessage.updateMode = UpdateCollectionMessage.ServerUpdate;
			// The unique identifier for the collection that was updated. For a collection filled with the 
			// DataService.fill() method this contains an Array of the parameters specified.
			updateCollectionMessage.collectionId = sequence.Parameters;
			updateCollectionMessage.destination = dataDestination.Id;
			updateCollectionMessage.correlationId = this.CorrelationId;
			updateCollectionMessage.messageId = "srv:" + Guid.NewGuid().ToString("D") + ":" + _idCounter.ToString();
			System.Threading.Interlocked.Increment(ref _idCounter);

			return updateCollectionMessage;
		}
		private UpdateCollectionMessage CreateUpdateCollectionMessage(DataMessage dataMessage, Sequence sequence, Identity identity, int position, int updateMode)
		{
			UpdateCollectionMessage updateCollectionMessage = new UpdateCollectionMessage();
			// The unique identifier for the collection that was updated. For a collection filled with the 
			// DataService.fill() method this contains an Array of the parameters specified.
			updateCollectionMessage.collectionId = sequence.Parameters;
			updateCollectionMessage.destination = dataMessage.destination;
			updateCollectionMessage.replace = false;
			updateCollectionMessage.updateMode = updateMode;
			updateCollectionMessage.messageId = "srv:" + Guid.NewGuid().ToString("D") + ":0";
			updateCollectionMessage.correlationId = dataMessage.correlationId;

			UpdateCollectionRange updateCollectionRange = new UpdateCollectionRange();
			// An Array of identity objects that represent which items were either deleted or inserted in the 
			// associated collection starting at the position indicated by the position property
			updateCollectionRange.identities = new object[1];
			//(updateCollectionRange.identities as IList).Add( identity );
			(updateCollectionRange.identities as object[])[0] = identity;
			updateCollectionRange.updateType = UpdateCollectionRange.InsertIntoCollection;
			updateCollectionRange.position = position;
					
			//ArrayList body = new ArrayList();
			//body.Add(updateCollectionRange);
			object[] body = new object[1]; body[0] = updateCollectionRange;
			updateCollectionMessage.body = body;
			return updateCollectionMessage;
		}
		public PagedMessage GetPagedMessage(DataMessage dataMessage, Sequence sequence)
		{
            int pageSize = (int)dataMessage.headers[DataMessage.PageSizeHeader];
            int pageIndex = 0;
            if (dataMessage.headers.ContainsKey(DataMessage.PageIndexHeader))
                pageIndex = (int)dataMessage.headers[DataMessage.PageIndexHeader];
            pageIndex = Math.Max(0, pageIndex);//negative pageIndex???
            int pageCount = (int)Math.Ceiling((double)sequence.Size / pageSize);
            int pageStart = pageIndex * pageSize;
            int pageEnd = Math.Min(pageStart + pageSize, sequence.Size);

            PagedMessage pagedMessage = new PagedMessage();
            pagedMessage.pageIndex = pageIndex;
            pagedMessage.pageCount = pageCount;
            pagedMessage.sequenceSize = sequence.Size;
            pagedMessage.sequenceId = sequence.Id;
            object[] pagedResult = new object[pageEnd - pageStart];
            lock (_objLock)
            {
                for (int i = pageStart; i < pageEnd; i++)
                {
                    Identity identity = sequence[i];
                    //pagedResult.Add( _itemIdToItemHash[identity] );
                    if (_itemIdToItemHash.Contains(identity))
                        pagedResult[i - pageStart] = (_itemIdToItemHash[identity] as ItemWrapper).Instance;
                }
            }
            pagedMessage.body = pagedResult;
            pagedMessage.destination = dataMessage.destination;
            pagedMessage.dataMessage = dataMessage;
            return pagedMessage;
		}
		public SequencedMessage GetSequencedMessage(DataMessage dataMessage, Sequence sequence)
		{
			if( dataMessage.headers != null && dataMessage.headers.ContainsKey(DataMessage.PageSizeHeader) )
			{
				return GetPagedMessage(dataMessage, sequence);
			}
			else
			{
				SequencedMessage sequencedMessage = new SequencedMessage();
				sequencedMessage.destination = dataMessage.destination;
				sequencedMessage.sequenceId = sequence.Id;
				sequencedMessage.sequenceSize = sequence.Size;
				//object[] body = new object[result.Count];
				//result.CopyTo(body, 0);
				object[] body = new object[sequence.Count];
				lock(_objLock)
				{
					for(int i = 0; i < sequence.Count; i++)
					{
						ItemWrapper itemWrapper = GetItem(sequence[i]) as ItemWrapper;
						if( itemWrapper != null )
							body[i] = itemWrapper.Instance;
					}
				}
				sequencedMessage.body = body;
				sequencedMessage.sequenceProxies = null;
				sequencedMessage.dataMessage = dataMessage;

				sequencedMessage.messageId = dataMessage.messageId;
				sequencedMessage.clientId = dataMessage.clientId;
				sequencedMessage.correlationId = dataMessage.messageId;
				//dataMessage.identity = new Hashtable(0);

				return sequencedMessage;
			}
		}
		public void RemoveSubscriberFromSequence(string clientId, Sequence sequence)
		{
			if( sequence != null )
			{
				if( log.IsDebugEnabled )
					log.Debug(__Res.GetString(__Res.SequenceManager_RemoveSubscriberSeq, clientId, sequence.Id));
				lock(_objLock)
				{
					if( _clientIdToSequenceHash.Contains(clientId) )
					{
						ArrayList sequences = _clientIdToSequenceHash[clientId] as ArrayList;
						for(int i = 0; i < sequences.Count; i++)
						{
							Sequence sequenceTmp = sequences[i] as Sequence;
							if( sequence == sequenceTmp )
							{
								sequence.RemoveSubscriber(clientId);
								//Delete the sequence if there are no subscribers left
								if( sequence.SubscriberCount == 0 )
								{
									if( log.IsDebugEnabled )
                                        log.Debug(__Res.GetString(__Res.SequenceManager_RemoveEmptySeq, sequence.Id));
									RemoveSequence(sequence.Id);
								}
								sequences.RemoveAt(i);//remove this sequence from client's list
								break;
							}
						}
					}
				}
			}
		}
		void ApplyUpdateCollectionMessage(Sequence sequence, UpdateCollectionMessage updateCollectionMessage)
		{
			IList updateCollectionRanges = updateCollectionMessage.body as IList;
			for(int k = 0; k < updateCollectionRanges.Count; k++)
			{
				UpdateCollectionRange updateCollectionRange = updateCollectionRanges[k] as UpdateCollectionRange;
				int insertCount = 0;
				for(int l = 0; l < updateCollectionRange.identities.Length; l++)
				{
					Identity identity = updateCollectionRange.identities[l] as Identity;
					if( identity == null )
					{
                        identity = new Identity(updateCollectionRange.identities[l] as IDictionary);
					}
					if( updateCollectionRange.updateType == UpdateCollectionRange.InsertIntoCollection )
					{
						this.AddIdentityToSequence(sequence, updateCollectionRange.position + insertCount, identity, null);
						insertCount++;
					}
					if( updateCollectionRange.updateType == UpdateCollectionRange.DeleteFromCollection )
						this.RemoveIdentityFromSequence(sequence, identity, updateCollectionRange.position, null);
				}
			}
		}
		public Sequence RefreshSequence(Sequence sequence, DataMessage dataMessage, object item, DataServiceTransaction dataServiceTransaction)
		{
            if (sequence.Parameters == null)
                return sequence;
			DotNetAdapter dotNetAdapter = _dataDestination.ServiceAdapter as DotNetAdapter;
			if( dotNetAdapter != null )
			{
				bool isCreate = (dataMessage.operation == DataMessage.CreateOperation || dataMessage.operation == DataMessage.CreateAndSequenceOperation);
				int fill = dotNetAdapter.RefreshFill( sequence.Parameters, item, isCreate );
				switch(fill)
				{
					case Assembler.ExecuteFill:
					{
						IList parameters = sequence.Parameters;
                        //if (parameters == null)
                        //    parameters = new object[0];
						DataMessage fillDataMessage = new DataMessage();
						fillDataMessage.clientId = dataMessage.clientId;
						fillDataMessage.operation = DataMessage.FillOperation;
                        fillDataMessage.body = parameters != null ? parameters : new object[0];
						IList result = _dataDestination.ServiceAdapter.Invoke(fillDataMessage) as IList;
                        return CreateSequence(dataMessage.clientId as string, result, parameters, dataServiceTransaction);
					} 
					case Assembler.AppendToFill:
					{
						Identity identity = Identity.GetIdentity(item, _dataDestination);
						if( !sequence.Contains(identity) )
							AddIdentityToSequence(sequence, identity, dataServiceTransaction);
                        _itemIdToItemHash[identity] = new ItemWrapper(item);
					}
						break;
					case Assembler.RemoveFromFill:
					{
						Identity identity = Identity.GetIdentity(item, _dataDestination);
						if( sequence.Contains(identity) )
							RemoveIdentityFromSequence(sequence, identity, dataServiceTransaction);
					}
						break;
					case Assembler.DoNotExecuteFill:
						break;
				}
			}
			return sequence;
		}
		public Sequence CreateSequence(string clientId, IList result, IList parameters, DataServiceTransaction dataServiceTransaction)
		{
			Sequence sequence = null;
			Identity[] identities = new Identity[result.Count];

			lock(_objLock)
			{
				for(int i = 0; i < identities.Length; i++)
				{
					if( result[i] != null )
					{
						Identity identity = Identity.GetIdentity(result[i], _dataDestination);
						identities[i] = identity;
						if( ! _itemIdToItemHash.ContainsKey(identity) )
							_itemIdToItemHash.Add(identity, new ItemWrapper(result[i]));
						else
						{
							ItemWrapper itemWrapper = _itemIdToItemHash[identity] as ItemWrapper;
							itemWrapper.Instance = result[i];
						}
					}
				}
				//Lookup existing sequence
                if (parameters != null)
                {
                    if (_parametersToSequenceIdHash.Contains(parameters))
                        sequence = _parametersToSequenceIdHash[parameters] as Sequence;
                }
                else
                {
                    IDictionary sequenceIdMap = _itemIdToSequenceIdMapHash[identities[0]] as IDictionary;
                    if (sequenceIdMap != null)
                    {
                        foreach (Sequence sequenceTmp in sequenceIdMap.Values)
                        {
                            if (sequenceTmp.Parameters == null)
                            {
                                sequence = sequenceTmp;
                                break;
                            }
                        }
                    }
                }
                //if (parameters == null)
                //    parameters = new ArrayList();
				
				if( sequence == null )
				{
					sequence = new Sequence();
					sequence.Id = sequence.GetHashCode();

                    object[] parametersArray = null;
                    if (parameters != null)
                    {
                        parametersArray = new object[parameters.Count];
                        parameters.CopyTo(parametersArray, 0);
                        sequence.Parameters = parametersArray;
                        _parametersToSequenceIdHash[parameters] = sequence;
                    }

					for(int i = 0; i < identities.Length; i++)
					{
						Identity identity = identities[i];
						AddIdentityToSequence(sequence, identity, dataServiceTransaction);
					}

					_sequenceIdToSequenceHash[sequence.Id] = sequence;

					if( log.IsDebugEnabled )
						log.Debug(__Res.GetString(__Res.SequenceManager_CreateSeq, sequence.Id, clientId));

				}
				else
				{
					for(int i = 0; i < identities.Length; i++)
					{
						Identity identity = identities[i];
						Identity existingIdentity = null;
						if( i < sequence.Count )
							existingIdentity = sequence[i];
						if( !identity.Equals(existingIdentity) )
						{
							//Identity not found in sequence
							if( !sequence.Contains(identity) )
							{
								int position = AddIdentityToSequence(sequence, identity, dataServiceTransaction);
							}
						}
					}
				}
				sequence.AddSubscriber(clientId);
				ArrayList sequences;
				if( _clientIdToSequenceHash.Contains(clientId) )
					sequences = _clientIdToSequenceHash[clientId] as ArrayList;
				else
				{
					sequences = new ArrayList();
					_clientIdToSequenceHash[clientId] = sequences;
				}
				if( !sequences.Contains(sequence) )
					sequences.Add(sequence);
			}
			return sequence;
		}
		public void RemoveIdentityFromSequence(Sequence sequence, Identity identity, int position, DataServiceTransaction dataServiceTransaction)
		{
			if( position == -1 )
				return;
			lock(_objLock)
			{
                IDictionary sequenceIdMap = _itemIdToSequenceIdMapHash[identity] as IDictionary;
                if (sequenceIdMap != null)
                {
                    sequenceIdMap.Remove(sequence.Id);
                    //Release the item if it does'n occur in any sequence
                    if (sequenceIdMap.Count == 0)
                    {
                        _itemIdToItemHash.Remove(identity);
                        _itemIdToSequenceIdMapHash.Remove(identity);
                    }
                    if (sequence[position].Equals(identity))
                        sequence.RemoveAt(position);
                    else
                        sequence.Remove(identity);

                    if (dataServiceTransaction != null)
                        dataServiceTransaction.GenerateUpdateCollectionMessage(UpdateCollectionRange.DeleteFromCollection, _dataDestination, sequence, position, identity);
                }
                else
                {
                    _itemIdToItemHash.Remove(identity);
                    sequence.Remove(identity);
                }
			}
		}
		public void RemoveIdentityFromSequence(Sequence sequence, Identity identity, DataServiceTransaction dataServiceTransaction)
		{
			RemoveIdentityFromSequence(sequence, identity, sequence.IndexOf(identity), dataServiceTransaction);
		}
		public int AddIdentityToSequence(Sequence sequence, Identity identity, DataServiceTransaction dataServiceTransaction)
		{
			return AddIdentityToSequence(sequence, -1, identity, dataServiceTransaction);
		}
		public int AddIdentityToSequence(Sequence sequence, int position, Identity identity, DataServiceTransaction dataServiceTransaction)
		{
			lock(_objLock)
			{
				if(position == -1 || position > sequence.Size)
					position = sequence.Add(identity);
				else
					sequence.Insert(position, identity);

                IDictionary sequenceIdMap = _itemIdToSequenceIdMapHash[identity] as IDictionary;
				if( sequenceIdMap == null )
				{
					sequenceIdMap = new Hashtable();
					_itemIdToSequenceIdMapHash[identity] = sequenceIdMap;
				}
				sequenceIdMap[sequence.Id] = sequence;

				if(dataServiceTransaction != null)
					dataServiceTransaction.GenerateUpdateCollectionMessage(UpdateCollectionRange.InsertIntoCollection, _dataDestination, sequence, position, identity);

				return position;
			}
		}