/// <summary>
        /// 
        /// </summary>
        /// <param name="inRequest"></param>
        /// <param name="mode"></param>
        /// <param name="authorizedLayerSet"></param>
        /// <returns></returns>
        private IMessage FilterLayerIds ( IMessage inRequest, SoapRequestType mode, HashSet<String> authorizedLayerSet )
        {
            // 1. Find the index of the layers parameter
            // 2. Get the value for the interested parameter
            // 3. Manipulate it
            // 4. Put it back into IMessage

            int idx = -1;
            IXMLSerializeData inRequestData = inRequest.Parameters;
            try
            {
                idx = inRequestData.Find("LayerIDs");
            }
            catch (Exception ignore)
            {
            }

            LongArray layerIdInLA = null;
            if (idx >= 0)
            {
                // Get all the requested layers
                layerIdInLA = (LongArray)inRequestData.GetObject(idx, inRequest.NamespaceURI, "ArrayOfInt");

                // Perform filtering based on access to different layers. 
                // Remove restricted ids in-place
                for (int i = layerIdInLA.Count - 1; i >= 0; i--)
                {

                    if (!authorizedLayerSet.Contains(layerIdInLA.Element[i].ToString()))
                    {
                        layerIdInLA.Remove(i);
                    }
                }
            }
            else //no LayerIDs specified, attaching authorized layer list instead
            {
                layerIdInLA = new LongArrayClass();
                foreach (var goodLayerId in authorizedLayerSet)
                {
                    layerIdInLA.Add(Int32.Parse(goodLayerId));
                }
                inRequestData.AddObject("LayerIDs", layerIdInLA);
            }

            // If binary request we dont have to create and copy in a new Message object
            if (mode == SoapRequestType.Binary)
            {
                return inRequest;
            }

            // Create new request message
            IMessage modifiedInRequest = _SoapSOIHelper.CreateNewIMessage(inRequest);
            IXMLSerializeData modifiedInRequestData = modifiedInRequest.Parameters;

            // Put all parameters back in IMessage
            for (int i = 0; i < inRequestData.Count; i++)
            {
                if (_SoapSOIHelper.GetSoapOperationParameterName(inRequest.Name, i).Equals("LayerIDs", StringComparison.CurrentCultureIgnoreCase))
                {
                    // Add the modified MapDescription
                    _SoapSOIHelper.AddObjectToXMLSerializeData(_SoapSOIHelper.GetSoapOperationParameterName(inRequest.Name, i),
                      layerIdInLA, _SoapSOIHelper.GetSoapOperationParameterTypeName(inRequest.Name, i), modifiedInRequestData);
                }
                else
                {
                    /*
                     * Add other parameters as is. Here we are using the SOI helper to add and get parameters
                     * because we don't care about the type we just want to copy from one IMessage object to
                     * another.
                     */
                    _SoapSOIHelper.AddObjectToXMLSerializeData(
                      _SoapSOIHelper.GetSoapOperationParameterName(inRequest.Name, i),
                      _SoapSOIHelper.GetObjectFromXMLSerializeData(i, inRequest.NamespaceURI,
                          _SoapSOIHelper.GetSoapOperationParameterTypeName(inRequest.Name, i), inRequestData),
                      _SoapSOIHelper.GetSoapOperationParameterTypeName(inRequest.Name, i), modifiedInRequestData);
                }
            }

            return modifiedInRequest;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="inRequest"></param>
        /// <param name="mode"></param>
        /// <param name="authorizedLayerSet"></param>
        /// <returns></returns>
        private IMessage FilterGetServerInfoResponse ( IMessage inRequest, SoapRequestType mode, HashSet<string> authorizedLayerSet )
        {
            int idx = -1;
            IXMLSerializeData inRequestData = inRequest.Parameters;
            idx = inRequestData.Find("Result");

            // Get MapServerInfo
            MapServerInfo mapServerInfo = (MapServerInfo)inRequestData.GetObject(idx, inRequest.NamespaceURI,
                    "MapServerInfo");

            // Perform filtering based on access to different layers
            IMapLayerInfos layerInfos = mapServerInfo.MapLayerInfos;
            for (int i = layerInfos.Count - 1; i >= 0; i--)
            {
                if (!authorizedLayerSet.Contains(layerInfos.Element[i].ID.ToString()))
                {
                    layerInfos.Remove(i);
                }
            }

            IMapDescription mapDescription = mapServerInfo.DefaultMapDescription;
            ILayerDescriptions lds = mapDescription.LayerDescriptions;
            for (int i = lds.Count - 1; i >= 0; i--)
            {
                if (!authorizedLayerSet.Contains(lds.Element[i].ID.ToString()))
                {
                    lds.Remove(i);
                }
            }

            // If binary request we don't have to create and copy in a new Message object
            if (mode == SoapRequestType.Binary)
            {
                return inRequest;
            }

            // Create new request message
            IMessage modifiedInRequest = _SoapSOIHelper.CreateNewIMessage(inRequest);
            IXMLSerializeData modifiedInRequestData = modifiedInRequest.Parameters;

            // Put all parameters back in IMessage
            for (int i = 0; i < inRequestData.Count; i++)
            {
                if (_SoapSOIHelper.GetSoapOperationParameterName(inRequest.Name, i).Equals("Result", StringComparison.CurrentCultureIgnoreCase))
                {
                    // Add the modified MapDescription
                    modifiedInRequestData.AddObject(_SoapSOIHelper.GetSoapOperationParameterName(inRequest.Name, i), mapServerInfo);
                }
                else
                {
                    /*
                     * Add other parameters as is. Here we are using the SOI helper to add and get parameters
                     * because we don't care about the type we just want to copy from one IMessage object to
                     * another.
                     */
                    modifiedInRequestData.AddObject(
                        _SoapSOIHelper.GetSoapOperationParameterName(inRequest.Name, i),
                        inRequestData.GetObject(i, inRequest.NamespaceURI,
                            _SoapSOIHelper.GetSoapOperationParameterTypeName(inRequest.Name, i)));
                }
            }

            return modifiedInRequest;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="inRequest"></param>
        /// <param name="mode"></param>
        /// <returns></returns>
        private SoapRequest FilterSoapRequest ( IMessage inRequest, SoapRequestType mode, HashSet<string> authorizedLayerSet )
        {
            // Get operation name
            String name = inRequest.Name;

            // Apply filter only on those operations we care about
            var nameInLowerCase = name.ToLower();
            switch (nameInLowerCase)
            {
                case "find":
                    inRequest = FilterLayerIds(inRequest, mode, authorizedLayerSet);
                    break;
                case "exportmapimage":
                    inRequest = FilterMapDescription(inRequest, mode, authorizedLayerSet);
                    break;
                case "identify":
                    inRequest = FilterLayerIds(inRequest, mode, authorizedLayerSet);
                    break;
                case "getlegendinfo":
                    inRequest = FilterLayerIds(inRequest, mode, authorizedLayerSet);
                    break;
                case "getserverinforesponse":
                    inRequest = FilterGetServerInfoResponse(inRequest, mode, authorizedLayerSet);
                    break;
            }

            return SoapRequestFactory.Create(mode, inRequest);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="inRequest"></param>
        /// <param name="mode"></param>
        /// <param name="authorizedLayerSet"></param>
        /// <returns></returns>
        private IMessage FilterMapDescription ( IMessage inRequest, SoapRequestType mode, HashSet<string> authorizedLayerSet )
        {
            // 1. Find the index of the MapDescription parameter
            // 2. Get the value for the interested parameter
            // 3. Manipulate it
            // 4. Put it back into IMessage

            // Get the parameters out from the request object
            int idx = -1;
            IXMLSerializeData inRequestData = inRequest.Parameters;
            idx = inRequestData.Find("MapDescription");

            MapDescription md =
                (MapDescription)inRequestData.GetObject(idx, inRequest.NamespaceURI,
                    _SoapSOIHelper.GetSoapOperationParameterTypeName(inRequest.Name, idx));
            // Manipulate the MapDescription to perform layer level security
            ILayerDescriptions lds = md.LayerDescriptions;
            for (int i = 0; i < lds.Count; i++)
            {
                ILayerDescription ld = lds.Element[i];
                if (!authorizedLayerSet.Contains(ld.ID.ToString()))
                {
                    ld.Visible = false;
                }
            }

            // If binary request we dont have to create and copy in a new Message object
            if (mode == SoapRequestType.Binary)
            {
                return inRequest;
            }

            // Create new request message
            IMessage modifiedInRequest = _SoapSOIHelper.CreateNewIMessage(inRequest);
            IXMLSerializeData modifiedInRequestData = modifiedInRequest.Parameters;

            // Put all parameters back in IMessage
            for (int i = 0; i < inRequestData.Count; i++)
            {
                if (_SoapSOIHelper.GetSoapOperationParameterName(inRequest.Name, i).Equals("MapDescription", StringComparison.CurrentCultureIgnoreCase))
                {
                    // Add the modified MapDescription
                    modifiedInRequestData.AddObject(_SoapSOIHelper.GetSoapOperationParameterName(inRequest.Name, i), md);
                }
                else
                {
                    /*
                     * Add other parameters as is. Here we are using the SOI helper to add and get parameters
                     * because we don't care about the type we just want to copy from one IMessage object to
                     * another.
                     */
                    modifiedInRequestData.AddObject(
                        _SoapSOIHelper.GetSoapOperationParameterName(inRequest.Name, i),
                        inRequestData.GetObject(i, inRequest.NamespaceURI,
                            _SoapSOIHelper.GetSoapOperationParameterTypeName(inRequest.Name, i)));
                }
            }

            return modifiedInRequest;
        }