Commit 869f4a16 authored by Andreas Cord-Landwehr's avatar Andreas Cord-Landwehr
Browse files

Remove obsolete LanguageResource and ResourceInterface

parent e9a26bf3
......@@ -24,7 +24,6 @@
#include "core/unit.h"
#include "core/phrase.h"
#include "core/phonemegroup.h"
#include "core/resources/languageresource.h"
#include "core/resources/courseresource.h"
#include <QTest>
......
......@@ -24,7 +24,6 @@
#include "core/unit.h"
#include "core/phrase.h"
#include "core/resources/courseparser.h"
#include "core/resources/languageresource.h"
#include "core/resources/editablecourseresource.h"
#include <memory>
......
......@@ -23,7 +23,6 @@
#include "core/language.h"
#include "core/unit.h"
#include "core/phrase.h"
#include "core/resources/languageresource.h"
#include "core/resources/skeletonresource.h"
#include <QTest>
......
......@@ -57,8 +57,6 @@ set(artikulateCore_SRCS
core/trainingaction.cpp
core/trainingactionicon.cpp
core/trainingsession.cpp
core/resources/resourceinterface.cpp
core/resources/languageresource.cpp
core/resources/courseparser.cpp
core/resources/courseresource.cpp
core/resources/editablecourseresource.cpp
......
......@@ -25,7 +25,6 @@
#include "phrase.h"
#include "phoneme.h"
#include "phonemegroup.h"
#include "resources/languageresource.h"
#include "resources/editablecourseresource.h"
#include "resources/skeletonresource.h"
#include "liblearnerprofile/src/profilemanager.h"
......@@ -44,16 +43,7 @@ ContributorRepository::ContributorRepository()
loadLanguageResources();
}
ContributorRepository::~ContributorRepository()
{
for (auto skeleton : m_skeletonResources) {
skeleton->deleteLater();
}
m_skeletonResources.clear();
for (auto language : m_languageResources) {
language->deleteLater();
}
}
ContributorRepository::~ContributorRepository() = default;
void ContributorRepository::loadLanguageResources()
{
......@@ -107,12 +97,12 @@ void ContributorRepository::addLanguage(const QUrl &languageFile)
return;
}
std::shared_ptr<LanguageResource> resource(new LanguageResource(languageFile));
auto language = Language::create(languageFile);
emit languageResourceAboutToBeAdded(resource.get(), m_languageResources.count());
m_languageResources.append(resource);
emit languageResourceAboutToBeAdded(language, m_languages.count());
m_languages.append(language);
m_loadedResources.append(languageFile.toLocalFile());
m_courses.insert(resource->identifier(), QVector<std::shared_ptr<EditableCourseResource>>());
m_courses.insert(language->id(), QVector<std::shared_ptr<EditableCourseResource>>());
emit languageResourceAdded();
}
......@@ -128,17 +118,13 @@ void ContributorRepository::setStorageLocation(const QString &path)
QVector<std::shared_ptr<Language>> ContributorRepository::languages() const
{
QVector<std::shared_ptr<Language>> languages;
for (auto resourse : m_languageResources) {
languages.append(resourse->language());
}
return languages;
return m_languages;
}
std::shared_ptr<Language> ContributorRepository::language(int index) const
{
Q_ASSERT(index >= 0 && index < m_languageResources.count());
return m_languageResources.at(index)->language();
Q_ASSERT(index >= 0 && index < m_languages.count());
return m_languages.at(index);
}
Language * ContributorRepository::language(LearnerProfile::LearningGoal *learningGoal) const
......@@ -150,9 +136,9 @@ Language * ContributorRepository::language(LearnerProfile::LearningGoal *learnin
qCritical() << "Cannot translate non-language learning goal to language";
return nullptr;
}
for (auto resource : m_languageResources) {
if (resource->identifier() == learningGoal->identifier()) {
return resource->language().get();
for (auto language : m_languages) {
if (language->id() == learningGoal->identifier()) {
return language.get();
}
}
qCritical() << "No language registered with identifier " << learningGoal->identifier() << ": aborting";
......
......@@ -170,7 +170,7 @@ public:
Q_SIGNALS:
void languageResourceAdded();
void languageResourceAboutToBeAdded(LanguageResource*,int);
void languageResourceAboutToBeAdded(std::shared_ptr<Language>,int);
void languageResourceRemoved();
void languageResourceAboutToBeRemoved(int);
void repositoryChanged();
......@@ -187,7 +187,7 @@ private:
*/
void loadLanguageResources();
QString m_storageLocation;
QVector<std::shared_ptr<LanguageResource>> m_languageResources;
QVector<std::shared_ptr<Language>> m_languages;
QMap<QString, QVector<std::shared_ptr<EditableCourseResource>> > m_courses; //!> (language-id, course-resource)
QVector<std::shared_ptr<IEditableCourse>> m_skeletonResources;
QStringList m_loadedResources;
......
......@@ -22,7 +22,6 @@
#include "core/language.h"
#include "core/resources/editablecourseresource.h"
#include "core/resources/skeletonresource.h"
#include "core/resources/languageresource.h"
#include "core/unit.h"
#include "core/phrase.h"
#include "core/contributorrepository.h"
......
......@@ -25,6 +25,48 @@
#include "artikulate_debug.h"
#include <KLocalizedString>
#include <QQmlEngine>
#include <QXmlSchema>
#include <QDomDocument>
#include "resources/courseparser.h"
std::shared_ptr<Language> Language::create(QUrl file)
{
QXmlSchema schema = CourseParser::loadXmlSchema(QStringLiteral("language"));
if (!schema.isValid()) {
return nullptr;
}
QDomDocument document = CourseParser::loadDomDocument(file, schema);
if (document.isNull()) {
qCWarning(ARTIKULATE_LOG) << "Could not parse document " << file.toLocalFile() << ", aborting.";
return nullptr;
}
QDomElement root(document.documentElement());
auto language = std::shared_ptr<Language>(new Language());
language->setFile(file);
language->setId(root.firstChildElement(QStringLiteral("id")).text());
language->setTitle(root.firstChildElement(QStringLiteral("title")).text());
language->seti18nTitle(root.firstChildElement(QStringLiteral("i18nTitle")).text());
// create phoneme groups
for (QDomElement groupNode = root.firstChildElement(QStringLiteral("phonemeGroups")).firstChildElement();
!groupNode.isNull();
groupNode = groupNode.nextSiblingElement())
{
auto group = language->addPhonemeGroup(
groupNode.firstChildElement(QStringLiteral("id")).text(),
groupNode.firstChildElement(QStringLiteral("title")).text());
group->setDescription(groupNode.attribute(QStringLiteral("description")));
// register phonemes
for (QDomElement phonemeNode = groupNode.firstChildElement(QStringLiteral("phonemes")).firstChildElement();
!phonemeNode.isNull();
phonemeNode = phonemeNode.nextSiblingElement())
{
group->addPhoneme(phonemeNode.firstChildElement(QStringLiteral("id")).text(), phonemeNode.firstChildElement(QStringLiteral("title")).text());
}
}
return language;
}
Language::Language()
: QObject()
......
......@@ -42,6 +42,8 @@ public:
explicit Language();
~Language();
static std::shared_ptr<Language> create(QUrl file);
QString id() const;
void setId(const QString &id);
QString title() const;
......
......@@ -21,7 +21,6 @@
#include "resourcerepository.h"
#include "artikulate_debug.h"
#include "resources/courseresource.h"
#include "resources/languageresource.h"
#include "core/language.h"
#include <QStandardPaths>
#include <QUrl>
......@@ -86,7 +85,7 @@ QVector<std::shared_ptr<Language>> ResourceRepository::languages() const
if (language == nullptr) {
continue;
}
languages.append(language->language());
languages.append(language);
}
return languages;
}
......@@ -94,7 +93,7 @@ QVector<std::shared_ptr<Language>> ResourceRepository::languages() const
Language * ResourceRepository::language(const QString &id) const
{
if (m_languages.contains(id)) {
return m_languages.value(id)->language().get();
return m_languages.value(id).get();
}
return nullptr;
}
......@@ -146,17 +145,15 @@ bool ResourceRepository::loadCourse(const QString &resourceFile)
bool ResourceRepository::loadLanguage(const QString &resourceFile)
{
std::shared_ptr<LanguageResource> resource(new LanguageResource(QUrl::fromLocalFile(resourceFile)));
if (!resource) {
auto language = Language::create(QUrl::fromLocalFile(resourceFile));
if (!language) {
qCWarning(ARTIKULATE_CORE()) << "Could not load language" << resourceFile;
resource->deleteLater();
return false;
}
if (m_languages.contains(resource->identifier())) {
if (m_languages.contains(language->id())) {
qCWarning(ARTIKULATE_CORE()) << "Could not load language" << resourceFile;
resource->deleteLater();
return false;
}
m_languages.insert(resource->identifier(), resource);
m_languages.insert(language->id(), language);
return true;
}
......@@ -89,7 +89,7 @@ private:
bool loadCourse(const QString &resourceFile);
bool loadLanguage(const QString &resourceFile);
QVector<std::shared_ptr<ICourse>> m_courses;
QHash<QString, std::shared_ptr<LanguageResource>> m_languages; ///>! (language-identifier, language resource)
QHash<QString, std::shared_ptr<Language>> m_languages; ///>! (language-identifier, language resource)
QStringList m_loadedCourses;
const QString m_storageLocation;
};
......
/*
* Copyright 2013 Andreas Cord-Landwehr <cordlandwehr@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "languageresource.h"
#include "courseparser.h"
#include "core/language.h"
#include "core/phoneme.h"
#include "core/phonemegroup.h"
#include <QXmlSchema>
#include <QXmlStreamReader>
#include <QDomDocument>
#include <QIODevice>
#include <QFile>
#include "artikulate_debug.h"
class LanguageResourcePrivate
{
public:
LanguageResourcePrivate() = default;
~LanguageResourcePrivate() = default;
std::shared_ptr<Language> m_language;
QString m_identifier;
QUrl m_path;
QString m_title;
QString m_i18nTitle;
};
LanguageResource::LanguageResource(const QUrl &path)
: d(new LanguageResourcePrivate)
{
d->m_path = path;
// load basic information from language file, but does not parse everything
QXmlStreamReader xml;
QFile file(path.toLocalFile());
if (file.open(QIODevice::ReadOnly)) {
xml.setDevice(&file);
xml.readNextStartElement();
while (xml.readNext() && !xml.atEnd()) {
if (xml.name() == "id") {
d->m_identifier = xml.readElementText();
}
if (xml.name() == "title") {
d->m_title = xml.readElementText();
}
if (xml.name() == "i18nTitle") {
d->m_i18nTitle = xml.readElementText();
}
// quit reading when basic elements are read
if (!d->m_identifier.isEmpty()
&& !d->m_title.isEmpty()
&& !d->m_i18nTitle.isEmpty()
)
{
break;
}
}
if (xml.hasError()) {
qCritical() << "Error occurred when reading Language XML file:" << path.toLocalFile();
}
}
xml.clear();
file.close();
}
LanguageResource::~LanguageResource()
{
}
QString LanguageResource::identifier()
{
return d->m_identifier;
}
QString LanguageResource::title()
{
return d->m_title;
}
QString LanguageResource::i18nTitle()
{
return d->m_i18nTitle;
}
bool LanguageResource::isOpen() const
{
return (d->m_language != nullptr);
}
QUrl LanguageResource::path() const
{
return d->m_path;
}
std::shared_ptr<Language> LanguageResource::language()
{
if (d->m_language) {
return d->m_language;
}
if (!d->m_path.isLocalFile()) {
qCWarning(ARTIKULATE_LOG) << "Cannot open language file at " << d->m_path.toLocalFile() << ", aborting.";
return nullptr;
}
QXmlSchema schema = CourseParser::loadXmlSchema(QStringLiteral("language"));
if (!schema.isValid()) {
return nullptr;
}
QDomDocument document = CourseParser::loadDomDocument(d->m_path, schema);
if (document.isNull()) {
qCWarning(ARTIKULATE_LOG) << "Could not parse document " << d->m_path.toLocalFile() << ", aborting.";
return nullptr;
}
QDomElement root(document.documentElement());
d->m_language = std::shared_ptr<Language>(new Language());
d->m_language->setFile(d->m_path);
d->m_language->setId(root.firstChildElement(QStringLiteral("id")).text());
d->m_language->setTitle(root.firstChildElement(QStringLiteral("title")).text());
d->m_language->seti18nTitle(root.firstChildElement(QStringLiteral("i18nTitle")).text());
// create phoneme groups
for (QDomElement groupNode = root.firstChildElement(QStringLiteral("phonemeGroups")).firstChildElement();
!groupNode.isNull();
groupNode = groupNode.nextSiblingElement())
{
auto group = d->m_language->addPhonemeGroup(
groupNode.firstChildElement(QStringLiteral("id")).text(),
groupNode.firstChildElement(QStringLiteral("title")).text());
group->setDescription(groupNode.attribute(QStringLiteral("description")));
// register phonemes
for (QDomElement phonemeNode = groupNode.firstChildElement(QStringLiteral("phonemes")).firstChildElement();
!phonemeNode.isNull();
phonemeNode = phonemeNode.nextSiblingElement())
{
group->addPhoneme(phonemeNode.firstChildElement(QStringLiteral("id")).text(), phonemeNode.firstChildElement(QStringLiteral("title")).text());
}
}
return d->m_language;
}
/*
* Copyright 2013 Andreas Cord-Landwehr <cordlandwehr@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LANGUAGERESOURCE_H
#define LANGUAGERESOURCE_H
#include "artikulatecore_export.h"
#include <memory>
#include <QObject>
class LanguageResourcePrivate;
class Language;
class ARTIKULATECORE_EXPORT LanguageResource : public QObject
{
Q_OBJECT
public:
explicit LanguageResource(const QUrl &path);
virtual ~LanguageResource();
/**
* \return unique identifier
*/
QString identifier();
/**
* \return human readable localized title
*/
QString title();
/**
* \return human readable title in English
*/
QString i18nTitle();
/**
* \return true if resource is loaded, otherwise false
*/
bool isOpen() const;
/**
* \return path to resource file
*/
QUrl path() const;
/**
* \return reference to the loaded resource
* if resource is not open yet, it will be loaded
*/
std::shared_ptr<Language> language();
private:
const QScopedPointer<LanguageResourcePrivate> d;
};
#endif
/*
* Copyright 2013-2015 Andreas Cord-Landwehr <cordlandwehr@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "resourceinterface.h"
#include "artikulate_debug.h"
#include <QUrl>
#include <QIODevice>
#include <QXmlSchema>
#include <QXmlSchemaValidator>
#include <QDomDocument>
#include <QFile>
#include <QStandardPaths>
ResourceInterface::ResourceInterface(ResourceManager *resourceManager)
: m_contributorResource(false)
{
Q_UNUSED(resourceManager)
}
ResourceInterface::~ResourceInterface()
{
}
void ResourceInterface::setContributorResource(bool contributorResource)
{
m_contributorResource = contributorResource;
}
bool ResourceInterface::isContributorResource() const
{
return m_contributorResource;
}
void ResourceInterface::sync()
{
qCWarning(ARTIKULATE_LOG) << "Resource does not implement syncing.";
}
void ResourceInterface::reload()
{
qCWarning(ARTIKULATE_LOG) << "Resource does not implement reloading.";
}
QXmlSchema ResourceInterface::loadXmlSchema(const QString &schemeName) const
{
QString relPath = QStringLiteral(":/artikulate/schemes/%1.xsd").arg(schemeName);
QUrl file = QUrl::fromLocalFile(relPath);
QXmlSchema schema;
if (file.isEmpty() || schema.load(file) == false) {
qCWarning(ARTIKULATE_LOG) << "Schema at file " << file.toLocalFile() << " is invalid.";
}
return schema;
}
QDomDocument ResourceInterface::loadDomDocument(const QUrl &path, const QXmlSchema &schema) const
{
QDomDocument document;
QXmlSchemaValidator validator(schema);
if (!validator.validate(path)) {
qCWarning(ARTIKULATE_LOG) << "Schema is not valid, aborting loading of XML document:" << path.toLocalFile();
return document;
}
QString errorMsg;
QFile file(path.toLocalFile());
if (file.open(QIODevice::ReadOnly)) {
if (!document.setContent(&file, &errorMsg)) {
qCWarning(ARTIKULATE_LOG) << errorMsg;
}
} else {
qCWarning(ARTIKULATE_LOG) << "Could not open XML document " << path.toLocalFile() << " for reading, aborting.";
}
return document;
}
/*
* Copyright 2013 Andreas Cord-Landwehr <cordlandwehr@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the