Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:12.1
kdebase4-runtime
1b66b02e-kderuntime-nepomuk-47branch-partialurl...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 1b66b02e-kderuntime-nepomuk-47branch-partialurls.diff of Package kdebase4-runtime
commit 1b66b02ecf6a055159290849c8bf708a7043bd0d Author: Sebastian Trueg <trueg@kde.org> Date: Thu Oct 20 21:32:14 2011 +0200 Handle parent folders or convertable URLs. So far we converted URLs which actually exist. Now we also handle partial URLs like /media/foo if a storage is mounted on /media/foobar. This is handled by adding additional regex filters to the already existing one. BUG: 284529 diff --git a/nepomuk/common/removablemediacache.cpp b/nepomuk/common/removablemediacache.cpp index dbb31c8..c6cde9b 100644 --- a/nepomuk/common/removablemediacache.cpp +++ b/nepomuk/common/removablemediacache.cpp @@ -165,6 +165,21 @@ const Nepomuk::RemovableMediaCache::Entry* Nepomuk::RemovableMediaCache::findEnt } +QList<const Nepomuk::RemovableMediaCache::Entry*> Nepomuk::RemovableMediaCache::findEntriesByMountPath(const QString &path) const +{ + QList<const Entry*> entries; + for( QHash<QString, Entry>::const_iterator it = m_metadataCache.constBegin(); + it != m_metadataCache.constEnd(); ++it ) { + const Entry& entry = *it; + if(entry.isMounted() && + entry.mountPath().startsWith(path)) { + entries.append(&entry); + } + } + return entries; +} + + bool Nepomuk::RemovableMediaCache::hasRemovableSchema(const KUrl &url) const { return m_usedSchemas.contains(url.scheme()); diff --git a/nepomuk/common/removablemediacache.h b/nepomuk/common/removablemediacache.h index 25982f0..8060765 100644 --- a/nepomuk/common/removablemediacache.h +++ b/nepomuk/common/removablemediacache.h @@ -74,6 +74,14 @@ public: const Entry* findEntryByFilePath( const QString& path ) const; const Entry* findEntryByUrl(const KUrl& url) const; + /** + * Searches for entries which are mounted at a path which starts with + * the given one. Example: a \p path \p /media will result in all + * entries which are mounted under \p /media like \p /media/disk1 or + * \p /media/cdrom. + */ + QList<const Entry*> findEntriesByMountPath(const QString& path) const; + QList<const Entry*> allMedia() const; /** diff --git a/nepomuk/services/storage/removablemediamodel.cpp b/nepomuk/services/storage/removablemediamodel.cpp index 836668e..aa3c49c 100644 --- a/nepomuk/services/storage/removablemediamodel.cpp +++ b/nepomuk/services/storage/removablemediamodel.cpp @@ -193,14 +193,15 @@ Soprano::QueryResultIterator Nepomuk::RemovableMediaModel::executeQuery(const QS return new QueryResultIteratorBackend(this, FilterModel::executeQuery(convertFileUrls(query), language, userQueryLanguage)); } -Soprano::Node Nepomuk::RemovableMediaModel::convertFileUrl(const Soprano::Node &node) const +Soprano::Node Nepomuk::RemovableMediaModel::convertFileUrl(const Soprano::Node &node, bool forRegEx) const { if(node.isResource()) { const QUrl url = node.uri(); if(url.scheme() == QLatin1String("file")) { const QString localFilePath = url.toLocalFile(); if(const RemovableMediaCache::Entry* entry = m_removableMediaCache->findEntryByFilePath(localFilePath)) { - if(entry->isMounted()) { + if(entry->isMounted() && + (!forRegEx || entry->mountPath().length() < localFilePath.length())) { return entry->constructRelativeUrl(localFilePath); } } @@ -270,11 +271,28 @@ QString Nepomuk::RemovableMediaModel::convertFileUrls(const QString &query) cons // is 0, 1, or 3 - nothing else int quoteCnt = 0; + + // if quoteCnt > 0, ie. we are in a literal this is the first char of it int literalStartPos = 0; + + // true if we are in a regex filter bool inRegEx = false; + + // if inRegEx is true this is the position where the regex starts in the new query + int newQueryRegExStart = 0; + + // if inRegEx is true this is the variable used in the regex (including any functions) + QString variable; + + // true if we are in a resource URI like: <....> bool inRes = false; + + // the char used for quote ' or " QChar quote; + + // the new query we construct QString newQuery; + for(int i = 0; i < query.length(); ++i) { const QChar c = query[i]; @@ -359,7 +377,21 @@ QString Nepomuk::RemovableMediaModel::convertFileUrls(const QString &query) cons query[i+2].toLower() == 'g' && query[i+3].toLower() == 'e' && query[i+4].toLower() == 'x') { - inRegEx = true; + // determine the variable + int pos = query.indexOf('(', i+4); + if(pos > i+4) { + int endPos = query.indexOf(',', pos+1); + if(endPos > pos+1) { + inRegEx = true; + variable = query.mid(pos+1, endPos-pos-1).trimmed(); + newQueryRegExStart = newQuery.length(); + // we already copy the entire start of the REGEX since our REGEX end check is way too simple + // It would not handle function calls like REGEX(STR(?var)),... + newQuery.append(query.mid(i, endPos-i+1)); + i = endPos; + continue; + } + } } } @@ -401,10 +433,44 @@ QString Nepomuk::RemovableMediaModel::convertFileUrls(const QString &query) cons if(pos > 0) { // convert the file URL into a filex URL (if necessary) const KUrl fileUrl = query.mid(i, pos-i); - newQuery += KUrl(convertFileUrl(fileUrl).uri()).url(); - // set i to last char we handled and let the loop continue with the end of the quote - i = pos-1; - continue; + KUrl convertedUrl = KUrl(convertFileUrl(fileUrl, true).uri()); + + // 1. Case: we have an exact match with one of the removable media (this always includes a trailing slash) + if(fileUrl != convertedUrl) { + newQuery += convertedUrl.url(); + // set i to last char we handled and let the loop continue with the end of the quote + i = pos-1; + continue; + } + + // 2. Case The query tries to match a super-folder of one of the removable media. In that case we need + // to add additional regex filters which match all candidates + else { + // create regex filters for all of them + // We need to append a slash since we do not want to include a possibly unmounted medium "foobar" if only "foo" is mounted. + QStringList filters; + foreach(const RemovableMediaCache::Entry* entry, m_removableMediaCache->findEntriesByMountPath(fileUrl.toLocalFile())) { + filters << QString::fromLatin1("REGEX(%1, '^%2/')").arg(variable, entry->constructRelativeUrl(QString()).url()); + } + if(!filters.isEmpty()) { + // 1. copy the original regex + filters.prepend(QString::fromLatin1("REGEX(%1, '^%2')").arg(variable, query.mid(i, pos-i))); + + // 2. Strip away the previsouly copied REGEX term + newQuery.truncate(newQueryRegExStart); + + // 3. append the new ones and add new parethesis + newQuery.append('('); + newQuery.append(filters.join(QLatin1String(" || "))); + newQuery.append(')'); + + // 4. update i: + // if we find a closing parenthesis, that is the last char we handled + // otherwise it is just pos+quoteCnt-1 since the last quote is what we handled + i = qMax(pos+quoteCnt-1, query.indexOf(')', pos+1)); + continue; + } + } } } } diff --git a/nepomuk/services/storage/removablemediamodel.h b/nepomuk/services/storage/removablemediamodel.h index 52e4eda..4926439 100644 --- a/nepomuk/services/storage/removablemediamodel.h +++ b/nepomuk/services/storage/removablemediamodel.h @@ -93,7 +93,13 @@ private: */ Soprano::Statement convertFileUrls(const Soprano::Statement& s) const; - Soprano::Node convertFileUrl(const Soprano::Node& node) const; + /** + * Convert a local file URL into its internal counterpart or return the + * given URL if it does not need to be converted. + * \param forRegEx If true the base path of the storage medium will not + * be converted. + */ + Soprano::Node convertFileUrl(const Soprano::Node& node, bool forRegEx = false) const; /** * Converts file:/ URLs into their filex:/ counterpart if necessary. diff --git a/nepomuk/services/storage/test/removablemediamodeltest.cpp b/nepomuk/services/storage/test/removablemediamodeltest.cpp index c47c26d..eeae40d 100644 --- a/nepomuk/services/storage/test/removablemediamodeltest.cpp +++ b/nepomuk/services/storage/test/removablemediamodeltest.cpp @@ -153,6 +153,10 @@ void RemovableMediaModelTest::testConvertFileUrlsInQuery_data() << QString::fromLatin1("select ?r where { ?r ?p <file:///media/XO-Y4/test.txt> . }") << QString::fromLatin1("select ?r where { ?r ?p <filex://xyz-123/test.txt> . }"); + QTest::newRow("queryWithConvertableFileUrl1WeirdFormatting") + << QString::fromLatin1("select ?r where { ?r ?p <file:///media/XO-Y4/test.txt> . }") + << QString::fromLatin1("select ?r where { ?r ?p <filex://xyz-123/test.txt> . }"); + QTest::newRow("queryWithConvertableFileUrl2") << QString::fromLatin1("select ?r where { ?r ?p <file:///media/nfs/test.txt> . }") << QString::fromLatin1("select ?r where { ?r ?p <nfs://thehost/solid-path/test.txt> . }"); @@ -161,14 +165,48 @@ void RemovableMediaModelTest::testConvertFileUrlsInQuery_data() << QString::fromLatin1("select ?r where { ?r nie:url ?u . FILTER(REGEX(?u, '^file:///media/XO-Y4/test')) . }") << QString::fromLatin1("select ?r where { ?r nie:url ?u . FILTER(REGEX(?u, '^filex://xyz-123/test')) . }"); + QTest::newRow("queryWithConvertableRegex1WithWeirdFormatting") + << QString::fromLatin1("select ?r where { ?r nie:url ?u . filter(reGEx( STR(?u) , 'file:///media/XO-Y4/test' ) ) . }") + << QString::fromLatin1("select ?r where { ?r nie:url ?u . filter(reGEx( STR(?u) , 'filex://xyz-123/test' ) ) . }"); + QTest::newRow("queryWithConvertableRegex2") << QString::fromLatin1("select ?r where { ?r nie:url ?u . FILTER(REGEX(?u, '^file:///media/nfs/')) . }") << QString::fromLatin1("select ?r where { ?r nie:url ?u . FILTER(REGEX(?u, '^nfs://thehost/solid-path/')) . }"); + QTest::newRow("queryWithConvertableRegex3") + << QString::fromLatin1("select ?r where { ?r nie:url ?u . FILTER(REGEX(?u, '''^file:///media/nfs/''')) . }") + << QString::fromLatin1("select ?r where { ?r nie:url ?u . FILTER(REGEX(?u, '''^nfs://thehost/solid-path/''')) . }"); + + // looking for anything in /media includes files from any storage mounted somewhere under /media + QTest::newRow("queryWithConvertableRegex4") + << QString::fromLatin1("select ?r where { ?r nie:url ?u . FILTER(REGEX(?u, '^file:///media')) . }") + << QString::fromLatin1("select ?r where { ?r nie:url ?u . " + "FILTER((" + "REGEX(?u, '^file:///media') || " + "REGEX(?u, '^optical://solidman_begins/') || " + "REGEX(?u, '^filex://whatever/') || " + "REGEX(?u, '^nfs://thehost/solid-path/') || " + "REGEX(?u, '^filex://xyz-123/'))" + ") . }"); + + QTest::newRow("queryWithConvertableRegex4WithWeirdFormatting") + << QString::fromLatin1("select ?r where { ?r nie:url ?u . filter ( reGEX( str( ?u) , '^file:///media' ) ) . }") + << QString::fromLatin1("select ?r where { ?r nie:url ?u . " + "filter ( (" + "REGEX(str( ?u), '^file:///media') || " + "REGEX(str( ?u), '^optical://solidman_begins/') || " + "REGEX(str( ?u), '^filex://whatever/') || " + "REGEX(str( ?u), '^nfs://thehost/solid-path/') || " + "REGEX(str( ?u), '^filex://xyz-123/'))" + " ) . }"); + + QTest::newRow("queryWithConvertableRegex4") + << QString::fromLatin1("select ?r where { ?r nie:url ?u . FILTER(REGEX(?u, '^file:///media/nfs')) . }") + << QString::fromLatin1("select ?r where { ?r nie:url ?u . FILTER((REGEX(?u, '^file:///media/nfs') || REGEX(?u, '^nfs://thehost/solid-path/'))) . }"); + QTest::newRow("queryWithNotReallyAFileUrl") << QString::fromLatin1("select ?r where { ?r ?p ?u . FILTER(REGEX(?u, 'ffile:///media/nfs/')) . }") << QString::fromLatin1("select ?r where { ?r ?p ?u . FILTER(REGEX(?u, 'ffile:///media/nfs/')) . }"); - // TODO: add queries that should NOT be converted } void RemovableMediaModelTest::testConvertFileUrlsInQuery()
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor