// TODO: Implement
        /*

        private SIF_Request createSIF_Request( ElementDef objectType, String refId, Zone zone )
        {
           SIF_Request request = new SIF_Request();
           request.getHeader().setSIF_MsgId( MSG_GUID );
           request.getHeader().setSIF_SourceId( "foo" );
           request.setSIF_MaxBufferSize("32768");
           request.setSIF_Version( ADK.getSIFVersion().toString() );
           Query query = new Query(objectType);
           query.addCondition(SifDtd.SIF_REPORTOBJECT_REFID, Condition.EQ, refId);

           SIF_Query q = SIFPrimitives.createSIF_Query(query, zone);
           SIF_QueryObject sqo = new SIF_QueryObject();
           sqo.setObjectName( objectType.name() );

           q.setSIF_QueryObject(sqo);
           request.setSIF_Query(q);

           return request;
        }

         */
        private SIF_Response createSIF_Response(IElementDef objType, bool storeInRequestCache, ISerializable stateObject)
        {
            SIF_Request req = createSIF_Request(objType);

             if (storeInRequestCache)
             {
            Query q = new Query(objType);
            q.UserData = stateObject;
            RequestCache.GetInstance(fAgent).StoreRequestInfo(req, q, fZone);
             }

             SIF_Response resp = new SIF_Response();
             resp.SIF_RequestMsgId = req.Header.SIF_MsgId;
             SIF_ObjectData sod = new SIF_ObjectData();
             resp.SIF_ObjectData = sod;

             Object responseObject = null;
             try
             {
            responseObject = ClassFactory.CreateInstance(objType.FQClassName, false);
             }
             catch (Exception cfe)
             {
            throw new AdkException("Unable to create instance of " + objType.Name, fZone, cfe);
             }

             sod.AddChild((SifElement)responseObject);
             return resp;
        }
 private void assertRequestCacheCleared(SIF_Response r)
 {
     // Now the RequestCache should no longer contain the specified object
      IRequestInfo inf = RequestCache.GetInstance(fAgent).LookupRequestInfo(r.SIF_RequestMsgId, fZone);
      Assert.IsNull(inf, "RequestInfo should be removed from the cache");
 }
        /// <summary>  Find the QueryResults object for a zone by searching up the message
        /// dispatching chain until a Zone, Topic, or Agent is found with a registered
        /// QueryResults implementation.
        /// 
        /// </summary>
        /// <param name="rsp">The SIF_Response message (if a SIF_Response was received).
        /// Either rsp or req must be specified, but not both.
        /// </param>
        /// <param name="req">The SIF_Request message (if a SIF_Request is being sent).
        /// Either rsp or req must be specified, but not both.
        /// </param>
        /// <param name="query">Only applicable when <i>req</i> is non-null: The Query
        /// associated with the SIF_Request
        /// </param>
        /// <param name="zone">The Zone to begin the search at
        /// </param>
        internal IQueryResults getQueryResultsTarget(SIF_Response rsp,
                                                      SIF_Request req,
                                                      IElementDef objType,
                                                      Query query,
                                                      IZone zone)
        {
            //
            //  - First check TrackQueryResults for a matching pending request
            //  - Next check the Topic, the Zone, and finally the Agent. The
            //    message is dispatched to the first one that results a
            //    QueryResults object
            //
            IQueryResults target = null;
            SifContext context = null;

            if (req != null)
            {
                //  First check TrackQueryResults
                string reqId = req.MsgId;

                // TODO: Implement SMB later
                //				TrackQueryResults tracker = (TrackQueryResults) TrackQueryResultsImpl.sRequestQueries[query];
                //				if (tracker != null)
                //				{
                //					TrackQueryResultsImpl.sRequestQueries.Remove( query );
                //					target = tracker;
                //				}
                //				else
                //				{
                SIF_Query q = req.SIF_Query;
                if (q == null)
                {
                    throw new SifException
                        (SifErrorCategoryCode.Xml, SifErrorCodes.XML_MISSING_MANDATORY_ELEMENT_6,
                          "SIF_Request message missing mandatory element", "SIF_Query is required",
                          fZone);
                }

                SIF_QueryObject qo = q.SIF_QueryObject;
                if (qo == null)
                {
                    throw new SifException
                        (SifErrorCategoryCode.Xml, SifErrorCodes.XML_MISSING_MANDATORY_ELEMENT_6,
                          "SIF_Request message missing mandatory element",
                          "SIF_QueryObject is required", fZone);
                }

                objType = Adk.Dtd.LookupElementDef(qo.ObjectName);
                if (objType == null)
                {
                    throw new SifException
                        (SifErrorCategoryCode.RequestResponse, SifErrorCodes.REQRSP_INVALID_OBJ_3,
                          "Agent does not support this object type", qo.ObjectName, fZone);
                }
                // Check to see if the Context is supported
                // TODO: Determine if a SIFException should be thrown at this point?
                try
                {

                    context = req.SifContexts[0];
                }
                catch (AdkNotSupportedException contextNotSupported)
                {
                    throw new SifException(
                            SifErrorCategoryCode.Generic,
                            SifErrorCodes.GENERIC_CONTEXT_NOT_SUPPORTED_4,
                            contextNotSupported.Message, fZone);
                }

            }
            else if (rsp != null)
            {
                // TODO Implement SMB
                //				//  First check TrackQueryResults object to see if it is expecting
                //				//  to be called for this SIF_Response
                //				string reqId = rsp.SIF_RequestMsgId;
                //				
                //				TrackQueryResults tracker = (TrackQueryResults) TrackQueryResultsImpl.sRequestMsgIds[reqId];
                //				if (tracker != null)
                //				{
                //					//  Dispatch to the TrackQueryResults object
                //					target = tracker;
                //				}

                // Check to see if the Context is supported
                // TODO: Determine if a SIFException should be thrown at this point?
                try
                {
                    context = rsp.SifContexts[0];
                }
                catch (AdkNotSupportedException contextNotSupported)
                {
                    throw new SifException(
                            SifErrorCategoryCode.Generic,
                            SifErrorCodes.GENERIC_CONTEXT_NOT_SUPPORTED_4,
                            contextNotSupported.Message, fZone);
                }


            }
            else
            {
                throw new ArgumentException
                    (
                    "A SIF_Request or SIF_Response object must be passed to getQueryResultsTarget");
            }

            if (target == null)
            {
                TopicImpl topic = (TopicImpl)fZone.Agent.TopicFactory.LookupInstance(objType, context);
                if (topic != null)
                {
                    target = topic.fQueryResults;
                }


                if (target == null)
                {
                    //  Next try the Zone...
                    target = fZone.GetQueryResults(context, objType);
                }
                if (target == null)
                {
                    //  Finally, try the Agent...
                    target = fZone.Agent.GetQueryResults(context, objType);
                }
            }

            return target;
        }
        /// <summary>  Dispatch a SIF_Response.
        /// 
        /// SIF_Response messages are dispatched as follows:
        /// 
        /// <ul>
        /// <li>
        /// If a TrackQueryResults object issued the original SIF_Request
        /// during this agent session (i.e. the agent process has not
        /// terminated since the SIF_Request was issued), the response is
        /// dispatched to that TrackQueryResults object via its QueryResults
        /// interface.
        /// </li>
        /// <li>
        /// If a Topic exists for the data type associated with the
        /// SIF_Response, it is dispatched to the QueryResults object
        /// registered with that Topic.
        /// </li>
        /// <li>
        /// If no Topic exists for the data type associated with the
        /// SIF_Response, it is dispatched to the QueryResults object
        /// registered with the Zone from which the SIF_Response was
        /// received.
        /// </li>
        /// </ul>
        /// 
        /// <b>SIF_ZoneStatus</b> is handled specially. When Zone.awaitingZoneStatus
        /// returns true, the agent is blocking on a call to Zone.getZoneStatus().
        /// In this case, the SIF_ZoneStatus object is routed directly to the Zone
        /// object instead of being dispatched via the usual QueryResults mechanism.
        /// 
        /// </summary>
        private void dispatchResponse(SIF_Response rsp)
        {
            //	block thread until Zone.Query() has completed in case it is in the
            //	midst of a SIF_Request. This is done to ensure that we don't receive
            //	the SIF_Response from the zone before the ADK and agent have finished
            //	with the SIF_Request in Zone.Query()
            fZone.WaitForRequestsToComplete();
            bool retry = false;
            IRequestInfo reqInfo = null;
            AdkException cacheErr = null;

            try
            {
                try
                {
                    reqInfo = fRequestCache.LookupRequestInfo(rsp.SIF_RequestMsgId, fZone);
                }
                catch (AdkException adke)
                {
                    cacheErr = adke;
                }

#if PROFILED
				if( objType != null ) 
				{
					ProfilerUtils.profileStart( com.OpenADK.sifprofiler.api.OIDs.ADK_SIFRESPONSE_REQUESTOR_MESSAGING.ToString(), Adk.Dtd.LookupElementDef(objType), rsp.MsgId );
				}
#endif

                SIF_Error error = null;
                SIF_ObjectData od = rsp.SIF_ObjectData;
                if (od == null)
                {
                    throw new SifException
                        (
                        SifErrorCategoryCode.Xml,
                        SifErrorCodes.XML_MISSING_MANDATORY_ELEMENT_6,
                        "SIF_Response missing mandatory element",
                        "SIF_ObjectData is a required element of SIF_Response",
                        fZone);
                }

                IList<SifElement> sel = od.GetChildList();
                if (sel.Count < 1)
                {
                    error = rsp.SIF_Error;

                    //
                    //  If the SIF_Response has no SIF_ObjectData elements but does
                    //  have a SIF_Error child, the associated object type can
                    //  only be gotten from the RequestCache, but that had
                    //  failed so try and call the UndeliverableMessageHandler.
                    //
                    if (cacheErr != null || reqInfo == null)
                    {
                        bool handled = false;

                        IUndeliverableMessageHandler errHandler = fZone.ErrorHandler;
                        if (errHandler != null)
                        {
                            SifMessageInfo msginfo = new SifMessageInfo(rsp, fZone);
                            msginfo.SIFRequestInfo = reqInfo;

                            handled = errHandler.OnDispatchError(rsp, fZone, msginfo);

                            //	Notify MessagingListeners...
                            NotifyMessagingListeners_OnMessageProcessed
                                (SifMessageType.SIF_Response, msginfo);
                        }

                        if (!handled)
                        {
                            fZone.Log.Warn
                                (
                                "Received a SIF_Response message with MsgId " + rsp.MsgId +
                                " (for SIF_Request with MsgId " + rsp.SIF_RequestMsgId + ") " +
                                " containing an empty result set or a SIF_Error, but failed to obtain the SIF Data Object" +
                                " type from the RequestCache" +
                                (cacheErr != null ? (" due to an error: " + cacheErr.Message) : ""));
                        }

                        return;
                    }
                }

                string objectType = reqInfo != null ? reqInfo.ObjectType : null;

                if (objectType == null && sel.Count > 0)
                {
                    objectType = sel[0].ElementDef.Tag(rsp.SifVersion);
                }

                if (objectType != null &&
                     (string.Compare(objectType, "SIF_ZoneStatus", true) == 0))
                {
                    //  SIF_ZoneStatus is a special case
                    if (fZone.AwaitingZoneStatus())
                    {
                        fZone.SetZoneStatus((SIF_ZoneStatus)sel[0]);
                        return;
                    }
                }

                if (reqInfo == null)
                {
                    reqInfo = new UnknownRequestInfo(rsp.SIF_RequestMsgId, objectType);
                }

                //  Decide where to send this response
                IQueryResults target =
                    getQueryResultsTarget
                        (rsp, null, Adk.Dtd.LookupElementDef(objectType), null, fZone);
                if (target == null)
                {
                    bool handled = false;
                    IUndeliverableMessageHandler errHandler = fZone.ErrorHandler;
                    if (errHandler != null)
                    {
                        SifMessageInfo msginfo = new SifMessageInfo(rsp, fZone);
                        if (reqInfo != null)
                        {
                            msginfo.SIFRequestInfo = reqInfo;
                        }

                        handled = errHandler.OnDispatchError(rsp, fZone, msginfo);

                        //	Notify MessagingListeners...
                        NotifyMessagingListeners_OnMessageProcessed
                            (SifMessageType.SIF_Response, msginfo);
                    }

                    if (!handled)
                    {
                        fZone.Log.Warn
                            ("Received a SIF_Response message with MsgId " + rsp.MsgId +
                              " (for SIF_Request with MsgId " + rsp.SIF_RequestMsgId +
                              "), but no QueryResults object is registered to handle it or the request was issued by a TrackQueryResults that has timed out");
                    }

                    return;
                }

                //
                //  Dispatch the message...
                //

                IElementDef sifRequestObjectDef = Adk.Dtd.LookupElementDef(objectType);
                DataObjectInputStreamImpl dataStr = DataObjectInputStreamImpl.newInstance();
                dataStr.fObjType = sifRequestObjectDef;

                if (error == null)
                {
                    //  Convert to a SifDataObject array
                    SifDataObject[] data = new SifDataObject[sel.Count];
                    for (int i = 0; i < sel.Count; i++)
                    {
                        data[i] = (SifDataObject)sel[i];
                    }

                    //  Let the QueryResults object process the message
                    dataStr.Data = data;
                }

                SifMessageInfo msgInf = new SifMessageInfo(rsp, fZone);
                msgInf.SIFRequestInfo = reqInfo;
                msgInf.SIFRequestObjectType = sifRequestObjectDef;
                target.OnQueryResults(dataStr, error, fZone, msgInf);

                //	Notify MessagingListeners...
                NotifyMessagingListeners_OnMessageProcessed(SifMessageType.SIF_Response, msgInf);
            }
            catch (AdkException adkEx)
            {
                retry = adkEx.Retry;
                throw;
            }
            catch (Exception thr)
            {
                throw new SifException
                    (
                    SifErrorCategoryCode.Generic,
                    SifErrorCodes.GENERIC_GENERIC_ERROR_1,
                    "Error processing SIF_Response",
                    "Exception in QueryResults message handler: " + thr.ToString(),
                    fZone);
            }
            finally
            {
                // If the reqInfo variable came from the cache, and retry is set to false,
                // remove it from the cache if this is the last packet
                if (!(reqInfo is UnknownRequestInfo) && !retry)
                {
                    String morePackets = rsp.SIF_MorePackets;
                    if (!(morePackets != null && morePackets.ToLower().Equals("yes")))
                    {
                        // remove from the cache
                        fRequestCache.GetRequestInfo(rsp.SIF_RequestMsgId, fZone);
                    }
                }
#if PROFILED
			if( BuildOptions.PROFILED ) {
				if( reqInfo != null ) {
					ProfilerUtils.profileStop();
				}
#endif
            }
        }
        /// <summary>  Calculate the size of a SIF_Response minus the SIF_ObjectData content.</summary>
        protected virtual long CalcEnvelopeSize( ZoneImpl zone )
        {
            long size = 400;

            try {
                SIF_Response rsp = new SIF_Response();
                rsp.SIF_MorePackets = "Yes";
                rsp.SIF_RequestMsgId = fReqId;
                rsp.SIF_PacketNumber = 100000000;
                SIF_ObjectData data = new SIF_ObjectData();
                data.TextValue = " ";
                rsp.SIF_ObjectData = data;

                SIF_Header hdr = rsp.Header;

                hdr.SIF_Timestamp = DateTime.Now;
                hdr.SIF_MsgId = "012345678901234567890123456789012";
                hdr.SIF_SourceId = zone.Agent.Id;
                hdr.SIF_Security = zone.Dispatcher.secureChannel();
                hdr.SIF_DestinationId = fDestId;

                using ( MemoryStream buffer = new MemoryStream() ) {
                    SifWriter writer = new SifWriter( buffer );
                    writer.Write( rsp );
                    writer.Flush();
                    size = buffer.Length + 10;
                    writer.Close();
                    buffer.Close();
                }
            }
            catch( Exception ex ) {
                zone.Log.Warn( "Error calculating packet size: " + ex, ex );
            }

            return size;
        }