changeset 45:efdbe9eb2403

thesaurus jetzt in datenbank
author dwinter
date Mon, 25 Nov 2013 08:12:11 +0100
parents a30307377ed9
children 7c1782d65c9b cb20308fe412
files MPIWGThesaurus.py MPIWGThesaurus_orig.py migrateThesaurus.py zpt/manageMPIWGThesaurus.zpt
diffstat 4 files changed, 2603 insertions(+), 670 deletions(-) [+]
line wrap: on
line diff
--- a/MPIWGThesaurus.py	Wed Nov 06 15:03:36 2013 +0100
+++ b/MPIWGThesaurus.py	Mon Nov 25 08:12:11 2013 +0100
@@ -4,7 +4,6 @@
 #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
 
@@ -15,6 +14,7 @@
 from BTrees.OOBTree import OOBTree
 from BTrees.OOBTree import OOSet
 from AccessControl import ClassSecurityInfo
+from Products.ZDBInterface.ZDBInterfaceFolder import ZDBInterfaceFolder
 
 #import os
 import re
@@ -27,6 +27,7 @@
 import random
 import urllib2
 import urllib
+import json
 
 from SrvTxtUtils import utf8ify
 
@@ -68,7 +69,7 @@
         self.userName=userName
         
 
-class MPIWGThesaurus(Folder):
+class MPIWGThesaurus(ZDBInterfaceFolder, Folder):
     """MPIWGThesaurus main folder"""
     security=ClassSecurityInfo()
 
@@ -96,17 +97,17 @@
     
     #BTrees fuer die Tags
     
-    projectPersons= OOBTree() #project --> personen IDs
-    projectObjects= OOBTree() #project --> objects
-    projectHistoricalPlaces= OOBTree()
+    #projectPersons= OOBTree() #project --> personen IDs
+    #projectObjects= OOBTree() #project --> objects
+    #projectHistoricalPlaces= OOBTree()
     projectSuggestedTags= OOBTree()
-    persons2Projects= OOBTree() #personenID --> projects
-    objects2Projects=OOBTree() #objects --> projects
-    historicalPlaces2Projects=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!
+    ##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.
     
@@ -176,7 +177,7 @@
     
     
     
-    manage_options = Folder.manage_options+(
+    manage_options = ZDBInterfaceFolder.manage_options+(
         {'label':'Thesaurus entries','action':'changeMPIWGThesaurusForm'},
         {'label':'Manage Thesaurus','action':'manageMPIWGThesaurus'},
         {'label':'Thesaurus Log','action':'manageMPIWGThesaurusLogs'},
@@ -327,7 +328,24 @@
                 
         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=[]
@@ -353,9 +371,9 @@
             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.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.append(";".join([person[1] for person in self.getObjectsFromProject(proj.getId())]))
             retProj+=self.getTags(proj.getId(),projectTags)
             retList.append("\t".join(retProj))
         
@@ -408,92 +426,92 @@
     #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])
+# 
+#     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.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)
+#             
 #           
-#        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)
+#             
+#                                     
+#         #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):
         
         
@@ -582,7 +600,7 @@
             
     security.declareProtected('View management screens','changeTags')            
     def changeTags(self,projectID,approaches=[],disciplines=[],periods=[],spaces=[],technologies=[],transfers=[],RESPONSE=None):
-        """change tags"""
+        """Aendert die Tags im angegebenen Project"""
         self.changeTagFromList(projectID,"approaches", approaches)
         self.changeTagFromList(projectID,"disciplines", disciplines)
         self.changeTagFromList(projectID,"periods", periods)
@@ -591,13 +609,13 @@
         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.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.historicalPlaces2Projects=self.historicalPlaces2Projects
         self.suggestedTags2Projects=self.suggestedTags2Projects;
         
         self.suggestedPersons=self.suggestedPersons;
@@ -605,7 +623,6 @@
     security.declareProtected('View management screens','deleteAllTags')                    
     def deleteAllTags(self):
         """deleteAllTags - TODO: take this out!!,"""
-        setattr(self,"tags",None)
         
         return "DONE!"
     
@@ -620,65 +637,139 @@
         
         return "DONE!"
     
-    security.declareProtected('View management screens','deleteAllObjects')                    
-    def deleteAllObjects(self):
-        """deleteAllTags - TODO: take this out!!,"""
-        logging.debug("delete all objects")
-        self.projectObjects= OOBTree()
-        self.objects2Projects=OOBTree()
-    
-        
-        return "DONE!"
-    
+  
     def changeTagFromList(self,projectID,tagType,tagList):
         
-        logging.debug("changing:"+projectID)
-        logging.debug("asking tag::"+tagType)
-        if type(tagList) is not ListType:
-            tagList=[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()
+    
     
-        tags = getattr(self,"tags",None)
-        if tags is None:
-            logging.debug("Create new tags")
-            tags=OOBTree()
-            setattr(self,"tags",tags)
+    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
     
-        tagsStored=tags.get(tagType,None)
-        if tagsStored is None:
-            tagsStored=OOBTree();
+    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))
         
         
         
-        for tag in tagsStored.keys(): #gehe durch alle gespeichteren tags
-            logging.debug("checking:"+tag)
-            projectsOfTag = tagsStored.get(tag,None)
-            logging.debug(projectsOfTag)
-            if projectsOfTag is None:
-                projectsOfTag=OOSet()
-            
-            if tag in tagList: #dieser ist getagged
-                projectsOfTag.update([projectID]);
-                self.storeChange("added",projectID,tag)
-                tagList.remove(tag); 
+        
+        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:
-                if projectsOfTag.has_key(projectID):
-                    projectsOfTag.remove(projectID);
-                    self.storeChange("remove",projectID,tag)
-                    
-            tagsStored.update({tag:projectsOfTag});
+                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])
+            
         
-        for tag in tagList: # alle Tags, die nicht abgearbeitet worden sind, muessen noch angelegt werden
-            logging.debug("adding:"+tag)
-            newApproach=OOSet()
-            newApproach.update([projectID]);
-            tagsStored.insert(tag, newApproach);
+        
+        return ids[0].id #sollte eigentlich auch nur genau einen geben.
         
-        tags.update({tagType:tagsStored})
         
-        transaction.commit()
-        
+  
     def getTitle(self,entry):
         return entry.title
     
@@ -753,39 +844,26 @@
         """get all  tags as hash or None if no tag exists"""
         retHash={}
         
-        tagCnt=0
-        tags = getattr(self,"tags",None)
-        
-        if tags is None:
-            return;
-        
         #falls nicht gesetzt
         if tagType is None:
-            tagTypes = tags.keys()
+            
+            
+            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:
-            tagsStored=tags.get(tagType,None)
             
-            if tagsStored is None:
-                # WTF: was: return
-                continue
-            
-            retHash[tagType]=[]
+            #retHash[tagType]=[]
+            tagCnt=0
 
-            for tag in tagsStored.keys(): #gehe durch alle gespeichteren approached
-                logging.debug("checking:"+tag)
-                currentTag = tagsStored.get(tag,None)
-                if currentTag is None:
-                    continue
-                if currentTag.has_key(projectID):
-                    tagCnt+=1
-                    retHash[tagType].append("""%s"""%tag)
-                    
-            if len(retHash[tagType]) == 0:
-                # empty tag list
-                del 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
@@ -796,135 +874,81 @@
     
     
     
-    def getTagsJSON(self,projectID,tagType,RESPONSE=None):
-        """get all selected tagList"""
-        #logging.debug("asking:"+projectID)
-        #logging.debug("asking tag::"+tagType)
-        retList=[]
-        tags = getattr(self,"tags",None)
-        if tags is None:
-            return;
+    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)
         
-        tagsStored=tags.get(tagType,None)
-        if tagsStored is None:
-            return;
-        
-        for tag in tagsStored.keys(): #gehe durch alle gespeichteren approached
-            logging.debug("checking:"+tag)
-            currentTag = tagsStored.get(tag,None)
-            if currentTag is None:
-                continue
-            if currentTag.has_key(projectID):
-                retList.append(""" "%s" """%tag)
         
         if RESPONSE:
             RESPONSE.setHeader('Content-Type', "application/json")
         
-        logging.debug(retList)
-        return "["+",".join(retList)+"]"
+        ret = json.dumps(tags)
+        
+        
+        logging.debug(ret)
+        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       
-#        logging.debug("asking:"+projectID)
-#        
-#        
-#        apps = self.getApproaches()+ self.getDisciplines();
-#        retList=[]
-#        for tagType in self.tags.keys():
-#        
-#            logging.debug("asking tag::"+repr(tagType))
-#            
-#            tags = getattr(self,"tags",None)
-#            if tags is None:
-#                continue;
-#            
-#            tagsStored=tags.get(tagType,None)
-#            if tagsStored is None:
-#                continue;
-#            
-#            for tag in tagsStored.keys(): #gehe durch alle gespeichteren approached
-#                logging.debug("checking:"+tag)
-#                currentTag = tagsStored.get(tag,None)
-#                if currentTag is None:
-#                    continue
-#                if currentTag.has_key(projectID):
-#                    retList.append(""" "%s" """%tag)
-#        
-#        if RESPONSE:
-#            RESPONSE.setHeader('Content-Type', "application/json")
-#        
-#        logging.debug(retList)
-#        return retList
-    
+  
     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"""
+    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();
-        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
+        
+        return self.getTagsJSON(tagType="object", startWith=term, RESPONSE=RESPONSE)
         
         
-    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
+#         
+#         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):
@@ -948,148 +972,149 @@
         return self.knowledgeTransfers
     
     
-    def getObjectsFromProject(self,projectID):
-        return self.getFromProject(self.projectObjects,projectID);
-    
-    def getHistoricalPlacesFromProject(self,projectID):
-        return self.getFromProject(self.projectHistoricalPlaces,projectID);
+#     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 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 zu projectID gehoerigen objekte aus dem objects-set. 
+        #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, gieb es zurueck
+        if objects.has_key(projectID): #wenn zu der ProjektID schon etwas abgespeichter ist, gibt es zurueck
             logging.debug("key exists:"+projectID)
-            persons=objects.get(projectID);
+            entries=objects.get(projectID);
         else: # andernfalls lege einen neuen Satz an.
-            persons=OOSet()
-            objects.update({projectID:persons})
+            entries=OOSet()
+            objects.update({projectID:entries})
             logging.debug("key does not exists:"+projectID)
-            
-        
-        return persons
-    
-    def getHistoricalPlacesFromProjectAsHTML(self,projectID):
-        """gertobjects"""
-        return self.getFromProjectAsHTML(self.projectHistoricalPlaces, projectID, "HistoricalPlace");
+             
+         
+        return entries
+     
+#    def getHistoricalPlacesFromProjectAsHTML(self,projectID):
+#        """gertobjects"""
+#        return self.getFromProjectAsHTML(self.projectHistoricalPlaces, projectID, "HistoricalPlace");
  
     def getObjectsFromProjectAsHTML(self,projectID):
         """gertobjects"""
-        return self.getFromProjectAsHTML(self.projectObjects, projectID, "Object");
+        return self.getFromProjectAsHTML( projectID, "object");
     
     def getPersonsFromProjectAsHTML(self,projectID):
         """getpersons"""
-        return self.getFromProjectAsHTML(self.projectPersons, projectID, "Person");
+        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,objects,projectID,type):
-        """getpersons"""
+  
+          
+    def getFromProjectAsHTML(self,projectID,tagType):
+        """Hole die Tags vom entsprechenden Tag-Type aus der Datenbank"""
         ret=""
-        if objects.has_key(projectID):
-            persons=objects.get(projectID);
-        else:
-            persons=OOSet()
+        
+        tags = self.getTagsFromDB(projectID, tagType, None);
+           
+        for tag in tags:
             
-        
-        for person in persons:
+            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>"""%(person[1],type,person[0])
+        </div>"""%(tagLabel,tagType,tag)
             
             
 #            ret+="""<div>
-#        <input type="checkbox" name="persons_remove"
+#        <input tagType="checkbox" name="persons_remove"
 #         value="%s">
 #        <span>%s</span>
 #        </div>"""%(person[0],person[1])
 #        
-        logging.debug(type+":"+ret)
+        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','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"""
+        """remove an object from the list"""
         logging.debug("remove:"+projectID+":"+value);
         
         
         self.storeChange("removeObject",projectID,value)
         
-        objects = self.getObjectsFromProject(projectID)
-        for object in objects.keys():
-           
-            logging.debug("trying:"+repr(object[0])+"::"+repr(value)+"__")
-            if object[0]==value:
-                logging.debug("---removed!")
-                objects.remove(object)
+        self.deleteTagInDB(projectID, "object", value)
         
-            #now also delete the project from the object.
-                objectsOfPerson=self.objects2Projects.get(object[0])
-               
-
-                if projectID in list(objectsOfPerson):
-                    objectsOfPerson.remove(projectID)
-                    #self.persons2Projects.update({person:projectsList})
-                    if (len(objectsOfPerson)==0): #loesche person aus der liste wenn keine Projekte dazu existieren.
-                        del self.objects2Projects[object[0]]
-             
-        self.projectObjects.update({projectID:objects})
         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)
         
-        persons = self.getPersonsFromProject(projectID) # hole alle personen die mit dem Projekt verbunden sind.
-        for person in persons.keys():
-           
-            logging.debug("trying:"+repr(person[0])+"::"+repr(value)+"__")
-            if person[0]==value:#person ist die zuloeschende, dann raus damit
-            
-                logging.debug("---removed!")
-                persons.remove(person)
-                
-                #now also delete the project from the person.
-                projectsOfPerson=self.persons2Projects.get(person[0])
-                logging.debug(projectsOfPerson)
-                if projectID in list(projectsOfPerson):
-                    projectsOfPerson.remove(projectID)
-                    #self.persons2Projects.update({person:projectsList})
-                    if (len(projectsOfPerson)==0): #loesche person aus der liste wenn keine Projekte dazu existieren.
-                        del self.persons2Projects[person[0]]
-             
-                     
-        #self.projectPersons.update({projectID:persons})
+     
+        self.deleteTagInDB(projectID, "person", value)
+        
         retstring = self.getPersonsFromProjectAsHTML(projectID)
         logging.debug(retstring)
         return retstring
@@ -1111,34 +1136,14 @@
         """ add a person so the project"""
         self.storeChange("addPerson",projectID,value+":"+label)
         
-        persons=self.getPersonsFromProject(projectID);
-        
+                    
         logging.debug("adding:"+projectID+":"+value+":"+label);
       
-        persons.insert([value,label])
-        self.projectPersons.update({projectID:persons})
+        personID = self.addTagToDB(projectID, tagType="person", tag=value) ##lege neue Person an oder gib exitierende ID 
         
-        for personTuple in persons:
-            #hole die abgespeicherten Projekte zu einer Person
-            person=personTuple[0] #hole die ID
-            
-            
-            if getattr(self,"persons2Projects",None)==None:
-                setattr(self,"persons2Projects",OOBTree())
-         
-            projects = self.persons2Projects.get(person,None)
-            logging.debug("found projects:"+ repr(projects))
-            if projects is None: #person hatte noch keine projekte
-                projects=OOSet();
-                
-            projects.insert(projectID )
-            logging.debug("update:"+person)
-            self.persons2Projects.update({person:projects})
-            
-            self.addPersonAndFirstNameFromTripleStore(person)
-            self.generateSortingOrderForPersonIDs();
-               
-        self.addNameTOPersonIDNames(value,label)
+        self.addLabel(personID,label)
+       
+       
         retstring = self.getPersonsFromProjectAsHTML(projectID)
         logging.debug(retstring)
         transaction.commit()
@@ -1146,155 +1151,155 @@
     
     
     
-    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 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 * 
@@ -1321,10 +1326,38 @@
         
     
         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 getPersonsWithProjectIDs(self,check=False):
+   
+    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={}
         
@@ -1384,46 +1417,46 @@
         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 getObjectsWithProjectIDsSortedkeys(self):
+#     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.getObjectsWithProjectIDs().keys()]
+        keys = [x for x in self.getObjectsWithProjects().keys()]
         keys.sort(sortF)
         return keys
     
-    def getObjectsWithProjectIDs(self):
-        """holt die getagten Personen mit Projekten"""
-        objects = self.objects2Projects;
+    def getObjectsWithProjects(self):
+        """holt die getagten Objekte mit Projekten"""
+       
+        #hole all objekte
+        objs = self.getTagsFromDB(None, "object", "")
+        
         ret={}
-        logging.debug("Check Object:"+repr(objects.keys()))
-        for object in objects.keys():
-            logging.debug("Check:"+object)
-            #TODO: object muss duch den namen von provuder geholt werden
-            list=[]
-            for projectID in objects.get(object):
-                list.append(self.getProjectDetails(projectID))
-            
-            ret[object]=list[0:]
-            
-        logging.debug(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"""
@@ -1479,106 +1512,79 @@
         
         #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','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);
-        
+        #objects=self.getObjectsFromProject(projectID);    
+        logging.debug("adding:"+projectID+":"+value);    
         self.storeChange("addObject",projectID,value)
      
         #TODO: Im moment noch keine Zuordnung zu einer ID.
-        objects.insert([value,value])
-        self.projectObjects.update({projectID:objects})
-        
-       
-        
-        for objectTuple in objects:
-            #hole die abgespeicherten Projekte zu einer Person
-            person=objectTuple[0] #hile die ID
-            
-            
-            if getattr(self,"objects2Projects",None)==None:
-                setattr(self,"objects2Projects",OOBTree())
          
-            projects = self.objects2Projects.get(person,None)
-                   
-            if projects==None:
-                projects=OOSet();
-            
-            projects.insert(projectID )
-            logging.debug("update:"+person)
-            self.objects2Projects.update({person:projects})
-        
-        
-        
+        self.addTagToDB(projectID, tagType="object", tag=value)
+         
         retstring = self.getObjectsFromProjectAsHTML(projectID)
         logging.debug(retstring)
         
-        
-        
+      
         return retstring
     
     
     def getProjectsWithTag(self,tagType,tagName):
-        tags = getattr(self,"tags",None)
-        if tags is None:
-            logging.debug("can't find Tags")
-            return []
-    
-        tagsStored=tags.get(tagType,None)
-        if tagsStored is None:
-            logging.debug("can't find Tag:"+tagType)
-            return []
+        """hole alle projekte mit tags vom typ tagType and tagName"""
         
-        projects = tagsStored.get(tagName,None)
-        if projects is None:
-            logging.debug("can't find any projects for Tag:"+tagName+"("+tagType+")")
-            return []
+        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 project in projects:
+        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:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MPIWGThesaurus_orig.py	Mon Nov 25 08:12:11 2013 +0100
@@ -0,0 +1,1753 @@
+#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
+
+#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
+
+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(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://127.0.0.1:8280/MetaDataManagerRestlet/persons"
+    EDIT_URL="http://127.0.0.1:8280/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 = Folder.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 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):
+        """change tags"""
+        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!!,"""
+        setattr(self,"tags",None)
+        
+        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!"
+    
+    security.declareProtected('View management screens','deleteAllObjects')                    
+    def deleteAllObjects(self):
+        """deleteAllTags - TODO: take this out!!,"""
+        logging.debug("delete all objects")
+        self.projectObjects= OOBTree()
+        self.objects2Projects=OOBTree()
+    
+        
+        return "DONE!"
+    
+    def changeTagFromList(self,projectID,tagType,tagList):
+        
+        logging.debug("changing:"+projectID)
+        logging.debug("asking tag::"+tagType)
+        if type(tagList) is not ListType:
+            tagList=[tagList]
+        
+    
+        tags = getattr(self,"tags",None)
+        if tags is None:
+            logging.debug("Create new tags")
+            tags=OOBTree()
+            setattr(self,"tags",tags)
+        
+    
+        tagsStored=tags.get(tagType,None)
+        if tagsStored is None:
+            tagsStored=OOBTree();
+        
+        
+        
+        for tag in tagsStored.keys(): #gehe durch alle gespeichteren tags
+            logging.debug("checking:"+tag)
+            projectsOfTag = tagsStored.get(tag,None)
+            logging.debug(projectsOfTag)
+            if projectsOfTag is None:
+                projectsOfTag=OOSet()
+            
+            if tag in tagList: #dieser ist getagged
+                projectsOfTag.update([projectID]);
+                self.storeChange("added",projectID,tag)
+                tagList.remove(tag); 
+            else:
+                if projectsOfTag.has_key(projectID):
+                    projectsOfTag.remove(projectID);
+                    self.storeChange("remove",projectID,tag)
+                    
+            tagsStored.update({tag:projectsOfTag});
+        
+        for tag in tagList: # alle Tags, die nicht abgearbeitet worden sind, muessen noch angelegt werden
+            logging.debug("adding:"+tag)
+            newApproach=OOSet()
+            newApproach.update([projectID]);
+            tagsStored.insert(tag, newApproach);
+        
+        tags.update({tagType:tagsStored})
+        
+        transaction.commit()
+        
+    def getTitle(self,entry):
+        return entry.title
+    
+    def thes_quote(self,txt):
+        import md5
+        logging.debug("@*%s*@"%txt)
+        return md5.md5(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={}
+        
+        tagCnt=0
+        tags = getattr(self,"tags",None)
+        
+        if tags is None:
+            return;
+        
+        #falls nicht gesetzt
+        if tagType is None:
+            tagTypes = tags.keys()
+        else:
+            tagTypes = [tagType]
+        
+        for tagType in tagTypes:
+            tagsStored=tags.get(tagType,None)
+            
+            if tagsStored is None:
+                # WTF: was: return
+                continue
+            
+            retHash[tagType]=[]
+
+            for tag in tagsStored.keys(): #gehe durch alle gespeichteren approached
+                logging.debug("checking:"+tag)
+                currentTag = tagsStored.get(tag,None)
+                if currentTag is None:
+                    continue
+                if currentTag.has_key(projectID):
+                    tagCnt+=1
+                    retHash[tagType].append("""%s"""%tag)
+                    
+            if len(retHash[tagType]) == 0:
+                # empty tag list
+                del retHash[tagType]
+            
+        if tagCnt==0:
+            return None
+        
+        return retHash
+    
+    
+    
+    
+    
+    def getTagsJSON(self,projectID,tagType,RESPONSE=None):
+        """get all selected tagList"""
+        #logging.debug("asking:"+projectID)
+        #logging.debug("asking tag::"+tagType)
+        retList=[]
+        tags = getattr(self,"tags",None)
+        if tags is None:
+            return;
+        
+        tagsStored=tags.get(tagType,None)
+        if tagsStored is None:
+            return;
+        
+        for tag in tagsStored.keys(): #gehe durch alle gespeichteren approached
+            logging.debug("checking:"+tag)
+            currentTag = tagsStored.get(tag,None)
+            if currentTag is None:
+                continue
+            if currentTag.has_key(projectID):
+                retList.append(""" "%s" """%tag)
+        
+        if RESPONSE:
+            RESPONSE.setHeader('Content-Type', "application/json")
+        
+        logging.debug(retList)
+        return "["+",".join(retList)+"]"
+    
+    
+    
+  
+    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       
+#        logging.debug("asking:"+projectID)
+#        
+#        
+#        apps = self.getApproaches()+ self.getDisciplines();
+#        retList=[]
+#        for tagType in self.tags.keys():
+#        
+#            logging.debug("asking tag::"+repr(tagType))
+#            
+#            tags = getattr(self,"tags",None)
+#            if tags is None:
+#                continue;
+#            
+#            tagsStored=tags.get(tagType,None)
+#            if tagsStored is None:
+#                continue;
+#            
+#            for tag in tagsStored.keys(): #gehe durch alle gespeichteren approached
+#                logging.debug("checking:"+tag)
+#                currentTag = tagsStored.get(tag,None)
+#                if currentTag is None:
+#                    continue
+#                if currentTag.has_key(projectID):
+#                    retList.append(""" "%s" """%tag)
+#        
+#        if RESPONSE:
+#            RESPONSE.setHeader('Content-Type', "application/json")
+#        
+#        logging.debug(retList)
+#        return retList
+    
+    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"""
+        term=term.lower();
+        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 zu 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, gieb es zurueck
+            logging.debug("key exists:"+projectID)
+            persons=objects.get(projectID);
+        else: # andernfalls lege einen neuen Satz an.
+            persons=OOSet()
+            objects.update({projectID:persons})
+            logging.debug("key does not exists:"+projectID)
+            
+        
+        return persons
+    
+    def getHistoricalPlacesFromProjectAsHTML(self,projectID):
+        """gertobjects"""
+        return self.getFromProjectAsHTML(self.projectHistoricalPlaces, projectID, "HistoricalPlace");
+ 
+    def getObjectsFromProjectAsHTML(self,projectID):
+        """gertobjects"""
+        return self.getFromProjectAsHTML(self.projectObjects, projectID, "Object");
+    
+    def getPersonsFromProjectAsHTML(self,projectID):
+        """getpersons"""
+        return self.getFromProjectAsHTML(self.projectPersons, projectID, "Person");
+       
+        
+    def getFromProjectAsHTML(self,objects,projectID,tagType):
+        """getpersons"""
+        ret=""
+        if objects.has_key(projectID):
+            persons=objects.get(projectID);
+        else:
+            persons=OOSet()
+            
+        
+        for person in persons:
+            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>"""%(person[1],tagType,person[0])
+            
+            
+#            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"""
+        logging.debug("remove:"+projectID+":"+value);
+        
+        
+        self.storeChange("removeObject",projectID,value)
+        
+        objects = self.getObjectsFromProject(projectID)
+        for object in objects.keys():
+           
+            logging.debug("trying:"+repr(object[0])+"::"+repr(value)+"__")
+            if object[0]==value:
+                logging.debug("---removed!")
+                objects.remove(object)
+        
+            #now also delete the project from the object.
+                objectsOfPerson=self.objects2Projects.get(object[0])
+               
+
+                if projectID in list(objectsOfPerson):
+                    objectsOfPerson.remove(projectID)
+                    #self.persons2Projects.update({person:projectsList})
+                    if (len(objectsOfPerson)==0): #loesche person aus der liste wenn keine Projekte dazu existieren.
+                        del self.objects2Projects[object[0]]
+             
+        self.projectObjects.update({projectID:objects})
+        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)
+        
+        persons = self.getPersonsFromProject(projectID) # hole alle personen die mit dem Projekt verbunden sind.
+        for person in persons.keys():
+           
+            logging.debug("trying:"+repr(person[0])+"::"+repr(value)+"__")
+            if person[0]==value:#person ist die zuloeschende, dann raus damit
+            
+                logging.debug("---removed!")
+                persons.remove(person)
+                
+                #now also delete the project from the person.
+                projectsOfPerson=self.persons2Projects.get(person[0])
+                logging.debug(projectsOfPerson)
+                if projectID in list(projectsOfPerson):
+                    projectsOfPerson.remove(projectID)
+                    #self.persons2Projects.update({person:projectsList})
+                    if (len(projectsOfPerson)==0): #loesche person aus der liste wenn keine Projekte dazu existieren.
+                        del self.persons2Projects[person[0]]
+             
+                     
+        #self.projectPersons.update({projectID:persons})
+        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)
+        
+        persons=self.getPersonsFromProject(projectID);
+        
+        logging.debug("adding:"+projectID+":"+value+":"+label);
+      
+        persons.insert([value,label])
+        self.projectPersons.update({projectID:persons})
+        
+        for personTuple in persons:
+            #hole die abgespeicherten Projekte zu einer Person
+            person=personTuple[0] #hole die ID
+            
+            
+            if getattr(self,"persons2Projects",None)==None:
+                setattr(self,"persons2Projects",OOBTree())
+         
+            projects = self.persons2Projects.get(person,None)
+            logging.debug("found projects:"+ repr(projects))
+            if projects is None: #person hatte noch keine projekte
+                projects=OOSet();
+                
+            projects.insert(projectID )
+            logging.debug("update:"+person)
+            self.persons2Projects.update({person:projects})
+            
+            self.addPersonAndFirstNameFromTripleStore(person)
+            self.generateSortingOrderForPersonIDs();
+               
+        self.addNameTOPersonIDNames(value,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
+        
+    security.declareProtected('View','getPersonsWithProjectIDs') 
+    def getPersonsWithProjectIDs(self,check=False):
+        """holt die getaggted Personen mit Projekten"""
+        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 getObjectsWithProjectIDsSortedkeys(self):
+        
+        def sortF(x,y):
+            return cmp(x.lower(),y.lower())
+        keys = [x for x in self.getObjectsWithProjectIDs().keys()]
+        keys.sort(sortF)
+        return keys
+    
+    def getObjectsWithProjectIDs(self):
+        """holt die getagten Personen mit Projekten"""
+        objects = self.objects2Projects;
+        ret={}
+        logging.debug("Check Object:"+repr(objects.keys()))
+        for object in objects.keys():
+            logging.debug("Check:"+object)
+            #TODO: object muss duch den namen von provuder geholt werden
+            list=[]
+            for projectID in objects.get(object):
+                list.append(self.getProjectDetails(projectID))
+            
+            ret[object]=list[0:]
+            
+        logging.debug(ret)
+        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.
+        objects.insert([value,value])
+        self.projectObjects.update({projectID:objects})
+        
+       
+        
+        for objectTuple in objects:
+            #hole die abgespeicherten Projekte zu einer Person
+            person=objectTuple[0] #hile die ID
+            
+            
+            if getattr(self,"objects2Projects",None)==None:
+                setattr(self,"objects2Projects",OOBTree())
+         
+            projects = self.objects2Projects.get(person,None)
+                   
+            if projects==None:
+                projects=OOSet();
+            
+            projects.insert(projectID )
+            logging.debug("update:"+person)
+            self.objects2Projects.update({person:projects})
+        
+        
+        
+        retstring = self.getObjectsFromProjectAsHTML(projectID)
+        logging.debug(retstring)
+        
+        
+        
+        return retstring
+    
+    
+    def getProjectsWithTag(self,tagType,tagName):
+        tags = getattr(self,"tags",None)
+        if tags is None:
+            logging.debug("can't find Tags")
+            return []
+    
+        tagsStored=tags.get(tagType,None)
+        if tagsStored is None:
+            logging.debug("can't find Tag:"+tagType)
+            return []
+        
+        projects = tagsStored.get(tagName,None)
+        if projects is None:
+            logging.debug("can't find any projects for Tag:"+tagName+"("+tagType+")")
+            return []
+        
+        ret=[]
+        for project in projects:
+            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')
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/migrateThesaurus.py	Mon Nov 25 08:12:11 2013 +0100
@@ -0,0 +1,178 @@
+import xml.etree.ElementTree as etree
+import web
+
+import urllib2
+import logging
+import urllib
+
+virtuosoServer="http://virtuoso.mpiwg-berlin.mpg.de:8890"
+virtuosoDAV="/DAV/home/websiteuser/"
+virtuosoDAVUser="websiteuser"
+virtuosoDAVPW="w3s45us3"
+virtuosoGraph="file://newpersonsFromProjects"
+   
+
+def callSparql(cmdString):
+        
+        print cmdString
+        auth_handler = urllib2.HTTPBasicAuthHandler()
+        auth_handler.add_password(realm='sparql',
+                          uri=virtuosoServer+"/sparql",
+                          user=virtuosoDAVUser,
+                          passwd=virtuosoDAVPW)
+                          
+        opener = urllib2.build_opener(auth_handler)
+        opener.addheaders = [('Content-Type','application/sparql-query')]
+        
+        logging.debug(cmdString)
+        try:
+            logging.debug(virtuosoServer+"/sparql?" + urllib.urlencode({'query':cmdString,'default-graph-uri':virtuosoGraph,'named-graph-uri':'','format':'text/csv'}))
+            #r= opener.open(virtuosoServer+"/sparql", urllib.urlencode({'query':cmdString,'default-graph-uri':virtuosoGraph,'named-graph-uri':'','format':'text/csv'}))
+            r= opener.open(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
+         
+    
+
+
+fl = file("/usr/local/testzope13/Products/MPIWGThesaurus/examples/ProjectsAndTags.xml")
+dom = etree.parse(fl)
+
+ns = {'fm':'http://www.filemaker.com/fmpdsoresult'}
+
+tagListShort=['spaces','approaches','disciplines','periods','transfers','technologies','objects']
+
+tagList=["{http://www.filemaker.com/fmpdsoresult}"+x for x in tagListShort]
+
+db =web.database(dbn="postgres", user="dwinter", pw="weikiki7",db="personalwww", host="localhost")
+
+
+
+for row in dom.findall(".//fm:ROW",ns):
+    tags={}
+    chds = row.getchildren();
+    for ch in chds:
+        print ch.tag
+        if ch.tag in tagList:
+            
+            
+            if ch.text is not None:
+                tags[ch.tag] = ch.text.split(";")
+            else:
+                tags[ch.tag] = []
+        if ch.tag == '{http://www.filemaker.com/fmpdsoresult}projectId':
+            projectID=ch.text
+            
+            
+
+    for tagTypeLong in tags.keys():
+       
+    
+       for tagName in tags[tagTypeLong]:
+           #suche nach tag order lege an
+           
+           tagType=tagTypeLong.replace('{http://www.filemaker.com/fmpdsoresult}','')
+           if tagType == "objects":
+               tagType ="object"
+           
+           res = db.query("select id from thesaurus_tags where tag_type = $tt and tag_name= $tn",vars={'tt':tagType,'tn':tagName})
+           if len(res)==0:
+               db.insert('thesaurus_tags',tag_type=tagType,tag_name=tagName);
+               res = db.query("select id from thesaurus_tags where tag_type = $tt and tag_name= $tn",vars={'tt':tagType,'tn':tagName})
+       
+       
+           #trage jetzt das projekt ein
+           tagID=res[0].id
+           qsSelect = "select id from thesaurus_projects_tags where project_id = $pi and tag_id= $ti"
+               
+           tag_ids = db.query(qsSelect,vars={'pi':projectID,'ti':tagID})
+               
+           if len (tag_ids) ==  0:
+                           
+                   qs="insert into thesaurus_projects_tags (project_id,tag_id) values ($pi,$ti)"
+               
+                   db.query(qs,vars={'pi':projectID,'ti':tagID})
+               
+                   print qs
+           
+    
+               
+#personen personen getaggte objekte
+# file von http://www.mpiwg-berlin.mpg.de:28080/www/en/research/thesaurus/getPersonsWithProjectIDsJSON
+import json
+
+fl = file('/usr/local/testzope13/Products/MPIWGThesaurus/examples/getPersonsWithProjectIDsJSON')
+personsProjects = json.load(fl)
+
+tagType="person"
+
+for tagName in personsProjects.keys():
+    res = db.query("select id from thesaurus_tags where tag_type = $tt and tag_name= $tn",vars={'tt':tagType,'tn':tagName})
+    if len(res)==0:
+        db.insert('thesaurus_tags',tag_type=tagType,tag_name=tagName);
+        res = db.query("select id from thesaurus_tags where tag_type = $tt and tag_name= $tn",vars={'tt':tagType,'tn':tagName})
+       
+           
+    #trage jetzt das projekt ein
+    tagID=res[0].id
+    
+    for proj in personsProjects.get(tagName):
+        projectID=proj[0]
+    
+        qsSelect = "select id from thesaurus_projects_tags where project_id = $pi and tag_id= $ti"
+           
+        tag_ids = db.query(qsSelect,vars={'pi':projectID,'ti':tagID})
+           
+        if len (tag_ids) ==  0:
+                       
+               qs="insert into thesaurus_projects_tags (project_id,tag_id) values ($pi,$ti)"
+           
+               db.query(qs,vars={'pi':projectID,'ti':tagID})
+           
+               print qs
+
+#finally ad labels:
+
+for tagName in personsProjects.keys():
+    res = db.query("select id from thesaurus_tags where tag_type = $tt and tag_name= $tn",vars={'tt':tagType,'tn':tagName})
+
+    personID=tagName
+    
+    cmdString ="""select * where { <%s> <http://xmlns.com/foaf/0.1/name> ?name}"""%personID
+    
+    names= callSparql(cmdString)
+        
+    cmdString ="""select * where { <%s> <http://xmlns.com/foaf/0.1/lastName> ?name}"""%personID
+    
+    lastName= callSparql(cmdString)
+        
+    cmdString ="""select * where { <%s> <http://xmlns.com/foaf/0.1/firstName> ?name}"""%personID
+    
+    firstName= callSparql(cmdString)
+        
+    if names != '':
+        qs = "update thesaurus_tags set tag_label=$tl where id=$ti"
+        print names
+        db.query(qs,vars={'tl':names.decode('latin-1'), 'ti':res[0].id})
+        
+     
+        
+    
+    
+
+
+       
+
+       
+    
\ No newline at end of file
--- a/zpt/manageMPIWGThesaurus.zpt	Wed Nov 06 15:03:36 2013 +0100
+++ b/zpt/manageMPIWGThesaurus.zpt	Mon Nov 25 08:12:11 2013 +0100
@@ -3,10 +3,6 @@
 <h2>Manage the thesaurus</h2>
 <ul>
 <li><a href="listAllSuggestedTags">Zeige alle vorgeschlagenen Tags</a></li>
-<li><a href="collectPersonNamesToIds">Hole/Update die Namenseintraege aus dem Triplestore, z.B. falls im Triplestore Namem geaendert worden</a></li>
-<li><a href="getPersonsWithProjectIDs?check=bool:True">Hole all Personen mit ProjectIDs, raeumt zu gleich den Cache Persone-->ProjectID auf</a></li>
-<li><a href="rearangePersonIDsHTML">Ordne neue IDs vorhandenen Personen zu, insbesondere ersetze temporaere IDs durch GND oder andere,</a></li>
-<li><a href="getUnifyPersonsList">Ordne GND ids zu, falls bisher IDs aus anderen Kontexten vergeben wurden.</a></li>
 
 <h3>Overview</h3>
 <li><a href="getProjectsAndTagsAsCSV">Uebersicht ueber alle vergebenenen Tags (TAB-getrennte Liste) </a></li>