File indexing completed on 2024-04-21 07:40:18

0001 /*
0002     This file is part of the KContacts framework.
0003     SPDX-FileCopyrightText: 2008 Tobias Koenig <tokoe@kde.org>
0004     SPDX-FileCopyrightText: 2008 Kevin Krammer <kevin.krammer@gmx.at>
0005 
0006     SPDX-License-Identifier: LGPL-2.0-or-later
0007 */
0008 
0009 #include "contactgrouptool.h"
0010 #include "contactgroup.h"
0011 
0012 #include <QIODevice>
0013 
0014 #include <QXmlStreamReader>
0015 #include <QXmlStreamWriter>
0016 
0017 using namespace KContacts;
0018 
0019 class XmlContactGroupWriter : public QXmlStreamWriter
0020 {
0021 public:
0022     XmlContactGroupWriter();
0023 
0024     void write(const ContactGroup &group, QIODevice *device);
0025     void write(const QList<ContactGroup> &groupLis, QIODevice *device);
0026 
0027 private:
0028     void writeGroup(const ContactGroup &group);
0029     void writeContactReference(const ContactGroup::ContactReference &reference);
0030     void writeContactGroupReference(const ContactGroup::ContactGroupReference &reference);
0031     void writeData(const ContactGroup::Data &data);
0032 };
0033 
0034 XmlContactGroupWriter::XmlContactGroupWriter()
0035 {
0036     setAutoFormatting(true);
0037 }
0038 
0039 void XmlContactGroupWriter::write(const ContactGroup &group, QIODevice *device)
0040 {
0041     setDevice(device);
0042 
0043     writeStartDocument();
0044 
0045     writeGroup(group);
0046 
0047     writeEndDocument();
0048 }
0049 
0050 void XmlContactGroupWriter::write(const QList<ContactGroup> &groupList, QIODevice *device)
0051 {
0052     setDevice(device);
0053 
0054     writeStartDocument();
0055 
0056     writeStartElement(QStringLiteral("contactGroupList"));
0057 
0058     for (const ContactGroup &group : groupList) {
0059         writeGroup(group);
0060     }
0061 
0062     writeEndElement();
0063 
0064     writeEndDocument();
0065 }
0066 
0067 void XmlContactGroupWriter::writeGroup(const ContactGroup &group)
0068 {
0069     writeStartElement(QStringLiteral("contactGroup"));
0070     writeAttribute(QStringLiteral("uid"), group.id());
0071     writeAttribute(QStringLiteral("name"), group.name());
0072 
0073     const uint contactCount(group.contactReferenceCount());
0074     for (uint i = 0; i < contactCount; ++i) {
0075         writeContactReference(group.contactReference(i));
0076     }
0077 
0078     const uint contactGroupReference(group.contactGroupReferenceCount());
0079     for (uint i = 0; i < contactGroupReference; ++i) {
0080         writeContactGroupReference(group.contactGroupReference(i));
0081     }
0082 
0083     const uint dataCount(group.dataCount());
0084     for (uint i = 0; i < dataCount; ++i) {
0085         writeData(group.data(i));
0086     }
0087 
0088     writeEndElement();
0089 }
0090 
0091 void XmlContactGroupWriter::writeContactReference(const ContactGroup::ContactReference &reference)
0092 {
0093     writeStartElement(QStringLiteral("contactReference"));
0094     writeAttribute(QStringLiteral("uid"), reference.uid());
0095     writeAttribute(QStringLiteral("gid"), reference.gid());
0096     if (!reference.preferredEmail().isEmpty()) {
0097         writeAttribute(QStringLiteral("preferredEmail"), reference.preferredEmail());
0098     }
0099 
0100     // TODO: customs
0101 
0102     writeEndElement();
0103 }
0104 
0105 void XmlContactGroupWriter::writeContactGroupReference(const ContactGroup::ContactGroupReference &reference)
0106 {
0107     writeStartElement(QStringLiteral("contactGroupReference"));
0108     writeAttribute(QStringLiteral("uid"), reference.uid());
0109 
0110     // TODO: customs
0111 
0112     writeEndElement();
0113 }
0114 
0115 void XmlContactGroupWriter::writeData(const ContactGroup::Data &data)
0116 {
0117     writeStartElement(QStringLiteral("contactData"));
0118     writeAttribute(QStringLiteral("name"), data.name());
0119     writeAttribute(QStringLiteral("email"), data.email());
0120 
0121     // TODO: customs
0122 
0123     writeEndElement();
0124 }
0125 
0126 class XmlContactGroupReader : public QXmlStreamReader
0127 {
0128 public:
0129     XmlContactGroupReader();
0130 
0131     bool read(QIODevice *device, ContactGroup &group);
0132     bool read(QIODevice *device, QList<ContactGroup> &groupList);
0133 
0134 private:
0135     bool readGroup(ContactGroup &group);
0136     bool readContactReference(ContactGroup::ContactReference &reference);
0137     bool readContactGroupReference(ContactGroup::ContactGroupReference &reference);
0138     bool readData(ContactGroup::Data &data);
0139 };
0140 
0141 XmlContactGroupReader::XmlContactGroupReader()
0142 {
0143 }
0144 
0145 bool XmlContactGroupReader::read(QIODevice *device, ContactGroup &group)
0146 {
0147     setDevice(device);
0148 
0149     while (!atEnd()) {
0150         readNext();
0151         if (isStartElement()) {
0152             if (name() == QLatin1String("contactGroup")) {
0153                 return readGroup(group);
0154             } else {
0155                 raiseError(QStringLiteral("The document does not describe a ContactGroup"));
0156             }
0157         }
0158     }
0159 
0160     return error() == NoError;
0161 }
0162 
0163 bool XmlContactGroupReader::read(QIODevice *device, QList<ContactGroup> &groupList)
0164 {
0165     setDevice(device);
0166 
0167     int depth = 0;
0168 
0169     while (!atEnd()) {
0170         readNext();
0171         if (isStartElement()) {
0172             ++depth;
0173             if (depth == 1) {
0174                 if (name() == QLatin1String("contactGroupList")) {
0175                     continue;
0176                 } else {
0177                     raiseError(QStringLiteral("The document does not describe a list of ContactGroup"));
0178                 }
0179             } else if (depth == 2) {
0180                 if (name() == QLatin1String("contactGroup")) {
0181                     ContactGroup group;
0182                     if (!readGroup(group)) {
0183                         return false;
0184                     }
0185 
0186                     groupList.append(group);
0187                 } else {
0188                     raiseError(QStringLiteral("The document does not describe a list of ContactGroup"));
0189                 }
0190             }
0191         }
0192 
0193         if (isEndElement()) {
0194             --depth;
0195         }
0196     }
0197 
0198     return error() == NoError;
0199 }
0200 
0201 bool XmlContactGroupReader::readGroup(ContactGroup &group)
0202 {
0203     const QXmlStreamAttributes elementAttributes = attributes();
0204     const auto uid = elementAttributes.value(QLatin1String("uid"));
0205     if (uid.isEmpty()) {
0206         raiseError(QStringLiteral("ContactGroup is missing a uid"));
0207         return false;
0208     }
0209 
0210     const auto groupName = elementAttributes.value(QLatin1String("name"));
0211     if (groupName.isEmpty()) {
0212         raiseError(QStringLiteral("ContactGroup is missing a name"));
0213         return false;
0214     }
0215 
0216     group.setId(uid.toString());
0217     group.setName(groupName.toString());
0218 
0219     while (!atEnd()) {
0220         readNext();
0221         if (isStartElement()) {
0222             if (name() == QLatin1String("contactData")) {
0223                 ContactGroup::Data data;
0224                 if (!readData(data)) {
0225                     return false;
0226                 }
0227                 group.append(data);
0228             } else if (name() == QLatin1String("contactReference")) {
0229                 ContactGroup::ContactReference reference;
0230                 if (!readContactReference(reference)) {
0231                     return false;
0232                 }
0233                 group.append(reference);
0234             } else if (name() == QLatin1String("contactGroupReference")) {
0235                 ContactGroup::ContactGroupReference reference;
0236                 if (!readContactGroupReference(reference)) {
0237                     return false;
0238                 }
0239                 group.append(reference);
0240             } else {
0241                 raiseError(QStringLiteral("The document does not describe a ContactGroup"));
0242             }
0243         }
0244 
0245         if (isEndElement()) {
0246             if (name() == QLatin1String("contactGroup")) {
0247                 return true;
0248             }
0249         }
0250     }
0251 
0252     return false;
0253 }
0254 
0255 bool XmlContactGroupReader::readData(ContactGroup::Data &data)
0256 {
0257     const QXmlStreamAttributes elementAttributes = attributes();
0258     const auto email = elementAttributes.value(QLatin1String("email"));
0259     if (email.isEmpty()) {
0260         raiseError(QStringLiteral("ContactData is missing an email address"));
0261         return false;
0262     }
0263 
0264     const auto name = elementAttributes.value(QLatin1String("name"));
0265 
0266     data.setName(name.toString());
0267     data.setEmail(email.toString());
0268 
0269     return true;
0270 }
0271 
0272 bool XmlContactGroupReader::readContactReference(ContactGroup::ContactReference &reference)
0273 {
0274     const QXmlStreamAttributes elementAttributes = attributes();
0275     const auto uid = elementAttributes.value(QLatin1String("uid"));
0276     const auto gid = elementAttributes.value(QLatin1String("gid"));
0277     if (uid.isEmpty() && gid.isEmpty()) {
0278         raiseError(QStringLiteral("ContactReference is missing both uid and gid"));
0279         return false;
0280     }
0281     const auto preferredEmail = elementAttributes.value(QLatin1String("preferredEmail"));
0282 
0283     reference.setUid(uid.toString());
0284     reference.setGid(gid.toString());
0285     reference.setPreferredEmail(preferredEmail.toString());
0286 
0287     return true;
0288 }
0289 
0290 bool XmlContactGroupReader::readContactGroupReference(ContactGroup::ContactGroupReference &reference)
0291 {
0292     const QXmlStreamAttributes elementAttributes = attributes();
0293     const auto uid = elementAttributes.value(QLatin1String("uid"));
0294     if (uid.isEmpty()) {
0295         raiseError(QStringLiteral("ContactGroupReference is missing a uid"));
0296         return false;
0297     }
0298 
0299     reference.setUid(uid.toString());
0300 
0301     return true;
0302 }
0303 
0304 bool ContactGroupTool::convertFromXml(QIODevice *device, ContactGroup &group, QString *errorMessage)
0305 {
0306     Q_UNUSED(errorMessage);
0307 
0308     XmlContactGroupReader reader;
0309 
0310     bool ok = reader.read(device, group);
0311 
0312     if (!ok && errorMessage != nullptr) {
0313         *errorMessage = reader.errorString();
0314     }
0315 
0316     return ok;
0317 }
0318 
0319 bool ContactGroupTool::convertToXml(const ContactGroup &group, QIODevice *device, QString *errorMessage)
0320 {
0321     Q_UNUSED(errorMessage);
0322 
0323     XmlContactGroupWriter writer;
0324     writer.write(group, device);
0325 
0326     return true;
0327 }
0328 
0329 bool ContactGroupTool::convertFromXml(QIODevice *device, QList<ContactGroup> &groupList, QString *errorMessage)
0330 {
0331     Q_UNUSED(errorMessage);
0332 
0333     XmlContactGroupReader reader;
0334 
0335     bool ok = reader.read(device, groupList);
0336 
0337     if (!ok && errorMessage != nullptr) {
0338         *errorMessage = reader.errorString();
0339     }
0340 
0341     return ok;
0342 }
0343 
0344 bool ContactGroupTool::convertToXml(const QList<ContactGroup> &groupList, QIODevice *device, QString *errorMessage)
0345 {
0346     Q_UNUSED(errorMessage);
0347 
0348     XmlContactGroupWriter writer;
0349     writer.write(groupList, device);
0350 
0351     return true;
0352 }