/*
 *
 * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $
 *
 * This file is part of the Nepomuk KDE project.
 * Copyright (C) 2006-2010 Sebastian Trueg <trueg@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) any later version.
 * See the file "COPYING" for the exact licensing terms.
 */


/** \mainpage The Nepomuk Meta Data Library

<p><b>
Overview |
\ref hacking "Using" |
\ref examples "Examples" |
\ref page_ontology "Desktop Ontologies" |
\ref nepomuk-rcgen "Resource Generator"
</b></p>

This is the KDE Meta Data library (not to confuse with KFileMetaData). It consists of
three parts: the main resource handling centered around Nepomuk::Resource, the handling of
ontologies via classes in the Nepomuk::Types namespace, and the desktop Nepomuk::Query API.


\section overview The General Idea

Three types of meta data can be identified:

-# Meta data that is stored with the data itself and is available at all
times. This includes id3 tags, the number of pages in a pdf document, or
even the size of a file or the subject of an email.
-# Meta data that is created by the user manually like annotations or tags
that are assigned to files, emails, or whatever resources.
-# Meta data that can be gathered automatically by applications such as the
source of a downloaded file or the email an attachment was saved from or the
original when copying a file locally.

Type 1 is already handled in many implementations. KDE itself includes the
KMetaFileInfo classes that allow extracting this kind of meta information from
files and the Strigi system even creates a searchable index of this information.

Nepomuk is intended for meta data of type 2 and 3. It provides an easy way to
create and read meta data for arbitrary resources (this includes for example files
or emails, but also contacts or maybe even a paragraph in a pdf file).

The simplest type of meta data that can be handled with Nepomuk is a comment. It
is a simple string associated with a resource (a file for example). This comment
is created by the user using an application that is based on Nepomuk.

Nepomuk's core is designed to allow arbitrary types of meta data, i.e. any resource
can be related with any other resource or value by simply naming the relation and
providing the value.
The power of Nepomuk, however, lies in that it provides a class for each type
of resource. Each of these classes provide convenience methods to allow a simple
handling of the meta data. These classes are automatically generated from a
description of types and properties, i.e. an ontology (see \ref page_ontology).

Nepomuk is resource based. Thus, working with Nepomuk is always done with instances
representing a certain resource. This resource has a list of properties. Properties
are named and have a certain type. The type can either be another resource (compare
a file that was an attachment from an email) or a literal (this means for example a
string, or an integer; the comment mentioned earlier would be a string literal).
Each property can either have a cardinality of 1 (again a file can only be saved from
one email) or greater than 1 (i.e. infinite, like one file can have arbitrary many
associated comments). See \ref hacking on how Nepomuk handles literals and cardinalities
greater than 1.

\section toc Further Reading

- \ref page_ontology
- \ref hacking
- \ref examples
- \ref nepomuk-rcgen
- <a href="http://techbase.kde.org/Development/Tutorials#Nepomuk">The Nepomuk techbase tutorials</a>

\authors
Sebastian Trueg \<trueg@kde.org\>

\maintainers
Sebastian Trueg \<trueg@kde.org\>

\licenses
\lgpl

*/


/** \page hacking Using Nepomuk

<p><b>
\ref index "Overview" |
Using |
\ref examples "Examples" |
\ref page_ontology "Desktop Ontologies" |
\ref nepomuk-rcgen "Resource Generator"
</b></p>

\section hacking_resources Handling Resources

In general there are two ways of using Nepomuk.

-# The preferred way: use the Resource subclasses as generated from \ref page_ontology
   This is also the much simpler way since Nepomuk takes care of all type casting and
   list handling automatically.
-# Using Nepomuk::Resource directly. This is much harder since in this case
   the type names (i.e. their URIs as defined in \ref page_ontology) have to be known.
   On the other hand it allows to use additional resource types not defined in the ontology
   and handle resources without knowing their type.

Since all resource classes are derived from Nepomuk::Resource and only add additional methods
both ways can be used interchangeably.

Resource objects (and thus also all objects of classes derived from Resource) with the same
URI share their data. Thus, if one is changed the other one is, too.


\subsection hacking_theeasyway Using Resource Subclasses

Using Resource subclasses directly is very simple. All that is necessary to handle a
resource is to know its type and its URI (the URI can vary a lot between resource types;
The simplest example is certainly a local file: the URI is the path to the file).

To access or create meta data for a resource one simply creates an instance of the
corresponding class and passes the resource URI to its constructor.

In case of a file this would look as follows.

\code
Nepomuk::File f( "/home/foo/bar.txt" );
\endcode

Now meta data can be read and set via the methods provided by Nepomuk::File
such as Nepomuk::File::setAnnotation.

Each resource class also provides a static method which returns all existing instances
of this type.
See Nepomuk::File::allFiles for an example.

See also \ref nepomuk-rcgen


\subsection hacking_thehardway Using Resource Directly

Using the Nepomuk::Resource class directly forces one to learn a little more about
the internals of Nepomuk. Resource provides four methods to handle the properties of a
resource (reminder: all Resource subclasses as generated from \ref page_ontology are based
one these methods):

- Nepomuk::Resource::property
- Nepomuk::Resource::setProperty
- Nepomuk::Resource::removeProperty
- Nepomuk::Resource::properties

Each property's value is represented by a Nepomuk::Variant object which can contain
another Resource or a literal (string, int, ...) or even a list of the former two. Other than
with the Resource subclasses no automatic type conversion is performed.

In case of a property that can have multiple values (cardinality greater than 1) Nepomuk::Resource::setProperty
has to be called with a list to set more than one (the Resource subclasses simplify this by
adding add methods in addition to the set method) and Nepomuk::Resource::getProperty
will also return a list (in both cases encapsulated in a Variant object).

When creating a Resource object there are two cases that are dealt with differently:

- The resource does not exist yet, i.e. no information about it is stored. In this case Nepomuk
  does not know the type of the resource and will fall back to %http://www.w3.org/2000/01/rdf-schema\#Resource.
- If the resource already exists the type may be empty. It will then be read from the local meta
  data store (where it was saved before by Nepomuk automatically).

As a rule of thumb one should always define the type when creating meta data and leave it empty when
reading meta data.

When using the plain Nepomuk::Resource class one is completely free to choose the
resource URIs, the type URIs, and the property URIs. However, to preserve compatibility with
other applications one is encouraged to stick to those define in \ref page_ontology.

\section hacking_general Nepomuk Details

Nepomuk is designed so the user (the developer of a client application) does not have to care about loading or
saving the data. All data is stored directly into the RDF storage and also read from it directly.

Although in normal operation it is sufficient to only work with Nepomuk::Resource and
its subclasses errors might occur. This is where the Nepomuk::ResourceManager comes
in: it provides the Nepomuk::ResourceManager::init method which can be called manually
(the resource manager will be initialized automatically anyway) to check if the initialization was
successful and Nepomuk can be used. In addition it provides the Nepomuk::ResourceManager::error
signal which is emitted whenever an error occurs.


See \ref examples for further examples.
*/


/** \page examples Nepomuk Examples

<p><b>
\ref index "Overview" |
\ref hacking "Using" |
Examples |
\ref page_ontology "Desktop Ontologies" |
\ref nepomuk-rcgen "Resource Generator"
</b></p>

\section examples_resource Resource Handling Examples

Add an annotation (a comment) to a file.

\code
Nepomuk::File f( "/home/foo/bar.txt" );
f.setAnnotation( "This is just a test file that contains nothing of interest." );
\endcode

The following example creates a new tag. The tag can be accessed through its name
which works as an identifier. Nepomuk automatically creates a new unique URI if this
tag does not already exist.

\code
Nepomuk::Tag tag( "MyTag" );
Nepomuk::File f( "/home/foo/bar.txt" );
f.addTag( tag );
\endcode

Reading the information using plain Resource methods:

\code
Nepomuk::Resource f( "/home/foo/bar.txt" );
QString annotation = f.getProperty( Soprano::Vocabulary::NAO::decription() ).toString();
QList<Resource> tags = f.getProperty( Soprano::Vocabulary::NAO::hasTag() ).toResourceList();
QListIterator<Resource> it( tags );
while( it.hasNext() )
  kdDebug() << "File tagged with tag: "
            << it.next().genericLabel();
\endcode

Reading the information using the convenience classes (be aware that these classes need to be generated
from an ontology using the \ref nepomuk-rcgen "Resource Generator"):

\code
Nepomuk::File f( "/home/foo/bar.txt" );
QString description = f.description();
QList<Tag> tags = f.getTags();
QListIterator<Tag> it( tags );
while( it.hasNext() )
  kdDebug() << "File tagged with tag: " << it.next().genericLabel();
\endcode

Present all defined properties of an arbitrary resource to the user including
internationalized labels:

\code
Nepomuk::Resource f( "/home/foo/bar.txt" );
QHash<QUrl, Variant> properties = f.properties();
QHashIterator<QUrl, Variant> it( properties );
while( it.hasNext() ) {
  it.next();
  kdDebug() << Nepomuk::Types::Property( it.key() ).label() << ": " << it.value().toString() << endl;
}
\endcode


\section examples_query Query Examples

Perform a simple full text query that looks for any resource containing
the value 'nepomuk':

\code
Nepomuk::Query::LiteralTerm nepomukTerm("nepomuk");
Nepomuk::Query::Query query( nepomukTerm );
\endcode

Create a query that lists all resources tagged with a tag whose name
matches 'nepomuk':

\code
Nepomuk::Query::ComparisonTerm term( Soprano::Vocabulary::NAO::hasTag(),
                                     Nepomuk::Query::LiteralTerm("nepomuk") );
Nepomuk::Query::Query query( term );
\endcode

Create a query that lists all resources tagged with a specific tag:

\code
Nepomuk::Tag tag = getFancyTag();
Nepomuk::Query::ComparisonTerm term( Soprano::Vocabulary::NAO::hasTag(),
                                     Nepomuk::Query::ResourceTerm( tag ) );
Nepomuk::Query::Query query( term );
\endcode

Create a query that lists all resource tagged with both the tags used
above:

\code
Nepomuk::Tag tag = getFancyTag();
Nepomuk::Query::ComparisonTerm fancyTagTerm( Soprano::Vocabulary::NAO::hasTag(),
                                             Nepomuk::Query::ResourceTerm( tag ) );
Nepomuk::Query::ComparisonTerm nepomukTagTerm( Soprano::Vocabulary::NAO::hasTag(),
                                               Nepomuk::Query::LiteralTerm("nepomuk") );
Nepomuk::Query::Query query( Nepomuk::Query::AndTerm(fancyTagTerm, nepomukTagTerm) );
\endcode


Create a query that lists all \b files tagged with a specific tag:

\code
Nepomuk::Tag tag = getFancyTag();
Nepomuk::Query::ComparisonTerm term( Soprano::Vocabulary::NAO::hasTag(),
                                     Nepomuk::Query::ResourceTerm( tag ) );
Nepomuk::Query::FileQuery fileQuery( term );
\endcode


Any other term can be used as sub term in a ComparisonTerm (%Vocabulary namespace generated via \ref nepomuk-rcgen).
The following query does return all resources related to person contacts that are tagged with \p tag.

\code
Nepomuk::Query::AndTerm andTerm;
andTerm.addSubTerm( Nepomuk::Query::ResourceTypeTerm( Nepomuk::Vocabulary::NCO::PersonContact() ) );
andTerm.addSubTerm( Nepomuk::Query::ComparisonTerm( Soprano::Vocabulary::NAO::hasTag(),
                                                    Nepomuk::Query::ResourceTerm( tag ) ) );
Nepomuk::Query::ComparisonTerm cterm( Nepomuk::Vocabulary::NAO::isRelated(),
                                      andTerm );
\endcode


To make matters even more complex the above ComparisonTerm can be inverted:

\code
cterm.setInverted(true);
\endcode

This will not match resources related to some tagged person contact but match
resources that some tagged person contact is related to (sounds confusing but
remember that the properties are not symmetric by default, i.e. the graph of
data is directed.)


\subsection query_examples_file Listing Files

Restrict the search to a specific folder:

\code
fileQuery.addIncludeFolder( KUrl("/home/foobar/thegoodstuff") );
\endcode

Restrict the search to files-only (Vocabulary namespace generated via
<a href="http://api.kde.org/kdesupport-api/kdesupport-apidocs/soprano/html/soprano_devel_tools.html">onto2vocabularyclass</a>
using \p ${SHAREDDESKTOPONTOLOGIES_ROOT_DIR}/nie/nfo.trig):

\code
Nepomuk::Query::Term folderTerm = Nepomuk::Query::ResourceTypeTerm( Vocabulary::NFO::Folder() );
Nepomuk::Query::Term noFolderTerm = Nepomuk::Query::NegationTerm::negateTerm(folderTerm);
fileQuery.setTerm( Nepomuk::Query::AndTerm( fileQuery.term(), noFolderTerm ) );
\endcode

List all query results in a KDirModel:

\code
KDirModel* model = getFancyDirModel();
Nepomuk::Query::Query query = buildFancyQuery();
KUrl searchUrl = query.toSearchUrl();
model->dirLister()->open( searchUrl );
\endcode

KIO will use the \p nepomuksearch:/ slave to list search results as file entries.

\subsection query_examples_misc Misc Query Examples

Match all EmailAddress instances with a specific email address:
\code
Nepomuk::Query::ComparisonTerm email( Vocabulary::NCO::emailAddress(), Soprano::LiteralValue( "trueg@kde.org" ) );
\endcode

Match all nco:PersonContact instances:
\code
Nepomuk::Query::ResourceTypeTerm type( Vocabulary::NCO::PersonContact() );
\endcode

Match all person contacts with a specific email address:
\code
Nepomuk::Query::AndTerm( type, Nepomuk::Query::ComparisonTerm( Vocabulary::NCO::hasEmailAddress(), email ) );
\endcode
*/


/** \page page_ontology The Desktop Ontologies

<p><b>
\ref index "Overview" |
\ref hacking "Using" |
\ref examples "Examples" |
Desktop Ontologies |
\ref nepomuk-rcgen "Resource Generator"
</b></p>

The Desktop ontologies define the possible types and properties that can be used as metadata.
The ontologies are based on RDF/S and NRL (The Nepomuk Representation Language which adds some
OWL-like properties like cardinality or also named graphs). The types and properties can either
be used directly with the Resource class or through generated classes.
*/


/** \page nepomuk-rcgen The Nepomuk Resource Generator

<p><b>
\ref index "Overview" |
\ref hacking "Using" |
\ref examples "Examples" |
\ref page_ontology "Desktop Ontologies" |
Resource Generator
</b></p>

The power of Nepomuk lies in the generated classes which allows the application developer to set
and retrieve metadata according to standards without knowing any specific RDF URIs or names of properties.
The idea is that the resource generator (which is installed along with the Nepomuk libraries) creates
Resource subclasses that provide wrapper methods for Resource::getProperty and Resource::setProperty from
ontology descriptions.


\section rcgen_cmake Usage through CMake

The simplest way to use the resource generator is through CMake. Nepomuk provides a macro to automatically
add the class generation target. The macro is used similar to the macro for adding ui files.

\code
include(NepomukAddOntologyClasses)
\endcode

This will provide a macro called NEPOMUK_ADD_ONTOLOGY_CLASSES:

\code
NEPOMUK_ADD_ONTOLOGY_CLASSES(<sources-var>
         [FAST]
         [ONTOLOGIES] <onto-file1> [<onto-file2> ...]
         [CLASSES <classname1> [<classname2> ...]]
         [VISIBILITY <visibility-name>]
       )
\endcode

If FAST is specified the rcgen parameter --fast will be used which results in resource classes
not based on Nepomuk::Resource but on a custom class which does not perform any checks and simply
writes the data to Nepomuk (hence the name fast).

The optional CLASSES parameter allows to specify the classes to be generated (RDF class names) in
case one does not want all classes in the ontologies to be generated. If omitted all classes in the
ontology files will be generated.

The optional VISIBILITY parameter can only be used in non-fast mode and allows to set the gcc visibility
to make the generated classes usable in a publically exported API. The <visibility-name> is used to create
the name of the export macro and the export include file. Thus, when using "VISIBILITY foobar" include
file "foobar_export.h" needs to define FOOBAR_EXPORT.

\subsection rcgen_cmake_example Example

\code
include(NepomukAddOntologyClasses)

set(SRCS [...])

nepomuk_add_ontology_classes(SRCS ONTOLOGIES ontology.trig)

kde4_add_executable(foobar ${SRCS})
target_link_libraries(foobar
  nepomuk
)
\endcode
*/

/** \namespace Nepomuk::Types
\brief The %Types namespace contains all classes used to handle ontology entities such as classes and properties.
*/

/** \namespace Nepomuk::Query

\brief The %Query namespace contains all classes that make up the Nepomuk %Query API.

Constructing queries consists of creating and combining different types of Term subclasses or using the
QueryParser to parse user queries (see the QueryParser documentation for details on the query syntax).

The constructed queries can then be executed on the nepomuk query service via the QueryServiceClient,
used directly on a Soprano::Model (for example the %Nepomuk main model which can be retrieved via
ResourceManager::mainModel()), or listed via KIO (see Query::Query::toSearchUrl()).

\section nepomuk_constructing_queries Constructing Queries

Basically all one needs to know is that each Term matches a set of resources. Different types of terms do
so in different ways. The simplest type is the ResourceTerm which matches exactly one resource by URI.
The ComparisonTerm matches all resources that have a property with a certain value. The LiteralTerm by
itselt matches all resources that contain the string value in one of their properties, and so on.

Thus, constructing a query means to combine all constraints that the results should fulfill using AndTerm
and maybe OrTerm. Everything can also the nested and most importantly (this is the one real graph query
thing in the API) ComparisonTerm can use any other term as object, meaning it can compare the value of
a property (if it is not a literal value) to the results of a subquery. A simple example would be the
following:

\code
// match all EmailAddress instances with a specific email address:
Nepomuk::Query::ComparisonTerm email( Vocabulary::NCO::emailAddress(), Soprano::LiteralValue( "trueg@kde.org" ) );

// match all nco:PersonContact instances
Nepomuk::Query::ResourceTypeTerm type( Vocabulary::NCO::PersonContact() );

// match all person contacts with a specific email address
Nepomuk::Query::AndTerm( type, Nepomuk::Query::ComparisonTerm( Vocabulary::NCO::hasEmailAddress(), email ) );
\endcode

\sa \ref examples_query
*/

// DOXYGEN_SET_RECURSIVE = NO
// DOXYGEN_SET_FILE_PATTERNS = *.h
// DOXYGEN_SET_INPUT = @topdir@/nepomuk/Mainpage.dox
// DOXYGEN_SET_INPUT += @topdir@/nepomuk/core
// DOXYGEN_SET_INPUT += @topdir@/nepomuk/ui
// DOXYGEN_SET_INPUT += @topdir@/nepomuk/types
// DOXYGEN_SET_INPUT += @topdir@/nepomuk/query
// DOXYGEN_SET_EXCLUDE = @topdir@/nepomuk/core/resourcedata.h
// DOXYGEN_SET_EXCLUDE += @topdir@/nepomuk/core/nepomukmainmodel.h
// DOXYGEN_SET_EXCLUDE += @topdir@/nepomuk/core/resourcefiltermodel.h
// DOXYGEN_SET_EXCLUDE += @topdir@/nepomuk/core/nie.h
// DOXYGEN_SET_EXCLUDE += @topdir@/nepomuk/types/entitymanager.h
// DOXYGEN_SET_EXCLUDE += @topdir@/nepomuk/ui/nepomukmassupdatejob.h
// DOXYGEN_SET_EXCLUDE += @topdir@/nepomuk/ui/tagcheckbox.h
// DOXYGEN_SET_EXCLUDE += @topdir@/nepomuk/ui/kblocklayout.h
// DOXYGEN_SET_EXCLUDE_PATTERNS += @topdir@/nepomuk/core/*_p.h
// DOXYGEN_SET_EXCLUDE_PATTERNS += @topdir@/nepomuk/types/*_p.h
// DOXYGEN_SET_EXCLUDE_PATTERNS += @topdir@/nepomuk/ui/*_p.h
// DOXYGEN_SET_EXCLUDE_PATTERNS += @topdir@/nepomuk/query/*_p.h
// DOXYGEN_SET_PROJECT_NAME = Nepomuk
// vim:ts=4:sw=4:expandtab:filetype=doxygen
