/// <summary>
        /// Parse an ItemId's Id from a base64 string to a ItemIdId object according to the defined format
        /// </summary>
        /// <param name="itemId">An ItemIdType object</param>
        /// <returns>An ItemIdId object as the result of parsing</returns>
        public ItemIdId ParseItemId(ItemIdType itemId)
        {
            Site.Assert.IsNotNull(itemId, "The input itemId should not be null.");
            ItemIdId parsedId = new ItemIdId();
            byte[] id = Convert.FromBase64String(itemId.Id);
            int currentIndex = 0;

            // [Byte] Compression Type
            parsedId.CompressionByte = id[currentIndex];
            if (parsedId.CompressionByte == 1)
            {
                // The max length of Base64-encoded Id is 512, which is 512*3/4=384 after decoding
                // Then minus 1 (Compress Byte),which is 383
                id = this.Decompress(id, 383).ToArray();
            }
            else
            {
                currentIndex++;
            }

            // [Byte] Id Storage Type
            Site.Assert.IsTrue(
                Enum.IsDefined(typeof(IdStorageType), id[currentIndex]),
               "The id storage type should be valid. Actually the value is '{0}'.",
               id[currentIndex]);
            parsedId.StorageType = (IdStorageType)id[currentIndex];
            currentIndex++;
            switch (parsedId.StorageType)
            {
                case IdStorageType.MailboxItemSmtpAddressBased:
                case IdStorageType.MailboxItemMailboxGuidBased:
                case IdStorageType.ConversationIdMailboxGuidBased:
                    {
                        parsedId.MonikerLength = BitConverter.ToInt16(id, currentIndex);
                        currentIndex += 2;

                        parsedId.MonikerBytes = new byte[(int)parsedId.MonikerLength];
                        Array.Copy(id, currentIndex, parsedId.MonikerBytes, 0, (int)parsedId.MonikerLength);
                        currentIndex += (int)parsedId.MonikerLength;

                        if (Enum.IsDefined(typeof(IdProcessingInstructionType), id[currentIndex]))
                        {
                            parsedId.IdProcessingInstruction = (IdProcessingInstructionType)id[currentIndex];
                            currentIndex++;
                        }
                        else 
                        {
                            Site.Assert.Fail("Undefined Id Processing Instruction Type value {0}", id[currentIndex]);
                        }

                        parsedId.StoreIdLength = BitConverter.ToInt16(id, currentIndex);
                        currentIndex += 2;
                        parsedId.StoreId = new byte[parsedId.StoreIdLength];
                        Array.Copy(id, currentIndex, parsedId.StoreId, 0, parsedId.StoreIdLength);
                        currentIndex += parsedId.StoreIdLength;

                        break;
                    }

                case IdStorageType.PublicFolder:
                case IdStorageType.ActiveDirectoryObject:
                    {
                        parsedId.StoreIdLength = BitConverter.ToInt16(id, currentIndex);
                        currentIndex += 2;

                        parsedId.StoreId = new byte[parsedId.StoreIdLength];
                        Array.Copy(id, currentIndex, parsedId.StoreId, 0, parsedId.StoreIdLength);
                        currentIndex += parsedId.StoreIdLength;

                        break;
                    }

                case IdStorageType.PublicFolderItem:
                    {
                        if (Enum.IsDefined(typeof(IdProcessingInstructionType), id[currentIndex]))
                        {
                            parsedId.IdProcessingInstruction = (IdProcessingInstructionType)id[currentIndex];
                            currentIndex++;
                        }
                        else
                        {
                            Site.Assert.Fail("Undefined Id Processing Instruction Type value {0}", id[currentIndex]);
                        }

                        parsedId.StoreIdLength = BitConverter.ToInt16(id, currentIndex);
                        currentIndex += 2;

                        parsedId.StoreId = new byte[parsedId.StoreIdLength];
                        Array.Copy(id, currentIndex, parsedId.StoreId, 0, parsedId.StoreIdLength);
                        currentIndex += parsedId.StoreIdLength;

                        parsedId.FolderIdLength = BitConverter.ToInt16(id, currentIndex);
                        currentIndex += 2;

                        parsedId.FolderId = new byte[(int)parsedId.FolderIdLength];
                        Array.Copy(id, currentIndex, parsedId.FolderId, 0, (int)parsedId.FolderIdLength);
                        currentIndex += (int)parsedId.FolderIdLength;

                        break;
                    }

                default:
                    {
                        Site.Assert.Fail("No format defined for Id Storage Type {0}", parsedId.StorageType.ToString("g"));
                        break;
                    }
            }

            if (currentIndex < id.Length)
            {
                parsedId.AttachmentIdCount = id[currentIndex];
                currentIndex++;

                short attachmentIdCount = Convert.ToInt16(parsedId.AttachmentIdCount);
                parsedId.AttachmentIds = new AttachmentId[attachmentIdCount];

                for (int i = 0; i < attachmentIdCount; i++)
                {
                    parsedId.AttachmentIds[i].AttachmentIdLength = BitConverter.ToInt16(id, currentIndex);
                    currentIndex += 2;

                    parsedId.AttachmentIds[i].Id = new byte[parsedId.AttachmentIds[i].AttachmentIdLength];
                    Array.Copy(id, currentIndex, parsedId.AttachmentIds[i].Id, 0, parsedId.AttachmentIds[i].AttachmentIdLength);
                    currentIndex += parsedId.AttachmentIds[i].AttachmentIdLength;
                }
            }

            Site.Assert.AreEqual<int>(id.Length, currentIndex, "There should be no bytes left after parsing item id!");
            return parsedId;
        }