view MPIWGThesaurus.py @ 49:0610142a2550

closed: small bug in export (https://otrs.mpiwg-berlin.mpg.de/otrs/index.pl?Action=AgentTicketZoom;TicketID=38)
author dwinter
date Thu, 05 Dec 2013 13:21:00 +0100
parents cb20308fe412
children 8bfd713e5d99
line wrap: on
line source

#Klasse zum Taggen und Anzeigen der Tags von Projekte bzw. allgemein Webseiten des Institutes
#Tags werden in der Instanz abgespeichert
#Personenname kommen aus dem Virtuoso-Triplestore , lokal erzeugte zusaetliche Name werden dort abgespeichert
#Fuer die Suche ueber die Personenname wird das MetaDataManagerRestlet benoetigt.
#TODO: Zur Zeit werden die entsprechenden Server URLs hier in der Klasse definiert.

# TODO: generell verwaltung der tags im triple store und nicht in zope.
# TODO: mache server und namespaces konfigurierbar im project


from OFS.Folder import Folder
from Globals import package_home
from Products.PageTemplates.PageTemplateFile import PageTemplateFile
from BTrees.OOBTree import OOBTree
from BTrees.OOBTree import OOSet
from AccessControl import ClassSecurityInfo
from Products.ZDBInterface.ZDBInterfaceFolder import ZDBInterfaceFolder

#import os
import re
import os.path
import logging
import time
import email.Utils
from types import ListType
import transaction
import random
import urllib2
import urllib
import json
import md5

from SrvTxtUtils import utf8ify

class projectHolder:
            projectHolder=""
            projectName=""
            projectID=""
            persons=""
            tags={}
            
            def __init__(self,ID):
                self.projectID=ID
                self.tags={}
                
#Entry beschreibt jeweils einen Tag mit dem Namen "title", entries enthaelt eine Liste von Subtags (der Klasse Entry), die diesem Tag untergeordnet sind.
class Entry:
    """publicClass"""
    
    #===========================================================================
    # __init__
    #===========================================================================
    def __init__(self,title,entries=[]):
        self.title=title
        self.entries=entries
        
    def getTitle(self):
        """getTitle"""
        return self.title
    
#Beschriebt einen von einem Benutzer vorgeschlagenen Tag      
class SuggestedTag:
    """publicClass"""
    type=""
    userName=""
    def __init__(self,name,comment,type,userName):
        self.name=name
        self.comment=comment
        self.type=type
        self.userName=userName
        

class MPIWGThesaurus(ZDBInterfaceFolder, Folder):
    """MPIWGThesaurus main folder"""
    security=ClassSecurityInfo()

    meta_type="MPIWGThesaurus"
   
    TMP_PERSON_NS="http://ontologies.mpiwg-berlin.mpg.de/tempObjects/person/"
    ONTOLOGY_NS="http://ontologies.mpiwg-berlin.mpg.de/authorities/namedIdentities/"
    #personproviderURL="http://127.0.0.1:8280/MetaDataManagerRestlet/person/"
    personproviderURL="http://virtuoso.mpiwg-berlin.mpg.de:8080/MetaDataManagerRestlet/person/"
    #PERSONS_LOOKUP_URL="http://127.0.0.1:8280/MetaDataManagerRestlet/search/persons"
    PERSONS_LOOKUP_URL="http://virtuoso.mpiwg-berlin.mpg.de:8080/MetaDataManagerRestlet/persons"
    EDIT_URL="http://virtuoso.mpiwg-berlin.mpg.de:8080/MetaDataManagerRestlet/edit?id="
    #PERSONS_LOOKUP_URL="http://virtuoso.mpiwg-berlin.mpg.de:8080/MetaDataManagerRestlet/person/"
    
    additionalNamesGraphURL="file://newpersonsFromProjects"
    
    #virtuosoServer="http://ontologies.mpiwg-berlin.mpg.de"
    virtuosoServer="http://virtuoso.mpiwg-berlin.mpg.de:8890"
    virtuosoDAV="/DAV/home/websiteuser/"
    virtuosoDAVUser="websiteuser"
    virtuosoDAVPW="w3s45us3"
    virtuosoGraph="file://newpersonsFromProjects"
    
    logpathDefault="/var/tmp/tagchanges.log"
    
    #BTrees fuer die Tags
    
    #projectPersons= OOBTree() #project --> personen IDs
    #projectObjects= OOBTree() #project --> objects
    #projectHistoricalPlaces= OOBTree()
    projectSuggestedTags= OOBTree()
    #persons2Projects= OOBTree() #personenID --> projects
    #objects2Projects=OOBTree() #objects --> projects
    #historicalPlaces2Projects=OOBTree()
    suggestedTags2Projects=OOBTree()
    ##personIDtoNames=OOBTree() # weist den personenIDs Klartextnamen aus dem Triplestore zu
    ##personsIDForSort=[] # liste personenID sortiert nach dem tupel (nachname,vorname)
    ##personsIDForSortFull=[] # liste (personenID,(nachname,vorname)) nicht sortiert!
   
    suggestedPersons= OOBTree(); #TODO: das sollte die ueberfluessig werde und nur im triple store stehen.
    
    tagList=[]
    
    #default liste fuer tags, wird ueber das Managementinterface ueberschrieben
    approachesTxt="""A
    ---
    ent1
    ---
    B
    ---
    enta
    entb
    entc
    """
    
    disciplines=[]
    disciplinesTxt="""A
   B
   C
    """
    
    periods=[]
    periodsTxt="""PA
   PB
   PC
    """
    
    spaces=[]
    spacesTxt="""SPA
    ---
    sPent1
    ---
    SPB
    ---
    SPenta
    SPentb
    SPentc
    """
    technologies=[]
    technologiesTxt="""TPA
    ---
    TPent1
    ---
    TPB
    ---
    TPenta
    TPentb
    TPentc
    """
    
    knowledgeTransfers=[]
    knowledgeTransfersTxt="""KTPA
    ---
    TPent1
    ---
    TPB
    ---
    TPenta
    TPentb
    TPentc
    """
    
    
    
    
    
    
    manage_options = ZDBInterfaceFolder.manage_options+(
        {'label':'Thesaurus entries','action':'changeMPIWGThesaurusForm'},
        {'label':'Manage Thesaurus','action':'manageMPIWGThesaurus'},
        {'label':'Thesaurus Log','action':'manageMPIWGThesaurusLogs'},
        #{'label':'Change Publications Special','action':'changePublications_specialForm'},
        )
    
    def __init__(self,id):
        """init"""
        self.id=id
       
        
    def index_html(self):
        """index file"""
              
        pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','index.html')).__of__(self)
        return pt()
    
    security.declareProtected('View management screens','changeMPIWGThesaurusForm')
    def changeMPIWGThesaurusForm(self):
        """form for changing the project"""
        pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','changeMPIWGThesaurusForm.zpt')).__of__(self)
        return pt()
    
    security.declareProtected('View management screens','manageMPIWGThesaurus')
    def manageMPIWGThesaurus(self):
        """form for changing the project"""
        pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','manageMPIWGThesaurus.zpt')).__of__(self)
        return pt()
    
    security.declareProtected('View management screens','manageMPIWGThesaurusLogs')
    def manageMPIWGThesaurusLogs(self):
        """form for changing the project"""
        pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','manageMPIWGThesaurusLog.zpt')).__of__(self)
        return pt()
    
    def changeMPIWGThesaurusLog(self,logpath,RESPONSE=None):
        """change log file path"""
        self.logpath=logpath
        
        if RESPONSE is not None:
            redirect(RESPONSE,'manage_main')
     
     
    security.declareProtected('View management screens','changeMPIWGThesaurus')
    def changeMPIWGThesaurus(self,approachesTxt,disciplinesTxt,periodsTxt,spacesTxt,technologiesTxt,knowledgeTransfersTxt,RESPONSE=None):
        """change it"""
        self.approachesTxt=approachesTxt
        self.disciplinesTxt=disciplinesTxt
        self.periodsTxt=periodsTxt
        self.spacesTxt=spacesTxt
        self.technologiesTxt=technologiesTxt
        self.knowledgeTransfersTxt=knowledgeTransfersTxt
    
        if RESPONSE is not None:
            redirect(RESPONSE,'manage_main')
    
    
#    def getAllProjectsAndTagsAsCSV(self,archived=1):
#        """alle projekte auch die nicht getaggten"""
#        retList=[]
#        for project in self.getProjectFields('WEB_title_or_short'):
#            proj = project[0]
#            p_name = project[1]
#            retProj=[]
#            if (not proj.isArchivedProject() and archived==1) or (proj.isArchivedProject() and archived==2):
#                retProj.append(self.utf8ify(p_name))  
#                retProj.append(self.utf8ify(proj.getContent('xdata_01')))   
#                retProj.append("|".join([person[1] for person in self.thesaurus.getPersonsFromProject(proj.getId())]))
#                retProj.append("|".join([person[1] for person in self.thesaurus.getHistoricalPlacesFromProject(proj.getId())]))
#                retProj.append("|".join([person[1] for person in self.thesaurus.getObjectsFromProject(proj.getId())]))
#                retProj.append("|".join(self.thesaurus.getTags(proj.getId())))
#                retList.append("\t".join(retProj))
#
#        return "\n".join(retList);
#    
    def getProjectsAndTags(self):
        """projekte und tags"""
       
        
        projectTags={}
        for tag in self.tags.keys():
            logging.debug("getProjectsAndTags:"+tag)
               # <div class="level1_projects" tal:repeat="proj
               #              python:here.getProjectsWithTag('approaches',here.getTitle(level1))"><a tal:attributes="href
               #                                                         python:proj[0]"><span  tal:content="python:proj[1]">my proj</span><tal:x define="person python:proj[2]"><span
               #                                                                                                          class="person_projects" tal:content="person"/></tal:x></a></div>
               #</div>
            
            for subTag in self.tags.get(tag):
                projs = self.getProjectsWithTag(tag,subTag)
                if not isinstance(projs, ListType):
                    projs=[projs]
                
                for proj in projs:
                    if proj is None:
                        continue
                    projectID=proj[0]
                    logging.debug("PTS"+repr(projectTags))
                    project=projectTags.get(projectID,projectHolder(projectID))
                    project.projectName=proj[1]
                    project.persons=proj[2]
                    logging.debug(project)
                    logging.debug(tag)
                    logging.debug("PROTS"+repr(project.tags))
                    tagsOfType=project.tags.get(tag,OOSet())
                    logging.debug(tagsOfType)
                    tagsOfType.add(subTag.decode('utf-8'))
                                  
                    logging.debug("Adding %s to %s"%(subTag,projectID))
                    project.tags[tag]=tagsOfType
                    
                    projectTags[projectID]=project
                    logging.debug("Saved %s to %s"%(repr(list(tagsOfType)),projectID))
        logging.debug(projectTags)
        
        
        
        return projectTags
    
    def getProjectsAndTagsAsCSV(self):
        """get the projects as tab"""
        ret=""
        
        #genereate headers
        headers=['date','projectPath','projectName','researchers resp']
        headers.extend(list(self.tags.keys()))
        ret+="\t".join(headers)+"\n"
        
        projectTags = self.getProjectsAndTags()
        for projectID in projectTags.keys():
            retarray=[]
            splitted = projectID.split("/") # hiern nur die eingetliche ID ohne den Pfad
            if len(splitted)>0:
                projectIDShort=splitted[-1]
                retarray.append(self.lastChangeInThesaurus.get(projectIDShort,''))
            else:
                retarray.append('')
            retarray.append(projectID)
            project = projectTags.get(projectID)
            retarray.append(project.projectName)
            retarray.append(project.persons)
            
            for tagType in self.tags.keys():
                tags = project.tags.get(tagType,[''])
                retarray.append(";".join(tags))
            
            ret+="\t".join(retarray)+"\n"
                
        return ret
    
    def getTags(self,projectID,projectTags,RESPONSE=None):
        """get all selected tagList"""
        
        #projectTags = self.getProjectsAndTags()
        #logging.debug(projectTags)
        
        project = projectTags.get(projectID)
        if project is None:
            project = projectTags.get("/en/research/projects/"+projectID) #TODO fix this projectTag list from getProjectsAndTags()contains  fullpath
        if project is None:
            return []    
        retarray=[]    
        for tagType in self.tags.keys():
                tags = project.tags.get(tagType,[''])
                retarray.append(utf8ify(";".join(tags)))
            
            
        return retarray 
    def getAllProjectsAndTagsAsCSV(self,active=0,archived=0,RESPONSE=None):
        """alle projekte auch die nicht getaggten"""
        retList=[]
        headers=['projectId','sortingNumber','projectName','scholars','startedAt','completedAt','lastChangeThesaurusAt','lastChangeProjectAt','projectCreatedAt','active','persons','objects']
        headers.extend(list(self.tags.keys()))
        retList.append("\t".join(headers))
        
        projectTags = self.getProjectsAndTags()
        projects = self.getMPIWGRoot().getProjectFolder().getProjectsAsList(active=active,archived=archived)
        for proj in projects:
            p_name = proj.getLabel()
            retProj=[]
            #if (not proj.isArchivedProject() and archived==1) or (proj.isArchivedProject() and archived==2):
            retProj.append(utf8ify(proj.getId()))
            retProj.append(utf8ify(proj.getContent('xdata_05')))
            retProj.append(utf8ify(p_name))  
            retProj.append(utf8ify(proj.getContent('xdata_01')))
            retProj.append(utf8ify(proj.getStartedAt()))
            retProj.append(utf8ify(proj.getCompletedAt()))
            changeDate=self.lastChangeInThesaurus.get(proj.getId(),'') 
            n = re.sub("[:\- ]","",str(changeDate))
            retProj.append(n)
            retProj.append(utf8ify(getattr(proj,'creationTime','20050101000000')))  
            retProj.append("")#TODO: project created at
            retProj.append(str(proj.isActiveProject()))
            #retProj.append(";".join([person[1] for person in self.getPersonsFromProject(proj.getId())]))
            #retProj.append(";".join([person[1] for person in self.thesaurus.getHistoricalPlacesFromProject(proj.getId())]))
            #retProj.append(";".join([person[1] for person in self.getObjectsFromProject(proj.getId())]))
            retProj+=self.getTags(proj.getId(),projectTags)
            retList.append("\t".join(retProj))
        
        if RESPONSE:            
            RESPONSE.setHeader('Content-Disposition','attachment; filename="ProjectsAndTags.tab"')
            RESPONSE.setHeader('Content-Type', "application/octet-stream")
      
        return "\n".join(retList);
    

    def getLogpath(self):
        return getattr(self,"logpath",self.logpathDefault) 
    
    def getLogfile(self,projectID="",date=""):
        
        # logfile format : YYYY-MM-TT HH:mm:ss\tUSER\ttype\tprojectid\CHANGED_TAG_or_OBJECT_or_PERSON 
        if not os.path.exists(self.getLogpath()):
            return ""
        
        fh = open(self.getLogpath(),"r")
        lines=fh.readlines()
    
        if (projectID!=""):
            ret=[]
            for line in lines:
                splitted=line.split("\t")
                if splitted[3]==projectID:
                    ret.append(line)
        
            lines=ret[0:]
            
        if (date!=""):
            ret=[]
            for line in lines:
                splitted=line.split("\t")
                if splitted[0]>=date:
                    ret.append(line)
        
            
            lines=ret[0:]
        
        txt= "".join(lines)
        fh.close()
            
       
            
            
        return txt
    
    #In der Anzeige soll der Name der zitierten Personen in Klartext angezeigt werden, ausserdem die Varianten, wie sie tatsaechlich
    #in den Projekten benutzt werden
    
# 
#     def addPersonAndFirstNameFromTripleStore(self, personID):
#         mainName, sortName = self.getMainNameFromTripleStore(personID) # hole die hauptbezeichnung aus dem triplestore
#         personNames = []
#         logging.debug("get person:"+ personID)
#         logging.debug("names:"+repr(mainName)+":"+ repr(sortName))
#         
#         projects=self.persons2Projects.get(personID)
#         logging.debug(repr(projects))
#         if projects is None:
#             projects=[]
#             
#         for project in projects: #hole die personen aus dem projekte
#             logging.debug("Found:project:" + project)
#             namesInProject = self.projectPersons.get(project)
#             for nameInProjectTuple in namesInProject:
#                 logging.debug(repr(nameInProjectTuple))
#                 nameInProject = nameInProjectTuple[1]
#                 logging.debug(nameInProjectTuple[0] + "??" + personID)
#                 if nameInProjectTuple[0] == personID:
#                     logging.debug("changing")
#                     if mainName == "": # es gibt keinen Eintrag im Triplestore fuer name (sollte eigentlich nicht sein, ist dann ein Fehler dort)
#                         mainName = nameInProject #nimm dann aber den ersten aus den projekten
#                     if nameInProject != mainName:
#                         personNames.append(nameInProject)
#         
#         logging.debug(str(mainName) + "- foundalso :" + ",".join(personNames))
#         self.personIDtoNames.update({personID:(mainName, personNames)})
#         self.personsIDForSortFull.append((personID, sortName))
#         
#    
#    
#     def generateSortingOrderForPersonIDs(self):
#         def sort(x,y):
#             logging.debug("sort:")
#             logging.debug((x[1][0],y[1][0]))
#             return cmp(x[1][0],y[1][0])
#             
#         self.personsIDForSortFull.sort(cmp=sort)
#            
#         self.personsIDForSort=[x[0] for x in self.personsIDForSortFull]
#                                       
#         self.personIDtoNames=self.personIDtoNames # make clear that it has changed #TODO: change this to variablen with names _p
#     
#     security.declareProtected('View management screens','collectPersonNamesToIds')
#     def collectPersonNamesToIds(self):
#         """Ordne Namen aus dem Triplestore bzw. die vergebenenden Label den Personen-Ids zu."""
#         #sollte z.B. gemacht werden, wenn im Triplestore editiert wurde.
#         self.personIDtoNames=OOBTree() # loesche alle 
#         self.personsIDForSort=[]
#         self.personsIDForSortFull=[]
#         for personID in self.persons2Projects:
#             self.addPersonAndFirstNameFromTripleStore(personID)
#             
#           
#             
#                                     
#         #sortiere personIDs nach erstmal nach Nachnamene TODO: sortiere nach name,vorname
#         
#         self.generateSortingOrderForPersonIDs();
# #        def sort(x,y):
# #            logging.debug("sort:")
# #            logging.debug((x[1][0],y[1][0]))
# #            return cmp(x[1][0],y[1][0])
# #            
# #        self.personsIDForSortFull.sort(cmp=sort)
# #           
# #        self.personsIDForSort=[x[0] for x in self.personsIDForSortFull]
# #                                      
# #        self.personIDtoNames=self.personIDtoNames # make clear that it has changed #TODO: change this to variablen with names _p
# #    
#     #Hole die Namen, die einer personID zugeordnet sind.
# #     def getNamesFromID(self,personID):
# #         personID=personID.rstrip().lstrip() #make sure no spaces
# #         logging.debug("<"+personID+">")
# #         retStr=""
# #         
# #         retStr+=self.personIDtoNames.get(personID,[personID])[0] # hole die Hauptbezeichnung, falls keine angeben ist, wird die ID ausgegeben, das is jedoch ein Felher in den Daten!!
# #         #additionalNames = self.personIDtoNames.get(personID,['',[]])[1]
# #         #if len(additionalNames)>0:
# #         #    retStr+=" ("+",".join(additionalNames)+","+")"
# #         return retStr
# #     
# #         
#     #Hole die Hauptnamemsansetzung aus dem Triplestore ),falls vorhanden, wenn nicht ist der String leer.
#     #ausserdem einen Namen zum sortieren, =  Tupel(nachname, vorname)
    def getMainNameFromTripleStore(self,personID):
        
        
        cmdString ="""select * where { <%s> <http://xmlns.com/foaf/0.1/name> ?name}"""%personID
    
        names= self.callSparql(cmdString)
        
        cmdString ="""select * where { <%s> <http://xmlns.com/foaf/0.1/lastName> ?name}"""%personID
    
        lastName= self.callSparql(cmdString)
        
        cmdString ="""select * where { <%s> <http://xmlns.com/foaf/0.1/firstName> ?name}"""%personID
    
        firstName= self.callSparql(cmdString)
        
        return names,(lastName,firstName)
    
    
    def callSparqlAll(self,cmdString):
        """list of results"""
        auth_handler = urllib2.HTTPBasicAuthHandler()
        auth_handler.add_password(realm='sparql',
                          uri=self.virtuosoServer+"/sparql",
                          user=self.virtuosoDAVUser,
                          passwd=self.virtuosoDAVPW)
                          
        opener = urllib2.build_opener(auth_handler)
        opener.addheaders = [('Content-Type','application/sparql-query')]
        
        logging.debug(cmdString)
        try:
            logging.debug(self.virtuosoServer+"/sparql?" + urllib.urlencode({'query':cmdString,'default-graph-uri':self.virtuosoGraph,'named-graph-uri':'','format':'text/csv'}))
            #r= opener.open(self.virtuosoServer+"/sparql", urllib.urlencode({'query':cmdString,'default-graph-uri':self.virtuosoGraph,'named-graph-uri':'','format':'text/csv'}))
            r= opener.open(self.virtuosoServer+"/sparql", urllib.urlencode({'query':cmdString,'default-graph-uri':'','named-graph-uri':'','format':'text/csv'}))
            namesTxt=r.read()
        except urllib2.URLError, e:
            logging.error(e.code)
            logging.error(e.read())
            
            
            return
        logging.debug(namesTxt)
        names=namesTxt.split("\n")
        if len(names) < 2: #in der ersten Zeile stehen bei der Rueckgabe die Spaltennamen, <2 heiss also es gibt keinen Eintrag
            return []
        
        ret=[]
        for name in names[1:]:
            line=[]
            for entry in name.split("\",\""):

                line.append(entry.replace('"',''));
            ret.append(line);
        return ret;
         
    def callSparql(self,cmdString):

        auth_handler = urllib2.HTTPBasicAuthHandler()
        auth_handler.add_password(realm='sparql',
                          uri=self.virtuosoServer+"/sparql",
                          user=self.virtuosoDAVUser,
                          passwd=self.virtuosoDAVPW)
                          
        opener = urllib2.build_opener(auth_handler)
        opener.addheaders = [('Content-Type','application/sparql-query')]
        
        logging.debug(cmdString)
        try:
            logging.debug(self.virtuosoServer+"/sparql?" + urllib.urlencode({'query':cmdString,'default-graph-uri':self.virtuosoGraph,'named-graph-uri':'','format':'text/csv'}))
            #r= opener.open(self.virtuosoServer+"/sparql", urllib.urlencode({'query':cmdString,'default-graph-uri':self.virtuosoGraph,'named-graph-uri':'','format':'text/csv'}))
            r= opener.open(self.virtuosoServer+"/sparql", urllib.urlencode({'query':cmdString,'default-graph-uri':'','named-graph-uri':'','format':'text/csv'}))
            namesTxt=r.read()
        except urllib2.URLError, e:
            logging.error(e.code)
            logging.error(e.read())
            
            
            return
        logging.debug(namesTxt)
        names=namesTxt.split("\n")
        if len(names) < 2: #in der ersten Zeile stehen bei der Rueckgabe die Spaltennamen, <2 heiss also es gibt keinen Eintrag
            return
         
        return names[1].replace('"','') # wir nehmen nur den ersten treffer
         
            
    security.declareProtected('View management screens','changeTags')            
    def changeTags(self,projectID,approaches=[],disciplines=[],periods=[],spaces=[],technologies=[],transfers=[],RESPONSE=None):
        """Aendert die Tags im angegebenen Project"""
        self.changeTagFromList(projectID,"approaches", approaches)
        self.changeTagFromList(projectID,"disciplines", disciplines)
        self.changeTagFromList(projectID,"periods", periods)
        self.changeTagFromList(projectID,"spaces", spaces)
        self.changeTagFromList(projectID,"technologies", technologies)
        self.changeTagFromList(projectID,"transfers", transfers)
        
        self.projectObjects=self.projectObjects #necessesary to make the object persistent after the first call
        #self.projectHistoricalPlaces=self.projectHistoricalPlaces #necessesary to make the object persistent after the first call
        self.projectPersons=self.projectPersons #necessesary to make the object persistent after the first call
        self.projectSuggestedTags=self.projectSuggestedTags
        
        self.persons2Projects=self.persons2Projects
        self.objects2Projects=self.objects2Projects
        #self.historicalPlaces2Projects=self.historicalPlaces2Projects
        self.suggestedTags2Projects=self.suggestedTags2Projects;
        
        self.suggestedPersons=self.suggestedPersons;
        
    security.declareProtected('View management screens','deleteAllTags')                    
    def deleteAllTags(self):
        """deleteAllTags - TODO: take this out!!,"""
        
        return "DONE!"
    
    security.declareProtected('View management screens','deleteAllPersons')                    
    def deleteAllPersons(self):
        """deleteAllTags - TODO: take this out!!,"""
        self.projectPersons= OOBTree()
        self.persons2Projects= OOBTree()
        self.personIDtoNames=OOBTree()
        self.suggestedPersons= OOBTree(); #TODO: das sollte die ueberfluessig werde und nur im triple store stehen.
    
        
        return "DONE!"
    
  
    def changeTagFromList(self,projectID,tagType,tagList):
        
        
        #hole alle tags des projektID vom Typ tagaTyle
        if isinstance(tagList,str):
            tagList=[tagList]        
        
        tggsOfProject = self.getTagsFromDB(projectID,tagType)
        for tagOfProject in tggsOfProject:
            if tagOfProject in tagList:
                #schon getagged
                #nichts mehr zu tun spater
                tagList.remove(tagOfProject)
            else:
                #nicht mehr getaggt
                #delete Entry from database
                self.deleteTagInDB(projectID,tagType,tagOfProject)
                
        
        
        #in der taglList sind jetzt nur noch die Tags uebrig die hinzugegefuegt werden muessen
        for tag in tagList:
            self.addTagToDB(projectID,tagType=tagType,tag=tag)
        
        transaction.commit()
    
    
    def getTagsFromDB(self,projectID=None,tagType=None,startsWith=""):
        # hole alle tags vom typ tagType des projectes mit ID
        ql =[]
        
        if tagType is not None:
            qs="select tag_name from thesaurus_tags where tag_type = %s"
            ql.append(tagType)
        else:
            qs="select tag_name from thesaurus_tags"
             
        if projectID is not None:
            qs=qs + " and id in (select tag_id as id from thesaurus_projects_tags where project_id = %s)"
            ql.append(projectID)
        
        
        res =self.executeZSQL(qs,ql)
        
        
        if (startsWith is None) or (startsWith ==""):
            ret = [r.tag_name for r in res]
        else:
            ret=[]
            for r in res:
                if r.tag_name.lower().startswith(startsWith):
                    ret.append(r.tag_name)
        
        logging.debug(ret)
        return ret
    
    
    def deleteTagInDB(self,projectID,tagType,tag):
        # loesche den tag von typ tagType aus der dem Project
        
        # first get tag_id
        
        qs = "select id from thesaurus_tags where tag_type = %s and tag_name= %s"
        logging.debug("DELETE")
        ids = self.executeZSQL(qs,[tagType,tag])
        
        for idR in ids:
            qs = "delete from thesaurus_projects_tags where project_id=%s and tag_id=%s"
            self.executeZSQL(qs,[projectID,idR.id])
            
        logging.debug("DELETE-END")
        return
    
    def addTagToDB(self,projectID,tagType=None,tag=None,tag_ID=None):
        """fuege den tag vom typ tagType zum Project hinzu, wenn tag_ID wird zuerst genommen, die anderen Felder werden
        nur genommen falls tag_ID None ist.
        """

        # schaue on es den tag schon gibt, wenn nicht anlegen
        
        if tag_ID is None and tagType is None and tag is None:
            raise Exception("either tag_id or tag_type and tag shouldn't be None")
        
        
        if tag_ID is not None:
            qsSelect = "select id from thesaurus_tags where id = %s "
            ids = self.executeZSQL(qsSelect,tag_ID)
        else:
            if tagType is None or tag is None:
                raise Exception("tag_type and tag shouldn't be None")
        
            else:
                qsSelect = "select id from thesaurus_tags where tag_type = %s and tag_name= %s"
                ids = self.executeZSQL(qsSelect,[tagType,tag])
      
        
        logging.debug(ids)
        logging.debug(len(ids))
        
        
        
        
        if len(ids) == 0:
            if tag_ID is None:
                qs = "insert into thesaurus_tags (tag_type,tag_name) values (%s,%s)"
                self.executeZSQL(qs,[tagType,tag]) # anlegen
                transaction.commit()
                ids = self.executeZSQL(qsSelect,[tagType,tag]) #ids holen
                
            else:
                raise Exception("no tag with tag_id: %s"%tag_ID)
      
    
        for idResult in ids:

            #check if already in
            qsSelect = "select id from thesaurus_projects_tags where project_id = %s and tag_id= %s"
            
            tag_ids = self.executeZSQL(qsSelect,[projectID,idResult.id])
            
            if len (tag_ids) ==  0:
                        
                qs="insert into thesaurus_projects_tags (project_id,tag_id) values (%s,%s)"
            
                self.executeZSQL(qs,[projectID,idResult.id])
            
        
        
        return ids[0].id #sollte eigentlich auch nur genau einen geben.
        
        
  
    def getTitle(self,entry):
        return entry.title
    
    def thes_quote(self,txt):
        logging.debug("@*%s*@"%repr(txt))
        return md5.md5(utf8ify(txt.lower())).hexdigest()

    
    def formatTag(self,tag):
        splitted= tag.split("_")
        return splitted[-1]
    
    def getEntriesFormatted(self,entries,formatType):
        if not hasattr(self,'levelFormatted'):
            pt=PageTemplateFile('zpt/levelFormatted', globals()).__of__(self)
            return pt(level1_entries=entries,type=formatType)
        
        pt = getattr(self,'levelFormatted')
        return pt(level1_entries=entries,type=formatType)
    
        
        #return self.levelFormatted(level1_entries=entries,type=formatType)
        
    def getEntries(self,entry):
        #logging.debug("GETENTRY:"+repr(entry))
        return entry.entries
    
    #nimmt ein eine Text der Form 
    # TAG1
    # ---
    # SUBTAG1_1
    # SUBTAG1_2
    # ---
    # TAG2
    # ---
    # SUBTAG2_1
    # SUBTAG2_2
    #....
    # und erzeugt daraus eine entsprechende Liste von Entries
    def getEntriesFromTxt(self,txt):
       
        apps=[]
        lines=txt.split("\n");
        level=False
        for line in lines:
            line=line.rstrip().lstrip()
            if line=="":
                continue
            if line=="---":
                
                if level:
                    level=False
                else:
                    level=True
            else:
                if not level:
                    entry=Entry(line,[])
                    apps.append(entry)
                else:
                    entry.entries.append(Entry(line))
                
        return apps[0:]
    
    def getApproaches(self):
        
        self.tagList=self.getEntriesFromTxt(self.approachesTxt)    
        return self.tagList
    
  
    def getTagsAsHash(self,projectID,tagType=None):
        """get all  tags as hash or None if no tag exists"""
        retHash={}
        
        #falls nicht gesetzt
        if tagType is None:
            
            
            tagTypes = [tag.tag_type for tag in self.executeZSQL("select distinct tag_type from thesaurus_tags")]
            #tagTypes = tags.keys()
        else:
            tagTypes = [tagType]
        
        tagCnt=0
        for tagType in tagTypes:
            
            #retHash[tagType]=[]


            tags =self.getTagsFromDB(projectID, tagType)
            if len(tags) !=0:
                retHash[tagType] = [self.getLabel(tag,tagType) for tag in tags]
                tagCnt+=1
           
            
        if tagCnt==0:
            return None
        
        return retHash
    
    
    
    
    
    def getTagsJSON(self,projectID=None,tagType=None,startWith="",RESPONSE=None):
        """get all selected tags returs them as a list"""
 
        tags = self.getTagsFromDB(projectID, tagType,startWith)
        
        
        if RESPONSE:
            RESPONSE.setHeader('Content-Type', "application/json")
        
        ret = json.dumps(tags)
        
        
        logging.debug(ret)
        return ret
    
    
    
  
  
    def getDisciplines(self):
        
        self.disciplines=self.getEntriesFromTxt(self.disciplinesTxt)    
        return self.disciplines
    
    
    def getObjectsJSON(self,term="",RESPONSE=None):    
        """ get all stored objects as json list starting with term, 
        need this for autocompletion from JQUERY which ads ?term= to the URL"""
        term=term.lower();
        
        return self.getTagsJSON(tagType="object", startWith=term, RESPONSE=RESPONSE)
        
        
#         
#         logging.debug("Asking:"+term)
#         #objectList=["baus","berg","lurg"]
#         objects = self.objects2Projects;
# 
#         objectList= [x for x in objects.keys()]   
#        
#         logging.debug("Create:"+repr(objectList))    
#         retList=[]
#         for object in objectList:
#             if object.find(term)>-1:
#                 retList.append(""" "%s" """%object)
#         ret="["
#         ret+=",".join(retList)
#         ret+="]"
#         logging.debug("Objects:"+ret)
#         if RESPONSE:
#             RESPONSE.setHeader('Content-Type', "application/json")
#         return ret
#         
        
#     def getHistoricalPlacesJSON(self,term="",RESPONSE=None):
#         """ get all stored historicalPlaces as json list starting with term"""
#         term=term.lower();
#         logging.debug("Asking:"+term)
#         #historicalPlaceList=["baus","berg","lurg"]
#         historicalPlaces = self.historicalPlaces2Projects;
# 
#         historicalPlaceList= [x for x in historicalPlaces.keys()]   
#        
#         logging.debug("Create:"+repr(historicalPlaceList))    
#         retList=[]
#         for historicalPlace in historicalPlaceList:
#             if historicalPlace.find(term)>-1:
#                 retList.append(""" "%s" """%historicalPlace)
#         ret="["
#         ret+=",".join(retList)
#         ret+="]"
#         logging.debug("historicalPlaces:"+ret)
#         if RESPONSE:
#             RESPONSE.setHeader('Content-Type', "application/json")
#         return ret
        
        
    def getPeriods(self):
        
        self.periodes=self.getEntriesFromTxt(self.periodsTxt)    
        return self.periodes
    
    def getSpaces(self):
        
        self.spaces=self.getEntriesFromTxt(self.spacesTxt)    
        return self.spaces
    
    def getTechnologies(self):
        
        self.technologies=self.getEntriesFromTxt(self.technologiesTxt)    
        return self.technologies
    
    def getKnowledgeTransfers(self):
        
        self.knowledgeTransfers=self.getEntriesFromTxt(self.knowledgeTransfersTxt)    
        return self.knowledgeTransfers
    
    
#     def getObjectsFromProject(self,projectID):
#         return self.getFromProject(self.projectObjects,projectID);
#     
#    def getHistoricalPlacesFromProject(self,projectID):
#       return self.getFromProject(self.projectHistoricalPlaces,projectID);
    
    def getSuggestedTagsFromProject(self,projectID):
        return self.getFromProject(self.projectSuggestedTags,projectID);
 
    
#     def getPersonsFromProject(self,projectID):
#         #hole alle personenID die zu einem Projekt gehoeren.
#         #zurueckgegeben wird ein OOSet()
#         return self.getFromProject(self.projectPersons,projectID);
#     
    def getFromProject(self,objects,projectID): 
        #holt die zur projectID gehoerigen objekte aus dem objects-set. 
        #oder legt einen neuen leeren Satz zu dieser ProjektID an.
        #zuruecgegeben wird ein OOSet()
        if objects.has_key(projectID): #wenn zu der ProjektID schon etwas abgespeichter ist, gibt es zurueck
            logging.debug("key exists:"+projectID)
            entries=objects.get(projectID);
        else: # andernfalls lege einen neuen Satz an.
            entries=OOSet()
            objects.update({projectID:entries})
            logging.debug("key does not exists:"+projectID)
             
         
        return entries
     
#    def getHistoricalPlacesFromProjectAsHTML(self,projectID):
#        """gertobjects"""
#        return self.getFromProjectAsHTML(self.projectHistoricalPlaces, projectID, "HistoricalPlace");
 
    def getObjectsFromProjectAsHTML(self,projectID):
        """gertobjects"""
        return self.getFromProjectAsHTML( projectID, "object");
    
    def getPersonsFromProjectAsHTML(self,projectID):
        """getpersons"""
        return self.getFromProjectAsHTML(projectID, "person");
       
      
    def getLabel(self,tag,tagType):
        
        qsSelect = "select tag_label from thesaurus_tags where tag_type = %s and tag_name= %s"
     
        ids = self.executeZSQL(qsSelect,[tagType,tag]) #ids holen
        
        
        if len(ids)==0: #sollte eigentlich nicht sein
            return None
        
        #es sollte nur genau einen geben, alle anderen werden ignoriert-
        
        if ids[0].tag_label is None or ids[0].tag_label == '':
            return tag
        
        else:
            return ids[0].tag_label
        
        
        
        
        
    def addLabel(self,tagID,label):
        """Fuege zu einem tag mit tagID den Label hinzu"""
        qs = "update thesaurus_tags set tag_label=%s where id=%s"
        
        self.executeZSQL(qs,[label,tagID]) # anlegen
        transaction.commit()
        
        
       
        
  
          
    def getFromProjectAsHTML(self,projectID,tagType):
        """Hole die Tags vom entsprechenden Tag-Type aus der Datenbank"""
        ret=""
        
        tags = self.getTagsFromDB(projectID, tagType, None);
           
        for tag in tags:
            
            tagLabel = self.getLabel(tag,tagType)
            
            ret+="""<div class="removeButton">
        <span>%s </span><div style="display:inline" class="remove%s"><span style="display:none" class="removeValue">%s</span>remove</div>
        </div>"""%(tagLabel,tagType,tag)
            
            
#            ret+="""<div>
#        <input tagType="checkbox" name="persons_remove"
#         value="%s">
#        <span>%s</span>
#        </div>"""%(person[0],person[1])
#        
        logging.debug(tagType+":"+ret)
        return ret
    
#     security.declareProtected('View management screens','removeHistoricalPlaceFromProject')                    
#     def removeHistoricalPlaceFromProject(self,projectID,value):
#         """remove"""
#         logging.debug("removeHP:"+projectID+":"+value);
#         
#         HistoricalPlaces = self.getHistoricalPlacesFromProject(projectID)
#         for HistoricalPlace in HistoricalPlaces.keys():
#            
#             logging.debug("trying:"+repr(HistoricalPlace[0])+"::"+repr(value)+"__")
#             if HistoricalPlace[0]==value:
#                 logging.debug("---removed!")
#                 HistoricalPlaces.remove(HistoricalPlace)
#         
#         self.projectHistoricalPlaces.update({projectID:HistoricalPlaces})
#         retstring = self.getHistoricalPlacesFromProjectAsHTML(projectID)
#         logging.debug(retstring)
#         return retstring
#     
    security.declareProtected('View management screens','removeObjectFromProject') 
    def removeObjectFromProject(self,projectID,value):
        """remove an object from the list"""
        logging.debug("remove:"+projectID+":"+value);
        
        
        self.storeChange("removeObject",projectID,value)
        
        self.deleteTagInDB(projectID, "object", value)
        
        retstring = self.getObjectsFromProjectAsHTML(projectID)
        logging.debug(retstring)
        return retstring
    
    
    security.declareProtected('View management screens','removePersonFromProject') 
    def removePersonFromProject(self,projectID,value):
        """remove a person from the projeckt"""
        logging.debug("remove:"+projectID+":"+value);
        self.storeChange("removePerson",projectID,value)
        
     
        self.deleteTagInDB(projectID, "person", value)
        
        retstring = self.getPersonsFromProjectAsHTML(projectID)
        logging.debug(retstring)
        return retstring
    

    #fuegt die neue Person zur personIDtoNames hinzu, fuer die spaetere Anzeige in der Personenliste
    def addNameTOPersonIDNames(self,personID,label):
        personName = self.personIDtoNames.get(personID)
        if personName==None: # Anlegen falls noch nicht existent
            personName=(label,[])
        else:
            if (not label in personName[1]) and (not label==personName[0]): # hinzufuegen falls der neuen name noch nicht als bezeichnugn fuer personID eingetragen ist
                personName[1].append(label) 
    
        self.personIDtoNames.update({personID:personName})
        
    security.declareProtected('View management screens','addPersonToProject')     
    def addPersonToProject(self,projectID,value,label):
        """ add a person so the project"""
        self.storeChange("addPerson",projectID,value+":"+label)
        
                    
        logging.debug("adding:"+projectID+":"+value+":"+label);
      
        personID = self.addTagToDB(projectID, tagType="person", tag=value) ##lege neue Person an oder gib exitierende ID 
        
        self.addLabel(personID,label)
       
       
        retstring = self.getPersonsFromProjectAsHTML(projectID)
        logging.debug(retstring)
        transaction.commit()
        return retstring
    
    
    
#     def rearangePersonIDsHTML(self,REQUEST=None):
#         """setze neue ID zu personen"""
#         ret=[]
#         for personID in self.persons2Projects.keys():
#             logging.debug(personID)
#             
#             masterID,name=self.findMasterIDAndName(personID.rstrip().lstrip())
#             logging.debug("        masterID -appending")
#             logging.debug(repr(name))
#             if len(name)==0:
#                 name=['']
#             ret.append((personID,self.personIDtoNames.get(personID,[''])[0],masterID,self.personIDtoNames.get(masterID,name)[0]))   
#                                       
#     
#         if REQUEST:
#             pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','rearrangePersons.zpt')).__of__(self)
#             return pt(changeList=ret,lookupUrl=self.PERSONS_LOOKUP_URL,editURL=self.EDIT_URL);
#         else:
#             return ret; 
#         
#     def rearangePersonIDs(self,REQUEST):
#         """unify a list of persons"""
#         
#         argv=REQUEST.form;
#         logging.debug(repr(argv))
#         changes=argv['changes']
#         if isinstance(changes,str):
#             changes=[changes]
#         
#         changeList=self.rearangePersonIDsHTML()
#         personToMaster={}
#         logging.debug("changelist:"+repr(changeList))
#         #aendere person2project
#         for change in changes:
#             changeItem=changeList[int(change)];
#             masterID=argv['newID_'+change].lstrip().rstrip() #make sure no spaces
#             personID=changeItem[0]
#             
#             personToMaster[personID]=masterID
#             masterIDProjects = self.persons2Projects.get(masterID,None);
#             if masterIDProjects==None:
#                 masterIDProjects=OOSet();
#                 #ret.append((personID,self.personIDtoNames.get(personID,[''])[0],masterID,self.personIDtoNames.get(masterID,[''])[0]))   
#                 
#             oldProjects= self.persons2Projects.get(personID)
#             logging.debug("personID:"+repr(personID))
#             logging.debug("masterID:"+repr(masterID))
#             logging.debug("keys:"+repr(self.persons2Projects.keys()))
#             logging.debug("oldProjects:"+repr(oldProjects))
#             masterIDProjects.update(oldProjects)
#             self.persons2Projects.update({masterID:masterIDProjects})
#             self.persons2Projects.pop(personID)
#             
#             self.addPersonAndFirstNameFromTripleStore(masterID) #addpersontotiplestore
#             
#             logging.debug("Change:" +personID+":"+ masterID)
#             
#             if personID!=masterID:
#                 self.addSameAsRelationToTripleStore(personID,masterID)
#             
#         #aendere nun projectperson
#         logging.debug(personToMaster)
#         for project in self.projectPersons.keys():
#             personsNew=OOSet()
#             
#             persons=self.projectPersons.get(project)
#             for person in persons:
#                 personsNew.insert([personToMaster.get(person[0],person[0]),person[1]])
#                 logging.debug("REPLACE in:"+project+":" +repr(person)+" by "+ repr(personToMaster.get(person[0],person[0])))
#             self.projectPersons.update({project:personsNew})
#             
#         self.generateSortingOrderForPersonIDs(); #now sort the new names
#         return personToMaster
#     #fuehre personen zusammen die ueber owl:sameAs verbunden sind
#     def getUnifyPersonsList(self,REQUEST=None):
#         """vereinheitlichung der personen auf eine ID aus der GND, wenn moeglich"""
#         ret=[]
#         for personID in self.persons2Projects.keys():
#             masterID,name=self.findMasterIDAndName(personID)
#             logging.debug("masterID:"+masterID)
#             if (masterID is not None) and (masterID is not "") and (not personID==masterID):
#                 #masterIDProjects = self.persons2Projects.get(masterID,None);
#                 ##if masterIDProjects==None:
#                 #    masterIDProjects=OOSet();
#                 logging.debug("        masterID -appending")
#                 logging.debug(repr(name))
# 
#             
#                 ret.append((personID,self.personIDtoNames.get(personID,[''])[0],masterID,self.personIDtoNames.get(masterID,name)[0]))   
#                 #masterIDProjects.update(self.persons2Projects.get(personID));
#                 #self.persons2Projects.update({masterID:masterIDProjects});
#                                         
#     
#         if REQUEST:
#             pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','unifyPersons.zpt')).__of__(self)
#             return pt(changeList=ret);
#         
#         else:
#             return ret; 
#     
#     def unifyPersons(self,changes,REQUEST=None):
#         """unify a list of persons"""
#         
#         if isinstance(changes,str):
#             changes=[changes]
#         
#         changeList=self.getUnifyPersonsList();
#         personToMaster={}
#         logging.debug("changelist:"+repr(changeList))
#         #aendere person2project
#         for change in changes:
#             changeItem=changeList[int(change)];
#             masterID=changeItem[2]
#             personID=changeItem[0]
#             
#             personToMaster[personID]=masterID
#             masterIDProjects = self.persons2Projects.get(masterID,None);
#             if masterIDProjects==None:
#                 masterIDProjects=OOSet();
#                 #ret.append((personID,self.personIDtoNames.get(personID,[''])[0],masterID,self.personIDtoNames.get(masterID,[''])[0]))   
#                 
#             oldProjects= self.persons2Projects.get(personID)
#             logging.debug("personID:"+repr(personID))
#             logging.debug("masterID:"+repr(masterID))
#             logging.debug("keys:"+repr(self.persons2Projects.keys()))
#             logging.debug("oldProjects:"+repr(oldProjects))
#             masterIDProjects.update(oldProjects)
#             self.persons2Projects.update({masterID:masterIDProjects})
#             self.persons2Projects.pop(personID)
#             
#             self.addPersonAndFirstNameFromTripleStore(masterID) #addpersontotiplestore
#             
#             logging.debug("Change:" +personID+":"+ masterID)
#             
#         #aendere nun projectperson
#         logging.debug(personToMaster)
#         for project in self.projectPersons.keys():
#             personsNew=OOSet()
#             
#             persons=self.projectPersons.get(project)
#             for person in persons:
#                 personsNew.insert([personToMaster.get(person[0],person[0]),person[1]])
#                 logging.debug("REPLACE in:"+project+":" +repr(person)+" by "+ repr(personToMaster.get(person[0],person[0])))
#             self.projectPersons.update({project:personsNew})
#             
#         self.generateSortingOrderForPersonIDs(); #now sort the new names
#         return personToMaster
#         
#         
    
    def findMasterIDAndName(self,ressourceID):
        queryString="""select * 
FROM <file://mpiwg_persons_dnb.rdf>  
FROM <file://mpiwg_persons_2.rdf> 
FROM <file:///GND.rdf> 
FROM <http://identifiedNames>
where {
?person <http://www.w3.org/2002/07/owl#sameAs> <%s>.

?ident <http://ontologies.mpiwg-berlin.mpg.de/authorities/namedIdentities/identifies_NamedEntity> ?person. 
?gnd crm:P1_is_identified_by ?ident.

?gnd <http://RDVocab.info/ElementsGr2/dateOfBirth> ?birthDate.
?gnd <http://RDVocab.info/ElementsGr2/dateOfDeath> ?deathDate.
?person <http://xmlns.com/foaf/0.1/name> ?name.
?person <http://xmlns.com/foaf/0.1/lastName> ?lastName.
?person <http://xmlns.com/foaf/0.1/firstName> ?firstName.
} 
"""%ressourceID
        entries = self.callSparqlAll(queryString);
        if len(entries)>0:
            return entries[0][0],entries[0][5:8] #nur den ersten Treffer und nur die personID
        
    
        return None,None
  
  
  
    def getPersonsWithProjectsSortedkeys(self):
        
        def sortF(x,y):
            return cmp(x.lower(),y.lower())
        keys = [x for x in self.getPersonsWithProjects().keys()]
        keys.sort(sortF)
        return keys      
    
    security.declareProtected('View','getPersonsWithProjectIDs') 
   
    def getPersonsWithProjects(self,check=False):
        """holt die getaggted Personen mit Projekten"""
        
       
        objs = self.getTagsFromDB(None, "person", "")
        
        ret={}
        #fuege jetzt die projekt informationen an
        for obj in objs:
            obs = self.getProjectsWithTag("person", obj)
            if len(obs)> 0:
                ret[obj]=obs
        
        return ret
    
        
        
        
        
        persons = self.persons2Projects;
        ret={}
        
        logging.debug("Check Person:"+repr(persons.keys()))
        personsList=[x for x in persons.keys()]
        
        def sort(x,y):
            try:
                sortNrx=self.personsIDForSort.index(x)
            except:
                logging.warn("couldn't find personsIDForSort:"+x)
                sortNrx=0
            
            try:
                sortNry=self.personsIDForSort.index(y)
            except:
                logging.warn("couldn't find personsIDForSort:"+y)
                sortNry=0
            #logging.debug("INSORT***")
            #logging.debug((sortNrx,sortNry))
            return cmp(sortNrx,sortNry)
        
        logging.debug("SORT***")
        logging.debug(self.personsIDForSort) 
        logging.debug("SORT.list")
        logging.debug(personsList) 
        personsList.sort(cmp=sort)
        #for person in persons.keys():
        logging.debug("AFTERSORT***")
        logging.debug(personsList) 
        for person in personsList:
            logging.debug("Check:"+person)
            #TODO: person muss duch den namen von provider geholt werden
            retlist=[]
            projectsList=persons.get(person)
            if projectsList is None:
                projectsList=[]
            for projectID in list(projectsList): #list notwendig da projectList in der folgenden iteration veraendert wird.
                if check: #teste ob im Projekt noch ein Verweis auf den Namen steht
                    #sollte eigentlich nicht sein.
                    personsProjects=self.getPersonsFromProject(projectID)
                    logging.debug("persons check mode")
                    personsProjectsCheck=[x[0] for x in personsProjects]
                    if not person in personsProjectsCheck: #falls es so ist korrigiere die Projektliste der Person
                        #loesche die person von projectListe
                        projectsList.remove(projectID)
                        persons.update({person:projectsList})
                        
                retlist.append(self.getProjectDetails(projectID))
            
            if check and (len(projectsList)==0): #loesche person aus der liste wenn keine Projekte dazu existieren.
                del persons[person]
                
            ret[person]=retlist[0:]
       
        logging.debug("AFTERSORT-ret***")
        logging.debug(ret.keys()) 
        return ret,personsList
    
#     def getHistoricalPlacesWithProjectIDs(self):
#         """holt die getaggted Personen mit Projekten"""
#         HistoricalPlaces = self.HistoricalPlaces2Projects;
#         ret={}
#         logging.debug("Check HistoricalPlace:"+repr(HistoricalPlaces.keys()))
#         for HistoricalPlace in HistoricalPlaces.keys():
#             logging.debug("Check:"+HistoricalPlace)
#             #TODO: HistoricalPlace muss duch den namen von provuder geholt werden
#             list=[]
#             for projectID in HistoricalPlaces.get(HistoricalPlace):
#                 list.append(self.getProjectDetails(projectID))
#             
#             ret[HistoricalPlace]=list[0:]
#         return ret
#     
    def getObjectsWithProjectsSortedkeys(self):
        
        def sortF(x,y):
            return cmp(x.lower(),y.lower())
        keys = [x for x in self.getObjectsWithProjects().keys()]
        keys.sort(sortF)
        return keys
    
    def getObjectsWithProjects(self):
        """holt die getagten Objekte mit Projekten"""
       
        #hole all objekte
        objs = self.getTagsFromDB(None, "object", "")
        
        ret={}
        #fuege jetzt die projekt informationen an
        for obj in objs:
            obs = self.getProjectsWithTag("object", obj)
            if len(obs)> 0:
                ret[obj]=obs
        
        return ret
    
    
    
    security.declareProtected('View management screens','listAllSuggestedTags')     
    def listAllSuggestedTags(self):
        """list all tags"""
        ret="<html><body>"
        for projectID in self.projectSuggestedTags:
            ret+="<h3>"+projectID+"</h3><table>"
            for tags in self.projectSuggestedTags.get(projectID):
                ret+="<tr><td>"+tags[0]+"</td><td>"+tags[1].type+"</td><td>"+tags[1].comment+"</td><td>"+tags[1].userName+"</td></tr>"
            ret+="</table>"
        ret+="</body></html>"
        logging.debug(ret);
        return ret
    
    security.declareProtected('View management screens','suggestTag')     
    def suggestTag(self,projectID,tagName,tagComment,tagType,tagUserName):
        """suggest a new tag"""
        """ add a person so the project"""
        SuggestedTags=self.getSuggestedTagsFromProject(projectID);
        
        logging.debug("suggested:"+projectID+":"+tagName);
        
     
        #TODO: Im moment noch keine Zuordnung zu einer ID.
        newTag = SuggestedTag(tagName,tagComment,tagType,tagUserName)
        SuggestedTags.insert([tagName,newTag])
        self.projectSuggestedTags.update({projectID:SuggestedTags})
        
       
        
        for SuggestedTagTuple in SuggestedTags:
            #hole die abgespeicherten Projekte zu einer Person
            person=SuggestedTagTuple[0] #hile die ID
            
            
            if getattr(self,"SuggestedTags2Projects",None)==None:
                setattr(self,"SuggestedTags2Projects",OOBTree())
         
            projects = self.SuggestedTags2Projects.get(person,None)
                   
            if projects==None:
                projects=OOSet();
            
            projects.insert(projectID )
            logging.debug("update:"+person)
            self.SuggestedTags2Projects.update({person:projects})
        
        
        
        #retstring = self.getSuggestedTagsFromProjectAsHTML(projectID)
        #logging.debug(retstring)
        
        
        
        #return retstring
        
#     security.declareProtected('View management screens','addHistoricalPlaceToProject')     
#     def addHistoricalPlaceToProject(self,projectID,value):
#         """ add a person so the project"""
#         HistoricalPlaces=self.getHistoricalPlacesFromProject(projectID);
#         
#         logging.debug("adding:"+projectID+":"+value);
#         
#      
#         #TODO: Im moment noch keine Zuordnung zu einer ID.
#         HistoricalPlaces.insert([value,value])
#         self.projectHistoricalPlaces.update({projectID:HistoricalPlaces})
#         
#        
#         
#         for HistoricalPlaceTuple in HistoricalPlaces:
#             #hole die abgespeicherten Projekte zu einer Person
#             person=HistoricalPlaceTuple[0] #hile die ID
#             
#             
#             if getattr(self,"HistoricalPlaces2Projects",None)==None:
#                 setattr(self,"HistoricalPlaces2Projects",OOBTree())
#          
#             projects = self.HistoricalPlaces2Projects.get(person,None)
#                    
#             if projects==None:
#                 projects=OOSet();
#             
#             projects.insert(projectID )
#             logging.debug("update:"+person)
#             self.HistoricalPlaces2Projects.update({person:projects})
#         
#         
#         
#         retstring = self.getHistoricalPlacesFromProjectAsHTML(projectID)
#         logging.debug(retstring)
#         
#         
#         
#         return retstring
#     
    security.declareProtected('View management screens','addObjectToProject')     
    def addObjectToProject(self,projectID,value):
        """ add a person so the project"""
        #objects=self.getObjectsFromProject(projectID);    
        logging.debug("adding:"+projectID+":"+value);    
        self.storeChange("addObject",projectID,value)
     
        #TODO: Im moment noch keine Zuordnung zu einer ID.
         
        self.addTagToDB(projectID, tagType="object", tag=value)
         
        retstring = self.getObjectsFromProjectAsHTML(projectID)
        logging.debug(retstring)
        
      
        return retstring
    
    
    def getProjectsWithTag(self,tagType,tagName):
        """hole alle projekte mit tags vom typ tagType and tagName"""
        
        qs = """select distinct project_id from thesaurus_projects_tags where tag_id in 
        (select id as tag_id from thesaurus_tags where tag_type = %s and tag_name = %s)
        """
        
        
        #hole alle projecte
        
        ret=[]
        for projectRes in self.executeZSQL(qs,[tagType,tagName]):
            
            project = projectRes.project_id
            
            logging.debug("found:"+project)
            proj =self.getProjectDetails(project);
            if proj is not None:
                ret.append(proj)

        return ret
    
    def getProjectDetails(self,projectId):
        pf = self.getMPIWGRoot().getProjectFolder()
        project=pf.get(projectId,None)
        if project is None:
            logging.debug("no project!! " +projectId)
            return None
        
        link=projectId
        
        title=project.getContent("WEB_title")
        #persons=project.getPersonKeyList()
        persons=project.getContent('xdata_01')
        logging.debug("%s %s %s"%(link,title,persons))
        
        thumb = project.getThumbUrl()
       
        return link,title,persons,thumb
    
#        $.post("addNewPerson",{"projectID":
#                     $('#projectID').val(),
#                     "personName":$("#suggest_newPerson").val(),
#                     "personComment":$("#suggest_newPerson_comment").val()}
#               
#              );         
#    
    
    security.declareProtected('View management screens','addAndCreateNewPerson')     
    def addAndCreateNewPerson(self,projectID,personName,personComment,personUserName):
        """adds anew person to the project which is not in the authority file"""
        
        id = random.randint(0, 1000000); 
        idstring="http://ontologies.mpiwg-berlin.mpg.de/tempObjects/person/"+str(id)
        while self.suggestedPersons.has_key(idstring):
            id = random.randint(0, 1000000); 
            #idstring="http://ontologies.mpiwg-berlin.mpg.de/tempObjects/person/"+str(id);
            idstring=self.TEMP_PERSON_NS+str(id);
            
            
        self.suggestedPersons.update({idstring:(personName,personComment,projectID,personUserName)})
        self.createTempPersonInVirtuoso(projectID, idstring, personName, personComment) #TODO: add suername to the triplestore
        return self.addPersonToProject(projectID, idstring, personName);
       
    def addSameAsRelationToTripleStore(self,personID,masterID):
        cmdString ="insert in GRAPH <"+self.virtuosoGraph+">  {"
        cmdString +="<%s> <http://www.w3.org/2002/07/owl#sameAs> <%s>."%(personID,masterID)
        cmdString +="<%s> <http://www.w3.org/2002/07/owl#sameAs> <%s>."%(masterID,personID)
        cmdString+="}"

        auth_handler = urllib2.HTTPBasicAuthHandler()
        auth_handler.add_password(realm='sparql',
                          uri=self.virtuosoServer+"/sparql",
                          user=self.virtuosoDAVUser,
                          passwd=self.virtuosoDAVPW)
                          
        opener = urllib2.build_opener(auth_handler)
        opener.addheaders = [('Content-Type','application/sparql-query')]
        
        logging.debug(cmdString)
        try:
            r= opener.open(self.virtuosoServer+"/sparql", urllib.urlencode({'query':cmdString,'default-graph-uri':self.virtuosoGraph,'named-graph-uri':None}))
            logging.debug(r.read())
        except urllib2.URLError, e:
            logging.error(e.code)
            logging.error(e.read())
            return
        
        
    security.declareProtected('View management screens','createTempPersonInVirtuoso')     
    def createTempPersonInVirtuoso(self,projectID,personURI, personName,personComment):
        """add a new person to the triple store of tempory persons"""
        triples=[];
        personID="<"+personURI+">"
        triples.append((personID,"<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>","<http://ontologies.mpiwg-berlin.mpg.de/authorities/namedIdentities/Person>"))
        triples.append((personID,"<http://erlangen-crm.org/110404/P3_has_note>",'"'+personComment+'"'))
        triples.append((personID,"<http://xmlns.com/foaf/0.1/name>",'"'+personName+'"'))
        triples.append((personID,"<http://ontologies.mpiwg-berlin.mpg.de/general/isMentionedOn>","<http://www.mpiwg-berlin.mpg.de/en/research/projects/"+projectID+">"))
        
        cmdString ="insert in GRAPH <"+self.virtuosoGraph+">  {"
        for triple in triples:
            cmdString+=" ".join(triple)+"."
        
        cmdString+="}"

        auth_handler = urllib2.HTTPBasicAuthHandler()
        auth_handler.add_password(realm='sparql',
                          uri=self.virtuosoServer+"/sparql",
                          user=self.virtuosoDAVUser,
                          passwd=self.virtuosoDAVPW)
                          
        opener = urllib2.build_opener(auth_handler)
        opener.addheaders = [('Content-Type','application/sparql-query')]
        
        logging.debug(cmdString)
        try:
            r= opener.open(self.virtuosoServer+"/sparql", urllib.urlencode({'query':cmdString,'default-graph-uri':self.virtuosoGraph,'named-graph-uri':None}))
            logging.debug(r.read())
        except urllib2.URLError, e:
            logging.error(e.code)
            logging.error(e.read())
            return
        
        opener2 = urllib2.build_opener()
       
        personIDencoded=urllib.quote(personURI,safe="")
        graphEncoded=urllib.quote(self.additionalNamesGraphURL,safe="")
        url = self.personproviderURL+"id/"+personIDencoded+"/"+graphEncoded
         
        try:
            request = urllib2.Request(url);
            request.get_method = lambda : 'PUT'
            r= opener2.open(request);
            logging.debug(r.read())
        except urllib2.URLError, e:
            logging.error(e.code)
            logging.error(e.read())
            return
       
        return
    
    #  self.storeChange("removePerson",projectID,value)    
    def storeChange(self,typeString,projectID,value):
        
        from time import gmtime,strftime
        fl = open(self.getLogpath(),"a")
        person = self.REQUEST.AUTHENTICATED_USER.getId()
        date = strftime("%Y-%m-%d %H:%M:%S", gmtime())
        writeString ="\t".join((date,person,typeString,projectID,value))
        fl.write(writeString+"\n")
        fl.flush()
        fl.close()
        
        lastChangeInThesaurus = getattr(self,'lastChangeInThesaurus',OOBTree())
        lastChangeInThesaurus.update({projectID:date})
        self.lastChangeInThesaurus=lastChangeInThesaurus
        
def redirect(RESPONSE,url):
        """mache ein redirect mit einem angehaengten time stamp um ein reload zu erzwingen"""
        
        timeStamp=time.time()
        
        if url.find("?")>-1: #giebt es schon parameter
            addStr="&time=%s"
        else:
            addStr="?time=%s"
            
        RESPONSE.setHeader('Last-Modified',email.Utils.formatdate().split("-")[0]+'GMT')
        logging.error(email.Utils.formatdate()+' GMT')
        RESPONSE.redirect(url+addStr%timeStamp)
        
def manage_addMPIWGThesaurusForm(self):
    """form for adding the project"""
    pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','addMPIWGThesaurusForm.zpt')).__of__(self)
    return pt()



def manage_addMPIWGThesaurus(self,id,RESPONSE=None):
    """add it"""
    newObj=MPIWGThesaurus(id)

    self._setObject(id,newObj)


    if RESPONSE is not None:
        redirect(RESPONSE,'manage_main')