initial commit
authorNicolas Chauvat <nicolas.chauvat@logilab.fr>
Tue, 30 Aug 2011 12:29:28 +0200
changeset 0 08e7250b6fc1
child 1 48e979b1473f
initial commit
MANIFEST.in
__init__.py
__pkginfo__.py
ccplugin.py
data/crystal_clear_broader.png
data/crystal_clear_bullet.png
data/crystal_clear_category.png
data/crystal_clear_disambiguate.png
data/crystal_clear_geocoord.png
data/crystal_clear_homepage.png
data/crystal_clear_link.png
data/crystal_clear_list_arrow.png
data/crystal_clear_location.png
data/crystal_clear_narrower.png
data/crystal_clear_pnd.png
data/crystal_clear_redirection.png
data/crystal_clear_related.png
data/cubes.cubipedia.css
data/wikipedia.png
debian/changelog
debian/compat
debian/control
debian/copyright
debian/cubicweb-cubipedia.prerm
debian/rules
entities/__init__.py
hooks.py
i18n/en.po
i18n/es.po
i18n/fr.po
migration/postcreate.py
ontology.py
readme
schema.py
setup.py
triplestore.py
uiprops.py
views/__init__.py
views/ner.py
views/primary.py
views/templates.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MANIFEST.in	Tue Aug 30 12:29:28 2011 +0200
@@ -0,0 +1,5 @@
+include *.py
+include */*.py
+recursive-include data *.gif *.png *.ico *.css *.js
+recursive-include i18n *.po
+recursive-include wdoc *
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/__init__.py	Tue Aug 30 12:29:28 2011 +0200
@@ -0,0 +1,4 @@
+"""cubicweb-cubipedia application package
+
+Cube for mananing and querying information from dbpedia
+"""
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/__pkginfo__.py	Tue Aug 30 12:29:28 2011 +0200
@@ -0,0 +1,48 @@
+# pylint: disable=W0622
+"""cubicweb-cubipedia application packaging information"""
+
+modname = 'cubipedia'
+distname = 'cubicweb-cubipedia'
+
+numversion = (0, 1, 0)
+version = '.'.join(str(num) for num in numversion)
+
+license = 'LGPL'
+author = 'LOGILAB S.A. (Paris, FRANCE)'
+author_email = 'contact@logilab.fr'
+description = 'Cube for mananing and querying information from dbpedia'
+web = 'http://www.cubicweb.org/project/%s' % distname
+
+__depends__ =  {'cubicweb': '>= 3.11.0',
+                'cubicweb-cubipedia': '>=0.1.0',
+                'cubicweb-keyword': None,
+                'cubicweb-file': None,
+                'cubicweb-link': None,
+                'cubicweb-card': None,
+                'cubicweb-tag': None,
+                }
+__recommends__ = {}
+
+
+from os import listdir as _listdir
+from os.path import join, isdir, exists
+from glob import glob
+
+THIS_CUBE_DIR = join('share', 'cubicweb', 'cubes', modname)
+
+def listdir(dirpath):
+    return [join(dirpath, fname) for fname in _listdir(dirpath)
+            if fname[0] != '.' and not fname.endswith('.pyc')
+            and not fname.endswith('~')
+            and not isdir(join(dirpath, fname))]
+
+data_files = [
+    # common files
+    [THIS_CUBE_DIR, [fname for fname in glob('*.py') if fname != 'setup.py']],
+    ]
+# check for possible extended cube layout
+for dname in ('entities', 'views', 'sobjects', 'hooks', 'schema', 'data', 'wdoc', 'i18n', 'migration'):
+    if isdir(dname):
+        data_files.append([join(THIS_CUBE_DIR, dname), listdir(dname)])
+# Note: here, you'll need to add subdirectories if you want
+# them to be included in the debian package
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ccplugin.py	Tue Aug 30 12:29:28 2011 +0200
@@ -0,0 +1,481 @@
+# -*- coding: utf-8 -*-
+"""gen-du cubicweb plugin
+
+Usage: cubicweb-ctl shell gen-du [options] <instance-name> <ark-list>
+
+This command will generate documentary units from the given list
+of arks. IndexDatabase options or (config file) can be specified
+via command line options. The default configuration file, if nothing
+is specified, is ~/.config/pivotdoc.ini
+
+After each import, one should launch:
+          vacuumdb -fz <dbname>
+
+Full Dbpedia Import
+*******************
+You should launch the following command:
+
+# Ontology
+cubicweb-ctl gen-ontology cubipedia dbpedia_3.6.owl
+# DbpediaPage
+cubicweb-ctl gen-pages cubipedia labels_en.nt
+# DbpediaCategory
+cubicweb-ctl gen-categories cubipedia category_labels_en.nt
+# Links
+cubicweb-ctl gen-categories-skos cubipedia skos_categories_en.nt
+cubicweb-ctl gen-ontology-links cubipedia instance_types_en.nt
+cubicweb-ctl gen-pages-disambiguates cubipedia disambiguations_en.nt
+cubicweb-ctl gen-pages-georelated cubipedia article_related_geo_countries_en.nt
+cubicweb-ctl gen-pages-redirections cubipedia redirects_en.nt
+cubicweb-ctl gen-categories-links cubipedia article_categories_en.nt
+# Attributes
+cubicweb-ctl gen-pages-abstracts cubipedia long_abstracts_en.nt
+cubicweb-ctl gen-pages-depictions cubipedia images_en.nt
+cubicweb-ctl gen-pages-thumbnails cubipedia images_en.nt
+cubicweb-ctl gen-pages-longitudes cubipedia geo_coordinates_en.nt
+cubicweb-ctl gen-pages-latitudes cubipedia geo_coordinates_en.nt
+cubicweb-ctl gen-pages-pnds cubipedia pnd_en.nt
+cubicweb-ctl gen-pages-wikipages cubipedia wikipedia_links_en.nt
+# Long... (17h
+cubicweb-ctl gen-pages-links cubipedia page_links_en.nt
+
+"""
+import os
+import os.path as osp
+import logging
+import time
+
+from logilab.database import get_connection, get_db_helper
+
+from cubicweb import AuthenticationError
+from cubicweb import cwconfig
+from cubicweb.server.utils import manager_userpasswd
+from cubicweb.dbapi import in_memory_repo_cnx
+from cubicweb.toolsutils import Command
+from cubicweb.cwctl import CWCTL
+
+from ontology import generate_ontology
+from triplestore import TripleStore, fulltext_indexation
+
+
+#################################################################################
+### CUBIPEDIA ABSTRACT GENERATION TOOLS #########################################
+#################################################################################
+class FullTextIndexation(Command):
+    """
+    Command for creating the fulltextindexation of a given etype
+    """
+    arguments = '<instance> etype'
+    max_args = 2
+    verbose = True
+    name = 'fulltext-indexation'
+
+    def _init_cw_connection(self, appid):
+        config = cwconfig.instance_configuration(appid)
+        sourcescfg = config.sources()
+        config.set_sources_mode(('system',))
+        cnx = repo = None
+        while cnx is None:
+            try:
+                login = sourcescfg['admin']['login']
+                pwd = sourcescfg['admin']['password']
+            except KeyError:
+                login, pwd = manager_userpasswd()
+            try:
+                repo, cnx = in_memory_repo_cnx(config, login=login, password=pwd)
+            except AuthenticationError:
+                print 'wrong user/password'
+            else:
+                break
+        session = repo._get_session(cnx.sessionid)
+        return cnx, session
+
+    def run(self, args):
+        appid = args.pop(0)
+        etype = args[0] if len(args) > 0 else None
+        if not etype:
+            print 'You should give the etype'
+        cw_cnx, session = self._init_cw_connection(appid)
+        session.set_pool()
+        start_time = time.time()
+        fulltext_indexation(session, etype)
+        print 'time', time.time() - start_time, (time.time() - start_time)/60.
+
+class AbstractGenerateCommand(Command):
+    """
+    Abstract generate command
+    """
+    arguments = '<instance> <dbpedia-filename>'
+    max_args = 2
+    verbose = True
+    default_tablespace = ''
+
+    def _init_cw_connection(self, appid):
+        config = cwconfig.instance_configuration(appid)
+        sourcescfg = config.sources()
+        config.set_sources_mode(('system',))
+        cnx = repo = None
+        while cnx is None:
+            try:
+                login = sourcescfg['admin']['login']
+                pwd = sourcescfg['admin']['password']
+            except KeyError:
+                login, pwd = manager_userpasswd()
+            try:
+                repo, cnx = in_memory_repo_cnx(config, login=login, password=pwd)
+            except AuthenticationError:
+                print 'wrong user/password'
+            else:
+                break
+        session = repo._get_session(cnx.sessionid)
+        return cnx, session
+
+    def run(self, args):
+        appid = args.pop(0)
+        filename = args[0] if len(args) > 0 else None
+        if not filename or not osp.exists(filename):
+            print 'You should give the dump of dbpedia'
+        cw_cnx, session = self._init_cw_connection(appid)
+        self.session = session
+        self.filename = filename
+        session.set_pool()
+        start_time = time.time()
+        self.generate_func()
+        print self.name
+        print 'time', time.time() - start_time, (time.time() - start_time)/60.
+
+class AbstractGenerateEntitiesCommand(AbstractGenerateCommand):
+    """
+    Abstract generate command for entities
+    """
+    etype = None # Should be defined in concrete subclasses
+    subject_attr = None # Should be defined in concrete subclasses
+    object_attr = None # Should be defined in concrete subclasses
+    subj_unicity = False
+    subj_index = False
+    obj_unicity = False
+    obj_index = False
+
+    def generate_func(self):
+        store = TripleStore(self.session, default_tablespace=self.default_tablespace, verbose=self.verbose)
+        store.generate_entities(self.filename, self.etype,
+                                self.subject_attr,
+                                self.object_attr,
+                                subj_unicity = self.subj_unicity,
+                                subj_index = self.subj_index,
+                                obj_unicity = self.obj_unicity,
+                                obj_index = self.obj_index,)
+        store.commit()
+
+class AbstractGenerateEntitiesAttributesCommand(AbstractGenerateCommand):
+    """
+    Abstract generate command for attributes of entities
+    """
+    dump_type = None # Should be defined in concrete subclasses
+    etype = None # Should be defined in concrete subclasses
+    subject_attr = None # Should be defined in concrete subclasses
+    rdf_voc =  None # Should be defined in concrete subclasses
+    object_attr = None # Should be defined in concrete subclasses
+    obj_unicity = False
+    obj_index = False
+    remove_duplicate = None
+
+    def generate_func(self):
+        store = TripleStore(self.session, default_tablespace=self.default_tablespace, verbose=self.verbose)
+        store.generate_entities_attributes(self.filename, self.dump_type, self.etype,
+                                           self.subject_attr, self.rdf_voc, self.object_attr,
+                                           obj_unicity = self.obj_unicity,
+                                           obj_index = self.obj_index,
+                                           remove_duplicate = self.remove_duplicate)
+        store.commit()
+
+class AbstractGenerateLinksCommand(AbstractGenerateCommand):
+    """
+    Abstract generate command for links
+    """
+    voc_rtypes = {} # Should be defined in concrete subclasses
+    subject_etype = None # Should be defined in concrete subclasses
+    object_etype = None # Should be defined in concrete subclasses
+    subject_attr = None # Should be defined in concrete subclasses
+    object_attr = None # Should be defined in concrete subclasses
+
+    def generate_func(self):
+        store = TripleStore(self.session, default_tablespace=self.default_tablespace, verbose=self.verbose)
+        store.generate_links(self.filename, self.voc_rtypes,
+                             self.subject_etype, self.object_etype,
+                             self.subject_attr, self.object_attr)
+        store.commit()
+
+
+#################################################################################
+### CUBIPEDIA PAGES GENERATION ##################################################
+#################################################################################
+class GeneratePagesCommand(AbstractGenerateEntitiesCommand):
+    """
+    Generate all Dbpedia pages. The english file is labels_en.nt
+    (takes 3221/53min)
+    """
+    name = 'gen-pages'
+    etype =  'DbpediaPage'
+    subject_attr = 'uri'
+    object_attr = 'label'
+    subj_unicity = True
+    subj_index = True
+
+class GeneratePagesHomepagesCommand(AbstractGenerateEntitiesAttributesCommand):
+    """
+    Generate all Dbpedia pages ids. The english file is homepages_en.nt
+    """
+    name = 'gen-pages-homepages'
+    dump_type = 'uri'
+    etype = 'DbpediaPage'
+    subject_attr = 'uri'
+    rdf_voc = 'http://xmlns.com/foaf/0.1/homepage'
+    object_attr = 'homepage'
+
+class GeneratePagesDepictionCommand(AbstractGenerateEntitiesAttributesCommand):
+    """
+    Generate all Dbpedia pages ids. The english file is images_en.nt
+    """
+    name = 'gen-pages-depictions'
+    dump_type = 'uri'
+    rdf_voc = 'http://xmlns.com/foaf/0.1/depiction'
+    etype = 'DbpediaPage'
+    subject_attr = 'uri'
+    object_attr = 'depiction'
+
+class GeneratePagesThumbnailCommand(AbstractGenerateEntitiesAttributesCommand):
+    """
+    Generate all Dbpedia pages  ds. The english file is images_en.nt
+    """
+    name = 'gen-pages-thumbnails'
+    dump_type = 'uri'
+    rdf_voc = 'http://dbpedia.org/ontology/thumbnail'
+    etype = 'DbpediaPage'
+    subject_attr = 'uri'
+    object_attr = 'thumbnail'
+
+class GeneratePagesAbstractsCommand(AbstractGenerateEntitiesAttributesCommand):
+    """
+     Generate all Dbpedia pages abstracts. The english file is long_abstracts_en.nt
+    """
+    name = 'gen-pages-abstracts'
+    dump_type = 'prop'
+    rdf_voc =  'http://dbpedia.org/ontology/abstract'
+    etype = 'DbpediaPage'
+    subject_attr = 'uri'
+    object_attr = 'abstract'
+
+class GeneratePagesIdsCommand(AbstractGenerateEntitiesAttributesCommand):
+    """
+     Generate all Dbpedia pages ids. The english file is page_ids_en.nt
+    """
+    name = 'gen-pages-ids'
+    dump_type = 'value'
+    rdf_voc =  'http://dbpedia.org/ontology/wikiPageID'
+    etype = 'DbpediaPage'
+    subject_attr = 'uri'
+    object_attr = 'pageid'
+
+class GeneratePagesPndsCommand(AbstractGenerateEntitiesAttributesCommand):
+    """
+     Generate all Dbpedia pages pnds. The english file is pnd_en.nt
+    """
+    name = 'gen-pages-pnds'
+    dump_type = 'prop'
+    rdf_voc =  'http://dbpedia.org/ontology/individualisedPnd'
+    etype = 'DbpediaPage'
+    subject_attr = 'uri'
+    object_attr = 'pnd'
+    remove_duplicate = 'subject'
+
+class GeneratePagesWikiPagesCommand(AbstractGenerateEntitiesAttributesCommand):
+    """
+     Generate all Dbpedia pages wikipages. The english file is wikipedia_links_en.nt
+    """
+    name = 'gen-pages-wikipages'
+    dump_type = 'uri'
+    rdf_voc =  'http://xmlns.com/foaf/0.1/page'
+    etype = 'DbpediaPage'
+    subject_attr = 'uri'
+    object_attr = 'wikipage'
+    remove_duplicate = 'object'
+
+class GeneratePagesLongitudeCommand(AbstractGenerateEntitiesAttributesCommand):
+    """
+     Generate all Dbpedia pages latitude. The english file is geo_coordinates_en.nt
+    """
+    name = 'gen-pages-longitudes'
+    dump_type = 'value'
+    rdf_voc = 'http://www.w3.org/2003/01/geo/wgs84_pos#long'
+    etype = 'DbpediaPage'
+    subject_attr = 'uri'
+    object_attr = 'longitude'
+
+class GeneratePagesLatitudeCommand(AbstractGenerateEntitiesAttributesCommand):
+    """
+     Generate all Dbpedia pages latitude. The english file is geo_coordinates_en.nt
+    """
+    name = 'gen-pages-latitudes'
+    dump_type = 'value'
+    rdf_voc = 'http://www.w3.org/2003/01/geo/wgs84_pos#lat'
+    etype = 'DbpediaPage'
+    subject_attr = 'uri'
+    object_attr = 'latitude'
+
+class GeneratePagesLinksCommand(AbstractGenerateLinksCommand):
+    """
+    Generate all Dbpedia pages redirections. The english file is redirects_en.nt
+    (takes 1884s/31min)
+    """
+    name = 'gen-pages-links'
+    voc_rtypes = {'http://dbpedia.org/ontology/wikiPageWikiLink': 'links_to'}
+    subject_etype = "DbpediaPage"
+    object_etype = "DbpediaPage"
+    subject_attr = "uri"
+    object_attr = "uri"
+
+class GeneratePagesAllLinksCommand(Command):
+    """
+    Full generate command - Takes for now approximately 245min (4h)
+    """
+    arguments = '<instance>'
+    max_args = 1
+    verbose = True
+    name = 'gen-pages-all-links'
+
+    def run(self, args):
+      for l in ('a','b','c','d','e','f','g','h','i','j','k','l','m','n'):
+         print 'Importing letter',l
+         os.system('cubicweb-ctl gen-pages-links cubipedia page_link_a%s' %l)
+
+class GeneratePagesRedirectionsCommand(AbstractGenerateLinksCommand):
+    """
+    Generate all Dbpedia pages redirections. The english file is redirects_en.nt
+    (takes 1884s/31min)
+    """
+    name = 'gen-pages-redirections'
+    voc_rtypes = {'http://dbpedia.org/ontology/wikiPageRedirects': 'redirects_to'}
+    subject_etype = "DbpediaPage"
+    object_etype = "DbpediaPage"
+    subject_attr = "uri"
+    object_attr = "uri"
+
+class GeneratePagesDisambiguatesCommand(AbstractGenerateLinksCommand):
+    """
+    Generate all Dbpedia pages disambiguates. The english file is disambiguations_en.nt
+    (takes 899s/15min)
+    """
+    name = 'gen-pages-disambiguates'
+    voc_rtypes = {'http://dbpedia.org/ontology/wikiPageDisambiguates': 'disambiguates'}
+    subject_etype = "DbpediaPage"
+    object_etype = "DbpediaPage"
+    subject_attr = "uri"
+    object_attr = "uri"
+
+class GeneratePagesGeoRelatedCommand(AbstractGenerateLinksCommand):
+    """
+    Generate all Dbpedia pages geo related. The english file is article_related_geo_countries_en.nt
+    (takes 754s/12min)
+    """
+    name = 'gen-pages-georelated'
+    voc_rtypes = {'http://dbpedia.org/ontology/related/geo': 'located_in'}
+    rtype = 'located_in'
+    subject_etype = "DbpediaPage"
+    object_etype = "DbpediaPage"
+    subject_attr = "uri"
+    object_attr = "uri"
+
+
+#################################################################################
+### CUBIPEDIA CATEGORIES GENERATION #############################################
+#################################################################################
+class GenerateCategoriesCommand(AbstractGenerateEntitiesCommand):
+    """
+    Generate all Dbpedia categories. The english file is category_labels_en.nt
+    (takes 1367s/22min)
+    """
+    name = 'gen-categories'
+    etype =  'DbpediaCategory'
+    subject_attr = 'uri'
+    object_attr = 'label'
+    subj_unicity = True
+    subj_index = True
+
+class GenerateCategoriesSkosVocabularyCommand(AbstractGenerateLinksCommand):
+    """
+    Generate Dbpedia categories skos vocabulary. The english file is skos_categories_en.nt
+    (takes 302s/5min)
+    """
+    name = 'gen-categories-skos'
+    voc_rtypes = {"http://www.w3.org/2004/02/skos/core#broader": "has_broader",
+                  "http://www.w3.org/2004/02/skos/core#related": "is_related"}
+    subject_etype = "DbpediaCategory"
+    object_etype = "DbpediaCategory"
+    subject_attr = "uri"
+    object_attr = "uri"
+
+class GenerateCategoriesLinksCommand(AbstractGenerateLinksCommand):
+    """
+    Generate all Dbpedia links to categories. The english file is article_categories_en.nt
+    """
+    name = 'gen-categories-links'
+    voc_rtypes = {'http://purl.org/dc/terms/subject': 'has_subject'}
+    subject_etype = "DbpediaPage"
+    object_etype = "DbpediaCategory"
+    subject_attr = "uri"
+    object_attr = "uri"
+
+
+#################################################################################
+### CUBIPEDIA ONTOLOGY GENERATION ###############################################
+#################################################################################
+class GenerateOntologyCommand(AbstractGenerateCommand):
+    """Generate Dbpedia ontology. The english file is dbpedia_3.6.owl
+    (takes 4s/0.06min)
+    """
+    name = 'gen-ontology'
+
+    def generate_func(self):
+        generate_ontology(self.session, self.filename)
+
+class GenerateOntologyLinksCommand(AbstractGenerateLinksCommand):
+    """
+    Generate all Dbpedia links to ontoloty. The english file is instance_types_en.nt
+    (takes 1323s/22min)
+    """
+    name = 'gen-ontology-links'
+    voc_rtypes = {'http://www.w3.org/1999/02/22-rdf-syntax-ns#type': 'has_type'}
+    subject_etype = "DbpediaPage"
+    object_etype = "DbpediaType"
+    subject_attr = "uri"
+    object_attr = "uri"
+
+
+#################################################################################
+## CUBIPEDIA COMMAND REGISTRATION #############################################
+#################################################################################
+CWCTL.register(FullTextIndexation)
+# Pages
+CWCTL.register(GeneratePagesCommand)
+CWCTL.register(GeneratePagesAbstractsCommand)
+CWCTL.register(GeneratePagesLongitudeCommand)
+CWCTL.register(GeneratePagesLatitudeCommand)
+CWCTL.register(GeneratePagesWikiPagesCommand)
+CWCTL.register(GeneratePagesIdsCommand)
+CWCTL.register(GeneratePagesAllLinksCommand)
+CWCTL.register(GeneratePagesHomepagesCommand)
+CWCTL.register(GeneratePagesThumbnailCommand)
+CWCTL.register(GeneratePagesPndsCommand)
+CWCTL.register(GeneratePagesDepictionCommand)
+CWCTL.register(GeneratePagesRedirectionsCommand)
+CWCTL.register(GeneratePagesDisambiguatesCommand)
+CWCTL.register(GeneratePagesGeoRelatedCommand)
+CWCTL.register(GeneratePagesLinksCommand)
+# Categories
+CWCTL.register(GenerateCategoriesCommand)
+CWCTL.register(GenerateCategoriesSkosVocabularyCommand)
+CWCTL.register(GenerateCategoriesLinksCommand)
+# Ontology
+CWCTL.register(GenerateOntologyCommand)
+CWCTL.register(GenerateOntologyLinksCommand)
Binary file data/crystal_clear_broader.png has changed
Binary file data/crystal_clear_bullet.png has changed
Binary file data/crystal_clear_category.png has changed
Binary file data/crystal_clear_disambiguate.png has changed
Binary file data/crystal_clear_geocoord.png has changed
Binary file data/crystal_clear_homepage.png has changed
Binary file data/crystal_clear_link.png has changed
Binary file data/crystal_clear_list_arrow.png has changed
Binary file data/crystal_clear_location.png has changed
Binary file data/crystal_clear_narrower.png has changed
Binary file data/crystal_clear_pnd.png has changed
Binary file data/crystal_clear_redirection.png has changed
Binary file data/crystal_clear_related.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/data/cubes.cubipedia.css	Tue Aug 30 12:29:28 2011 +0200
@@ -0,0 +1,1357 @@
+/*
+ *  :organization: Logilab
+ *  :copyright: 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+ *  :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
+ */
+
+/***************************************/
+/* xhtml tags                          */
+/***************************************/
+* {
+  margin: 0px;
+  padding: 0px;
+}
+
+ html, body {}/*background-color: black;}*/
+
+
+/*##############################################################################*/
+/* HEADER */
+/*##############################################################################*/
+div#header{
+  text-align: left;
+  padding: 0px 0px 0px 10px;
+ }
+
+div#frontheader{
+  text-align: left;
+  padding: 20px;
+ }
+
+h1.smallheadline{
+  font-family: Gill Sans, Verdana;
+  font-size: 11px;
+  line-height: 14px;
+  text-transform: uppercase;
+  letter-spacing: 2px;
+  font-weight: bold;
+ }
+
+h1.largeheadline{
+  font-family: times, Times New Roman, times-roman, georgia, serif;
+  color: #444;
+  margin: 0;
+  padding: 0px 0px 6px 0px;
+  font-size: 51px;
+  line-height: 44px;
+  letter-spacing: -2px;
+  font-weight: bold;
+ }
+
+div#header a, a:active, a:visited, a:link  {
+  color: #444;
+}
+
+
+
+/*##############################################################################*/
+/* STARTUP */
+/*##############################################################################*/
+div#FrontNews{
+  text-align: left;
+  margin: 10px;
+  /*border: 6px solid #ccc;*/
+ }
+
+div#FrontNews span.title{
+  font-family: times, Times New Roman, times-roman, georgia, serif;
+  text-align: center;
+  letter-spacing: -1px;
+  font-weight: bold;
+  font-size: 30px;
+  text-transform:uppercase;
+  padding: 4px;
+  margin-top: 20px;
+ }
+
+div#FrontNews ul li{
+  /*list-style-image: url("rss-syndicate.png");*/
+ }
+
+div#FrontNews  li span{
+  display: block;
+  color: #444;
+  margin-left: 10px;
+  font-family: Gill Sans, Verdana;
+  font-size: 16px;
+  font-weight: bold;
+ }
+
+div#FrontNews  li a.datafeed{
+  font-family: times, Times New Roman, times-roman, georgia, serif;
+  display: block;
+  margin-left: 10px;
+  font-size: 12px;
+  font-style: italic;
+ }
+
+div#FrontNews div.rss-abstract{
+font-family: georgia, serif;
+font-size: 12px;
+font-weight: normal;
+text-transform: normal;
+letter-spacing: normal;
+line-height: 1.5em;
+margin: 10px;
+padding: 10px;
+max-width: 600px;
+ }
+
+div#FrontNews ul.rss-cluster li{
+  display: inline-block;
+  vertical-align:text-top;
+ }
+
+div#FrontNews li a.dbpediapage-rss{
+  text-align: left;
+  display: block;
+  color: #444;
+  margin-left: 10px;
+  font-family: times, Times New Roman, times-roman, georgia, serif;
+  font-size: 14px;
+  padding-right: 40px;
+  font-weight: normal;
+ }
+
+div#FrontNews ul.rss-cluster li ul li{
+  display: block;
+ }
+
+div#FrontNews ul.small-rss li a.small-rss{
+  text-align: right;
+  display: block;
+  color: #444;
+  margin-left: 10px;
+  font-family: Gill Sans, Verdana;
+  font-size: 12px;
+  font-weight: bold;
+ }
+
+div#FrontNews ul.small-rss li a.small-datafeed{
+  display: block;
+  text-align: right;
+  font-family: times, Times New Roman, times-roman, georgia, serif;
+  margin-left: 10px;
+  font-size: 12px;
+  font-style: italic;
+ }
+
+div#FrontNews ul.small-rss li a.rss-all-sources{
+  display: block;
+  text-align: right;
+  display: block;
+  color: #444;
+  margin-left: 10px;
+  font-family: Gill Sans, Verdana;
+  font-size: 12px;
+  margin-bottom: 20px;
+  font-weight: normal;
+ }
+
+
+ul#HeadLines li{
+  display: inline-block;
+  text-align: center;
+  margin-left: 10px;
+  border: 2px solid #ccc;
+  vertical-align:text-top;
+ }
+
+ul#HeadLines span.title{
+  font-family: times, Times New Roman, times-roman, georgia, serif;
+  text-align: center;
+  letter-spacing: -1px;
+  font-weight: bold;
+  font-size: 18px;
+  text-transform:uppercase;
+  padding: 4px;
+ }
+
+ ul#HeadLines  li a{
+  display: block;
+  color: #444;
+  margin-left: 10px;
+  font-family: Gill Sans, Verdana;
+  font-size: 10px;
+  font-weight: bold;
+ }
+
+div#searchBox {
+  font-family: times, Times New Roman, times-roman, georgia, serif;
+  text-align: center;
+  letter-spacing: -1px;
+  font-weight: bold;
+  font-size: 18px;
+  text-transform:uppercase;
+  padding: 4px;
+  margin-top: 5px;
+  margin-bottom: 5px;
+ }
+
+div#relationGraph {
+  margin-top: 20px;
+  text-align: center;
+ }
+
+div#relationGraph div.title{
+  font-family: times, Times New Roman, times-roman, georgia, serif;
+  text-align: center;
+  letter-spacing: -1px;
+  font-weight: bold;
+  font-size: 18px;
+  text-transform:uppercase;
+ }
+
+div#namedEntities {
+  text-align: center;
+  margin-top: 20px;
+ }
+
+
+/*##############################################################################*/
+/* PAGE */
+/*##############################################################################*/
+
+/* PAGE CONTENT */
+div#pageContent {
+  padding: 10px 1em 2em;
+  /*background: black;*/
+  /*border: 1px solid #ccc;*/
+}
+
+div#pageContent h1.page{
+  text-align: center;
+  text-transform:uppercase;
+  font-size: 20px;
+  color: #444;
+  padding:0 40px;
+ }
+
+/* INFORMATION */
+div#pageInformation {
+  margin: 20px;
+}
+
+
+/*##############################################################################*/
+/* DBPEDIAPAGE */
+/*##############################################################################*/
+
+/* INFORMATION */
+div#pageInformation div.abstract{
+font-family: georgia, serif;
+font-size: 12px;
+font-weight: normal;
+text-transform: normal;
+letter-spacing: normal;
+line-height: 1.5em;
+min-height:160px;/* do not mess with image*/
+ }
+
+div#pageInformation div.abstract a.title{
+  font-size: 20px;
+  text-transform: uppercase;
+ }
+
+div#pageInformation img.depiction{
+  float: right;
+  padding: 0 0 0 10px;
+ }
+
+div#pageInformation span{
+  margin-top: 5px;
+  padding: 5px;
+  border :1px solid #ccc;
+  text-transform:uppercase;
+  display: block;
+ }
+
+div#pageInformation span a{
+  font-weight: bold;
+ }
+
+div#pageInformation span ul{
+  padding: 0 0 0 20px;
+  list-style-image: url("crystal_clear_bullet.png");
+ }
+
+
+/* LINKS */
+
+
+div#pageContent div.has-type{
+ }
+
+div#pageContent div.has-no-type{
+  border-top:1px solid #ccc;
+ }
+
+
+div#pageContent div.has-type ul{
+  list-style:none;
+  text-align:center;
+  border-top:1px solid #ccc;
+  border-bottom:1px solid #ccc;
+  padding:10px 0;
+ }
+div#pageContent div.has-type ul li{
+  display:inline;
+  text-transform:uppercase;
+  padding:0 20px;
+  letter-spacing:5px;
+  border-right: 1px solid #ccc;
+ }
+div#pageContent div.has-type ul li a{
+  text-decoration:none;
+  color:#444;
+ }
+div#pageContent div.has-type ul li a:hover{
+  text-decoration:underline;
+ }
+
+
+
+/*##############################################################################*/
+/* DBPEDIACATEGORY */
+/*##############################################################################*/
+div#pageContent ul.cat-broader{
+  padding: 0px 30px;
+  list-style:url("crystal_clear_broader.png");
+}
+
+div#pageContent ul.cat-broader a{
+  vertical-align: top;
+}
+
+div#pageContent ul.cat-narrower{
+  padding: 0px 30px;
+  list-style:url("crystal_clear_narrower.png");
+}
+
+div#pageContent ul.cat-narrower a{
+  vertical-align: top;
+}
+
+div#pageContent div.cat-entities{
+  border: 1px solid #ccc;
+}
+
+div#pageContent ul.cat-entities{
+  padding: 0px 30px;
+  list-style:url("crystal_clear_list_arrow.png");
+}
+
+
+div#page {
+  /*background: #e2e2e2;*/
+  position: relative;
+  min-height: 800px;
+}
+
+
+
+/*##############################################################################*/
+/* RSSFEED */
+/*##############################################################################*/
+h1#RSSFeedTitle{
+  text-align: center;
+  text-transform:uppercase;
+  font-size: 16px;
+  color: #444;
+  padding:0 40px;
+  border-bottom: 1px solid #ccc;
+  text-decoration:none;
+ }
+
+h1#RSSFeedTitle a{
+  font-weight: bold;
+  text-decoration:none;
+ }
+
+div#pageContent ul.related-entities{
+  padding: 0px 30px;
+  list-style:url("crystal_clear_list_arrow.png");
+}
+
+
+
+/* ACTIONS AND COMPONENTS*/
+.search_box div.boxBody {
+  padding: 4px 4px 3px;
+}
+
+div.boxTitle span,
+div.sideBoxTitle span {
+  padding: 0px 5px;
+  white-space: nowrap;
+}
+
+.contextFreeBox div.boxTitle {
+  color: white;
+  font-family: verdana;
+}
+
+input.rqlsubmit{
+  display: block;
+  width: 20px;
+  height: 20px;
+  background: url("go.png") 50% 50% no-repeat;
+  vertical-align: bottom;
+}
+
+
+/*
+########################################################################
+## CUBICWEB CSS ########################################################
+########################################################################
+*/
+
+body {
+  font-size: 69%;
+  font-weight: normal;
+  font-family: Verdana, sans-serif;
+}
+
+
+h2, h3 {
+  margin-top: 0.2em;
+  margin-bottom: 0.3em;
+}
+
+h2 {
+  font-size: 135%;
+}
+
+h3 {
+  font-size: 130%;
+}
+
+h4 {
+  font-size: 120%;
+  margin: 0.2em 0px;
+}
+
+h5 {
+  font-size:110%;
+}
+
+h6{
+  font-size:105%;
+}
+
+
+/*a, a:active, a:visited, a:link {
+  color: %(aColor)s;
+  text-decoration: none;
+}*/
+
+a:hover{
+  text-decoration: underline;
+}
+
+a img, img {
+  border: none;
+  text-align: center;
+}
+
+img.prevnext {
+  width: 22px;
+  height: 22px;
+}
+
+img.prevnext_nogo {
+  width: 22px;
+  height: 22px;
+  filter:alpha(opacity=25); /* IE */
+  opacity:.25;
+}
+
+p {
+  margin: 0em 0px 0.2em;
+  padding-top: 2px;
+}
+
+table, td, input, select{
+  font-size: 100%;
+}
+
+table {
+  border-collapse: collapse;
+  border: none;
+}
+
+table th, table td {
+  vertical-align: top;
+}
+
+table td img {
+  vertical-align: middle;
+  margin-right: 10px;
+}
+
+ol {
+  margin: 1px 0px 1px 16px;
+}
+
+ul{
+  margin: 1px 0px 1px 4px;
+  list-style-type: none;
+}
+
+
+dt {
+  font-size:1.17em;
+  font-weight:600;
+}
+
+dd {
+  margin: 0.6em 0 1.5em 2em;
+}
+
+fieldset {
+  border: none;
+}
+
+legend {
+  padding: 0px 2px;
+  font: bold 1em Verdana, sans-serif;
+}
+
+input, textarea {
+  padding: 0.2em;
+  vertical-align: middle;
+  border: 1px solid #ccc;
+}
+
+input:focus {
+  border: 1px inset #ff7700;
+}
+
+label, .label {
+  font-weight: bold;
+}
+
+iframe {
+  border: 0px;
+}
+
+pre {
+  font-family: Courier, "Courier New", Monaco, monospace;
+  font-size: 100%;
+  color: #000;
+  background-color: #f2f2f2;
+  border: 1px solid #ccc;
+}
+
+code {
+  font-size: 120%;
+  color: #000;
+  background-color: #f2f2f2;
+  border: 1px solid #ccc;
+}
+
+blockquote {
+  font-family: Courier, "Courier New", serif;
+  font-size: 120%;
+  margin: 5px 0px;
+  padding: 0.8em;
+  background-color: #f2f2f2;
+  border: 1px solid #ccc;
+}
+
+/***************************************/
+/* generic classes                     */
+/***************************************/
+
+.odd {
+  background-color: #f7f6f1;
+}
+
+.even {
+  background-color: transparent;
+}
+
+.hr {
+  border-bottom: 1px dotted #ccc;
+  margin: 1em 0px;
+}
+
+.left {
+  float: left;
+}
+
+.right {
+  float: right;
+}
+
+.clear {
+  clear: both;
+}
+
+.hidden {
+  display: none;
+  visibility: hidden;
+}
+
+li.invisible { list-style: none; background: none; padding: 0px 0px
+1px 1px; }
+
+li.invisible div {
+  display: inline;
+}
+
+.caption {
+    font-weight: bold;
+}
+
+.legend{
+    font-style: italic;
+}
+
+.align-center{
+    text-align: center;
+}
+
+/***************************************/
+/*   LAYOUT                            */
+/***************************************/
+
+/* header */
+
+
+/* FIXME appear with 4px width in IE6 */
+div#stateheader{
+  min-width: 66%;
+}
+
+/* Popup on login box and userActionBox */
+
+.popupWrapper{
+  position:relative;
+}
+
+div.popup {
+  position: absolute;
+  background: #fff;
+  border: 1px solid black;
+  text-align: left;
+  z-index: 400;
+}
+
+div.popup ul li a {
+  text-decoration: none;
+  color: black;
+}
+
+/* main zone */
+
+table#mainLayout{
+ padding: 0px 3px;
+}
+
+table#mainLayout td#contentColumn {
+  padding: 8px 10px 5px;
+}
+
+table#mainLayout td#navColumnLeft,
+table#mainLayout td#navColumnRight {
+  width: 16em;
+}
+
+#contentheader {
+  margin: 0px;
+  padding: 0.2em 0.5em 0.5em 0.5em;
+}
+
+#contentheader a {
+  color: #000;
+}
+
+/* rql bar */
+
+div#rqlinput {
+  border: 1px solid #cfceb7;
+  margin-bottom: 8px;
+  padding: 1px;
+  background: #cfceb7;
+  width: 100%;
+}
+
+input#rql {
+  width: 99%;
+}
+
+/* old boxes, deprecated */
+
+div.boxFrame {
+  width: 100%;
+}
+
+d
+
+div.sideBoxTitle span {
+  color: #222211;
+}
+
+.boxFrame a {
+  color: #000;
+}
+
+div.boxContent {
+  padding: 3px 0px;
+  background: #fff;
+  border-top: none;
+}
+
+div.shadow{
+  height: 14px;
+  background: url("shadow.gif") no-repeat top right;
+}
+
+/*
+div.sideBoxTitle {
+  background: #cfceb7;
+  display: block;
+  font: bold 100% Georgia;
+}*/
+
+div.sideBox {
+  padding: 0 0 0.2em;
+  margin-bottom: 0.5em;
+}
+
+ul.sideBox li {
+ list-style: none;
+ background: none;
+ padding: 0px 0px 1px 1px;
+ }
+
+div.sideBoxBody {
+  padding: 0.2em 5px;
+  background: #eeedd9;
+}
+
+div.sideBoxBody a {
+  color:#555544;
+}
+
+div.sideBoxBody a:hover {
+  text-decoration: underline;
+}
+
+div.sideBox table td {
+  padding-right: 1em;
+}
+
+/* boxes */
+
+div.navboxes {
+  padding-top: 0.5em;
+}
+
+/*
+div.boxTitle {
+  overflow: hidden;
+  font-weight: bold;
+}
+
+div.boxTitle span {
+  padding: 0px 0.5em;
+  white-space: nowrap;
+}
+
+div.boxBody {
+  padding: 3px 3px;
+  border-top: none;
+  background-color: %(leftrightBoxBodyBgColor)s;
+}
+
+div.boxBody a {
+  color: %(leftrightBoxBodyColor)s;
+}
+
+div.boxBody a:hover {
+  text-decoration: none;
+  cursor: pointer;
+  background-color: %(leftrightBoxBodyHoverBgColor)s;
+}
+
+hr.boxSeparator {
+  margin-top: 0.5em;
+  margin-bottom: 0.5em;
+}*/
+
+/* boxes contextual customization */
+/*
+.contextFreeBox div.boxTitle {
+  background: %(contextFreeBoxTitleBg)s;
+  color: %(contextFreeBoxTitleColor)s;
+}*/
+
+.contextualBox div.boxTitle {
+  background: %(contextualBoxTitleBg)s;
+  color: %(contextualBoxTitleColor)s;
+}
+
+.primaryRight div.boxTitle {
+  background: %(incontextBoxTitleBg)s;
+  color: %(incontextBoxTitleColor)s;
+}
+
+.primaryRight div.boxBody {
+  padding: 0.2em 5px;
+  background: %(incontextBoxBodyBgColor)s;
+}
+
+.primaryRight div.boxBody a {
+  color: %(incontextBoxBodyColor)s;
+}
+
+.primaryRight div.boxBody a:hover {
+  background-color: %(incontextBoxBodyHoverBgColor)s;
+}
+
+.primaryRight div.boxFooter {
+  margin-bottom: 1em;
+}
+
+
+/* boxes lists and menus */
+
+ul.boxListing {
+  margin: 0;
+  padding: 0;
+}
+
+ul.boxListing ul {
+  padding: 1px 3px;
+}
+
+ul.boxListing a {
+  color: %(defaultColor)s;
+  padding: 1px 3px;
+  display: block; /* necessary to get links across all width available (see on mouse over) */
+}
+
+ul.boxListing a.action {
+  padding: 0;
+  display: inline;
+}
+
+ul.boxListing a.action + a{
+  display: inline;
+}
+
+ul.boxListing li {
+  margin: 0px;
+  padding: 0px;
+  background-image: none;
+}
+
+ul.boxListing ul li {
+  margin: 0px;
+  padding-left: 1em;
+}
+
+ul.boxListing ul li a {
+  padding-left: 10px;
+  background-repeat: no-repeat;
+  background-position: 0 6px;
+}
+
+ul.boxListing .selected {
+  color: %(aColor)s;
+  font-weight: bold;
+}
+
+ul.boxListing a.boxMenu:hover {
+  border-top: medium none;
+  background: %(leftrightBoxBodyHoverBgColor)s;
+}
+
+a.boxMenu,
+ul.boxListing a.boxMenu {
+  display: block;
+  padding: 1px 3px;
+  background: transparent %(bulletDownImg)s;
+}
+
+ul.boxListing a.boxMenu:hover {
+  border-top: medium none;
+  background: %(leftrightBoxBodyHoverBgColor)s %(bulletDownImg)s;
+}
+
+a.boxMenu:hover {
+  cursor: pointer;
+}
+
+a.popupMenu {
+  background: transparent url("puce_down_black.png") 2% 6px no-repeat;
+  padding-left: 2em;
+}
+
+
+/* custom boxes */
+
+
+.bookmarks_box ul.boxListing div {
+  padding-bottom: 0.3em;
+}
+
+.download_box div.boxTitle {
+  background : #8fbc8f !important;
+}
+
+.download_box div.boxBody {
+  background : #eefed9;
+  vertical-align: center;
+}
+
+/* user actions menu */
+a.logout, a.logout:visited, a.logout:hover{
+  color: #fff;
+  text-decoration: none;
+}
+
+div#userActionsBox {
+  width: 14em;
+  text-align: right;
+}
+
+div#userActionsBox a.popupMenu {
+  color: black;
+  text-decoration: underline;
+  padding-right: 2em;
+}
+
+/**************/
+/* navigation */
+/**************/
+div#etyperestriction {
+  margin-bottom: 1ex;
+  border-bottom: 1px solid #ccc;
+}
+
+div.pagination{
+  margin: 0.5em 0;
+}
+
+span.slice a:visited,
+span.slice a:hover{
+  color: #555544;
+}
+
+span.selectedSlice a:visited,
+span.selectedSlice a {
+  background-color: #EBE8D9;
+}
+
+/* FIXME should be moved to cubes/folder */
+div.navigation a {
+  text-align: center;
+  text-decoration: none;
+}
+
+div.prevnext {
+  width: 100%;
+  margin-bottom: 1em;
+}
+
+div.prevnext a {
+  color: #000;
+}
+
+/***************************************/
+/* entity views                        */
+/***************************************/
+
+.mainInfo  {
+  margin-right: 1em;
+  padding: 0.2em;
+}
+
+
+div.mainRelated {
+  border: none;
+  margin-right: 1em;
+  padding: 0.5em 0.2em 0.2em;
+}
+
+div.primaryRight{
+ }
+
+div.metadata {
+  font-size: 90%;
+  margin: 5px 0px 3px;
+  color: #666;
+  font-style: italic;
+  text-align: right;
+}
+
+div.section {
+  margin-top: 0.5em;
+  width:100%;
+}
+
+div.section a:hover {
+  text-decoration: none;
+}
+
+/* basic entity view */
+
+tr.entityfield th {
+  text-align: left;
+  padding-right: 0.5em;
+}
+
+div.field {
+  display: inline;
+}
+
+div.ctxtoolbar {
+  float: right;
+  padding-left: 24px;
+  position: relative;
+}
+div.toolbarButton {
+  display: inline;
+}
+
+/***************************************/
+/* messages                            */
+/***************************************/
+
+.warning,
+.message,
+.errorMessage ,
+.searchMessage{
+  padding: 0.3em 0.3em 0.3em 1em;
+  font-weight: bold;
+}
+
+.loginMessage {
+  margin: 4px 0px;
+  font-weight: bold;
+  color: #ff7700;
+}
+
+div#appMsg, div.appMsg{
+  border: 1px solid #cfceb7;
+  margin-bottom: 8px;
+  padding: 3px;
+  background: #f8f8ee;
+}
+
+.message {
+  margin: 0px;
+  background: #f8f8ee url("information.png") 5px center no-repeat;
+  padding-left: 15px;
+}
+
+.errorMessage {
+  margin: 10px 0px;
+  padding-left: 25px;
+  background: #f7f6f1 url("critical.png") 2px center no-repeat;
+  color: #ed0d0d;
+  border: 1px solid #cfceb7;
+}
+
+.searchMessage {
+  margin-top: 0.5em;
+  border-top: 1px solid #cfceb7;
+  background: #eeedd9 url("information.png") 0% 50% no-repeat; /*dcdbc7*/
+}
+
+.stateMessage {
+  border: 1px solid #ccc;
+  background: #f8f8ee url("information.png") 10px 50% no-repeat;
+  padding:4px 0px 4px 20px;
+  border-width: 1px 0px 1px 0px;
+}
+
+/* warning messages like "There are too many results ..." */
+.warning {
+  padding-left: 25px;
+  background: #f2f2f2 url("critical.png") 3px 50% no-repeat;
+}
+
+/* label shown in the top-right hand corner during form validation */
+div#progress {
+  position: fixed;
+  right: 5px;
+  top: 0px;
+  background: #222211;
+  color: white;
+  font-weight: bold;
+  display: none;
+}
+
+/***************************************/
+/* listing table                       */
+/***************************************/
+
+table.listing {
+ padding: 10px 0em;
+ color: #000;
+ width: 100%;
+ border-right: 1px solid #dfdfdf;
+}
+
+
+table.listing thead th.over {
+  background-color: #746B6B;
+  cursor: pointer;
+}
+
+table.listing tr th {
+  border: 1px solid #dfdfdf;
+  border-right:none;
+  font-size: 8pt;
+  padding: 4px;
+}
+
+table.listing tr .header {
+  border-right: 1px solid #dfdfdf;
+  cursor: pointer;
+}
+
+table.listing td {
+  color: #3D3D3D;
+  padding: 4px;
+  background-color: #FFF;
+  vertical-align: top;
+}
+
+table.listing th,
+table.listing td {
+  padding: 3px 0px 3px 5px;
+  border: 1px solid #dfdfdf;
+  border-right: none;
+}
+
+table.listing th {
+  font-weight: bold;
+  background: #ebe8d9 url("button.png") repeat-x;
+}
+
+table.listing td a,
+table.listing td a:visited {
+  color: #666;
+}
+
+table.listing a:hover,
+table.listing tr.highlighted td a {
+  color:#000;
+}
+
+table.listing td.top {
+  border: 1px solid white;
+  border-bottom: none;
+  text-align: right ! important;
+  /* insane IE row bug workaround */
+  position: relative;
+  left: -1px;
+  top: -1px;
+}
+
+table.htableForm {
+  vertical-align: middle;
+}
+table.htableForm td{
+  padding-left: 1em;
+  padding-top: 0.5em;
+}
+table.htableForm th{
+  padding-left: 1em;
+}
+table.htableForm .validateButton {
+  margin-right: 0.2em;
+  vertical-align: top;
+  margin-bottom: 0.2em; /* because vertical-align doesn't seems to have any effect */
+}
+
+table.ajaxEditRelationTable{
+  margin-bottom: 0.5em;
+}
+table.ajaxEditRelationTable td.entity{
+  padding-left: 0.5em;
+}
+
+/***************************************/
+/* error view (views/management.py)    */
+/***************************************/
+
+div.pycontext { /* html traceback */
+  font-family: Verdana, sans-serif;
+  font-size: 80%;
+  padding: 1em;
+  margin: 10px 0px 5px 20px;
+  background-color: #dee7ec;
+}
+
+div.pycontext span.name {
+  color: #ff0000;
+}
+
+
+/***************************************/
+/* addcombobox                         */
+/***************************************/
+
+input#newopt{
+ width:120px ;
+ display:block;
+ float:left;
+ }
+
+div#newvalue{
+ margin-top:2px;
+ }
+
+#add_newopt{
+ background: #fffff8 url("go.png") 50% 50% no-repeat;
+ width: 20px;
+ line-height: 20px;
+ display:block;
+ float:left;
+}
+
+/***************************************/
+/* buttons                             */
+/***************************************/
+
+input.button{
+  margin: 1em 1em 0px 0px;
+  border: 1px solid #edecd2;
+  border-color:#edecd2 #cfceb7 #cfceb7  #edecd2;
+  background: #fffff8 url("button.png") bottom left repeat-x;
+}
+
+/* FileItemInnerView  jquery.treeview.css */
+.folder {
+  /* disable odd/even under folder class */
+  background-color: transparent;
+}
+
+a.addButton {
+  margin-left: 0.5em;
+  padding-left: 16px;
+  background: transparent url("add_button.png") 0% 50% no-repeat;
+}
+
+/***************************************/
+/* footer                              */
+/***************************************/
+
+div#footer {
+  text-align: center;
+}
+div#footer a {
+  color: #000;
+  text-decoration: none;
+}
+
+
+/****************************************/
+/* FIXME must by managed by cubes       */
+/****************************************/
+.needsvalidation {
+  font-style: italic;
+  color: gray;
+}
+
+
+/***************************************/
+/* FIXME : Deprecated ? entity view ?  */
+/***************************************/
+.title {
+  text-align: left;
+  font-size:  large;
+  font-weight: bold;
+}
+
+.validateButton {
+  margin: 1em 1em 0px 0px;
+  border: 1px solid #edecd2;
+  border-color:#edecd2 #cfceb7 #cfceb7  #edecd2;
+  background: #fffff8 url("button.png") bottom left repeat-x;
+}
+
+/********************************/
+/* placement of alt. view icons */
+/********************************/
+
+.otherView {
+  float: right;
+}
+
+
+/******************************/
+/* reledit                    */
+/******************************/
+
+.releditField {
+    display: inline;
+}
+
+.releditForm {
+ display:none;
+}
+
+/********************************/
+/* overwite other css here      */
+/********************************/
+
+.ui-menu li.ui-menu-item {
+  /* remove background image (orange bullet) for autocomplete suggestions */
+  background-image: none;
+}
+
+div.ui-tabs.ui-widget-content {
+  background:none;
+  border:none;
+  color:inherit;
+}
+
+div.ui-tabs ul.ui-tabs-nav {
+  padding-left: 0.5em;
+}
+
+div.ui-tabs ul.ui-tabs-nav a {
+  color:#27537A;
+  padding: 0.3em 0.6em;
+  outline:0;
+}
+
+div.ui-tabs ul.ui-tabs-nav li.ui-tabs-selected a {
+  color:black;
+}
+
+div.ui-tabs ul.ui-tabs-nav li.ui-state-hover, div.ui-tabs ul.ui-tabs-nav li.ui-state-focus {
+  background:white;
+}
+
+div.ui-tabs .ui-widget-header {
+  background:none;
+  border:none;
+}
+
+div.ui-tabs .ui-widget-header li {
+  border-color:#333333;
+}
+
+div.ui-tabs .ui-tabs-panel {
+  border-top:1px solid #97A5B0;
+  padding-left:0.5em;
+  color:inherit;
+}
\ No newline at end of file
Binary file data/wikipedia.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debian/changelog	Tue Aug 30 12:29:28 2011 +0200
@@ -0,0 +1,6 @@
+cubicweb-cubipedia (0.1.0-1) unstable; urgency=low
+
+  * initial release
+
+ -- 
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debian/compat	Tue Aug 30 12:29:28 2011 +0200
@@ -0,0 +1,1 @@
+5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debian/control	Tue Aug 30 12:29:28 2011 +0200
@@ -0,0 +1,19 @@
+Source: cubicweb-cubipedia
+Section: web
+Priority: optional
+Maintainer: LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
+Build-Depends: debhelper (>= 5.0.37.1), python (>=2.4), python-dev (>=2.4)
+Standards-Version: 3.8.0
+
+
+Package: cubicweb-cubipedia
+Architecture: all
+Depends: cubicweb-common (>= 3.13.0), python-rql (>= 0.28.0-1), python-yams (>= 0.30.3-1),
+	cubicweb-keyword, cubicweb-file, cubicweb-link, cubicweb-card, cubicweb-tag
+Description: Cube for mananing and querying information from dbpedia
+ CubicWeb is a semantic web application framework.
+ .
+ Cube for mananing and querying information from dbpedia
+ .
+ This package will install all the components you need to run the
+ cubicweb-cubipedia application (cube :)..
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debian/copyright	Tue Aug 30 12:29:28 2011 +0200
@@ -0,0 +1,8 @@
+Upstream Author: 
+
+  LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
+
+Copyright:
+
+Copyright (c) 2011 LOGILAB S.A. (Paris, FRANCE).
+http://www.logilab.fr -- mailto:contact@logilab.fr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debian/cubicweb-cubipedia.prerm	Tue Aug 30 12:29:28 2011 +0200
@@ -0,0 +1,27 @@
+#!/bin/sh -e
+
+delete_pyo_pyc () {
+  find /usr/share/cubicweb/cubes/cubipedia -name "*.pyc" | xargs rm -f
+  find /usr/share/cubicweb/cubes/cubipedia -name "*.pyo" | xargs rm -f
+}
+
+
+case "$1" in
+    failed-upgrade|abort-install|abort-upgrade|disappear)
+    ;;
+    upgrade)
+    delete_pyo_pyc
+    ;;
+    remove)
+    delete_pyo_pyc
+    ;;
+    purge)
+    ;;
+
+    *)
+        echo "postrm called with unknown argument \`$1'" >&2
+        exit 1
+
+esac
+
+#DEBHELPER#
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debian/rules	Tue Aug 30 12:29:28 2011 +0200
@@ -0,0 +1,53 @@
+#!/usr/bin/make -f
+# Sample debian/rules that uses debhelper.
+# GNU copyright 1997 to 1999 by Joey Hess.
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+build: build-stamp
+build-stamp:
+	dh_testdir
+	NO_SETUPTOOLS=1 python setup.py -q build
+	touch build-stamp
+
+clean:
+	dh_testdir
+	dh_testroot
+	rm -f build-stamp configure-stamp
+	rm -rf build
+	find . -name "*.pyc" | xargs rm -f
+	dh_clean
+
+install: build
+	dh_testdir
+	dh_testroot
+	dh_clean -k
+	dh_installdirs -i
+	NO_SETUPTOOLS=1 python setup.py -q install --no-compile --prefix=debian/cubicweb-cubipedia/usr/
+	# remove generated .egg-info file
+	rm -rf debian/cubicweb-cubipedia/usr/lib/python*
+
+
+# Build architecture-independent files here.
+binary-indep: build install
+	dh_testdir
+	dh_testroot
+	dh_install -i
+	dh_installchangelogs -i
+	dh_installexamples -i
+	dh_installdocs -i
+	dh_installman -i
+	dh_link -i
+	dh_compress -i -X.py -X.ini -X.xml -Xtest
+	dh_fixperms -i
+	dh_installdeb -i
+	dh_gencontrol -i
+	dh_md5sums -i
+	dh_builddeb -i
+
+
+# Build architecture-dependent files here.
+binary-arch:
+
+binary: binary-indep
+.PHONY: build clean binary-arch binary-indep binary
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/entities/__init__.py	Tue Aug 30 12:29:28 2011 +0200
@@ -0,0 +1,28 @@
+"""
+Module for defining cubipedia entities
+"""
+from cubicweb.entities import AnyEntity, fetch_config
+
+### DBPEDIA CATEGORY
+class DbpediaCategory(AnyEntity):
+    __regid__ = 'DbpediaCategory'
+    fetch_attrs, fetch_order = fetch_config(('uri', 'label'))
+
+    def dc_title(self):
+        return self.label
+
+### DBPEDIA ENTITY
+class DbpediaPage(AnyEntity):
+    __regid__ = 'DbpediaPage'
+    fetch_attrs, fetch_order = fetch_config(('uri', 'label'))
+
+    def dc_title(self):
+        return self.label
+
+### DBPEDIA CLASS
+class DbpediaType(AnyEntity):
+    __regid__ = 'DbpediaType'
+    fetch_attrs, fetch_order = fetch_config(('uri', 'label'))
+
+    def dc_title(self):
+        return self.label
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hooks.py	Tue Aug 30 12:29:28 2011 +0200
@@ -0,0 +1,17 @@
+# copyright 2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr -- mailto:contact@logilab.fr
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by the Free
+# Software Foundation, either version 2.1 of the License, or (at your option)
+# any later version.
+#
+# 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 Lesser General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""cubicweb-cubipedia specific hooks and operations"""
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/i18n/en.po	Tue Aug 30 12:29:28 2011 +0200
@@ -0,0 +1,8 @@
+msgid ""
+msgstr ""
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: pygettext.py 1.5\n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/i18n/es.po	Tue Aug 30 12:29:28 2011 +0200
@@ -0,0 +1,8 @@
+msgid ""
+msgstr ""
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: pygettext.py 1.5\n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/i18n/fr.po	Tue Aug 30 12:29:28 2011 +0200
@@ -0,0 +1,8 @@
+msgid ""
+msgstr ""
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: pygettext.py 1.5\n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/migration/postcreate.py	Tue Aug 30 12:29:28 2011 +0200
@@ -0,0 +1,25 @@
+# copyright 2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr -- mailto:contact@logilab.fr
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by the Free
+# Software Foundation, either version 2.1 of the License, or (at your option)
+# any later version.
+#
+# 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 Lesser General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""cubicweb-cubipedia postcreate script, executed at instance creation time or when
+the cube is added to an existing instance.
+
+You could setup site properties or a workflow here for example.
+"""
+
+# Example of site property change
+#set_property('ui.site-title', "<sitename>")
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ontology.py	Tue Aug 30 12:29:28 2011 +0200
@@ -0,0 +1,83 @@
+"""
+Tools for importing the Dbpedia ontology
+"""
+import os.path as osp
+import codecs
+from lxml import etree
+
+from logilab.common.shellutils import ProgressBar
+
+
+def generate_ontology(cw_db, filename, verbose=False):
+    """
+    Generate the types ontology
+    """
+    tree = etree.parse(filename)
+    pb = ProgressBar(273, size=50, title="Generating ontology")
+    pb.refresh()
+    ns_owl = 'http://www.w3.org/2002/07/owl#'
+    ns_rdf = 'http://www.w3.org/2000/01/rdf-schema#'
+    ns_xml = 'http://www.w3.org/XML/1998/namespace'
+    ns_about = '{http://www.w3.org/1999/02/22-rdf-syntax-ns#}about'
+    ns_resource = '{http://www.w3.org/1999/02/22-rdf-syntax-ns#}resource'
+    entity_cwtype= cw_db.execute('Any X WHERE X is CWEType, X name "DbpediaPage"').get_entity(0, 0)
+    # Use cw_db to create entity to have hooks
+    classif = cw_db.create_entity('Classification', name=u'Dbpedia ontology',
+                                  classifies=entity_cwtype)
+    classes = {}
+    is_subclasses = {}
+    # Get all class
+    total = 0
+    for node in tree.findall('{%s}Class' % ns_owl):
+        kw = {}
+        kw['included_in'] = classif
+        # Create entity only if it has an uri
+        if ns_about in dict(node.items()):
+            uri = dict(node.items())[ns_about]
+            kw['uri'] = unicode(uri)
+            kw['name'] = unicode(uri.split('/')[-1])
+            label = node.find('{%s}label[@{%s}lang="en"]' % (ns_rdf, ns_xml))
+            if label is not None and label.text:
+                kw['label'] = unicode(label.text)
+            comment = node.find('{%s}comment[@{%s}lang="en"]' % (ns_rdf, ns_xml))
+            if comment is not None and comment.text:
+                kw['comment'] = unicode(comment.text)
+            subclass = node.find('{%s}subClassOf' % ns_rdf)
+            if subclass is not None and ns_resource in dict(subclass.items()):
+                subclass = dict(subclass.items())[ns_resource]
+            if subclass:
+                is_subclasses[uri] = subclass
+            kw = cw_db.create_entity('DbpediaType', **kw)
+            classes[uri] = kw
+            total += 1
+            pb.update()
+            pb.refresh()
+    # Create hierarchy
+    # Create 'http://www.w3.org/2002/07/owl#Thing'
+    kw = {}
+    kw['uri'] = unicode('http://www.w3.org/2002/07/owl#Thing')
+    kw['name'] = unicode('owl#Thing')
+    kw['label'] = unicode('Thing')
+    kw['included_in'] = classif
+    kw['sort_key'] = 0
+    kw = cw_db.create_entity('DbpediaType', **kw)
+    classes['http://www.w3.org/2002/07/owl#Thing'] = kw
+    already_seen = set()
+    for subclass, mainclass in is_subclasses.iteritems():
+        if subclass != 'http://www.w3.org/2002/07/owl#Thing': # Should not be possible...
+            if subclass != mainclass:
+                subclasseid = classes[subclass].eid
+                mainclasseid =  classes[mainclass].eid
+                if (subclasseid, mainclasseid) not in already_seen:
+                    already_seen.add( (subclasseid, mainclasseid) )
+                    cw_db.add_relation(subclasseid, 'subkeyword_of', mainclasseid)
+    # Create sort_key
+    next_kw = [kw.reverse_subkeyword_of]
+    while next_kw:
+        new_next_kw = []
+        for k in next_kw:
+            k[0].set_attributes(sort_key=k[0].subkeyword_of[0].sort_key)
+            new_next_kw.extend(k[0].reverse_subkeyword_of)
+        next_kw = new_next_kw
+    # Commit
+    cw_db.commit()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/readme	Tue Aug 30 12:29:28 2011 +0200
@@ -0,0 +1,3 @@
+Summary
+-------
+Cube for mananing and querying information from dbpedia
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/schema.py	Tue Aug 30 12:29:28 2011 +0200
@@ -0,0 +1,115 @@
+# copyright 2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr -- mailto:contact@logilab.fr
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by the Free
+# Software Foundation, either version 2.1 of the License, or (at your option)
+# any later version.
+#
+# 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 Lesser General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""cubicweb-cubipedia schema"""
+
+
+from yams.buildobjs import (EntityType, RelationDefinition, Int, String)
+from cubes.keyword.schema import Keyword
+
+################################################################################
+### ENTITIES ###################################################################
+################################################################################
+class DbpediaPage(EntityType):
+    """
+    Main Dbpedia entity (page), initialize from labels_en.nt
+    """
+    uri = String(unique=True, indexed=True) # Uri of the dbpedia ressource
+    label = String(indexed=True) # Corresponds to http://www.w3.org/2000/01/rdf-schema#label
+    pageid = String() # Corresponds to http://dbpedia.org/ontology/wikiPageID
+    abstract = String() # Corresponds to http://dbpedia.org/ontology/abstract
+    homepage = String() # Corresponds to http://xmlns.com/foaf/0.1/homepage
+    thumbnail = String() # Corresponds to http://dbpedia.org/ontology/thumbnail
+    depiction = String() # Corresponds to http://xmlns.com/foaf/0.1/depiction
+    wikipage = String() # Corresponds to http://xmlns.com/foaf/0.1/page
+    pnd = String() # Corresponds to http://dbpedia.org/ontology/individualisedPnd
+    latitude = String() # Corresponds to http://www.w3.org/2003/01/geo/wgs84_pos#lat
+    longitude = String() # Corresponds to http://www.w3.org/2003/01/geo/wgs84_pos#long
+    dblp = String()
+    musicbrainz = String()
+    newyorktimes = String()
+    projectgutenberg = String()
+    diseasome = String()
+
+
+class DbpediaType(Keyword):
+    __specializes_schema__ = True
+    uri = String(unique=True, indexed=True)
+    label = String(indexed=True)
+    comment = String()
+    sort_key = Int()
+
+class DbpediaCategory(EntityType):
+    uri = String(unique=True, indexed=True) # Uri of the dbpedia ressource
+    label = String(indexed=True) # Corresponds to <http://www.w3.org/2000/01/rdf-schema#label>
+
+
+################################################################################
+### RELATIONS ##################################################################
+################################################################################
+class links_to(RelationDefinition):
+    rdf = 'http://dbpedia.org/ontology/wikiPageWikiLink'
+    subject = 'DbpediaPage'
+    object = 'DbpediaPage'
+    cardinality = '**'
+    symmetric = True
+
+class redirects_to(RelationDefinition):
+    rdf = 'http://dbpedia.org/ontology/wikiPageRedirects'
+    subject = 'DbpediaPage'
+    object = 'DbpediaPage'
+    cardinality = '*?'
+
+class disambiguates(RelationDefinition):
+    rdf = 'http://dbpedia.org/ontology/wikiPageDisambiguates'
+    subject = 'DbpediaPage'
+    object = 'DbpediaPage'
+    cardinality = '**'
+
+class applied_to(RelationDefinition):
+    """tagged objects"""
+    subject = 'DbpediaType'
+    object = 'DbpediaPage'
+
+class has_type(RelationDefinition):
+    rdf = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type'
+    subject = 'DbpediaPage'
+    object = 'DbpediaType'
+    cardinality = '**'
+
+class has_subject(RelationDefinition):
+    rdf = 'http://purl.org/dc/terms/subject'
+    subject = 'DbpediaPage'
+    object = 'DbpediaCategory'
+    cardinality = '**'
+
+class has_broader(RelationDefinition):
+    rdf = 'http://www.w3.org/2004/02/skos/core#broader'
+    subject = 'DbpediaCategory'
+    object = 'DbpediaCategory'
+    cardinality = '**'
+
+class is_related(RelationDefinition):
+    rdf = 'http://www.w3.org/2004/02/skos/core#related'
+    subject = 'DbpediaCategory'
+    object = 'DbpediaCategory'
+    cardinality = '**'
+    symmetric = True
+
+class located_in(RelationDefinition):
+    subject = ('DbpediaPage', 'DbpediaCategory')
+    object = ('DbpediaPage', 'DbpediaCategory')
+    cardinality = '*?'
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/setup.py	Tue Aug 30 12:29:28 2011 +0200
@@ -0,0 +1,200 @@
+#!/usr/bin/env python
+# pylint: disable=W0142,W0403,W0404,W0613,W0622,W0622,W0704,R0904,C0103,E0611
+#
+# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
+#
+# This file is part of CubicWeb tag cube.
+#
+# CubicWeb is free software: you can redistribute it and/or modify it under the
+# terms of the GNU Lesser General Public License as published by the Free
+# Software Foundation, either version 2.1 of the License, or (at your option)
+# any later version.
+#
+# CubicWeb 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 Lesser General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
+"""Generic Setup script, takes package info from __pkginfo__.py file
+"""
+__docformat__ = "restructuredtext en"
+
+import os
+import sys
+import shutil
+from os.path import isdir, exists, join, walk
+
+try:
+    if os.environ.get('NO_SETUPTOOLS'):
+        raise ImportError() # do as there is no setuptools
+    from setuptools import setup
+    from setuptools.command import install_lib
+    USE_SETUPTOOLS = True
+except ImportError:
+    from distutils.core import setup
+    from distutils.command import install_lib
+    USE_SETUPTOOLS = False
+from distutils.command import install_data
+
+# import required features
+from __pkginfo__ import modname, version, license, description, web, \
+     author, author_email
+
+if exists('README'):
+    long_description = file('README').read()
+else:
+    long_description = ''
+
+# import optional features
+import __pkginfo__
+if USE_SETUPTOOLS:
+    requires = {}
+    for entry in ("__depends__",): # "__recommends__"):
+        requires.update(getattr(__pkginfo__, entry, {}))
+    install_requires = [("%s %s" % (d, v and v or "")).strip()
+                       for d, v in requires.iteritems()]
+else:
+    install_requires = []
+
+distname = getattr(__pkginfo__, 'distname', modname)
+scripts = getattr(__pkginfo__, 'scripts', ())
+include_dirs = getattr(__pkginfo__, 'include_dirs', ())
+data_files = getattr(__pkginfo__, 'data_files', None)
+ext_modules = getattr(__pkginfo__, 'ext_modules', None)
+dependency_links = getattr(__pkginfo__, 'dependency_links', ())
+
+BASE_BLACKLIST = ('CVS', '.svn', '.hg', 'debian', 'dist', 'build')
+IGNORED_EXTENSIONS = ('.pyc', '.pyo', '.elc', '~')
+
+
+def ensure_scripts(linux_scripts):
+    """
+    Creates the proper script names required for each platform
+    (taken from 4Suite)
+    """
+    from distutils import util
+    if util.get_platform()[:3] == 'win':
+        scripts_ = [script + '.bat' for script in linux_scripts]
+    else:
+        scripts_ = linux_scripts
+    return scripts_
+
+def export(from_dir, to_dir,
+           blacklist=BASE_BLACKLIST,
+           ignore_ext=IGNORED_EXTENSIONS,
+           verbose=True):
+    """make a mirror of from_dir in to_dir, omitting directories and files
+    listed in the black list
+    """
+    def make_mirror(arg, directory, fnames):
+        """walk handler"""
+        for norecurs in blacklist:
+            try:
+                fnames.remove(norecurs)
+            except ValueError:
+                pass
+        for filename in fnames:
+            # don't include binary files
+            if filename[-4:] in ignore_ext:
+                continue
+            if filename[-1] == '~':
+                continue
+            src = join(directory, filename)
+            dest = to_dir + src[len(from_dir):]
+            if verbose:
+                print >> sys.stderr, src, '->', dest
+            if os.path.isdir(src):
+                if not exists(dest):
+                    os.mkdir(dest)
+            else:
+                if exists(dest):
+                    os.remove(dest)
+                shutil.copy2(src, dest)
+    try:
+        os.mkdir(to_dir)
+    except OSError, ex:
+        # file exists ?
+        import errno
+        if ex.errno != errno.EEXIST:
+            raise
+    walk(from_dir, make_mirror, None)
+
+
+class MyInstallLib(install_lib.install_lib):
+    """extend install_lib command to handle  package __init__.py and
+    include_dirs variable if necessary
+    """
+    def run(self):
+        """overridden from install_lib class"""
+        install_lib.install_lib.run(self)
+        # manually install included directories if any
+        if include_dirs:
+            base = modname
+            for directory in include_dirs:
+                dest = join(self.install_dir, base, directory)
+                export(directory, dest, verbose=False)
+
+# re-enable copying data files in sys.prefix
+old_install_data = install_data.install_data
+if USE_SETUPTOOLS:
+    # overwrite InstallData to use sys.prefix instead of the egg directory
+    class MyInstallData(old_install_data):
+        """A class that manages data files installation"""
+        def run(self):
+            _old_install_dir = self.install_dir
+            if self.install_dir.endswith('egg'):
+                self.install_dir = sys.prefix
+            old_install_data.run(self)
+            self.install_dir = _old_install_dir
+    try:
+        import setuptools.command.easy_install # only if easy_install avaible
+        # monkey patch: Crack SandboxViolation verification
+        from setuptools.sandbox import DirectorySandbox as DS
+        old_ok = DS._ok
+        def _ok(self, path):
+            """Return True if ``path`` can be written during installation."""
+            out = old_ok(self, path) # here for side effect from setuptools
+            realpath = os.path.normcase(os.path.realpath(path))
+            allowed_path = os.path.normcase(sys.prefix)
+            if realpath.startswith(allowed_path):
+                out = True
+            return out
+        DS._ok = _ok
+    except ImportError:
+        pass
+
+def install(**kwargs):
+    """setup entry point"""
+    if USE_SETUPTOOLS:
+        if '--force-manifest' in sys.argv:
+            sys.argv.remove('--force-manifest')
+    # install-layout option was introduced in 2.5.3-1~exp1
+    elif sys.version_info < (2, 5, 4) and '--install-layout=deb' in sys.argv:
+        sys.argv.remove('--install-layout=deb')
+    cmdclass = {'install_lib': MyInstallLib}
+    if USE_SETUPTOOLS:
+        kwargs['install_requires'] = install_requires
+        kwargs['dependency_links'] = dependency_links
+        kwargs['zip_safe'] = False
+        cmdclass['install_data'] = MyInstallData
+
+    return setup(name = distname,
+                 version = version,
+                 license = license,
+                 description = description,
+                 long_description = long_description,
+                 author = author,
+                 author_email = author_email,
+                 url = web,
+                 scripts = ensure_scripts(scripts),
+                 data_files = data_files,
+                 ext_modules = ext_modules,
+                 cmdclass = cmdclass,
+                 **kwargs
+                 )
+
+if __name__ == '__main__' :
+    install()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/triplestore.py	Tue Aug 30 12:29:28 2011 +0200
@@ -0,0 +1,604 @@
+"""
+Some basic tools for importing triplets data in cubicweb,
+without to much pain...
+"""
+import os.path as osp
+from datetime import datetime
+import re
+import codecs
+import bz2
+
+import rdflib
+
+from cubicweb.schema import META_RTYPES
+
+import cubes.cubipedia.schema as fileschema
+
+
+################################################################################
+### MAIN TRIPLETS FUNCTION #####################################################
+################################################################################
+class TripleStore(object):
+    """
+    Triple store use for generating entities or links from dumps of triplets (.nt)
+    """
+
+    META_RELATIONS = (META_RTYPES - set(('has_text', 'eid')))
+
+    def __init__(self, cw_db, baseurl=None, default_tablespace='', verbose=False):
+        self.verbose = verbose
+        self.session = cw_db
+        self.default_tablespace = default_tablespace
+        self.source = self.session.repo.system_source
+        self.time = datetime.now()
+        if baseurl is None:
+            config = self.session.vreg.config
+            baseurl = config['base-url'] or config.default_base_url()
+        if not baseurl[-1] == '/':
+            baseurl += '/'
+        self.baseurl =  baseurl
+        self.etype_attrs = []
+        self.etype_rels = []
+        schema = self.session.vreg.schema
+        rschema = schema.rschema
+        for rtype in self.META_RELATIONS:
+            if rschema(rtype).final:
+                self.etype_attrs.append(rtype)
+            else:
+                self.etype_rels.append(rtype)
+
+    def commit(self):
+        """
+        Function for final commit
+        """
+        self.session.commit()
+
+    ############################################################################
+    ### TOOLS FOR GENERATING META DATA #########################################
+    ############################################################################
+    def mass_generate(self, etype):
+        for attr in self.etype_attrs:
+            self._generate(etype, attr)
+        for rel in self.etype_rels:
+            self._generate(etype, rel)
+        self._gen_entities(etype)
+
+    def _generate(self, etype, rtype):
+        return getattr(self, '_gen_%s' % rtype)(etype)
+
+    def _gen_cwuri(self, etype):
+        # Now, directly deal with in specific sql_dump_function
+        return None
+
+    def _gen_modification_date(self, etype):
+        # Now, directly deal with in specific sql_dump_function
+        return None
+
+    def _gen_creation_date(self, etype):
+        # Now, directly deal with in specific sql_dump_function
+        return None
+
+    def _gen_created_by(self, etype):
+        self.metagen_push_relation(etype, self.session.user.eid, 'created_by_relation')
+
+    def _gen_owned_by(self, etype):
+        self.metagen_push_relation(etype, self.session.user.eid, 'owned_by_relation')
+
+    def _gen_identity(self, etype):
+        rtype = 'identity_relation'
+        self.relation_drop_constraint(rtype)
+        sql = ("INSERT INTO %s (eid_from, eid_to) SELECT eid, eid FROM tmp;" % rtype)
+        self.session.system_sql(sql)
+        self.relation_create_constraint(rtype)
+
+    def _gen_cw_source(self, etype):
+        source_eid = self.session.execute('Any X WHERE X is CWSource')[0][0]
+        self.metagen_push_relation(etype, source_eid, 'cw_source_relation')
+
+    def _gen_is(self, etype):
+        source_eid = self.session.execute('Any X WHERE X is CWEType')[0][0]
+        self.metagen_push_relation(etype, source_eid, 'is_relation')
+
+    def _gen_is_instance_of(self, etype):
+        source_eid = self.session.execute('Any X WHERE X is CWEType')[0][0]
+        self.metagen_push_relation(etype, source_eid, 'is_instance_of_relation')
+
+    def metagen_push_relation(self, etype, eid_to, rtype):
+        self.relation_drop_constraint(rtype)
+        sql = ("INSERT INTO %s (eid_from, eid_to) SELECT eid, %s FROM tmp;"
+               % (rtype, eid_to))
+        self.session.system_sql(sql)
+        self.relation_create_constraint(rtype)
+
+    def _gen_entities(self, etype):
+        # Drop constraints
+        sql = 'ALTER TABLE entities DROP CONSTRAINT entities_pkey'
+        self.session.system_sql(sql)
+        sql = 'DROP INDEX entities_extid_idx'
+        self.session.system_sql(sql)
+        sql = 'DROP INDEX entities_mtime_idx'
+        self.session.system_sql(sql)
+        sql = 'DROP INDEX entities_type_idx'
+        self.session.system_sql(sql)
+        # Push data
+        # XXX is "system" as string ? or an encoded parameter ?
+        sql = ("INSERT INTO entities (eid, type, source, asource, mtime, extid) "
+               " SELECT eid, '%s', 'system', 'system', '%s', NULL FROM tmp;" % (etype, self.time))
+        self.session.system_sql(sql)
+        # Create constraints
+        sql = 'ALTER TABLE entities ADD PRIMARY KEY (eid)'
+        self.session.system_sql(sql)
+        sql = 'CREATE INDEX entities_extid_idx ON entities (extid) %s' % self.default_tablespace
+        self.session.system_sql(sql)
+        sql = 'CREATE INDEX entities_mtime_idx ON entities (mtime) %s' % self.default_tablespace
+        self.session.system_sql(sql)
+        sql = 'CREATE INDEX entities_type_idx ON entities (type) %s' % self.default_tablespace
+        self.session.system_sql(sql)
+
+    def preprocess_generation(self, etype):
+        # Create additional meta information
+        if self.verbose:
+            print "Generate meta data for etype", etype
+        self.mass_generate(etype=etype)
+        # Drop pkey constraints on entities eid
+        if self.verbose:
+            print "Drop pkey constraints on entities eid", etype
+        sql = "ALTER TABLE cw_%s DROP CONSTRAINT cw_%s_pkey" %(etype.lower(), etype.lower())
+        self.session.system_sql(sql)
+
+
+    ############################################################################
+    ### CONSTRAINTS MANAGEMENT #################################################
+    ############################################################################
+    def relation_drop_constraint(self, rtype):
+        sql = 'ALTER TABLE %s DROP CONSTRAINT %s_p_key' % (rtype, rtype)
+        self.session.system_sql(sql)
+        sql = 'DROP INDEX %s_to_idx' % rtype
+        self.session.system_sql(sql)
+        sql = 'DROP INDEX %s_from_idx' % rtype
+        self.session.system_sql(sql)
+
+    def relation_create_constraint(self, rtype):
+        sql = 'ALTER TABLE %s ADD PRIMARY KEY (eid_from, eid_to)' % rtype
+        self.session.system_sql(sql)
+        sql = 'ALTER INDEX %s_pkey RENAME TO %s_p_key' % (rtype, rtype)
+        self.session.system_sql(sql)
+        sql = 'CREATE INDEX %s_to_idx ON %s (eid_to) %s' % (rtype, rtype, self.default_tablespace)
+        self.session.system_sql(sql)
+        sql = 'CREATE INDEX %s_from_idx ON %s (eid_from) %s' % (rtype, rtype, self.default_tablespace)
+        self.session.system_sql(sql)
+
+    def entity_drop_unicity_constraint(self, etype, attr):
+        self.session.system_sql("ALTER TABLE cw_%(etype)s DROP CONSTRAINT cw_%(etype)s_cw_%(attr)s_key"
+                                % {'etype': etype.lower(), 'attr': attr.lower()})
+
+    def entity_create_unicity_constraint(self, etype, attr):
+        self.session.system_sql("ALTER TABLE cw_%(etype)s ADD CONSTRAINT cw_%(etype)s_cw_%(attr)s_key "
+                                "UNIQUE (cw_%(attr)s)"
+                                % {'etype': etype.lower(), 'attr': attr.lower()})
+
+    def entity_drop_index_constraint(self, etype, attr):
+        self.session.system_sql("DROP INDEX cw_%(etype)s_cw_%(attr)s_idx"
+                                % {'etype': etype.lower(), 'attr': attr.lower()})
+
+    def entity_create_index_constraint(self, etype, attr):
+        self.session.system_sql("CREATE INDEX cw_%(etype)s_cw_%(attr)s_idx ON cw_%(etype)s (cw_%(attr)s) %(ts)s"
+
+                                % {'etype': etype.lower(), 'attr': attr.lower(), 'ts': self.default_tablespace})
+
+    def drop_constraints(self, etype, attr, unicity, index):
+        if unicity:
+            self.entity_drop_unicity_constraint(etype, attr)
+        if index:
+            self.entity_drop_index_constraint(etype, attr)
+
+    def create_constraints(self, etype, attr, unicity, index):
+        if index:
+            self.entity_create_index_constraint(etype, attr)
+        if unicity:
+            self.entity_create_unicity_constraint(etype, attr)
+
+
+    ############################################################################
+    ### TOOLS FOR FILE PROCESSING/DATA IMPORT ##################################
+    ########################t####################################################
+    DBPEDIA_URI_REGEXP = '^<(.*?)>\s+<(.*?)>\s+<(.*?)> .$'
+    DBPEDIA_PROP_REGEXP = '^<(.*?)>\s+<(.*?)>\s+"(.*)"%s .$'
+    DBPEDIA_VALUE_REGEXP = '^<(.*?)>\s+<(.*?)>\s+"(.*)"(?:.*)'
+
+    def open_file(self, filename):
+        """
+        Function for opening multiple kinds of file.
+        """
+        if filename.endswith('.bz2'):
+            fobj = bz2.BZ2File(filename)
+        else:
+            fobj = open(filename, 'r')
+        return fobj
+
+    def load_file(self, filename, create_eid=True, delimiter=' '):
+        """
+        Function importing a file of triplets of properties,
+        that should be in the following format:
+            subject relation object
+        Delimiter could be choose (' ' by default)
+        """
+        # Creating temporary table
+        if self.verbose:
+            print "Creating temporary table"
+        columns = []
+        if create_eid:
+            columns.append("eid integer PRIMARY KEY DEFAULT nextval('entities_id_seq')")
+        columns.append('subject text')
+        columns.append('relation text')
+        columns.append('object text')
+        sql =  "CREATE TABLE tmp (%s) %s" % (', '.join(columns), self.default_tablespace)
+        cursor = self.session.system_sql(sql)
+        # Fill table with file
+        if self.verbose:
+            print "Fill table with file"
+        filename = osp.abspath(filename)
+        cursor.copy_from(file(filename, 'r'), 'tmp', sep=delimiter,null='NULL',
+                         columns=('subject', 'relation', 'object'))
+
+    def parse_file(self, fobj, line_regexp):
+        """
+        Function parsing a line with a specific Regexp,
+        yielding the three groups (subject, relation, object)
+        """
+        for line in fobj:
+            line = codecs.unicode_escape_decode(line)[0]
+            match = line_regexp.search(line)
+            if match is not None:
+                yield match.group(1), match.group(2), match.group(3)
+
+    def format_file(self, filename, line_regexp, voc_rtypes={}, delimiter='\t'):
+        """
+        This function is used when delimiters can appears in one of the triples (e.g " " in text property).
+        It rewrite the file in another one, replacing the delimiter of interest by another one (e.g '\t')
+        that should not appear in the data, using a specific Regular Expression.
+        Additional formating is also performed in this function to avoid to much time consumption in postgres.
+        """
+        if self.verbose:
+            print "Formating file"
+        filename = osp.abspath(filename)
+        fobj = self.open_file(filename)
+        filename_processed = filename.split('.',1)[0] + '.processed'
+        fobj_processed = open(filename_processed, 'w')
+        for subj, rel, obj in self.parse_file(fobj, line_regexp):
+            rel = self.format_chunk(rel, delimiter, repl_del=' ')
+            if len(voc_rtypes) == 0 or rel in voc_rtypes:
+                line = ('%(subj)s%(del)s%(rel)s%(del)s%(obj)s'
+                        % {'subj': self.format_chunk(subj, delimiter, repl_del=' '),
+                           'rel': rel,
+                           'obj': self.format_chunk(obj, delimiter, repl_del=' '),
+                           'del': delimiter})
+                fobj_processed.write(line + '\n')
+        fobj_processed.close()
+        fobj.close()
+        return filename_processed
+
+    def format_chunk(self, chunk, delimiter='\t', repl_del=' '):
+        """
+        Basic chunk formating before writing the processed file
+        """
+        return chunk.replace('\\', '').replace(delimiter, repl_del).strip().encode('utf-8')
+
+
+    ############################################################################
+    ### TOOLS FOR TABLE MANIPULATION ###########################################
+    ############################################################################
+    def drop_tmp_table(self):
+        """
+        Function droping the temporary table
+        """
+        # Droping temporary table (make space in disk for creating index and pkey)
+        if self.verbose:
+            print "Droping temporary table"
+        sql = "DROP TABLE tmp;"
+        self.session.system_sql(sql)
+
+    def drop_tmp_relations_table(self):
+        """
+        Function droping the temporary relations table
+        """
+        # Droping temporary relations table (make space in disk for creating index and pkey)
+        if self.verbose:
+            print "Droping temporary relations table"
+        sql = "DROP TABLE tmp_relations;"
+        self.session.system_sql(sql)
+
+    def drop_relations(self):
+        """
+        Drop the relation column, that may not be useful for some import
+        """
+        # Drop unuseful column is required
+        if self.verbose:
+            print "Drop relation column"
+        sql =  "ALTER TABLE tmp DROP COLUMN relation;"
+        self.session.system_sql(sql)
+
+    def remove_duplicates(self, distinct_on=''):
+        """
+        Remove duplicated entries.
+        XXX For now, dummy procedure using another temporary base, perhaps it coulb be more clever.
+        """
+        if self.verbose:
+            print 'Removing duplicated entries'
+        sql = "CREATE TABLE tmp1 %s AS SELECT DISTINCT %s * FROM tmp" % (self.default_tablespace, distinct_on)
+        self.session.system_sql(sql)
+        sql =  "DROP TABLE tmp;"
+        self.session.system_sql(sql)
+        sql =  "ALTER TABLE tmp1 RENAME TO tmp;"
+        self.session.system_sql(sql)
+
+
+    ############################################################################
+    ### TOOLS FOR LINKS AND RELATIONS GENERATION ###############################
+    ############################################################################
+    def relations_to_eid(self, subject_etype, object_etype, subject_attr, object_attr):
+        """
+        Function replacing relations by corresponding eid couples.
+        attr SHOULD BE INDEXED in etype table.
+        """
+        # Create temporary table
+        if self.verbose:
+            print "Create temporary table"
+        sql =  ("CREATE TABLE tmp_relations (eid_from integer DEFAULT NULL, eid_to integer DEFAULT NULL) %s"
+                % self.default_tablespace)
+        self.session.system_sql(sql)
+        # Push data
+        if self.verbose:
+            print "Push eid data"
+        sql = ("INSERT INTO tmp_relations (eid_from, eid_to) "
+               "SELECT t.cw_eid, cw_%(etypeo)s.cw_eid "
+               "FROM (SELECT cw_%(etypes)s.cw_eid, tmp.object FROM tmp, cw_%(etypes)s "
+               "WHERE tmp.subject = cw_%(etypes)s.cw_%(attrs)s) as t, cw_%(etypeo)s "
+               "WHERE t.object = cw_%(etypeo)s.cw_%(attro)s"
+               % {'etypes': subject_etype.lower(), 'etypeo': object_etype.lower(),
+                  'attrs': subject_attr.lower(), 'attro': object_attr.lower()})
+        self.session.system_sql(sql)
+        ## Dont' need to remove NULL eid as this is dealt with within the CROSS JOIN
+        # Droping temporary table (make space in disk for creating index and pkey)
+        self.drop_tmp_table()
+
+    def complete_relations_to_eid(self, subject_etype, object_etype, subject_attr, object_attr):
+        """
+        Function replacing relations by corresponding eid couples.
+        attr SHOULD BE INDEXED in etype table.
+        This version keep the relation table, as they might be different.
+        """
+        # Create temporary table
+        if self.verbose:
+            print "Create temporary table"
+        sql =  ("CREATE TABLE tmp_relations (eid_from integer DEFAULT NULL, "
+                "eid_to integer DEFAULT NULL, relation text) %s" % self.default_tablespace)
+        self.session.system_sql(sql)
+        # Push data
+        if self.verbose:
+            print "Push eid data"
+        sql = ("INSERT INTO tmp_relations (eid_from, eid_to, relation) "
+               "SELECT t.cw_eid, cw_%(etypeo)s.cw_eid, t.relation "
+               "FROM (SELECT cw_%(etypes)s.cw_eid, tmp.object, tmp.relation "
+               "FROM tmp, cw_%(etypes)s "
+               "WHERE tmp.subject = cw_%(etypes)s.cw_%(attrs)s) as t, cw_%(etypeo)s "
+               "WHERE t.object = cw_%(etypeo)s.cw_%(attro)s"
+               % {'etypes': subject_etype.lower(), 'etypeo': object_etype.lower(),
+                  'attrs': subject_attr.lower(), 'attro': object_attr.lower()})
+        self.session.system_sql(sql)
+        ## Dont' need to remove NULL eid as this is dealt with within the CROSS JOIN
+        # Droping temporary table (make space in disk for creating index and pkey)
+        self.drop_tmp_table()
+
+    def attributes_relations_to_eid(self, etype, attr):
+        """
+        Function replacing relations by corresponding eid couples.
+        attr SHOULD BE INDEXED in etype table.
+        """
+        # Create temporary table
+        if self.verbose:
+            print "Create temporary table"
+        sql =  ("CREATE TABLE tmp_attributes (eid integer DEFAULT NULL, relation text, object text) %s"
+                % self.default_tablespace)
+        self.session.system_sql(sql)
+        print sql
+        # Push data
+        if self.verbose:
+            print "Push eid relations"
+        sql = ("INSERT INTO tmp_attributes (eid, relation, object) "
+               "SELECT cw_%(etype)s.cw_eid, tmp.relation, tmp.object FROM tmp, cw_%(etype)s "
+               "WHERE tmp.subject = cw_%(etype)s.cw_%(attr)s"
+               % {'etype': etype.lower(), 'attr': attr.lower()})
+        self.session.system_sql(sql)
+        # Droping temporary table (make space in disk for creating index and pkey)
+        self.drop_tmp_table()
+        sql =  "ALTER TABLE tmp_attributes RENAME TO tmp;"
+        self.session.system_sql(sql)
+
+    def push_links(self, voc_rtypes, table, column_from, column_to, column_rel):
+        """
+        Function pushing links from a table in database
+        """
+        for rdf_voc, rtype in voc_rtypes.iteritems():
+            # Push links in cw table
+            if self.verbose:
+                print "Push links in cw table", rtype
+            self.relation_drop_constraint('%s_relation' % rtype)
+            self.session.system_sql("INSERT INTO %(rtype)s_relation (eid_from, eid_to) "
+                                    "SELECT %(table)s.%(from)s, %(table)s.%(to)s FROM %(table)s "
+                                    "WHERE %(table)s.%(rel)s = '%(rdf)s'"
+                                    % {'rtype': rtype, 'table': table,
+                                       'from': column_from, 'to': column_to,
+                                       'rel': column_rel,'rdf': rdf_voc})
+            self.relation_create_constraint('%s_relation' % rtype)
+
+
+    ############################################################################
+    ### TOOLS FOR ENTITIES GENERATION ##########################################
+    ############################################################################
+    def generate_entities(self, filename, etype, subject_attr, object_attr,
+                          subj_unicity=False, subj_index=False,
+                          obj_unicity=False, obj_index=False, lang='@en'):
+        """
+        High level function for generating a bunch of entities from the temporary table.
+        """
+        # Create and file temporary table
+        line_regexp = re.compile(self.DBPEDIA_PROP_REGEXP % lang)
+        filename_processed = self.format_file(filename, line_regexp, delimiter='\t')
+        self.load_file(filename_processed, create_eid=True, delimiter='\t')
+        # Drop relation column
+        self.drop_relations()
+        # Remove duplicated uris
+        self.remove_duplicates(distinct_on='ON (subject) ')
+        # Preprocess for the generation
+        self.preprocess_generation(etype)
+        # Drop other constraints on entities attr
+        if self.verbose:
+            print "Drop other constraints on entities attr", etype
+        self.drop_constraints(etype, subject_attr, subj_unicity, subj_index)
+        self.drop_constraints(etype, object_attr, obj_unicity, obj_index)
+        # Push table in cw tables
+        if self.verbose:
+            print "Push data in cw table"
+        self.session.system_sql("INSERT INTO cw_%(etype)s (cw_%(subject)s, cw_%(object)s, "
+                                "cw_modification_date, cw_creation_date, cw_cwuri, cw_eid) "
+                                "SELECT subject, object, %%(time)s, %%(time)s, "
+                                "'eid/' || eid, eid FROM tmp;"
+                                % {'etype': etype.lower(), 'subject': subject_attr.lower(),
+                                   'object': object_attr. lower()},
+                                {'time': self.time})
+        # Droping temporary table (make space in disk for creating index and pkey)
+        self.drop_tmp_table()
+        # Create constraints on entities eid
+        if self.verbose:
+            print "Create constraints on entities eid", etype
+        sql = "ALTER TABLE cw_%s ADD PRIMARY KEY (cw_eid)" % etype.lower()
+        self.session.system_sql(sql)
+        # Create other constraints on entities attr
+        if self.verbose:
+            print "Create other constraints on entities attr", etype
+        self.create_constraints(etype, subject_attr, subj_unicity, subj_index)
+        self.create_constraints(etype, object_attr, obj_unicity, obj_index)
+
+
+    ############################################################################
+    ### TOOLS FOR ENTITIES/ATTRS GENERATION ####################################
+    ############################################################################
+    def generate_entities_attributes(self, filename, dump_type, etype,
+                                     subject_attr, rdf_voc, object_attr,
+                                     obj_unicity=False, obj_index=False,
+                                     remove_duplicate=None, lang='@en'):
+        """
+        High level function for generating a bunch of entities from the temporary table,.
+        """
+        # Create and fill temporary table
+        if dump_type == 'uri':
+            line_regexp = re.compile(self.DBPEDIA_URI_REGEXP)
+        elif dump_type == 'prop':
+            line_regexp = re.compile(self.DBPEDIA_PROP_REGEXP % lang)
+        elif dump_type == 'value':
+            line_regexp = re.compile(self.DBPEDIA_VALUE_REGEXP)
+        filename_processed = self.format_file(filename, line_regexp, voc_rtypes = (rdf_voc,), delimiter='\t')
+        self.load_file(filename_processed, create_eid=False, delimiter='\t')
+        # Remove duplicated uris
+        if remove_duplicate == 'subject':
+            self.remove_duplicates(distinct_on='ON (subject) ')
+        elif remove_duplicate == 'object':
+            self.remove_duplicates(distinct_on='ON (object) ')
+        elif remove_duplicate == 'all':
+            self.remove_duplicates()
+        # Subject->eid table
+        self.attributes_relations_to_eid(etype, subject_attr)
+        # Switch table
+        if self.verbose:
+            print "Switch temporary entities table"
+        sql =  "ALTER TABLE cw_%s RENAME TO tmp_entities" % etype.lower()
+        self.session.system_sql(sql)
+        # Create new table
+        if self.verbose:
+            print "Create new table"
+        sql =  "CREATE TABLE cw_%s AS SELECT * FROM tmp_entities WHERE 1=2" % etype.lower()
+        self.session.system_sql(sql)
+        # Push data in cw table
+        sql = ("SELECT attname FROM pg_attribute, pg_type WHERE typname = 'cw_%s' AND attrelid = typrelid "
+               "AND attname NOT IN ('cmin', 'cmax', 'ctid', 'oid', 'tableoid', 'xmin', 'xmax')"
+               % etype.lower())
+        columns = self.session.system_sql(sql).fetchall()
+        if self.verbose:
+            print "Push data in cw table"
+        sql = "INSERT INTO cw_%s (" % etype.lower()
+        for col in columns:
+            col = col[0]
+            if col != 'cw_%s' % object_attr.lower():
+                sql +='%s, ' % col
+        sql += 'cw_%s) ' % object_attr.lower()
+        sql += 'SELECT '
+        for col in columns:
+            col = col[0]
+            if col != 'cw_%s' % object_attr.lower():
+                sql += 'tmp_entities.%s, ' % col
+        sql += 'tmp.object FROM tmp_entities LEFT OUTER JOIN tmp ON(tmp_entities.cw_eid = tmp.eid)'
+        print sql
+        self.session.system_sql(sql)
+        # Create constraints on entities eid
+        if self.verbose:
+            print "Create constraints on entities eid", etype
+        sql = "ALTER TABLE cw_%s ADD PRIMARY KEY (cw_eid)" % etype.lower()
+        self.session.system_sql(sql)
+        # Create other constraints on entities attr
+        if self.verbose:
+            print "Create other constraints on entities attr", etype
+        self.create_constraints(etype, object_attr, obj_unicity, obj_index)
+        self.drop_tmp_table()
+        sql = 'DROP TABLE tmp_entities'
+        self.session.system_sql(sql)
+
+
+    ############################################################################
+    ### TOOLS FOR LINKS AND RELATIONS GENERATION ###############################
+    ############################################################################
+    def generate_links(self, filename, voc_rtypes,
+                       subject_etype, object_etype,
+                       subject_attr, object_attr):
+        """
+        High level function for generating a bunch of links from the temporary table.
+        Different types of links can be provided through the voc_rtypes dictionnary
+        """
+        # Create and file temporary table
+        line_regexp = re.compile(self.DBPEDIA_URI_REGEXP)
+        filename_processed = self.format_file(filename, line_regexp, voc_rtypes=voc_rtypes, delimiter='\t')
+        self.load_file(filename_processed, create_eid=False, delimiter='\t')
+        # Remove duplicated entries
+        self.remove_duplicates()
+        # Create uri->eid relations
+        self.complete_relations_to_eid(subject_etype, object_etype, subject_attr, object_attr)
+        # Push links in cw table
+        self.push_links(voc_rtypes, 'tmp_relations', 'eid_from', 'eid_to', 'relation')
+        # Drop table
+        self.drop_tmp_relations_table()
+
+
+
+
+############################################################################
+### TOOLS FOR FULLTEXT INDEXATION ##########################################
+############################################################################
+def fulltext_indexation(session, etype, step=500000):
+    """
+    Function for a fulltext indexation.
+    """
+    source = session.repo.system_source
+    schema = session.repo.vreg.schema
+    count = int(session.execute('Any COUNT(X) WHERE X is %s' % etype)[0][0])
+    print 'Fulltext indexation for %s entities, step %s' % (count, step)
+    still_fti = list(schema[etype].indexable_attributes())
+    for offset in range(0, count, step):
+        print offset
+        rset = session.execute('Any X LIMIT %s OFFSET %s WHERE X is %s' % (step, offset, etype))
+        for entity in rset.entities():
+            source.fti_unindex_entities(session, [entity])
+            for container in entity.cw_adapt_to('IFTIndexable').fti_containers():
+                if still_fti or container is not entity:
+                    source.fti_unindex_entities(session, [container])
+                    source.fti_index_entities(session, [container])
+        session.commit(reset_pool=False)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uiprops.py	Tue Aug 30 12:29:28 2011 +0200
@@ -0,0 +1,24 @@
+# -*- shell-script -*-
+###############################################################################
+#
+# put here information about external resources used by your components,
+# or to overides existing external resources configuration
+#
+###############################################################################
+
+
+# CSS stylesheets to include in HTML headers
+STYLESHEETS = [data('cubes.cubipedia.css')]
+
+WIKIPEDIA = data('wikipedia.png')
+LINK = data('crystal_clear_link.png')
+REDIRECTION = data('crystal_clear_redirection.png')
+DISAMBIGUATE = data('crystal_clear_disambiguate.png')
+PND = data('crystal_clear_pnd.png')
+LOCATION = data('crystal_clear_location.png')
+HOMEPAGE = data('crystal_clear_homepage.png')
+GEOCOORD = data('crystal_clear_geocoord.png')
+CATEGORY = data('crystal_clear_category.png')
+BROADER = data('crystal_clear_broader.png')
+NARROWER = data('crystal_clear_narrower.png')
+RELATED = data('crystal_clear_related.png')
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/views/__init__.py	Tue Aug 30 12:29:28 2011 +0200
@@ -0,0 +1,3 @@
+"""
+Module for cubipedia views
+"""
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/views/ner.py	Tue Aug 30 12:29:28 2011 +0200
@@ -0,0 +1,30 @@
+# -*- coding: utf-8 -*-
+"""
+Named entities recognition for cubipedia
+"""
+from cubicweb.web import action, Redirect
+from cubicweb.web.views import forms
+from cubicweb.web import formwidgets as fwdgs, formfields
+from cubicweb.web.views.basecontrollers import Controller
+
+
+################################################################################
+### FORM, ACTION AND CONTROLLER ################################################
+################################################################################
+class SearchLabelForm(forms.FieldsForm):
+    __regid__ = 'search-label'
+    text = formfields.StringField(label='text', required=True,
+                                  widget=fwdgs.TextInput)
+    form_buttons = [fwdgs.SubmitButton()]
+
+    @property
+    def action(self):
+        return self._cw.build_url(u'search-label', text=self.text)
+
+class SearchLabelController(Controller):
+    __regid__ = 'search-label'
+
+    def publish(self, rset=None):
+        rset = self._cw.execute('Any X WHERE X label "%(text)s"' % {'text': self._cw.form['text']})
+        if len(rset):
+            raise Redirect(rset.get_entity(0,0).absolute_url())
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/views/primary.py	Tue Aug 30 12:29:28 2011 +0200
@@ -0,0 +1,200 @@
+"""databnf specific primary views"""
+import numpy as np
+
+from logilab.mtconverter import xml_escape
+
+from cubicweb.selectors import is_instance
+from cubicweb.utils import UStringIO
+from cubicweb.view import EntityView, Component
+from cubicweb.web import uicfg
+from cubicweb.view import View
+from cubicweb.web.views import primary as cw_primary
+from cubicweb.web.views import baseviews
+
+
+#################################################################################
+### CUBIPEDIA ENTITIES ABSTRACT VIEW ############################################
+#################################################################################
+class DbpediaAbstractPrimaryView(cw_primary.PrimaryView):
+    """
+    Abstarct primary view for different cubipedia entities
+    """
+    __abstract__ = True
+    __select__ = cw_primary.PrimaryView.__select__
+
+    def render_header(self, entity):
+        # Title and dbpedia link
+        self.w(u'<h1>%s</h1>' % entity.dc_title())
+        self.w(u'<a href="%s">(%s)</a>' % (entity.uri, self._cw._('See on dbpedia.org')))
+
+    def render_informations(self, entity):
+        # Should be defined in concrete subclasses
+        return None
+
+    def render_relations(self, entity):
+        # Should be defined in concrete subclasses
+        return None
+
+    def render_entity(self, entity):
+        ### header
+        self.render_header(entity)
+        ### INFORMATION
+        self.w(u'<div id="pageInformation">')
+        # Render informations
+        self.render_informations(entity)
+        # Render relations
+        self.render_relations(entity)
+        self.w(u'</div>')
+
+    def _icon_href(self, label, target_label, target_url, icon):
+        self.w(u'<span ><img src="%(icon)s" />%(text)s '
+               '<a href ="%(url)s">%(target)s</a></span>'
+               % {'icon': xml_escape(icon), 'text': label, 'url': target_url,'target': target_label})
+
+    def _icon_multiple_href(self, label, targets, icon,):
+        self.w(u'<span ><img src="%(icon)s" />%(text)s<ul>'
+               % {'icon': xml_escape(icon), 'text': label})
+        for target in targets:
+            self.w(u'<li><a href ="%(url)s">%(target)s</a></li>'
+                   %{'url': target.absolute_url(),'target': xml_escape(target.dc_title())})
+        self.w(u'</ul></span>')
+
+
+#################################################################################
+### CUBIPEDIA PAGE PRIMARY VIEW #################################################
+#################################################################################
+class DbpediaPagePrimaryView(DbpediaAbstractPrimaryView):
+    __select__ = DbpediaAbstractPrimaryView.__select__ & is_instance('DbpediaPage')
+
+    def render_header(self, entity):
+        self.w(u'<h1 class="page">%s</h1>' % entity.dc_title())
+        if entity.has_type:
+            self.w(u'<div class="has-type"><ul>')
+            for dbtype in entity.has_type:
+                types = []
+                self.w(u'<li><a href="%s">%s</a></li>' %
+                       (dbtype.absolute_url(), xml_escape(dbtype.label)))
+            self.w(u'</ul></div>')
+        else:
+            self.w(u'<div class="has-no-type"></div>')
+
+    def render_informations(self, entity):
+        self.w(u'<p>')
+        # Image
+        image = entity.depiction or entity.thumbnail
+        if image:
+            image = xml_escape(image)
+            self.w(u'<a href="%s"><img class="depiction" href="%s" src="%s" height="160px"/></a>'
+                   % (image, image, image))
+        # Abstract
+        abstract = entity.abstract
+        if abstract:
+            title, abstract = abstract[0], abstract[1:]
+            self.w(u'<div class="abstract"><a class="title">%s</a>%s</div>' % (title, abstract))
+        self.w(u'</p>')
+        # Wikipage
+        wikipage = entity.wikipage
+        if wikipage:
+            self._icon_href(self._cw._('See on wikipedia'), xml_escape(wikipage),
+                            wikipage, self._cw.uiprops['WIKIPEDIA'])
+        # Pnd
+        pnd = entity.pnd
+        if pnd:
+            self._icon_href(self._cw._('(Name Authority File'), xml_escape(pnd),
+                            pnd, self._cw.uiprops['PND'])
+        # Location
+        location = entity.located_in
+        if location:
+            self._icon_href(self._cw._('Located in'), xml_escape(location[0].dc_title()),
+                            location[0].absolute_url(), self._cw.uiprops['LOCATION'])
+        # Geo coordinates
+        latitude = entity.latitude
+        longitude = entity.longitude
+        if latitude or longitude:
+            self.w(u'<span ><img src="%(icon)s" />%(text)s<ul><li>%(textlat)s %(lat)s</li>'
+                   '<li>%(textlon)s %(lon)s</li></ul></span>'
+                   % {'icon': xml_escape(self._cw.uiprops['GEOCOORD']),
+                      'text': self._cw._('Geographics Coordinate'),
+                      'textlat': self._cw._('Latitude'), 'lat': xml_escape(latitude or "-"),
+                      'textlon': self._cw._('Longitude'), 'lon': xml_escape(longitude or "-")})
+        #Homepage
+        homepage = entity.homepage
+        if homepage:
+            self._icon_href(self._cw._('See homepage'), xml_escape(homepage),
+                            homepage, self._cw.uiprops['HOMEPAGE'])
+
+
+    def render_relations(self, entity):
+        ### REDIRECTION ONLY
+        redirection = entity.redirects_to
+        if redirection:
+            self._icon_href(self._cw._('Redirects to'), xml_escape(redirection[0].dc_title()),
+                            redirection[0].absolute_url(), self._cw.uiprops['REDIRECTION'])
+        ### WHOLE LINKS
+        if entity.has_subject:
+            self._icon_multiple_href(self._cw._('Categorized in'), entity.has_subject,
+                                     self._cw.uiprops['CATEGORY'])
+        if entity.reverse_redirects_to:
+            self._icon_multiple_href(self._cw._('Redirections from'), entity.reverse_redirects_to,
+                                     self._cw.uiprops['REDIRECTION'])
+        if entity.disambiguates:
+            self._icon_multiple_href(self._cw._('Disambiguates'), entity.disambiguates,
+                                     self._cw.uiprops['DISAMBIGUATE'])
+        if entity.links_to:
+            self._icon_multiple_href(self._cw._('Related pages'), entity.links_to,
+                                     self._cw.uiprops['LINK'])
+
+
+#################################################################################
+### CUBIPEDIA CATEGORY PRIMARY VIEW #############################################
+#################################################################################
+class DbpediaCategoryPrimaryView(DbpediaAbstractPrimaryView):
+    __select__ = DbpediaAbstractPrimaryView.__select__ & is_instance('DbpediaCategory')
+
+    def render_header(self, entity):
+        self.w(u'<h1 class="page">%s</h1>' % entity.dc_title())
+
+    def render_relations(self, entity):
+        # Related
+        if entity.is_related:
+            self._icon_multiple_href(self._cw._('Related categories'), entity.is_related,
+                                     self._cw.uiprops['REDIRECTION'])
+        # Broader
+        if entity.has_broader:
+            self._icon_multiple_href(self._cw._('Broader categories'), entity.has_broader,
+                                     self._cw.uiprops['BROADER'])
+        # Narrower
+        if entity.reverse_has_broader:
+            self._icon_multiple_href(self._cw._('Narrower categories'), entity.reverse_has_broader,
+                                     self._cw.uiprops['NARROWER'])
+        # Related pagesct
+        if entity.reverse_has_subject:
+            self._icon_multiple_href(self._cw._('Categorized (limited to 20)'), entity.reverse_has_subject[:20],
+                                     self._cw.uiprops['CATEGORY'])
+
+
+#################################################################################
+### CUBIPEDIA CLASS PRIMARY VIEW ################################################
+#################################################################################
+class DbpediaClassPrimaryView(DbpediaAbstractPrimaryView):
+    __select__ = DbpediaAbstractPrimaryView.__select__ & is_instance('DbpediaType')
+
+    def render_relations(self, entity):
+        return None
+
+    def render_header(self, entity):
+        self.w(u'<h1 class="page">%s</h1>' % entity.dc_title())
+        self.w(u'<div class="has-type"><ul>')
+        types = []
+        parent = entity
+        while parent.subkeyword_of:
+            types.append(parent.subkeyword_of[0])
+            parent = parent.subkeyword_of[0]
+        for dbtype in reversed(types):
+            self.w(u'<li><a href="%s">%s</a></li>' %
+                   (dbtype.absolute_url(), xml_escape(dbtype.label)))
+        self.w(u'</ul></div>')
+
+    def render_relations(self, entity):
+        # Subkeywords
+        pass
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/views/templates.py	Tue Aug 30 12:29:28 2011 +0200
@@ -0,0 +1,88 @@
+"""
+Defining the main template
+"""
+import numpy as np
+import numpy.random as nr
+
+from logilab.mtconverter import xml_escape
+
+from cubicweb.utils import UStringIO
+from cubicweb.selectors import yes
+from cubicweb.web import component
+from cubicweb.web import controller
+from cubicweb.web.views import basetemplates
+from cubicweb.web.views import startup
+
+
+#################################################################################
+### STARTUP #####################################################################
+#################################################################################
+class CubipediaIndexView(startup.IndexView):
+    __select__ = startup.IndexView.__select__ & yes()
+
+    def call(self, **kwargs):
+        w = self.w
+        w(u'<div id="frontheader">')
+        w(u'<h1 class = "largeheadline"><a href="/">Cubipedia</a></h1>')
+        w(u'</div>')
+        w(u'<div id="searchEntities">')
+        w(u'Exact search (quick)')
+        form = self._cw.vreg['forms'].select('search-label', self._cw)
+        form.render(w=self.w)
+        w(u'</div>')
+
+class CubipediaHTMLStartupPageHeader(basetemplates.HTMLPageHeader):
+    __select__ = startup.IndexView.__select__ & yes()
+
+    def main_header(self, view):
+        pass
+
+class CubipediaHTMLStartupPageFooter(basetemplates.HTMLPageFooter):
+    __select__ = startup.IndexView.__select__ & yes()
+
+    def footer_content(self):
+        pass
+
+
+#################################################################################
+### TEMPLATES ###################################################################
+#################################################################################
+class CubipediaMainTemplate(basetemplates.TheMainTemplate):
+    """
+    Redefine Cubicweb main template
+    """
+    def template_body_header(self, view):
+        w = self.w
+        w(u'<body>\n')
+        self.wview('header', rset=self.cw_rset, view=view)
+        w(u'<div id="page"><table width="100%" border="0" id="mainLayout"><tr>\n')
+        w(u'<td id="contentColumn">\n')
+        self.content_header(view)
+
+class CubipediaHTMLPageHeader(basetemplates.HTMLPageHeader):
+    """
+    Redefine Cubicweb HTML page header
+    """
+    def main_header(self, view):
+        w = self.w
+        w(u'<div id="header">')
+        w(u'<h1 class = "largeheadline"><a href="/">Cubipedia</a></h1>')
+        w(u'</div>')
+
+class CubipediaHTMLPageFooter(basetemplates.HTMLPageFooter):
+    """
+    Redefine Cubicweb HTML page header
+    """
+    def footer_content(self):
+        pass
+
+
+
+
+def registration_callback(vreg):
+    vreg.register_and_replace(CubipediaHTMLPageHeader, basetemplates.HTMLPageHeader)
+    vreg.register_and_replace(CubipediaHTMLPageFooter, basetemplates.HTMLPageFooter)
+    vreg.register_and_replace(CubipediaMainTemplate, basetemplates.TheMainTemplate)
+    vreg.register(CubipediaIndexView)
+    vreg.register(CubipediaHTMLStartupPageHeader)
+    vreg.register(CubipediaHTMLStartupPageFooter)