/// <summary>
        /// This method is called whenever an Item has been successfully
        /// reconstituted from the request's entity.
        /// It uses the information curren tin the XmlInventoryCollection
        /// to complete the item's specification, including any implied
        /// context and asset associations.
        /// It fails the request if any necessary item or asset information
        /// is missing.
        /// </summary>

        private void Validate(XmlInventoryCollection ic)
        {
            // There really should be an item present if we've
            // called validate. So fail if there is not.

            if (ic.Item == null)
            {
                Rest.Log.ErrorFormat("{0} Unable to parse request", MsgId);
                ic.Fail(Rest.HttpStatusCodeBadRequest, "request parse error");
            }

            // Every item is required to have a name (via REST anyway)

            if (ic.Item.Name == String.Empty)
            {
                Rest.Log.ErrorFormat("{0} An item name MUST be specified", MsgId);
                ic.Fail(Rest.HttpStatusCodeBadRequest, "item name required");
            }

            // An item MUST have an asset ID. AssetID should never be zero
            // here. It should always get set from the information stored
            // when the Asset element was processed.

            if (ic.Item.AssetID == UUID.Zero)
            {
                Rest.Log.ErrorFormat("{0} Unable to complete request", MsgId);
                Rest.Log.InfoFormat("{0} Asset information is missing", MsgId);
                ic.Fail(Rest.HttpStatusCodeBadRequest, "asset information required");
            }

            // If the item is new, then assign it an ID

            if (ic.Item.ID == UUID.Zero)
            {
                ic.Item.ID = UUID.Random();
            }

            // If the context is being implied, obtain the current
            // folder item's ID. If it was specified explicitly, make
            // sure that theparent folder exists.

            if (ic.Item.Folder == UUID.Zero)
            {
                ic.Item.Folder = ic.Parent();
            }
            else
            {
                bool found = false;

                foreach (InventoryFolderBase parent in ic.rdata.folders)
                {
                    if (parent.ID == ic.Item.Folder)
                    {
                        found = true;
                        break;
                    }
                }

                if (!found)
                {
                    Rest.Log.ErrorFormat("{0} Invalid parent ID ({1}) in item {2}",
                                         MsgId, ic.Item.Folder, ic.Item.ID);
                    ic.Fail(Rest.HttpStatusCodeBadRequest, "parent information required");
                }
            }

            // If this is an inline asset being constructed in the context
            // of a new Item, then use the itm's name here too.

            if (ic.Asset != null)
            {
                if (ic.Asset.Name == String.Empty)
                    ic.Asset.Name = ic.Item.Name;
                if (ic.Asset.Description == String.Empty)
                    ic.Asset.Description = ic.Item.Description;
            }

            // Assign permissions

            ic.Item.CurrentPermissions  = ic.CurrentPermissions;
            ic.Item.EveryOnePermissions = ic.EveryOnePermissions;
            ic.Item.BasePermissions     = ic.BasePermissions;
            ic.Item.GroupPermissions    = ic.GroupPermissions;
            ic.Item.NextPermissions     = ic.NextPermissions;

            // If no type was specified for this item, we can attempt to
            // infer something from the file type maybe. This is NOT as
            // good as having type be specified in the XML.

            if (ic.Item.AssetType == (int) AssetType.Unknown ||
                ic.Item.InvType   == (int) InventoryType.Unknown)
            {
                Rest.Log.DebugFormat("{0} Attempting to infer item type", MsgId);

                string[] parts = ic.Item.Name.Split(Rest.CA_PERIOD);

                if (Rest.DEBUG)
                {
                    for (int i = 0; i < parts.Length; i++)
                    {
                        Rest.Log.DebugFormat("{0} Name part {1} : {2}",
                                             MsgId, i, parts[i]);
                    }
                }

                // If the associated item name is multi-part, then maybe
                // the last part will indicate the item type - if we're
                // lucky.

                if (parts.Length > 1)
                {
                    Rest.Log.DebugFormat("{0} File type is {1}",
                                         MsgId, parts[parts.Length - 1]);
                    switch (parts[parts.Length - 1])
                    {
                    case "jpeg2000" :
                    case "jpeg-2000" :
                    case "jpg2000" :
                    case "jpg-2000" :
                        Rest.Log.DebugFormat("{0} Type {1} inferred",
                                             MsgId, parts[parts.Length-1]);
                        if (ic.Item.AssetType == (int) AssetType.Unknown)
                            ic.Item.AssetType = (int) AssetType.ImageJPEG;
                        if (ic.Item.InvType == (int) InventoryType.Unknown)
                            ic.Item.InvType   = (int) InventoryType.Texture;
                        break;
                    case "jpg" :
                    case "jpeg" :
                        Rest.Log.DebugFormat("{0} Type {1} inferred",
                                             MsgId, parts[parts.Length - 1]);
                        if (ic.Item.AssetType == (int) AssetType.Unknown)
                            ic.Item.AssetType = (int) AssetType.ImageJPEG;
                        if (ic.Item.InvType == (int) InventoryType.Unknown)
                            ic.Item.InvType   = (int) InventoryType.Texture;
                        break;
                    case "tga" :
                        if (parts[parts.Length - 2].IndexOf("_texture") != -1)
                        {
                            if (ic.Item.AssetType == (int) AssetType.Unknown)
                                ic.Item.AssetType = (int) AssetType.TextureTGA;
                            if (ic.Item.InvType == (int) AssetType.Unknown)
                                ic.Item.InvType   = (int) InventoryType.Texture;
                        }
                        else
                        {
                            if (ic.Item.AssetType == (int) AssetType.Unknown)
                                ic.Item.AssetType = (int) AssetType.ImageTGA;
                            if (ic.Item.InvType == (int) InventoryType.Unknown)
                                ic.Item.InvType   = (int) InventoryType.Snapshot;
                        }
                        break;
                    default :
                        Rest.Log.DebugFormat("{0} Asset/Inventory type could not be inferred for {1}",
                               MsgId,ic.Item.Name);
                        break;
                    }
                }
            }

            /// If this is a TGA remember the fact

            if (ic.Item.AssetType == (int) AssetType.TextureTGA ||
                ic.Item.AssetType == (int) AssetType.ImageTGA)
            {
                Bitmap temp;
                Stream tgadata = new MemoryStream(ic.Asset.Data);

                temp = LoadTGAClass.LoadTGA(tgadata);
                try
                {
                    ic.Asset.Data = OpenJPEG.EncodeFromImage(temp, true);
                }
                catch (DllNotFoundException)
                {
                    Rest.Log.ErrorFormat("OpenJpeg is not installed correctly on this system.   Asset Data is emtpy for {0}", ic.Item.Name);
                    ic.Asset.Data = new Byte[0];
                }
                catch (IndexOutOfRangeException)
                {
                    Rest.Log.ErrorFormat("OpenJpeg was unable to encode this.   Asset Data is emtpy for {0}", ic.Item.Name);
                    ic.Asset.Data = new Byte[0];
                }
                catch (Exception)
                {
                    Rest.Log.ErrorFormat("OpenJpeg was unable to encode this.   Asset Data is emtpy for {0}", ic.Item.Name);
                    ic.Asset.Data = new Byte[0];
                }
            }

            ic.reset();
        }
        /// <summary>
        /// This method creates an inventory Folder from the
        /// information supplied in the request's entity.
        /// A folder instance is created and initialized to reflect
        /// default values. These values are then overridden
        /// by information supplied in the entity.
        /// If context was not explicitly provided, then the
        /// appropriate ID values are determined.
        /// </summary>

        private void CollectFolder(XmlInventoryCollection ic)
        {
            Rest.Log.DebugFormat("{0} Interpret folder element", MsgId);

            InventoryFolderBase result = new InventoryFolderBase();

            // Default values

            result.Name     = String.Empty;
            result.ID       = UUID.Zero;
            result.Owner    = ic.UserID;
            result.ParentID = UUID.Zero; // Context
            result.Type     = (short) AssetType.Folder;
            result.Version  = 1;

            if (ic.xml.HasAttributes)
            {
                for (int i = 0; i < ic.xml.AttributeCount; i++)
                {
                    ic.xml.MoveToAttribute(i);
                    switch (ic.xml.Name)
                    {
                    case "name":
                        result.Name     =     ic.xml.Value;
                        break;
                    case "uuid":
                        result.ID       = new UUID(ic.xml.Value);
                        break;
                    case "parent":
                        result.ParentID = new UUID(ic.xml.Value);
                        break;
                    case "owner":
                        result.Owner    = new UUID(ic.xml.Value);
                        break;
                    case "type":
                        result.Type     =     Int16.Parse(ic.xml.Value);
                        break;
                    case "version":
                        result.Version  =     UInt16.Parse(ic.xml.Value);
                        break;
                    default:
                        Rest.Log.DebugFormat("{0} Folder: unrecognized attribute: {1}:{2}",
                                             MsgId, ic.xml.Name, ic.xml.Value);
                        ic.Fail(Rest.HttpStatusCodeBadRequest, String.Format("unrecognized attribute <{0}>",
                                 ic.xml.Name));
                        break;
                    }
                }
            }

            ic.xml.MoveToElement();

            // The client is relying upon the reconstitution process
            // to determine the parent's UUID based upon context. This
            // is necessary where a new folder may have been
            // introduced.

            if (result.ParentID == UUID.Zero)
            {
                result.ParentID = ic.Parent();
            }
            else
            {
                bool found = false;

                foreach (InventoryFolderBase parent in ic.rdata.folders)
                {
                    if (parent.ID == result.ParentID)
                    {
                        found = true;
                        break;
                    }
                }

                if (!found)
                {
                    Rest.Log.ErrorFormat("{0} Invalid parent ID ({1}) in folder {2}",
                                         MsgId, ic.Item.Folder, result.ID);
                    ic.Fail(Rest.HttpStatusCodeBadRequest, "invalid parent");
                }
            }

            // This is a new folder, so no existing UUID is available
            // or appropriate

            if (result.ID == UUID.Zero)
            {
                result.ID = UUID.Random();
            }

            // Treat this as a new context. Any other information is
            // obsolete as a consequence.

            ic.Push(result);
        }