summaryrefslogtreecommitdiffstats
path: root/src/modeling
diff options
context:
space:
mode:
Diffstat (limited to 'src/modeling')
-rw-r--r--src/modeling/modeling.pro20
-rw-r--r--src/modeling/qmetamodelplugin.cpp (renamed from src/modeling/qwrappedobject.cpp)21
-rw-r--r--src/modeling/qmetamodelplugin.h73
-rw-r--r--src/modeling/qtmodelingglobal.h43
-rw-r--r--src/modeling/qtmodelingnamespace.h12
-rw-r--r--src/modeling/qwrappedobject.h246
-rw-r--r--src/modeling/qxmireader.cpp317
-rw-r--r--src/modeling/qxmireader.h84
-rw-r--r--src/modeling/qxmireader_p.h80
-rw-r--r--src/modeling/qxmiwriter.cpp287
-rw-r--r--src/modeling/qxmiwriter.h83
-rw-r--r--src/modeling/qxmiwriter_p.h81
12 files changed, 1079 insertions, 268 deletions
diff --git a/src/modeling/modeling.pro b/src/modeling/modeling.pro
index 4fef7dbd..7c56cf48 100644
--- a/src/modeling/modeling.pro
+++ b/src/modeling/modeling.pro
@@ -1,17 +1,29 @@
load(qt_build_config)
TARGET = QtModeling
-QT = core core-private
+QT = core-private
QMAKE_DOCS = $$PWD/doc/qtmodeling.qdocconf
load(qt_module)
-HEADERS += \
+PUBLIC_HEADERS += \
qtmodelingglobal.h \
qtmodelingnamespace.h \
- qmodelingobject.h
+ qmodelingobject.h \
+ qmetamodelplugin.h \
+ qxmiwriter.h \
+ qxmireader.h
+
+PRIVATE_HEADERS += \
+ qxmiwriter_p.h \
+ qxmireader_p.h
SOURCES += \
qtmodelingnamespace.cpp \
- qmodelingobject.cpp
+ qmodelingobject.cpp \
+ qmetamodelplugin.cpp \
+ qxmiwriter.cpp \
+ qxmireader.cpp
+
+HEADERS += $$PUBLIC_HEADERS $$PRIVATE_HEADERS
diff --git a/src/modeling/qwrappedobject.cpp b/src/modeling/qmetamodelplugin.cpp
index 1f265a1a..69677943 100644
--- a/src/modeling/qwrappedobject.cpp
+++ b/src/modeling/qmetamodelplugin.cpp
@@ -38,29 +38,16 @@
** $QT_END_LICENSE$
**
****************************************************************************/
-#include "qwrappedobject.h"
+#include "qmetamodelplugin.h"
QT_BEGIN_NAMESPACE
-QWrappedObject::QWrappedObject(QWrappedObject *wrapper, QObject *parent) :
- QObject(*new QWrappedObjectPrivate, parent)
+QMetaModelPlugin::QMetaModelPlugin(QObject *parent)
+ : QObject(parent)
{
- setWrapper(wrapper);
}
-QWrappedObject::~QWrappedObject()
-{
- Q_D(QWrappedObject);
- qDeleteAll(d->wrappedObjects);
-}
-
-QWrappedObject::QWrappedObject(QWrappedObjectPrivate &dd, QWrappedObject *wrapper, QObject *parent) :
- QObject(dd, parent)
-{
- setWrapper(wrapper);
-}
-
-#include "moc_qwrappedobject.cpp"
+#include "moc_qmetamodelplugin.cpp"
QT_END_NAMESPACE
diff --git a/src/modeling/qmetamodelplugin.h b/src/modeling/qmetamodelplugin.h
new file mode 100644
index 00000000..16ea2c08
--- /dev/null
+++ b/src/modeling/qmetamodelplugin.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Sandro S. Andrade <sandroandrade@kde.org>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtModeling module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QTMODELING_QMETAMODELPLUGIN_H
+#define QTMODELING_QMETAMODELPLUGIN_H
+
+#include <QtModeling/QtModelingGlobal>
+
+#include <QtCore/QObject>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(QtModeling)
+
+class QScriptEngine;
+class QModelingObject;
+
+class Q_MODELING_EXPORT QMetaModelPlugin : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit QMetaModelPlugin(QObject *parent = 0);
+
+ virtual void initMetaModel(QScriptEngine *scriptEngine = 0) = 0;
+ virtual QModelingObject *createModelingObject(QString type) = 0;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QTMODELING_QMETAMODELPLUGIN_H
+
diff --git a/src/modeling/qtmodelingglobal.h b/src/modeling/qtmodelingglobal.h
index c1f40d20..809531ed 100644
--- a/src/modeling/qtmodelingglobal.h
+++ b/src/modeling/qtmodelingglobal.h
@@ -43,6 +43,9 @@
#include <QtCore/QtGlobal>
#include <QtCore/QVariant>
+#include <QtScript/QScriptValue>
+#include <QtScript/QScriptEngine>
+#include <QtScript/QScriptValueIterator>
QT_BEGIN_NAMESPACE
@@ -63,7 +66,45 @@ class QModelingObject;
template<class T>
T qmodelingobjectproperty_cast(const QObject *object)
{
- return object->property("modelingObject").value<T>();
+ return object ? object->property("modelingObject").value<T>():T();
+}
+
+template <class T>
+QScriptValue qSetToScriptValue(QScriptEngine *engine, const QSet<T *> &elements)
+{
+ QScriptValue array = engine->newArray();
+ foreach (T *element, elements)
+ array.property(QString::fromLatin1("push")).call(array, QScriptValueList() << engine->newQObject(element));
+ return array;
+}
+
+template <class T>
+void scriptValueToQSet(const QScriptValue &obj, QSet<T *> &elements)
+{
+ QScriptValueIterator it(obj);
+ while (it.hasNext()) {
+ it.next();
+ elements.insert(qobject_cast<T *>(it.value().toQObject()));
+ }
+}
+
+template <class T>
+QScriptValue qListToScriptValue(QScriptEngine *engine, const QList<T *> &elements)
+{
+ QScriptValue array = engine->newArray();
+ foreach (T *element, elements)
+ array.property(QString::fromLatin1("push")).call(array, QScriptValueList() << engine->newQObject(element));
+ return array;
+}
+
+template <class T>
+void scriptValueToQList(const QScriptValue &obj, QList<T *> &elements)
+{
+ QScriptValueIterator it(obj);
+ while (it.hasNext()) {
+ it.next();
+ elements.append(qobject_cast<T *>(it.value().toQObject()));
+ }
}
#endif // QTMODELINGGLOBAL_H
diff --git a/src/modeling/qtmodelingnamespace.h b/src/modeling/qtmodelingnamespace.h
index 1c9459a8..e6f76bb0 100644
--- a/src/modeling/qtmodelingnamespace.h
+++ b/src/modeling/qtmodelingnamespace.h
@@ -56,6 +56,7 @@ class Q_MODELING_EXPORT QtModeling : public QObject
Q_OBJECT
Q_ENUMS(MetaPropertyDataRole)
+ Q_ENUMS(ModelingObjectRole)
public:
enum MetaPropertyDataRole
@@ -72,12 +73,23 @@ public:
UserRole = 0x0100
};
+ enum ModelingObjectRole
+ {
+ ModelElementRole = 0,
+ ImportedElementRole,
+ ImportedPackageRole,
+ AppliedProfileRole
+ };
+
private:
explicit QtModeling();
};
QT_END_NAMESPACE
+Q_DECLARE_METATYPE (QT_PREPEND_NAMESPACE(QtModeling::MetaPropertyDataRole))
+Q_DECLARE_METATYPE (QT_PREPEND_NAMESPACE(QtModeling::ModelingObjectRole))
+
QT_END_HEADER
#endif // QTMODELINGNAMESPACE_H
diff --git a/src/modeling/qwrappedobject.h b/src/modeling/qwrappedobject.h
deleted file mode 100644
index cf2d273d..00000000
--- a/src/modeling/qwrappedobject.h
+++ /dev/null
@@ -1,246 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Sandro S. Andrade <sandroandrade@kde.org>
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtModeling module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, 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, Digia gives you certain additional
-** rights. These rights are described in the Digia 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.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-#ifndef QWRAPPEDOBJECT_H
-#define QWRAPPEDOBJECT_H
-
-#include <QtModeling/QtModelingGlobal>
-
-#include <QtCore/QObject>
-#include "private/qobject_p.h"
-
-#include <QtCore/QSet>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(QtModeling)
-
-#define Q_WRAPPEDOBJECT_REGISTRY \
- QHash<QString, QWrappedObject *> &wrappedObjectsRegistry = this->wrappedObjectsRegistry(); \
- QWrappedObject *wrappedObject;
-
-#define Q_WRAP_OBJECT(className) \
- wrappedObject = wrappedObjectsRegistry.value(QStringLiteral(#className)); \
- if (!wrappedObject) { \
- wrappedObject = new className(this, parent); \
- wrappedObjectsRegistry.insert(QStringLiteral(#className), wrappedObject); \
- } \
- wrappedObject->setWrapper(this)
-
-#define Q_DERIVEDUNION_CONNECTION(subsetting, subsetted) \
- QObject::connect(&subsetting, SIGNAL(objectInserted(QObject*)), &subsetted, SLOT(insert(QObject*))); \
- QObject::connect(&subsetting, SIGNAL(objectRemoved(QObject*)), &subsetted, SLOT(remove(QObject*)));
-
-class QWrappedObjectPrivate;
-
-class Q_MODELING_EXPORT QWrappedObject : public QObject
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QWrappedObject)
-
-public:
- explicit QWrappedObject(QWrappedObject *wrapper, QObject *parent = 0);
-
- virtual ~QWrappedObject();
-
- inline QWrappedObject *wrapper() const;
- inline void setWrapper(QWrappedObject *wrapper);
- inline QList<QPointer<QWrappedObject> > &wrappedObjects();
-
- inline void setObjectName(const QString &name)
- {
- QObject::setObjectName(name);
- foreach (QWrappedObject *wrapped, wrappedObjects())
- wrapped->setObjectName(name);
- }
-
-// template <class T>
-// inline const T *as() const;
-
- template <class T>
- inline T *as();
-
-// template <class T>
-// inline const T *privateAs() const;
-
- template <class T>
- inline T *privateAs();
-
-protected:
- explicit QWrappedObject(QWrappedObjectPrivate &dd, QWrappedObject *wrapper = 0, QObject *parent = 0);
- inline QHash<QString, QWrappedObject *> &wrappedObjectsRegistry();
-
-private:
- inline void initialize(QWrappedObject *wrapper);
-};
-
-template <class T>
-inline T qwrappedobject_cast(QWrappedObject *base, bool restoreToWrapper = true)
-{
- if (!base)
- return T(); // invalid pointer
- while (restoreToWrapper && base->wrapper())
- base = base->wrapper();
- if (dynamic_cast<T>(base))
- return dynamic_cast<T>(base);
- foreach (QWrappedObject *wrappedObject, base->wrappedObjects()) {
- T returnValue = qwrappedobject_cast<T>(wrappedObject, false);
- if (returnValue != T())
- return returnValue;
- }
- return T(); // not found
-}
-
-template <class T>
-inline T qwrappedobject_cast(const QWrappedObject *base, bool restoreToWrapper = true)
-{
- return qwrappedobject_cast<T>(const_cast<QWrappedObject *>(base), restoreToWrapper);
-}
-
-//template <class T>
-//inline const T *QWrappedObject::QWrappedObject::as() const
-//{
-// return qwrappedobject_cast<T *>(this);
-//}
-
-template <class T>
-inline T *QWrappedObject::QWrappedObject::as()
-{
- return qwrappedobject_cast<T *>(this);
-}
-
-//template <class T>
-//inline const T *QWrappedObject::QWrappedObject::privateAs() const
-//{
-// Q_D(const QWrappedObject);
-// return qwrappedobject_cast<T *>(d);
-//}
-
-template <class T>
-inline T *QWrappedObject::QWrappedObject::privateAs()
-{
- Q_D(QWrappedObject);
- return qwrappedobject_cast<T *>(d);
-}
-
-inline QWrappedObject *qTopLevelWrapper(QWrappedObject *wrapped)
-{
- if (!wrapped)
- return 0;
- while (wrapped->wrapper())
- wrapped = wrapped->wrapper();
- return wrapped;
-}
-
-class Q_MODELING_EXPORT QWrappedObjectPrivate : public QObjectPrivate
-{
- Q_DECLARE_PUBLIC(QWrappedObject)
-
-public:
- explicit QWrappedObjectPrivate() : wrapper(0) { }
-
- inline static QWrappedObjectPrivate *get(QWrappedObject *o)
- {
- return dynamic_cast<QWrappedObjectPrivate *>(o->d_func());
- }
-
- QWrappedObject *wrapper;
- QList< QPointer<QWrappedObject> > wrappedObjects;
- QHash<QString, QWrappedObject *>wrappedObjectsRegistry;
-};
-
-template <class T>
-inline T qwrappedobject_cast(QWrappedObjectPrivate *base, bool restoreToWrapper = true)
-{
- if (!base)
- return T(); // invalid pointer
- while (restoreToWrapper && base->wrapper)
- base = QWrappedObjectPrivate::get(base->wrapper);
- if (dynamic_cast<T>(base))
- return dynamic_cast<T>(base);
- foreach (QWrappedObject *wrappedObject, base->wrappedObjects) {
- T returnValue = qwrappedobject_cast<T>(QWrappedObjectPrivate::get(wrappedObject), false);
- if (returnValue != T())
- return returnValue;
- }
- return T(); // not found
-}
-
-template <class T>
-inline T qwrappedobject_cast(const QWrappedObjectPrivate *base, bool restoreToWrapper = true)
-{
- return qwrappedobject_cast<T>(const_cast<QWrappedObjectPrivate *>(base), restoreToWrapper);
-}
-
-inline QWrappedObject *QWrappedObject::wrapper() const
-{
- Q_D(const QWrappedObject);
- return d->wrapper;
-}
-
-inline void QWrappedObject::setWrapper(QWrappedObject *wrapper)
-{
- Q_D(QWrappedObject);
- if (wrapper) {
- d->wrapper = wrapper;
- QList< QPointer<QWrappedObject> > &wrappedObjects = wrapper->d_func()->wrappedObjects;
- if (!wrappedObjects.contains(this))
- wrappedObjects.append(this);
- }
-}
-
-inline QList< QPointer<QWrappedObject> > &QWrappedObject::wrappedObjects()
-{
- Q_D(QWrappedObject);
- return d->wrappedObjects;
-}
-
-inline QHash<QString, QWrappedObject *> &QWrappedObject::wrappedObjectsRegistry()
-{
- return qTopLevelWrapper(this)->d_func()->wrappedObjectsRegistry;
-}
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // QWRAPPEDOBJECT_H
diff --git a/src/modeling/qxmireader.cpp b/src/modeling/qxmireader.cpp
new file mode 100644
index 00000000..58b938ec
--- /dev/null
+++ b/src/modeling/qxmireader.cpp
@@ -0,0 +1,317 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Sandro S. Andrade <sandroandrade@kde.org>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtModeling module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "qxmireader.h"
+#include "qxmireader_p.h"
+#include "qmetamodelplugin.h"
+
+#include <QtModeling/QtModelingNamespace>
+
+#include <QtCore/QDir>
+#include <QtCore/QUrl>
+#include <QtCore/QStack>
+#include <QtCore/QJsonObject>
+#include <QtCore/QPluginLoader>
+#include <QtCore/QMetaProperty>
+#include <QtCore/QCoreApplication>
+
+QT_BEGIN_NAMESPACE
+
+QXmiReaderPrivate::QXmiReaderPrivate()
+{
+}
+
+QXmiReaderPrivate::~QXmiReaderPrivate()
+{
+}
+
+QXmiReader::QXmiReader(QScriptEngine *scriptEngine, bool initMetaModel, QObject *parent) :
+ QObject(*new QXmiReaderPrivate, parent)
+{
+ Q_D(QXmiReader);
+ d->scriptEngine = scriptEngine;
+ d->initMetaModel = initMetaModel;
+ loadPlugins();
+}
+
+QXmiReader::~QXmiReader()
+{
+}
+
+void QXmiReader::loadPlugins()
+{
+ Q_D(QXmiReader);
+
+ d->metaModelPlugins.clear();
+ QMetaModelPlugin *metaModelPlugin = 0;
+ foreach (QString pluginPath, QCoreApplication::libraryPaths()) {
+ QDir pluginsDir(pluginPath);
+ pluginsDir.cd(QString::fromLatin1("metamodels"));
+ foreach (QString fileName, pluginsDir.entryList(QDir::Files)) {
+ QPluginLoader loader(pluginsDir.absoluteFilePath(fileName));
+ QObject *plugin = loader.instance();
+ if (plugin && (metaModelPlugin = qobject_cast<QMetaModelPlugin *>(plugin)))
+ d->metaModelPlugins.insert(loader.metaData().value(QString::fromLatin1("MetaData")).toObject().value(QString::fromLatin1("MetaModelNamespaceUri")).toString(), QPair<QMetaModelPlugin *, QJsonObject>(metaModelPlugin, loader.metaData().value(QString::fromLatin1("MetaData")).toObject()));
+ }
+ }
+}
+
+QObjectList QXmiReader::readFile(QIODevice *device, QString importedId)
+{
+ Q_D(QXmiReader);
+
+ if (importedId.isEmpty()) {
+ d->idMap.clear();
+ d->errors.clear();
+ d->xmlNamespaceToImplementationNamespace.clear();
+ }
+ QXmlStreamReader reader;
+ reader.setDevice(device);
+ QObjectList modelingObjectList;
+ QObject *rootElement = 0;
+ bool importedIdFound = false;
+ QStack<QString> idStack;
+ int insertPosition = 0;
+
+ while (!reader.atEnd()) {
+ reader.readNext();
+
+ if (!importedId.isEmpty() && !importedIdFound && reader.attributes().value(QString::fromLatin1("xmi:id")).toString() != importedId)
+ continue;
+
+ if (!importedId.isEmpty() && !importedIdFound)
+ importedIdFound = true;
+
+ if (reader.isStartElement()) {
+ idStack.push(reader.name().toString());
+ QString elementName = reader.name().toString();
+ if (elementName == QString::fromLatin1("importedPackage") || elementName == QString::fromLatin1("importedElement") || elementName == QString::fromLatin1("appliedProfile")) {
+ QFile importFile(reader.attributes().value(QString::fromLatin1("href")).toString().split(QString::fromLatin1("#")).first());
+ if (!importFile.open(QFile::ReadOnly | QFile::Text))
+ d->errors << QString::fromLatin1("Could not open imported file '%1'").arg(importFile.fileName());
+ QObjectList importList = readFile(&importFile, reader.attributes().value(QString::fromLatin1("href")).toString().split(QString::fromLatin1("#")).last());
+ if (importList.count() > 0) {
+ if (elementName == QString::fromLatin1("importedPackage"))
+ importList.first()->setProperty("role", QtModeling::ImportedPackageRole);
+ else if (elementName == QString::fromLatin1("importedElement"))
+ importList.first()->setProperty("role", QtModeling::ImportedElementRole);
+ else if (elementName == QString::fromLatin1("appliedProfile"))
+ importList.first()->setProperty("role", QtModeling::AppliedProfileRole);
+ }
+ foreach (QObject *importedObject, importList) {
+ modelingObjectList.append(importedObject);
+ }
+ }
+
+ foreach (const QXmlStreamNamespaceDeclaration &namespaceDeclaration, reader.namespaceDeclarations()) {
+ QMetaModelPlugin *metaModelPlugin = d->metaModelPlugins.value(namespaceDeclaration.namespaceUri().toString()).first;
+ if (metaModelPlugin) {
+ if (d->initMetaModel)
+ metaModelPlugin->initMetaModel(d->scriptEngine);
+ d->xmlNamespaceToImplementationNamespace.insert(namespaceDeclaration.prefix().toString(), d->metaModelPlugins.value(namespaceDeclaration.namespaceUri().toString()).second.value(QString::fromLatin1("MetaModelPrefix")).toString());
+ }
+ else {
+ d->errors << QString::fromLatin1("Could not find metamodel for namespace URI '%1'").arg(namespaceDeclaration.namespaceUri().toString());
+ }
+ }
+ QString xmiType = reader.attributes().value(QString::fromLatin1("xmi:type")).toString();
+ if (xmiType.isEmpty() && reader.qualifiedName() != reader.name())
+ xmiType = reader.qualifiedName().toString();
+ if (xmiType.isEmpty() || d->xmlNamespaceToImplementationNamespace[xmiType.split(':').first()].isEmpty())
+ continue;
+ xmiType = QString::fromLatin1("%1%2 *").arg(d->xmlNamespaceToImplementationNamespace[xmiType.split(':').first()]).arg(xmiType.split(':').last());
+ QString instanceName = reader.attributes().value(QString::fromLatin1("name")).toString();
+ if (instanceName.isEmpty())
+ instanceName = reader.attributes().value(QString::fromLatin1("xmi:id")).toString();
+ QObject *modelingObject = createInstance(xmiType, instanceName);
+ if (modelingObject) {
+ d->idMap.insert(reader.attributes().value(QString::fromLatin1("xmi:id")).toString(), modelingObject);
+ if (!rootElement) {
+ rootElement = modelingObject;
+ modelingObjectList.insert(insertPosition, rootElement);
+ }
+ }
+ else
+ d->errors << QString::fromLatin1("Could not create instance with id '%1' and type '%2'. Corresponding metamodel loaded ?").arg(instanceName).arg(xmiType);
+ }
+ else if (reader.isEndElement()) {
+ idStack.pop();
+ if (idStack.isEmpty() && !importedId.isEmpty())
+ break;
+ if (idStack.count() == 1 && importedId.isEmpty()) {
+ rootElement = 0;
+ ++insertPosition;
+ }
+ }
+ }
+
+ importedIdFound = false;
+
+ device->reset();
+ reader.clear();
+ reader.setDevice(device);
+ QStack< QPair<QString, QObject *> > stack;
+
+ while (!reader.atEnd()) {
+ reader.readNext();
+
+ if (!importedId.isEmpty() && !importedIdFound && reader.attributes().value(QString::fromLatin1("xmi:id")).toString() != importedId)
+ continue;
+
+ if (!importedId.isEmpty() && !importedIdFound)
+ importedIdFound = true;
+
+ if (reader.isStartElement()) {
+ QString id = reader.attributes().value(QString::fromLatin1("xmi:id")).toString();
+ if (id.isEmpty())
+ id = reader.attributes().value(QString::fromLatin1("xmi:idref")).toString();
+ if (id.isEmpty())
+ id = reader.attributes().value(QString::fromLatin1("href")).toString().split(QString::fromLatin1("#")).last();
+ if (id.isEmpty() && !stack.isEmpty())
+ continue;
+
+ QObject *modelingObject = d->idMap.value(id);
+
+ if (modelingObject) {
+ const QMetaObject *metaObject = modelingObject->metaObject();
+ foreach (QXmlStreamAttribute attribute, reader.attributes()) {
+ int propertyIndex;
+ if ((propertyIndex = metaObject->indexOfProperty(attribute.name().toString().toLatin1())) != -1) {
+ QMetaProperty metaProperty = metaObject->property(propertyIndex);
+ if (metaProperty.type() == QVariant::Bool) {
+ if (!modelingObject->setProperty(attribute.name().toString().toLatin1(), attribute.value().toString() == QString::fromLatin1("true") ? true:false))
+ d->errors << QString::fromLatin1("Error when setting property '%1' of object with id '%2'.").arg(attribute.name().toString()).arg(id);
+ }
+ else if (metaProperty.isEnumType()) {
+ QString enumName = attribute.value().toString();
+ enumName = enumName.left(1).toUpper() + enumName.mid(1);
+ QString propertyName = QString::fromLatin1(metaProperty.name());
+ enumName.prepend(propertyName.left(1).toUpper() + propertyName.mid(1));
+ if (!modelingObject->setProperty(attribute.name().toString().toLatin1(), enumName))
+ d->errors << QString::fromLatin1("Error when setting property '%1' of object with id '%2'.").arg(attribute.name().toString()).arg(id);
+ }
+ else if (metaProperty.type() == QVariant::String) {
+ if (!modelingObject->setProperty(attribute.name().toString().toLatin1(), attribute.value().toString()))
+ d->errors << QString::fromLatin1("Error when setting property '%1' of object with id '%2'.").arg(attribute.name().toString()).arg(id);
+ }
+ else if (metaProperty.type() == QVariant::UserType) {
+ QObject *propertyObject = d->idMap.value(attribute.value().toString());
+ if (propertyObject) {
+ QString elementName = attribute.name().toString();
+ elementName = elementName.left(1).toUpper() + elementName.mid(1);
+ int methodCount = modelingObject->metaObject()->methodCount();
+ int i;
+ for (i = 0; i < methodCount; ++i) {
+ QMetaMethod metaMethod = modelingObject->metaObject()->method(i);
+ if (QString::fromLatin1(metaMethod.name()) == QString::fromLatin1("set%1").arg(elementName)) {
+ if (!metaMethod.invoke(modelingObject, ::Q_ARG(QObject *, propertyObject)))
+ d->errors << QString::fromLatin1("Error when invoking metamethod '%1' on object '%2'.").arg(QString::fromLatin1(metaMethod.name())).arg(propertyObject->objectName());
+ break;
+ }
+ }
+ if (i == methodCount)
+ d->errors << QString::fromLatin1("Metamethod add/set'%1' not found on object '%2'.").arg(elementName).arg(propertyObject->objectName());
+
+ }
+ }
+ }
+ else
+ d->errors << QString::fromLatin1("Property '%1' not found in object of type '%2'. Corresponding metamodel loaded ?").arg(attribute.name().toString()).arg(QString::fromLatin1(modelingObject->metaObject()->className()));
+ }
+ if (!stack.isEmpty()) {
+ QObject *containerObject = stack.top().second;
+ QString elementName = reader.name().toString();
+ elementName = elementName.left(1).toUpper() + elementName.mid(1);
+ int methodCount = containerObject->metaObject()->methodCount();
+ int i;
+ for (i = 0; i < methodCount; ++i) {
+ QMetaMethod metaMethod = containerObject->metaObject()->method(i);
+ if (QString::fromLatin1(metaMethod.name()) == QString::fromLatin1("add%1").arg(elementName) ||
+ QString::fromLatin1(metaMethod.name()) == QString::fromLatin1("set%1").arg(elementName)) {
+ if (!metaMethod.invoke(containerObject, ::Q_ARG(QObject *, modelingObject)))
+ d->errors << QString::fromLatin1("Error when invoking metamethod '%1' on object '%2'.").arg(QString::fromLatin1(metaMethod.name())).arg(containerObject->objectName());
+ break;
+ }
+ }
+ if (i == methodCount)
+ d->errors << QString::fromLatin1("Metamethod add/set'%1' not found on object '%2'.").arg(elementName).arg(containerObject->objectName());
+ }
+ stack.push(QPair<QString, QObject *>(reader.name().toString(), modelingObject));
+ }
+ else
+ d->errors << QString::fromLatin1("Could not cross reference instance with id '%1' in element '%2'. Bad formed XMI file ?").arg(id).arg(reader.name().toString());
+ }
+ else if (reader.isEndElement() && !stack.isEmpty() && stack.top().first == reader.name()) {
+ stack.pop();
+ if (stack.isEmpty() && !importedId.isEmpty())
+ break;
+ }
+ }
+
+ return modelingObjectList;
+}
+
+QObject *QXmiReader::createInstance(QString instanceClass, QString instanceName)
+{
+ int type;
+ if ((type = QMetaType::type(instanceClass.toLatin1())) != QMetaType::UnknownType) {
+ const QMetaObject *metaObject = QMetaType::metaObjectForType(type);
+ if (metaObject) {
+ QObject *modelingObject = dynamic_cast<QObject *>(metaObject->newInstance());
+ if (modelingObject) {
+ modelingObject->setObjectName(instanceName);
+ return modelingObject;
+ }
+ }
+ }
+ return 0;
+}
+
+QStringList QXmiReader::errorStrings() const
+{
+ Q_D(const QXmiReader);
+
+ return d->errors;
+}
+
+#include "moc_qxmireader.cpp"
+
+QT_END_NAMESPACE
+
diff --git a/src/modeling/qxmireader.h b/src/modeling/qxmireader.h
new file mode 100644
index 00000000..8dea082f
--- /dev/null
+++ b/src/modeling/qxmireader.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Sandro S. Andrade <sandroandrade@kde.org>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtModeling module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QTMODELING_QXMIREADER_H
+#define QTMODELING_QXMIREADER_H
+
+#include <QtModeling/QtModelingGlobal>
+
+#include <QtCore/QObject>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(QtModeling)
+
+class QIODevice;
+class QObject;
+
+class QScriptEngine;
+class QXmiReaderPrivate;
+
+class Q_MODELING_EXPORT QXmiReader : public QObject
+{
+ Q_OBJECT
+
+ Q_DISABLE_COPY(QXmiReader)
+ Q_DECLARE_PRIVATE(QXmiReader)
+
+public:
+ explicit QXmiReader(QScriptEngine *scriptEngine = 0, bool initMetaModel = false, QObject *parent = 0);
+ virtual ~QXmiReader();
+
+ QObjectList readFile(QIODevice *device, QString importedId = QString::fromLatin1(""));
+ QStringList errorStrings() const;
+
+protected:
+ void loadPlugins();
+ QObject *createInstance(QString instanceClass, QString instanceName);
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QTMODELING_QXMIREADER_H
+
diff --git a/src/modeling/qxmireader_p.h b/src/modeling/qxmireader_p.h
new file mode 100644
index 00000000..966d5971
--- /dev/null
+++ b/src/modeling/qxmireader_p.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Sandro S. Andrade <sandroandrade@kde.org>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtModeling module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QTMODELING_QXMIREADER_P_H
+#define QTMODELING_QXMIREADER_P_H
+
+#include "qtmodelingglobal.h"
+#include "private/qobject_p.h"
+
+#include <QtCore/QStringList>
+#include <QtCore/QXmlStreamReader>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(QtModeling)
+
+class QMetaModelPlugin;
+class QScriptEngine;
+
+class Q_MODELING_EXPORT QXmiReaderPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QXmiReader)
+
+public:
+ explicit QXmiReaderPrivate();
+ virtual ~QXmiReaderPrivate();
+
+ QHash<QString, QObject *> idMap;
+ QHash< QString, QPair<QMetaModelPlugin *, QJsonObject> > metaModelPlugins;
+ QHash<QString, QString> xmlNamespaceToImplementationNamespace;
+ QStringList errors;
+ QScriptEngine *scriptEngine;
+ bool initMetaModel;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QTMODELING_QXMIREADER_P_H
+
diff --git a/src/modeling/qxmiwriter.cpp b/src/modeling/qxmiwriter.cpp
new file mode 100644
index 00000000..17fb00e3
--- /dev/null
+++ b/src/modeling/qxmiwriter.cpp
@@ -0,0 +1,287 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Sandro S. Andrade <sandroandrade@kde.org>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtModeling module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "qxmiwriter.h"
+#include "qxmiwriter_p.h"
+#include "qmetamodelplugin.h"
+
+#include <QtModeling/QModelingObject>
+
+#include <QtCore/QSet>
+#include <QtCore/QDir>
+#include <QtCore/QJsonObject>
+#include <QtCore/QPluginLoader>
+#include <QtCore/QMetaClassInfo>
+#include <QtCore/QCoreApplication>
+#include <QtCore/QRegularExpression>
+
+QT_BEGIN_NAMESPACE
+
+QXmiWriterPrivate::QXmiWriterPrivate(QObject *modelingObject)
+ : modelingObject(modelingObject)
+{
+ writer.setAutoFormatting(true);
+ writer.setAutoFormattingIndent(2);
+}
+
+QXmiWriterPrivate::~QXmiWriterPrivate()
+{
+}
+
+QXmiWriter::QXmiWriter(QObject *modelingObject, QObject *parent) :
+ QObject(*new QXmiWriterPrivate(modelingObject), parent)
+{
+ loadPlugins();
+}
+
+QXmiWriter::~QXmiWriter()
+{
+}
+
+void QXmiWriter::loadPlugins()
+{
+ Q_D(QXmiWriter);
+
+ d->metaModelPlugins.clear();
+ QMetaModelPlugin *metaModelPlugin = 0;
+ foreach (QString pluginPath, QCoreApplication::libraryPaths()) {
+ QDir pluginsDir(pluginPath);
+ pluginsDir.cd(QString::fromLatin1("metamodels"));
+ foreach (QString fileName, pluginsDir.entryList(QDir::Files)) {
+ QPluginLoader loader(pluginsDir.absoluteFilePath(fileName));
+ QObject *plugin = loader.instance();
+ if (plugin && (metaModelPlugin = qobject_cast<QMetaModelPlugin *>(plugin)))
+ d->metaModelPlugins.insert(loader.metaData().value(QString::fromLatin1("MetaData")).toObject().value(QString::fromLatin1("MetaModelNamespaceUri")).toString(), QPair<QMetaModelPlugin *, QJsonObject>(metaModelPlugin, loader.metaData().value(QString::fromLatin1("MetaData")).toObject()));
+ }
+ }
+}
+
+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"));
+
+ QString metaModelClassName = QString::fromLatin1(d->modelingObject->metaObject()->className());
+ int pos = 2;
+ while (metaModelClassName[pos] == metaModelClassName[pos].toLower()) pos++;
+ QString metaModelImplementationNamespace = metaModelClassName.left(pos);
+ typedef QPair<QMetaModelPlugin *, QJsonObject> PluginData;
+ foreach (const PluginData &pair, d->metaModelPlugins.values()) {
+ if (pair.second.value(QString::fromLatin1("MetaModelPrefix")).toString() == metaModelImplementationNamespace) {
+ d->metaModelXmlNamespace = pair.second.value(QString::fromLatin1("MetaModelPrefix")).toString().mid(1).toLower();
+ d->writer.writeNamespace(pair.second.value(QString::fromLatin1("MetaModelNamespaceUri")).toString(), d->metaModelXmlNamespace);
+ break;
+ }
+ }
+
+ d->idMap.clear();
+ d->idStack.clear();
+ d->blacklistedOppositeEnds.clear();
+
+ d->visitedObjects.clear();
+ populateIdMap(d->modelingObject);
+ d->visitedObjects.clear();
+ writeObject(d->modelingObject);
+
+ d->writer.writeEndDocument();
+ return true;
+}
+
+void QXmiWriter::populateIdMap(QObject *modelingObject, int index)
+{
+ Q_D(QXmiWriter);
+
+ if (modelingObject->metaObject()->indexOfProperty("name") != -1)
+ d->idStack << modelingObject->property("name").toString();
+ else
+ d->idStack << QString::fromLatin1(modelingObject->metaObject()->className()).remove(QString::fromLatin1(modelingObject->metaObject()->classInfo(modelingObject->metaObject()->indexOfClassInfo("MetaModelPrefix")).value())) +
+ QString::fromLatin1((index != -1) ? ".%1":"").arg(index);
+ d->idMap.insert(modelingObject, d->idStack.join(QString::fromLatin1("-")));
+ d->visitedObjects.append(modelingObject);
+
+ const QMetaObject *metaObject = modelingObject->metaObject();
+ int propertyCount = metaObject->propertyCount();
+
+ for (int i = 0; i < propertyCount; ++i) {
+ QMetaProperty metaProperty = metaObject->property(i);
+ QString typeName = QString::fromLatin1(metaProperty.typeName());
+ QVariant variant = metaProperty.read(modelingObject);
+ QString aggregationRole = QModelingObject::propertyData(metaProperty, QtModeling::AggregationRole).toString();
+
+ if (aggregationRole == QString::fromLatin1("composite"))
+ if (!QModelingObject::propertyData(metaProperty, QtModeling::OppositeEndRole).toString().isEmpty()) {
+ d->blacklistedOppositeEnds << QModelingObject::propertyData(metaProperty, QtModeling::OppositeEndRole).toString();
+ }
+
+ if (QModelingObject::propertyData(metaProperty, QtModeling::AggregationRole).toString() != QString::fromLatin1("composite"))
+ continue;
+
+ if (typeName.endsWith('*') && qvariant_cast<QObject *>(variant))
+ populateIdMap(qvariant_cast<QObject *>(variant), 0);
+ else if (typeName.contains(QString::fromLatin1("QSet")) && variant.isValid()) {
+ QSet<QObject *> elements = *(static_cast<QSet<QObject *> *>(variant.data()));
+ int i = 0;
+ foreach (QObject *objectElement, elements) {
+ if (!d->visitedObjects.contains(objectElement))
+ populateIdMap(objectElement, i++);
+ }
+ }
+ else if (typeName.contains(QString::fromLatin1("QList")) && variant.isValid()) {
+ QList<QObject *> elements = *(static_cast<QList<QObject *> *>(variant.data()));
+ int i = 0;
+ foreach (QObject *objectElement, elements) {
+ if (!d->visitedObjects.contains(objectElement))
+ populateIdMap(objectElement, i++);
+ }
+ }
+ }
+
+ d->idStack.removeLast();
+}
+
+void QXmiWriter::writeObject(QObject *modelingObject, QString elementName)
+{
+ Q_D(QXmiWriter);
+
+ if (d->visitedObjects.contains(modelingObject))
+ return;
+
+ d->visitedObjects.append(modelingObject);
+
+ d->writer.writeStartElement(elementName.isEmpty() ? QString::fromLatin1(d->modelingObject->metaObject()->className()).split(QString::fromLatin1("::")).last().remove(QString::fromLatin1(modelingObject->metaObject()->classInfo(modelingObject->metaObject()->indexOfClassInfo("MetaModelPrefix")).value())).prepend(QString::fromLatin1("%1:").arg(d->metaModelXmlNamespace))
+ :
+ elementName);
+ if (!elementName.isEmpty())
+ d->writer.writeAttribute(QString::fromLatin1("xmi:type"), QString::fromLatin1(modelingObject->metaObject()->className()).remove(QString::fromLatin1(modelingObject->metaObject()->classInfo(modelingObject->metaObject()->indexOfClassInfo("MetaModelPrefix")).value())).prepend(QString::fromLatin1(modelingObject->metaObject()->classInfo(modelingObject->metaObject()->indexOfClassInfo("MetaModelPrefix")).value()).mid(1).toLower().append(QString::fromLatin1(":"))));
+
+ const QMetaObject *metaObject = modelingObject->metaObject();
+ int propertyCount = metaObject->propertyCount();
+
+ for (int i = propertyCount - 1; i >= 0; --i) {
+ QMetaProperty metaProperty = metaObject->property(i);
+ QVariant variant = metaProperty.read(modelingObject);
+
+ if (!metaProperty.isStored() || QString::fromLatin1(metaProperty.name()) == QString::fromLatin1("objectName") || QModelingObject::propertyData(metaProperty, QtModeling::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() && modelingObject->isPropertyModified(metaProperty)))
+ d->writer.writeAttribute(QString::fromLatin1(metaProperty.name()), QString::fromLatin1(variant.toBool() ? "true":"false"));
+ }
+ else if (metaProperty.isEnumType()) {
+ //if (!metaProperty.isResettable() || (metaProperty.isResettable() && modelingObject->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(modelingObject));
+ for (int i = propertyCount - 1; i >= 0; --i) {
+ QMetaProperty metaProperty = metaObject->property(i);
+
+ if (d->blacklistedOppositeEnds.contains(QString::fromLatin1("%1::%2").arg(QString::fromLatin1(metaObject->className())).arg(QString::fromLatin1(metaProperty.name()).remove(QRegularExpression(QString::fromLatin1("_$"))))))
+ continue;
+
+ QString typeName = QString::fromLatin1(metaProperty.typeName());
+ QVariant variant = metaProperty.read(modelingObject);
+ QString aggregationRole = QModelingObject::propertyData(metaProperty, QtModeling::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() || QModelingObject::propertyData(metaProperty, QtModeling::IsDerivedUnionRole).toBool())
+ continue;
+
+ if (typeName.endsWith('*') && qvariant_cast<QObject *>(variant)) {
+ if (aggregationRole == QString::fromLatin1("composite")) {
+ writeObject(qvariant_cast<QObject *>(variant), modifiedPropertyName);
+ }
+ else {
+ d->writer.writeStartElement(QString::fromLatin1(metaProperty.name()));
+ d->writer.writeAttribute(QString::fromLatin1("xmi:idref"), d->idMap.value(qvariant_cast<QObject *>(variant)));
+ d->writer.writeEndElement();
+ }
+ }
+ else if (typeName.contains(QString::fromLatin1("QSet")) && variant.isValid()) {
+ QSet<QObject *> elements = *(static_cast<QSet<QObject *> *>(variant.data()));
+ if (aggregationRole == QString::fromLatin1("composite")) {
+ foreach (QObject *objectElement, elements)
+ writeObject(objectElement, modifiedPropertyName);
+ }
+ else {
+ foreach (QObject *objectElement, elements) {
+ d->writer.writeStartElement(QString::fromLatin1(metaProperty.name()));
+ d->writer.writeAttribute(QString::fromLatin1("xmi:idref"), d->idMap.value(objectElement));
+ d->writer.writeEndElement();
+ }
+ }
+ }
+ else if (typeName.contains(QString::fromLatin1("QList")) && variant.isValid()) {
+ QList<QObject *> elements = *(static_cast<QList<QObject *> *>(variant.data()));
+ if (aggregationRole == QString::fromLatin1("composite")) {
+ foreach (QObject *objectElement, elements)
+ writeObject(objectElement, modifiedPropertyName);
+ }
+ else {
+ foreach (QObject *objectElement, elements) {
+ d->writer.writeStartElement(QString::fromLatin1(metaProperty.name()));
+ d->writer.writeAttribute(QString::fromLatin1("xmi:idref"), d->idMap.value(objectElement));
+ d->writer.writeEndElement();
+ }
+ }
+ }
+ }
+
+ d->writer.writeEndElement();
+}
+
+#include "moc_qxmiwriter.cpp"
+
+QT_END_NAMESPACE
+
diff --git a/src/modeling/qxmiwriter.h b/src/modeling/qxmiwriter.h
new file mode 100644
index 00000000..93795e85
--- /dev/null
+++ b/src/modeling/qxmiwriter.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Sandro S. Andrade <sandroandrade@kde.org>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtModeling module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QTMODELING_QXMIWRITER_H
+#define QTMODELING_QXMIWRITER_H
+
+#include <QtModeling/QtModelingGlobal>
+
+#include <QtCore/QObject>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(QtModeling)
+
+class QIODevice;
+class QObject;
+
+class QXmiWriterPrivate;
+
+class Q_MODELING_EXPORT QXmiWriter : public QObject
+{
+ Q_OBJECT
+
+ Q_DISABLE_COPY(QXmiWriter)
+ Q_DECLARE_PRIVATE(QXmiWriter)
+
+public:
+ explicit QXmiWriter(QObject *modelingObject, QObject *parent = 0);
+ virtual ~QXmiWriter();
+
+ bool writeFile(QIODevice *device);
+
+protected:
+ void loadPlugins();
+ void populateIdMap(QObject *modelingObject, int index = -1);
+ void writeObject(QObject *modelingObject, QString elementName = QStringLiteral(""));
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QTMODELING_QXMIWRITER_H
+
diff --git a/src/modeling/qxmiwriter_p.h b/src/modeling/qxmiwriter_p.h
new file mode 100644
index 00000000..ae99d850
--- /dev/null
+++ b/src/modeling/qxmiwriter_p.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Sandro S. Andrade <sandroandrade@kde.org>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtModeling module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QTMODELING_QXMIWRITER_P_H
+#define QTMODELING_QXMIWRITER_P_H
+
+#include "qtmodelingglobal.h"
+#include "private/qobject_p.h"
+
+#include <QtCore/QStringList>
+#include <QtCore/QXmlStreamWriter>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(QtModeling)
+
+class QMetaModelPlugin;
+
+class Q_MODELING_EXPORT QXmiWriterPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QXmiWriter)
+
+public:
+ explicit QXmiWriterPrivate(QObject *modelingObject);
+ virtual ~QXmiWriterPrivate();
+
+ QObject *modelingObject;
+ QXmlStreamWriter writer;
+ QHash< QString, QPair<QMetaModelPlugin *, QJsonObject> > metaModelPlugins;
+ QObjectList visitedObjects;
+ QHash<QObject *, QString> idMap;
+ QStringList idStack;
+ QString metaModelXmlNamespace;
+ QStringList blacklistedOppositeEnds;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QTMODELING_QXMIWRITER_P_H
+