summaryrefslogtreecommitdiffstats
path: root/src/wrappedobjects/qxmiwriter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/wrappedobjects/qxmiwriter.cpp')
-rw-r--r--src/wrappedobjects/qxmiwriter.cpp264
1 files changed, 264 insertions, 0 deletions
diff --git a/src/wrappedobjects/qxmiwriter.cpp b/src/wrappedobjects/qxmiwriter.cpp
new file mode 100644
index 00000000..7c87f229
--- /dev/null
+++ b/src/wrappedobjects/qxmiwriter.cpp
@@ -0,0 +1,264 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Sandro S. Andrade <sandroandrade@kde.org>
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the QtWrappedObjects module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qxmiwriter.h"
+#include "qxmiwriter_p.h"
+
+#include <QtCore/QSet>
+#include <QtCore/QRegularExpression>
+
+#include <QtWrappedObjects/QWrappedObject>
+#include <QtWrappedObjects/QMetaPropertyInfo>
+
+QT_BEGIN_NAMESPACE
+
+QXmiWriterPrivate::QXmiWriterPrivate(QWrappedObject *wrappedObject)
+ : wrappedObject(wrappedObject)
+{
+ writer.setAutoFormatting(true);
+ writer.setAutoFormattingIndent(2);
+}
+
+QXmiWriterPrivate::~QXmiWriterPrivate()
+{
+}
+
+QXmiWriter::QXmiWriter(QWrappedObject *wrappedObject, QObject *parent) :
+ QObject(*new QXmiWriterPrivate(wrappedObject), parent)
+{
+}
+
+QXmiWriter::~QXmiWriter()
+{
+}
+
+bool QXmiWriter::writeFile(QIODevice *device)
+{
+ Q_D(QXmiWriter);
+ d->writer.setDevice(device);
+
+ d->writer.writeStartDocument();
+ d->writer.writeStartElement(QString::fromLatin1("xmi:XMI"));
+ d->writer.writeNamespace(QString::fromLatin1("http://www.omg.org/spec/XMI/20110701"), QString::fromLatin1("xmi"));
+ d->writer.writeNamespace(QString::fromLatin1("http://www.omg.org/spec/UML/20110701"), QString::fromLatin1("uml"));
+ d->writer.writeNamespace(QString::fromLatin1("http://www.omg.org/spec/MOF/20110701"), QString::fromLatin1("mofext"));
+
+ d->visitedObjects.clear();
+ d->idMap.clear();
+ d->idStack.clear();
+ d->blacklistedOppositeEnds.clear();
+
+ populateIdMap(d->wrappedObject);
+ writeWrappedObject(d->wrappedObject);
+
+ d->writer.writeEndDocument();
+ return true;
+}
+
+void QXmiWriter::populateIdMap(QWrappedObject *wrappedObject, int index)
+{
+ Q_D(QXmiWriter);
+
+ if (wrappedObject->metaWrappedObject()->indexOfProperty("name") != -1)
+ d->idStack << wrappedObject->property("name").toString();
+ else
+ d->idStack << QString::fromLatin1(wrappedObject->metaObject()->className()).remove(QRegularExpression(QString::fromLatin1("^Q"))) +
+ QString::fromLatin1((index != -1) ? ".%1":"").arg(index);
+ d->idMap.insert(wrappedObject, d->idStack.join(QString::fromLatin1("-")));
+
+ const QMetaWrappedObject *metaWrappedObject = wrappedObject->metaWrappedObject();
+ int propertyCount = metaWrappedObject->propertyCount();
+
+ for (int i = 0; i < propertyCount; ++i) {
+ QMetaPropertyInfo metaPropertyInfo = metaWrappedObject->property(i);
+ QMetaProperty metaProperty = metaPropertyInfo.metaProperty;
+ QWrappedObject *propertyWrappedObject = metaPropertyInfo.propertyWrappedObject;
+ QString typeName = QString::fromLatin1(metaProperty.typeName());
+ QVariant variant = metaProperty.read(propertyWrappedObject);
+ QString aggregationRole = wrappedObject->propertyData(QString::fromLatin1(metaPropertyInfo.propertyMetaObject->className()),
+ metaProperty,
+ QtWrappedObjects::QtWrappedObjects::AggregationRole).toString();
+
+ if (aggregationRole == QString::fromLatin1("composite"))
+ if (!wrappedObject->propertyData(QString::fromLatin1(metaPropertyInfo.propertyMetaObject->className()),
+ metaProperty,
+ QtWrappedObjects::QtWrappedObjects::OppositeEndRole).toString().isEmpty())
+ d->blacklistedOppositeEnds << wrappedObject->propertyData(QString::fromLatin1(metaPropertyInfo.propertyMetaObject->className()),
+ metaProperty,
+ QtWrappedObjects::QtWrappedObjects::OppositeEndRole).toString();
+
+ if (wrappedObject->propertyData(QString::fromLatin1(metaPropertyInfo.propertyMetaObject->className()),
+ metaProperty,
+ QtWrappedObjects::QtWrappedObjects::AggregationRole).toString() != QString::fromLatin1("composite"))
+ continue;
+
+ if (typeName.endsWith('*') && qvariant_cast<QWrappedObject *>(variant))
+ populateIdMap(qTopLevelWrapper(qvariant_cast<QWrappedObject *>(variant)), 0);
+ else if (typeName.contains(QString::fromLatin1("QSet")) && variant.isValid()) {
+ QSet<QWrappedObject *> elements = *(static_cast<QSet<QWrappedObject *> *>(variant.data()));
+ int i = 0;
+ foreach (QWrappedObject *objectElement, elements)
+ populateIdMap(qTopLevelWrapper(objectElement), i++);
+ }
+ else if (typeName.contains(QString::fromLatin1("QList")) && variant.isValid()) {
+ QList<QWrappedObject *> elements = *(static_cast<QList<QWrappedObject *> *>(variant.data()));
+ int i = 0;
+ foreach (QWrappedObject *objectElement, elements)
+ populateIdMap(qTopLevelWrapper(objectElement), i++);
+ }
+ }
+
+ d->idStack.removeLast();
+}
+
+void QXmiWriter::writeWrappedObject(QWrappedObject *wrappedObject, QString elementName)
+{
+ Q_D(QXmiWriter);
+
+ if (d->visitedObjects.contains(wrappedObject))
+ return;
+
+ d->visitedObjects.append(wrappedObject);
+
+ d->writer.writeStartElement(elementName.isEmpty() ? QString::fromLatin1(d->wrappedObject->metaObject()->className()).remove(QRegularExpression(QString::fromLatin1("^Q"))).prepend(QString::fromLatin1("uml:"))
+ :
+ elementName);
+ if (!elementName.isEmpty())
+ d->writer.writeAttribute(QString::fromLatin1("xmi:type"), QString::fromLatin1(wrappedObject->metaObject()->className()).remove(QRegularExpression(QString::fromLatin1("^Q"))).prepend(QString::fromLatin1("uml:")));
+
+ const QMetaWrappedObject *metaWrappedObject = wrappedObject->metaWrappedObject();
+ int propertyCount = metaWrappedObject->propertyCount();
+
+ for (int i = propertyCount - 1; i >= 0; --i) {
+ QMetaPropertyInfo metaPropertyInfo = metaWrappedObject->property(i);
+ QMetaProperty metaProperty = metaPropertyInfo.metaProperty;
+ QWrappedObject *propertyWrappedObject = metaPropertyInfo.propertyWrappedObject;
+ QVariant variant = metaProperty.read(propertyWrappedObject);
+
+ if (!metaProperty.isStored() || QString::fromLatin1(metaProperty.name()) == QString::fromLatin1("objectName") || QWrappedObject::propertyData(QString::fromLatin1(metaPropertyInfo.propertyMetaObject->className()),
+ metaProperty,
+ QtWrappedObjects::QtWrappedObjects::IsDerivedUnionRole).toBool())
+ continue;
+
+ if (metaProperty.type() == QVariant::String) {
+ QString value = variant.toString();
+ if (!value.isEmpty())
+ d->writer.writeAttribute(QString::fromLatin1(metaProperty.name()), value);
+ }
+ else if (metaProperty.type() == QVariant::Bool) {
+ if (!metaProperty.isResettable() || (metaProperty.isResettable() && propertyWrappedObject->isPropertyModified(metaProperty)))
+ d->writer.writeAttribute(QString::fromLatin1(metaProperty.name()), QString::fromLatin1(variant.toBool() ? "true":"false"));
+ }
+ else if (metaProperty.isEnumType()) {
+ if (!metaProperty.isResettable() || (metaProperty.isResettable() && propertyWrappedObject->isPropertyModified(metaProperty))) {
+ QMetaEnum metaEnum = metaProperty.enumerator();
+ if (!QString::fromLatin1(metaEnum.key(variant.toInt())).isEmpty())
+ d->writer.writeAttribute(QString::fromLatin1(metaProperty.name()), QString::fromLatin1(metaEnum.key(variant.toInt())).toLower().remove(QString::fromLatin1(metaProperty.name())));
+ }
+ }
+ }
+
+ d->writer.writeAttribute(QString::fromLatin1("xmi:id"), d->idMap.value(wrappedObject));
+ for (int i = propertyCount - 1; i >= 0; --i) {
+ QMetaPropertyInfo metaPropertyInfo = metaWrappedObject->property(i);
+ QMetaProperty metaProperty = metaPropertyInfo.metaProperty;
+
+ if (d->blacklistedOppositeEnds.contains(QString::fromLatin1("%1::%2").arg(QString::fromLatin1(metaPropertyInfo.propertyMetaObject->className())).arg(QString::fromLatin1(metaProperty.name()).remove(QRegularExpression(QString::fromLatin1("_$"))))))
+ continue;
+
+ QWrappedObject *propertyWrappedObject = metaPropertyInfo.propertyWrappedObject;
+ QString typeName = QString::fromLatin1(metaProperty.typeName());
+ QVariant variant = metaProperty.read(propertyWrappedObject);
+ QString aggregationRole = wrappedObject->propertyData(QString::fromLatin1(metaPropertyInfo.propertyMetaObject->className()),
+ metaProperty,
+ QtWrappedObjects::QtWrappedObjects::AggregationRole).toString();
+ QString modifiedPropertyName = QString::fromLatin1(metaProperty.name()).remove(QRegularExpression(QString::fromLatin1("_$"))).remove(QRegularExpression(QString::fromLatin1("s$"))).replace(QRegularExpression(QString::fromLatin1("ie$")), QString::fromLatin1("y")).replace(QRegularExpression(QString::fromLatin1("sse$")), QString::fromLatin1("ss")).replace(QRegularExpression(QString::fromLatin1("ice$")), QString::fromLatin1("ex")).replace(QRegularExpression(QString::fromLatin1("ce$")), QString::fromLatin1("x"));
+
+ if (!metaProperty.isStored() || QWrappedObject::propertyData(QString::fromLatin1(metaPropertyInfo.propertyMetaObject->className()), metaProperty, QtWrappedObjects::QtWrappedObjects::IsDerivedUnionRole).toBool())
+ continue;
+
+ if (typeName.endsWith('*') && qvariant_cast<QWrappedObject *>(variant)) {
+ if (aggregationRole == QString::fromLatin1("composite")) {
+ writeWrappedObject(qTopLevelWrapper(qvariant_cast<QWrappedObject *>(variant)), modifiedPropertyName);
+ }
+ else {
+ d->writer.writeStartElement(QString::fromLatin1(metaProperty.name()));
+ d->writer.writeAttribute(QString::fromLatin1("xmi:idref"), d->idMap.value(qTopLevelWrapper(qvariant_cast<QWrappedObject *>(variant))));
+ d->writer.writeEndElement();
+ }
+ }
+ else if (typeName.contains(QString::fromLatin1("QSet")) && variant.isValid()) {
+ QSet<QWrappedObject *> elements = *(static_cast<QSet<QWrappedObject *> *>(variant.data()));
+ if (aggregationRole == QString::fromLatin1("composite")) {
+ foreach (QWrappedObject *objectElement, elements)
+ writeWrappedObject(qTopLevelWrapper(objectElement), modifiedPropertyName);
+ }
+ else {
+ foreach (QWrappedObject *objectElement, elements) {
+ d->writer.writeStartElement(QString::fromLatin1(metaProperty.name()));
+ d->writer.writeAttribute(QString::fromLatin1("xmi:idref"), d->idMap.value(qTopLevelWrapper(objectElement)));
+ d->writer.writeEndElement();
+ }
+ }
+ }
+ else if (typeName.contains(QString::fromLatin1("QList")) && variant.isValid()) {
+ QList<QWrappedObject *> elements = *(static_cast<QList<QWrappedObject *> *>(variant.data()));
+ if (aggregationRole == QString::fromLatin1("composite")) {
+ foreach (QWrappedObject *objectElement, elements)
+ writeWrappedObject(qTopLevelWrapper(objectElement), modifiedPropertyName);
+ }
+ else {
+ foreach (QWrappedObject *objectElement, elements) {
+ d->writer.writeStartElement(QString::fromLatin1(metaProperty.name()));
+ d->writer.writeAttribute(QString::fromLatin1("xmi:idref"), d->idMap.value(qTopLevelWrapper(objectElement)));
+ d->writer.writeEndElement();
+ }
+ }
+ }
+ }
+
+ d->writer.writeEndElement();
+}
+
+#include "moc_qxmiwriter.cpp"
+
+QT_END_NAMESPACE
+