File indexing completed on 2024-12-22 04:57:05
0001 /* 0002 SPDX-FileCopyrightText: 2015-2017 Krzysztof Nowicki <krissn@op.pl> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #pragma once 0008 0009 #include <functional> 0010 0011 #include <QList> 0012 #include <QXmlStreamReader> 0013 0014 #include "ewsclient_debug.h" 0015 0016 template<typename T> 0017 class EwsXml 0018 { 0019 public: 0020 typedef std::function<bool(QXmlStreamReader &, QVariant &)> ReadFunction; 0021 typedef std::function<bool(QXmlStreamWriter &, const QVariant &)> WriteFunction; 0022 typedef std::function<bool(QXmlStreamReader &, const QString &)> UnknownElementFunction; 0023 0024 typedef QHash<T, QVariant> ValueHash; 0025 0026 static constexpr T Ignore = static_cast<T>(-1); 0027 0028 struct Item { 0029 Item() 0030 : key(Ignore) 0031 { 0032 } 0033 0034 Item(T k, const QString &n, const ReadFunction &rfn = ReadFunction(), const WriteFunction &wfn = WriteFunction()) 0035 : key(k) 0036 , elmName(n) 0037 , readFn(rfn) 0038 , writeFn(wfn) 0039 { 0040 } 0041 0042 T key; 0043 QString elmName; 0044 ReadFunction readFn; 0045 WriteFunction writeFn; 0046 }; 0047 0048 EwsXml() 0049 { 0050 } 0051 0052 EwsXml(const QList<Item> &items) 0053 : mItems(items) 0054 { 0055 rebuildItemHash(); 0056 } 0057 0058 EwsXml(const EwsXml &other) 0059 : mItems(other.mItems) 0060 , mValues(other.mValues) 0061 , mItemHash(other.mItemHash) 0062 { 0063 } 0064 0065 void setItems(const QList<Item> &items) 0066 { 0067 mItems = items; 0068 rebuildItemHash(); 0069 } 0070 0071 bool readItem(QXmlStreamReader &reader, const QString &parentElm, const QString &nsUri, UnknownElementFunction unknownElmFn = &defaultUnknownElmFunction) 0072 { 0073 typename QHash<QString, Item>::iterator it = mItemHash.find(reader.name().toString()); 0074 if (it != mItemHash.end() && nsUri == reader.namespaceUri()) { 0075 if (it->key == Ignore) { 0076 qCInfoNC(EWSCLI_LOG) << QStringLiteral("Unsupported %1 child element %2 - ignoring.").arg(parentElm, reader.name().toString()); 0077 reader.skipCurrentElement(); 0078 return true; 0079 } else if (!it->readFn) { 0080 qCWarning(EWSCLI_LOG) << QStringLiteral("Failed to read %1 element - no read support for %2 element.").arg(parentElm, reader.name().toString()); 0081 return false; 0082 } else { 0083 QVariant val = mValues[it->key]; 0084 if (it->readFn(reader, val)) { 0085 mValues[it->key] = val; 0086 return true; 0087 } 0088 return false; 0089 } 0090 } 0091 return unknownElmFn(reader, parentElm); 0092 } 0093 0094 bool readItems(QXmlStreamReader &reader, const QString &nsUri, const UnknownElementFunction &unknownElmFn = &defaultUnknownElmFunction) 0095 { 0096 QString elmName(reader.name().toString()); 0097 while (reader.readNextStartElement()) { 0098 if (!readItem(reader, elmName, nsUri, unknownElmFn)) { 0099 return false; 0100 } 0101 } 0102 return true; 0103 } 0104 0105 bool writeItems(QXmlStreamWriter &writer, 0106 const QString &parentElm, 0107 const QString &nsUri, 0108 const ValueHash &values, 0109 const QList<T> &keysToWrite = QList<T>()) const 0110 { 0111 bool hasKeysToWrite = !keysToWrite.isEmpty(); 0112 for (const Item &item : std::as_const(mItems)) { 0113 if (!hasKeysToWrite || keysToWrite.contains(item.key)) { 0114 typename ValueHash::const_iterator it = values.find(item.key); 0115 if (it != values.end()) { 0116 if (!item.writeFn) { 0117 qCWarning(EWSCLI_LOG) << QStringLiteral("Failed to write %1 element - no write support for %2 element.").arg(parentElm, item.elmName); 0118 return false; 0119 } 0120 writer.writeStartElement(nsUri, item.elmName); 0121 bool status = item.writeFn(writer, *it); 0122 writer.writeEndElement(); 0123 if (!status) { 0124 return false; 0125 } 0126 } 0127 } 0128 } 0129 return true; 0130 } 0131 0132 ValueHash values() const 0133 { 0134 return mValues; 0135 } 0136 0137 private: 0138 static bool defaultUnknownElmFunction(QXmlStreamReader &reader, const QString &parentElm) 0139 { 0140 qCWarning(EWSCLI_LOG) << QStringLiteral("Failed to read %1 element - invalid %2 element.").arg(parentElm, reader.name().toString()); 0141 return false; 0142 } 0143 0144 const QList<Item> mItems; 0145 ValueHash mValues; 0146 QHash<QString, Item> mItemHash; 0147 0148 void rebuildItemHash() 0149 { 0150 for (const Item &item : std::as_const(mItems)) { 0151 mItemHash.insert(item.elmName, item); 0152 } 0153 } 0154 }; 0155 0156 template<typename T> 0157 T readXmlElementValue(QXmlStreamReader &reader, bool &ok, const QString &parentElement); 0158 0159 extern bool ewsXmlBoolReader(QXmlStreamReader &reader, QVariant &val); 0160 extern bool ewsXmlBoolWriter(QXmlStreamWriter &writer, const QVariant &val); 0161 extern bool ewsXmlBase64Reader(QXmlStreamReader &reader, QVariant &val); 0162 extern bool ewsXmlBase64Writer(QXmlStreamWriter &writer, const QVariant &val); 0163 extern bool ewsXmlIdReader(QXmlStreamReader &reader, QVariant &val); 0164 extern bool ewsXmlIdWriter(QXmlStreamWriter &writer, const QVariant &val); 0165 extern bool ewsXmlTextReader(QXmlStreamReader &reader, QVariant &val); 0166 extern bool ewsXmlTextWriter(QXmlStreamWriter &writer, const QVariant &val); 0167 extern bool ewsXmlUIntReader(QXmlStreamReader &reader, QVariant &val); 0168 extern bool ewsXmlUIntWriter(QXmlStreamWriter &writer, const QVariant &val); 0169 extern bool ewsXmlDateTimeReader(QXmlStreamReader &reader, QVariant &val); 0170 extern bool ewsXmlItemReader(QXmlStreamReader &reader, QVariant &val); 0171 extern bool ewsXmlFolderReader(QXmlStreamReader &reader, QVariant &val); 0172 0173 extern bool ewsXmlEnumReader(QXmlStreamReader &reader, QVariant &val, const QList<QString> &items); 0174 extern bool ewsXmlSensitivityReader(QXmlStreamReader &reader, QVariant &val); 0175 extern bool ewsXmlImportanceReader(QXmlStreamReader &reader, QVariant &val); 0176 extern bool ewsXmlCalendarItemTypeReader(QXmlStreamReader &reader, QVariant &val); 0177 extern bool ewsXmlLegacyFreeBusyStatusReader(QXmlStreamReader &reader, QVariant &val); 0178 extern bool ewsXmlResponseTypeReader(QXmlStreamReader &reader, QVariant &val);