File indexing completed on 2024-04-21 03:41:35

0001 /*
0002     SPDX-FileCopyrightText: 2005, 2006 Carsten Niehaus <cniehaus@kde.org>
0003     SPDX-License-Identifier: GPL-2.0-or-later
0004 */
0005 
0006 #include "elementparser.h"
0007 
0008 #include "chemicaldataobject.h"
0009 #include "element.h"
0010 
0011 
0012 #include <KLocalizedString>
0013 #include <KUnitConversion/Converter>
0014 
0015 class ElementSaxParser::Private
0016 {
0017 public:
0018     Private()
0019         : currentUnit(KUnitConversion::NoUnit)
0020         , currentElement(nullptr)
0021         , inElement(false)
0022         , inName(false)
0023         , inMass(false)
0024         , inExactMass(false)
0025         , inAtomicNumber(false)
0026         , inSymbol(false)
0027         , inIonization(false)
0028         , inElectronAffinity(false)
0029         , inElectronegativityPauling(false)
0030         , inRadiusCovalent(false)
0031         , inRadiusVDW(false)
0032         , inBoilingPoint(false)
0033         , inMeltingPoint(false)
0034         , inPeriodTableBlock(false)
0035         , inNameOrigin(false)
0036         , inDiscoveryDate(false)
0037         , inDiscoverers(false)
0038         , inPeriod(false)
0039         , inCrystalstructure(false)
0040         , inAcidicbehaviour(false)
0041         , inFamily(false)
0042         , inGroup(false)
0043         , inElectronicconfiguration(false)
0044         , inDangerSymbol(false)
0045         , inRPhrase(false)
0046         , inSPhrase(false)
0047         , inCountry(false)
0048         , inOxidation(false)
0049     {
0050     }
0051 
0052     ~Private()
0053     {
0054         delete currentElement;
0055         // qDeleteAll(elements);
0056     }
0057 
0058     ChemicalDataObject currentDataObject;
0059     int currentUnit; // KUnitConversion::UnitId
0060     Element *currentElement = nullptr;
0061 
0062     QList<Element *> elements;
0063 
0064     bool inElement;
0065     bool inName;
0066     bool inMass;
0067     bool inExactMass;
0068     bool inAtomicNumber;
0069     bool inSymbol;
0070     bool inIonization;
0071     bool inElectronAffinity;
0072     bool inElectronegativityPauling;
0073     bool inRadiusCovalent;
0074     bool inRadiusVDW;
0075     bool inBoilingPoint;
0076     bool inMeltingPoint;
0077     bool inPeriodTableBlock;
0078     bool inNameOrigin;
0079     bool inDiscoveryDate;
0080     bool inDiscoverers;
0081     bool inPeriod;
0082     bool inCrystalstructure;
0083     bool inAcidicbehaviour;
0084     bool inFamily;
0085     bool inGroup;
0086     bool inElectronicconfiguration;
0087     bool inDangerSymbol;
0088     bool inRPhrase;
0089     bool inSPhrase;
0090     bool inCountry;
0091     bool inOxidation;
0092 };
0093 
0094 ElementSaxParser::ElementSaxParser()
0095     : QXmlDefaultHandler()
0096     , d(new Private)
0097 {
0098 }
0099 
0100 ElementSaxParser::~ElementSaxParser()
0101 {
0102     delete d;
0103 }
0104 
0105 bool ElementSaxParser::startElement(const QString &, const QString &localName, const QString &, const QXmlAttributes &attrs)
0106 {
0107     if (localName == QLatin1String("atom")) {
0108         d->currentElement = new Element();
0109         d->inElement = true;
0110     } else if ((d->inElement && localName == QLatin1String("scalar")) || localName == QLatin1String("array")) {
0111         for (int i = 0; i < attrs.length(); ++i) {
0112             if (attrs.localName(i) == QLatin1String("units")) {
0113                 //                 qCDebug(KALZIUM_LIBSCIENCE_LOG) << "value of the unit: " << attrs.value(i);
0114                 d->currentUnit = unit(attrs.value(i));
0115                 //                 qCDebug(KALZIUM_LIBSCIENCE_LOG) << "Took " << d->currentUnit;
0116                 continue;
0117             }
0118 
0119             if (attrs.value(i) == QLatin1String("bo:atomicNumber")) {
0120                 d->inAtomicNumber = true;
0121             } else if (attrs.value(i) == QLatin1String("bo:mass")) {
0122                 d->inMass = true;
0123             } else if (attrs.value(i) == QLatin1String("bo:exactMass")) {
0124                 d->inExactMass = true;
0125             } else if (attrs.value(i) == QLatin1String("bo:ionization")) {
0126                 d->inIonization = true;
0127             } else if (attrs.value(i) == QLatin1String("bo:electronAffinity")) {
0128                 d->inElectronAffinity = true;
0129             } else if (attrs.value(i) == QLatin1String("bo:electronegativityPauling")) {
0130                 d->inElectronegativityPauling = true;
0131             } else if (attrs.value(i) == QLatin1String("bo:radiusCovalent")) {
0132                 d->inRadiusCovalent = true;
0133             } else if (attrs.value(i) == QLatin1String("bo:radiusVDW")) {
0134                 d->inRadiusVDW = true;
0135             } else if (attrs.value(i) == QLatin1String("bo:meltingpoint")) {
0136                 d->inMeltingPoint = true;
0137             } else if (attrs.value(i) == QLatin1String("bo:boilingpoint")) {
0138                 d->inBoilingPoint = true;
0139             } else if (attrs.value(i) == QLatin1String("bo:periodTableBlock")) {
0140                 d->inPeriodTableBlock = true;
0141             } else if (attrs.value(i) == QLatin1String("bo:nameOrigin")) {
0142                 d->inNameOrigin = true;
0143             } else if (attrs.value(i) == QLatin1String("bo:discoveryDate")) {
0144                 d->inDiscoveryDate = true;
0145             } else if (attrs.value(i) == QLatin1String("bo:discoverers")) {
0146                 d->inDiscoverers = true;
0147             } else if (attrs.value(i) == QLatin1String("bo:discoveryCountry")) {
0148                 d->inCountry = true;
0149             } else if (attrs.value(i) == QLatin1String("bo:period")) {
0150                 d->inPeriod = true;
0151             } else if (attrs.value(i) == QLatin1String("bo:crystalstructure")) {
0152                 d->inCrystalstructure = true;
0153             } else if (attrs.value(i) == QLatin1String("bo:acidicbehaviour")) {
0154                 d->inAcidicbehaviour = true;
0155             } else if (attrs.value(i) == QLatin1String("bo:family")) {
0156                 d->inFamily = true;
0157             } else if (attrs.value(i) == QLatin1String("bo:group")) {
0158                 d->inGroup = true;
0159             } else if (attrs.value(i) == QLatin1String("bo:electronicConfiguration")) {
0160                 d->inElectronicconfiguration = true;
0161             } else if (attrs.value(i) == QLatin1String("bo:dangerSymbol")) {
0162                 d->inDangerSymbol = true;
0163             } else if (attrs.value(i) == QLatin1String("bo:RPhrase")) {
0164                 d->inRPhrase = true;
0165             } else if (attrs.value(i) == QLatin1String("bo:SPhrase")) {
0166                 d->inSPhrase = true;
0167             } else if (attrs.value(i) == QLatin1String("bo:oxidation")) {
0168                 d->inOxidation = true;
0169             }
0170         }
0171     } else if (d->inElement && localName == QLatin1String("label")) {
0172         for (int i = 0; i < attrs.length(); ++i) {
0173             if (attrs.localName(i) != QLatin1String("dictRef")) {
0174                 continue;
0175             }
0176 
0177             if (attrs.value(i) == QLatin1String("bo:symbol")) {
0178                 for (int i = 0; i < attrs.length(); ++i) {
0179                     if (attrs.localName(i) == QLatin1String("value")) {
0180                         d->currentDataObject.setData(attrs.value(i));
0181                         d->currentDataObject.setType(ChemicalDataObject::symbol);
0182 
0183                         if (d->currentElement) {
0184                             d->currentElement->addData(d->currentDataObject);
0185                         }
0186                     }
0187                 }
0188             } else if (attrs.value(i) == QLatin1String("bo:name")) {
0189                 for (int i = 0; i < attrs.length(); ++i) {
0190                     if (attrs.localName(i) == QLatin1String("value")) {
0191                         d->currentDataObject.setData(i18n(attrs.value(i).toUtf8().constData()));
0192                         d->currentDataObject.setType(ChemicalDataObject::name);
0193 
0194                         if (d->currentElement) {
0195                             d->currentElement->addData(d->currentDataObject);
0196                         }
0197                     }
0198                 }
0199             }
0200         }
0201     }
0202     return true;
0203 }
0204 
0205 bool ElementSaxParser::endElement(const QString &, const QString &localName, const QString &)
0206 {
0207     if (localName == QLatin1String("atom")) {
0208         if (d->currentElement->dataAsString(ChemicalDataObject::symbol) != QLatin1String("Xx")) {
0209             d->elements.append(d->currentElement);
0210         } else {
0211             delete d->currentElement;
0212         }
0213 
0214         d->currentElement = nullptr;
0215         d->inElement = false;
0216     } else if (localName == QLatin1String("scalar") || localName == QLatin1String("label") || localName == QLatin1String("array")) {
0217         d->currentDataObject.setUnit(d->currentUnit);
0218     }
0219     return true;
0220 }
0221 
0222 bool ElementSaxParser::characters(const QString &ch)
0223 {
0224     d->currentDataObject = ChemicalDataObject();
0225     ChemicalDataObject::BlueObelisk type;
0226     QVariant value;
0227 
0228     if (d->inMass) {
0229         value = ch.toDouble();
0230         type = ChemicalDataObject::mass;
0231         d->inMass = false;
0232     } else if (d->inExactMass) {
0233         value = ch.toDouble();
0234         type = ChemicalDataObject::exactMass;
0235         d->inExactMass = false;
0236     } else if (d->inAtomicNumber) {
0237         value = ch.toInt();
0238         type = ChemicalDataObject::atomicNumber;
0239         d->inAtomicNumber = false;
0240     } else if (d->inIonization) {
0241         value = ch.toDouble();
0242         ;
0243         type = ChemicalDataObject::ionization;
0244         d->inIonization = false;
0245     } else if (d->inElectronAffinity) {
0246         value = ch.toDouble();
0247         type = ChemicalDataObject::electronAffinity;
0248         d->inElectronAffinity = false;
0249     } else if (d->inElectronegativityPauling) {
0250         value = ch.toDouble();
0251         type = ChemicalDataObject::electronegativityPauling;
0252         d->inElectronegativityPauling = false;
0253     } else if (d->inRadiusCovalent) {
0254         value = ch.toDouble();
0255         type = ChemicalDataObject::radiusCovalent;
0256         d->inRadiusCovalent = false;
0257     } else if (d->inRadiusVDW) {
0258         value = ch.toDouble();
0259         type = ChemicalDataObject::radiusVDW;
0260         d->inRadiusVDW = false;
0261     } else if (d->inMeltingPoint) {
0262         value = ch.toDouble();
0263         type = ChemicalDataObject::meltingpoint;
0264         d->inMeltingPoint = false;
0265     } else if (d->inBoilingPoint) {
0266         value = ch.toDouble();
0267         type = ChemicalDataObject::boilingpoint;
0268         d->inBoilingPoint = false;
0269     } else if (d->inPeriodTableBlock) {
0270         value = ch;
0271         type = ChemicalDataObject::periodTableBlock;
0272         d->inPeriodTableBlock = false;
0273     } else if (d->inNameOrigin) {
0274         value = i18n(ch.toUtf8().constData());
0275         type = ChemicalDataObject::nameOrigin;
0276         d->inNameOrigin = false;
0277     } else if (d->inDiscoveryDate) {
0278         value = ch.toInt();
0279         type = ChemicalDataObject::date;
0280         d->inDiscoveryDate = false;
0281     } else if (d->inDiscoverers) {
0282         value = ch;
0283         type = ChemicalDataObject::discoverers;
0284         d->inDiscoverers = false;
0285     } else if (d->inPeriod) {
0286         value = ch.toInt();
0287         type = ChemicalDataObject::period;
0288         d->inPeriod = false;
0289     } else if (d->inCrystalstructure) {
0290         value = ch;
0291         type = ChemicalDataObject::crystalstructure;
0292         d->inCrystalstructure = false;
0293     } else if (d->inAcidicbehaviour) {
0294         value = ch.toInt();
0295         type = ChemicalDataObject::acidicbehaviour;
0296         d->inAcidicbehaviour = false;
0297     } else if (d->inFamily) {
0298         value = ch;
0299         type = ChemicalDataObject::family;
0300         d->inFamily = false;
0301     } else if (d->inGroup) {
0302         value = ch.toInt();
0303         type = ChemicalDataObject::group;
0304         d->inGroup = false;
0305     } else if (d->inElectronicconfiguration) {
0306         value = ch;
0307         type = ChemicalDataObject::electronicConfiguration;
0308         d->inElectronicconfiguration = false;
0309     } else if (d->inDangerSymbol) {
0310         value = ch;
0311         type = ChemicalDataObject::dangerSymbol;
0312         d->inDangerSymbol = false;
0313     } else if (d->inRPhrase) {
0314         value = ch;
0315         type = ChemicalDataObject::RPhrase;
0316         d->inRPhrase = false;
0317     } else if (d->inSPhrase) {
0318         value = ch;
0319         type = ChemicalDataObject::SPhrase;
0320         d->inSPhrase = false;
0321     } else if (d->inCountry) {
0322         if (ch == QLatin1String("ancient")) {
0323             value = 0;
0324             type = ChemicalDataObject::date;
0325         } else {
0326             value = ch;
0327             type = ChemicalDataObject::discoveryCountry;
0328         }
0329         d->inCountry = false;
0330     } else if (d->inOxidation) {
0331         value = ch;
0332         type = ChemicalDataObject::oxidation;
0333         d->inOxidation = false;
0334     } else { // it is a non known value. Do not create a wrong object but return
0335         return true;
0336     }
0337 
0338     d->currentDataObject.setData(value);
0339     d->currentDataObject.setType(type);
0340     d->currentDataObject.setUnit(d->currentUnit);
0341 
0342     if (d->currentElement) {
0343         d->currentElement->addData(d->currentDataObject);
0344     }
0345 
0346     return true;
0347 }
0348 
0349 int ElementSaxParser::unit(const QString &unit) const
0350 {
0351     if (unit == QLatin1String("siUnits:kelvin")) {
0352         return KUnitConversion::Kelvin;
0353     } else if (unit == QLatin1String("units:ev")) {
0354         return KUnitConversion::Electronvolt;
0355     } else if (unit == QLatin1String("units:ang")) {
0356         return KUnitConversion::Angstrom;
0357     } else if (unit == QLatin1String("bo:noUnit")) {
0358         return KUnitConversion::NoUnit;
0359     } else {
0360         return KUnitConversion::NoUnit;
0361     }
0362 }
0363 
0364 QList<Element *> ElementSaxParser::getElements() const
0365 {
0366     return d->elements;
0367 }