~ubuntu-branches/ubuntu/karmic/kdepim/karmic-backports

« back to all changes in this revision

Viewing changes to akonadi/agents/nepomuk_email_feeder/nepomukemailfeeder.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Christian Mangold
  • Date: 2009-07-10 06:34:50 UTC
  • mfrom: (1.1.40 upstream)
  • Revision ID: james.westby@ubuntu.com-20090710063450-neojgew2fh0n3y0u
Tags: 4:4.2.96-0ubuntu1
* New upstream release
* Bump kde build-deps to 4.2.96

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
    Copyright (c) 2006 Volker Krause <vkrause@kde.org>
3
 
    Copyright (c) 2008 Sebastian Trueg <trueg@kde.org>
4
 
 
5
 
    This library is free software; you can redistribute it and/or modify it
6
 
    under the terms of the GNU Library General Public License as published by
7
 
    the Free Software Foundation; either version 2 of the License, or (at your
8
 
    option) any later version.
9
 
 
10
 
    This library is distributed in the hope that it will be useful, but WITHOUT
11
 
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
 
    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
13
 
    License for more details.
14
 
 
15
 
    You should have received a copy of the GNU Library General Public License
16
 
    along with this library; see the file COPYING.LIB.  If not, write to the
17
 
    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18
 
    02110-1301, USA.
19
 
*/
20
 
 
21
 
#include "nepomukemailfeeder.h"
22
 
#include "email.h"
23
 
#include "emailaddress.h"
24
 
#include "personcontact.h"
25
 
 
26
 
#include <akonadi/changerecorder.h>
27
 
#include <akonadi/item.h>
28
 
#include <akonadi/itemfetchscope.h>
29
 
#include <akonadi/kmime/messageparts.h>
30
 
 
31
 
#include <kmime/kmime_message.h>
32
 
#include <kmime/kmime_content.h>
33
 
#include <boost/shared_ptr.hpp>
34
 
 
35
 
#include <Nepomuk/Resource>
36
 
#include <Nepomuk/ResourceManager>
37
 
#include <Nepomuk/Variant>
38
 
#include <kurl.h>
39
 
 
40
 
#include <Soprano/Vocabulary/Xesam>
41
 
#include <Soprano/Vocabulary/NAO>
42
 
#include <Soprano/Vocabulary/XMLSchema>
43
 
#include <Soprano/Model>
44
 
#include <Soprano/QueryResultIterator>
45
 
#include <soprano/node.h>
46
 
#include <soprano/nodeiterator.h>
47
 
#include <soprano/nrl.h>
48
 
 
49
 
#define USING_SOPRANO_NRLMODEL_UNSTABLE_API 1
50
 
#include <soprano/nrlmodel.h>
51
 
 
52
 
 
53
 
using namespace Akonadi;
54
 
typedef boost::shared_ptr<KMime::Message> MessagePtr;
55
 
 
56
 
static void removeItemFromNepomuk( const Akonadi::Item &item )
57
 
{
58
 
  // find the graph that contains our item and delete the complete graph
59
 
  QList<Soprano::Node> list = Nepomuk::ResourceManager::instance()->mainModel()->executeQuery(
60
 
                QString( "select ?g where { ?g <http://www.semanticdesktop.org/ontologies/2007/01/19/nie#dataGraphFor> %1. }")
61
 
                       .arg( Soprano::Node::resourceToN3( item.url() ) ),
62
 
                Soprano::Query::QueryLanguageSparql ).iterateBindings( 0 ).allNodes();
63
 
 
64
 
  foreach ( const Soprano::Node &node, list )
65
 
    Nepomuk::ResourceManager::instance()->mainModel()->removeContext( node );
66
 
}
67
 
 
68
 
Akonadi::NepomukEMailFeeder::NepomukEMailFeeder( const QString &id ) :
69
 
  AgentBase( id )
70
 
{
71
 
  changeRecorder()->itemFetchScope().fetchPayloadPart( MessagePart::Envelope );
72
 
  changeRecorder()->setMimeTypeMonitored( "message/rfc822" );
73
 
  changeRecorder()->setMimeTypeMonitored( "message/news" );
74
 
  changeRecorder()->setChangeRecordingEnabled( false );
75
 
 
76
 
  // initialize Nepomuk
77
 
  Nepomuk::ResourceManager::instance()->init();
78
 
 
79
 
  mNrlModel = new Soprano::NRLModel( Nepomuk::ResourceManager::instance()->mainModel() );
80
 
}
81
 
 
82
 
NepomukEMailFeeder::~NepomukEMailFeeder()
83
 
{
84
 
  delete mNrlModel;
85
 
}
86
 
 
87
 
void NepomukEMailFeeder::itemAdded(const Akonadi::Item & item, const Akonadi::Collection & collection)
88
 
{
89
 
  Q_UNUSED( collection );
90
 
  itemChanged( item, QSet<QByteArray>() );
91
 
}
92
 
 
93
 
void NepomukEMailFeeder::itemChanged(const Akonadi::Item & item, const QSet<QByteArray> & partIdentifiers)
94
 
{
95
 
  Q_UNUSED( partIdentifiers );
96
 
  if ( !item.hasPayload<MessagePtr>() )
97
 
    return;
98
 
 
99
 
  // first remove the item: since we use a graph that has a reference to all parts
100
 
  // of the item's semantic representation this is a really fast operation
101
 
  removeItemFromNepomuk( item );
102
 
 
103
 
  // create a new graph for the item
104
 
  QUrl metaDataGraphUri;
105
 
  QUrl graphUri = mNrlModel->createGraph( Soprano::Vocabulary::NRL::InstanceBase(), &metaDataGraphUri );
106
 
 
107
 
  // remember to which graph the item belongs to (used in search query in removeItemFromNepomuk())
108
 
  mNrlModel->addStatement( graphUri,
109
 
                           QUrl::fromEncoded( "http://www.semanticdesktop.org/ontologies/2007/01/19/nie#dataGraphFor", QUrl::StrictMode ),
110
 
                           item.url(), metaDataGraphUri );
111
 
 
112
 
  MessagePtr msg = item.payload<MessagePtr>();
113
 
 
114
 
  // FIXME: make a distinction between email and news
115
 
  NepomukFast::Email r( item.url(), graphUri );
116
 
 
117
 
  if ( msg->subject( false ) ) {
118
 
    r.setMessageSubject( msg->subject()->asUnicodeString() );
119
 
  }
120
 
 
121
 
  if ( msg->date( false ) ) {
122
 
    r.setReceivedDate( msg->date()->dateTime().dateTime() );
123
 
  }
124
 
 
125
 
  if ( msg->from( false ) ) {
126
 
    r.setSenders( extractContactsFromMailboxes( msg->from()->mailboxes(), graphUri ) );
127
 
  }
128
 
 
129
 
  if ( msg->to( false ) ) {
130
 
    r.setTos( extractContactsFromMailboxes( msg->to()->mailboxes(), graphUri ) );
131
 
  }
132
 
 
133
 
  if ( msg->cc( false ) ) {
134
 
    r.setCcs( extractContactsFromMailboxes( msg->cc()->mailboxes(), graphUri ) );
135
 
  }
136
 
 
137
 
  if ( msg->bcc( false ) ) {
138
 
    r.setBccs( extractContactsFromMailboxes( msg->bcc()->mailboxes(), graphUri ) );
139
 
  }
140
 
 
141
 
  KMime::Content* content = msg->mainBodyPart( "text/plain" );
142
 
 
143
 
  // FIXME: simplyfy this text as in: remove all html tags. Is there a quick way to do this?
144
 
  if ( content ) {
145
 
    QString text = content->decodedText( true, true );
146
 
    if ( !text.isEmpty() ) {
147
 
      r.addProperty( Soprano::Vocabulary::Xesam::asText(), Soprano::LiteralValue( text ) );
148
 
    }
149
 
  }
150
 
 
151
 
  // FIXME: is xesam:id the best idea here?
152
 
  if ( msg->messageID( false ) ) {
153
 
    r.addProperty( Soprano::Vocabulary::Xesam::id(), Soprano::LiteralValue( msg->messageID()->asUnicodeString() ) );
154
 
  }
155
 
 
156
 
  // IDEA: use Strigi to index the attachments
157
 
}
158
 
 
159
 
void NepomukEMailFeeder::itemRemoved(const Akonadi::Item & item)
160
 
{
161
 
  removeItemFromNepomuk( item );
162
 
}
163
 
 
164
 
QList<NepomukFast::Contact> NepomukEMailFeeder::extractContactsFromMailboxes( const KMime::Types::Mailbox::List& mbs,
165
 
                                                                              const QUrl &graphUri )
166
 
{
167
 
  QList<NepomukFast::Contact> contacts;
168
 
 
169
 
  foreach( const KMime::Types::Mailbox& mbox, mbs ) {
170
 
    if ( mbox.hasAddress() ) {
171
 
      bool found = false;
172
 
      NepomukFast::Contact c = findContact( mbox.address(), graphUri, &found );
173
 
      if ( !found && mbox.hasName() )
174
 
        c.addFullname( mbox.name() );
175
 
      contacts << c;
176
 
    }
177
 
  }
178
 
 
179
 
  return contacts;
180
 
}
181
 
 
182
 
NepomukFast::PersonContact NepomukEMailFeeder::findContact( const QByteArray& address, const QUrl &graphUri, bool *found )
183
 
{
184
 
  //
185
 
  // Querying with the exact address string is not perfect since email addresses
186
 
  // are case insensitive. But for the moment we stick to it and hope Nepomuk
187
 
  // alignment fixes any duplicates
188
 
  //
189
 
  Soprano::QueryResultIterator it =
190
 
    Nepomuk::ResourceManager::instance()->mainModel()->executeQuery( QString( "select distinct ?r where { ?r <%1> ?a . ?a <%2> \"%3\"^^<%4> . }" )
191
 
                                                                     .arg( NepomukFast::Role::emailAddressUri().toString() )
192
 
                                                                     .arg( NepomukFast::EmailAddress::emailAddressUri().toString() )
193
 
                                                                     .arg( QString::fromAscii( address ) )
194
 
                                                                     .arg( Soprano::Vocabulary::XMLSchema::string().toString() ),
195
 
                                                                     Soprano::Query::QueryLanguageSparql );
196
 
  if ( it.next() ) {
197
 
    *found = true;
198
 
    return NepomukFast::PersonContact( it.binding( 0 ).uri(), graphUri );
199
 
  }
200
 
  else {
201
 
    *found = false;
202
 
    // create a new contact
203
 
    NepomukFast::PersonContact contact( QUrl(), graphUri );
204
 
    NepomukFast::EmailAddress email( QUrl( "mailto:" + address ), graphUri );
205
 
    email.setEmailAddress( QString::fromAscii( address ) );
206
 
    contact.addEmailAddress( email );
207
 
    return contact;
208
 
  }
209
 
}
210
 
 
211
 
AKONADI_AGENT_MAIN( NepomukEMailFeeder )
212
 
 
213
 
#include "nepomukemailfeeder.moc"