/// <summary>
        /// Get the existing sync state for this item, if it exists and is of the appropriate
        /// type, else null.
        /// </summary>
        /// <remarks>Outlook items are not true objects and don't have a common superclass,
        /// so we have to use this rather clumsy overloading.</remarks>
        /// <param name="appointment">The item.</param>
        /// <returns>The appropriate sync state, or null if none.</returns>
        /// <exception cref="UnexpectedSyncStateClassException">if the sync state found is not of the expected class (shouldn't happen).</exception>
        public AppointmentSyncState GetSyncState(Outlook.AppointmentItem appointment)
        {
            SyncState result;

            try
            {
                result = (appointment.IsValid() && this.byOutlookId.ContainsKey(appointment.EntryID)) ? this.byOutlookId[appointment.EntryID] : null;
                CrmId crmId = result == null?appointment.GetCrmId() : CheckForDuplicateSyncState(result, appointment.GetCrmId());

                if (CrmId.IsValid(crmId))
                {
                    if (result == null && this.byCrmId.ContainsKey(crmId))
                    {
                        result = this.byCrmId[crmId];
                    }
                    else if (result != null && this.byCrmId.ContainsKey(crmId) == false)
                    {
                        this.byCrmId[crmId] = result;
                        result.CrmEntryId   = crmId;
                    }
                }

                if (result != null && !(result is AppointmentSyncState))
                {
                    throw new UnexpectedSyncStateClassException("AppointmentSyncState", result);
                }
            }
            catch (COMException)
            {
                // dead item passed.
                result = null;
            }

            return(result as AppointmentSyncState);
        }
        /// <summary>
        /// Get the CRM id for this item, if known, else the empty string.
        /// </summary>
        /// <param name="olItem">The Outlook item under consideration.</param>
        /// <returns>the CRM id for this item, if known, else null.</returns>
        public static CrmId GetCrmId(this Outlook.AppointmentItem olItem)
        {
            string result;

            if (olItem.IsValid())
            {
                try
                {
                    Outlook.UserProperty property = olItem.UserProperties[SyncStateManager.CrmIdPropertyName];

                    if (property == null)
                    {
                        /* #6661: fail over to legacy property name if current property
                         * name not found */
                        property = olItem.UserProperties[SyncStateManager.LegacyCrmIdPropertyName];
                    }

                    if (property != null && !string.IsNullOrEmpty(property.Value))
                    {
                        result = property.Value;
                    }
                    else
                    {
                        result = olItem.GetVCalId();
                    }
                }
                catch (COMException)
                {
                    /* this is bad! It shouldn't be possible to get here, but
                     * it is. */
                    try
                    {
                        result = olItem.GetVCalId();
                    }
                    catch (COMException)
                    {
                        result = null;
                    }
                }
            }
            else
            {
                result = null;
            }

            return(CrmId.Get(result));
        }