EwsSyncFolderHierarchyRequest::Response::Response(QXmlStreamReader &reader)
    : EwsRequest::Response(reader)
{
    if (mClass == EwsResponseParseError) {
        return;
    }

    static const QVector<EwsXml<SyncResponseElementType>::Item> items = {
        {SyncState, QStringLiteral("SyncState"), &ewsXmlTextReader},
        {IncludesLastFolderInRange, QStringLiteral("IncludesLastFolderInRange"), &ewsXmlBoolReader},
        {Changes, QStringLiteral("Changes"), &EwsSyncFolderHierarchyRequest::Response::changeReader},
    };
    static const EwsXml<SyncResponseElementType> staticReader(items);

    EwsXml<SyncResponseElementType> ewsReader(staticReader);

    if (!ewsReader.readItems(reader, ewsMsgNsUri,
        [this](QXmlStreamReader &reader, const QString &) {
            if (!readResponseElement(reader)) {
                setErrorMsg(QStringLiteral("Failed to read EWS request - invalid response element."));
                return false;
            }
            return true;
        }))
    {
        mClass = EwsResponseParseError;
        return;
    }

    QHash<SyncResponseElementType, QVariant> values = ewsReader.values();

    mSyncState = values[SyncState].toString();
    mIncludesLastFolder = values[IncludesLastFolderInRange].toBool();
    mChanges = values[Changes].value<Change::List>();
}
EwsSyncFolderItemsRequest::Change::Change(QXmlStreamReader &reader)
{
    static const QVector<EwsXml<ChangeElementType>::Item> items = {
        {Item, QStringLiteral("Item"), &ewsXmlItemReader},
        {Item, QStringLiteral("Message"), &ewsXmlItemReader},
        {Item, QStringLiteral("CalendarItem"), &ewsXmlItemReader},
        {Item, QStringLiteral("Contact"), &ewsXmlItemReader},
        {Item, QStringLiteral("DistributionList"), &ewsXmlItemReader},
        {Item, QStringLiteral("MeetingMessage"), &ewsXmlItemReader},
        {Item, QStringLiteral("MeetingRequest"), &ewsXmlItemReader},
        {Item, QStringLiteral("MeetingResponse"), &ewsXmlItemReader},
        {Item, QStringLiteral("MeetingCancellation"), &ewsXmlItemReader},
        {Item, QStringLiteral("Task"), &ewsXmlItemReader},
        {ItemId, QStringLiteral("ItemId"), &ewsXmlIdReader},
        {IsRead, QStringLiteral("IsRead"), &ewsXmlBoolReader}
    };
    static const EwsXml<ChangeElementType> staticReader(items);

    EwsXml<ChangeElementType> ewsReader(staticReader);

    if (reader.name() == QStringLiteral("Create")) {
        mType = Create;
    }
    else if (reader.name() == QStringLiteral("Update")) {
        mType = Update;
    }
    else if (reader.name() == QStringLiteral("Delete")) {
        mType = Delete;
    }
    else if (reader.name() == QStringLiteral("ReadFlagChange")) {
        mType = ReadFlagChange;
    }
    if (!ewsReader.readItems(reader, ewsTypeNsUri)) {
        return;
    }

    QHash<ChangeElementType, QVariant> values = ewsReader.values();

    switch (mType) {
    case Create:
    case Update:
        mItem = values[Item].value<EwsItem>();
        mId = mItem[EwsItemFieldItemId].value<EwsId>();
        break;
    case ReadFlagChange:
        mIsRead = values[IsRead].toBool();
    /* no break */
    case Delete:
        mId = values[ItemId].value<EwsId>();
        break;
    default:
        break;
    }
}
EwsSyncFolderHierarchyRequest::Change::Change(QXmlStreamReader &reader)
{
    static const QVector<EwsXml<ChangeElementType>::Item> items = {
        {Folder, QStringLiteral("Folder"), &ewsXmlFolderReader},
        {Folder, QStringLiteral("CalendarFolder"), &ewsXmlFolderReader},
        {Folder, QStringLiteral("ContactsFolder"), &ewsXmlFolderReader},
        {Folder, QStringLiteral("SearchFolder"), &ewsXmlFolderReader},
        {Folder, QStringLiteral("TasksFolder"), &ewsXmlFolderReader},
        {FolderId, QStringLiteral("FolderId"), &ewsXmlIdReader},
        {IsRead, QStringLiteral("IsRead"), &ewsXmlBoolReader}
    };
    static const EwsXml<ChangeElementType> staticReader(items);

    EwsXml<ChangeElementType> ewsReader(staticReader);

    if (reader.name() == QStringLiteral("Create")) {
        mType = Create;
    }
    else if (reader.name() == QStringLiteral("Update")) {
        mType = Update;
    }
    else if (reader.name() == QStringLiteral("Delete")) {
        mType = Delete;
    }
    if (!ewsReader.readItems(reader, ewsTypeNsUri)) {
        return;
    }

    QHash<ChangeElementType, QVariant> values = ewsReader.values();

    switch (mType) {
    case Create:
    case Update:
        mFolder = values[Folder].value<EwsFolder>();
        mId = mFolder[EwsFolderFieldFolderId].value<EwsId>();
        break;
    case Delete:
        mId = values[FolderId].value<EwsId>();
        break;
    default:
        break;
    }
}