view MPIWGThesaurus.py @ 17:8e2ddcef1e8d

overviews
author dwinter
date Fri, 27 Jan 2012 14:48:02 +0100
parents f9a65eaaa59c
children 8cbb34593ca9
line wrap: on
line source

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


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


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

#import os
import os.path
import logging
import time
import email.Utils
from types import ListType
import transaction
import random
import urllib2
import urllib
from Ft.Lib.DistExt.ImageHlp import Array
from aetypes import IsType


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 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:
                    
                    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 getProjectsAndTagsTSV(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 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 getEntriesFormatted(self,entries,formatType):
        errorString="<H1>template with name <em>levelFormatted</em> does not exist in the thesaurus folder!"
        if not hasattr(self,'levelFormatted'):
            pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','levelFormatted.zpt')).__of__(self)
            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 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 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,type):
        """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],type,person[0])
            
            
#            ret+="""<div>
#        <input type="checkbox" name="persons_remove"
#         value="%s">
#        <span>%s</span>
#        </div>"""%(person[0],person[1])
#        
        logging.debug(type+":"+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:]
        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)
            ret.append(self.getProjectDetails(project))

        return ret
    
    def getProjectDetails(self,getID):
        project=getattr(self.www_neu.projects,getID,None)
        if project is None:
            logging.debug("no project!! " +getID)
            return
        
        link="/en/research/projects/"+getID
        
        title=project.getContent("short_title")
        #persons=project.getPersonKeyList()
        persons=project.getContent('xdata_01')
        logging.debug("%s %s %s"%(link,title,persons))
        return link,title,persons
    
#        $.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')