#!c:\Program Files\Python39\python.exe
# -*- coding: UTF-8 -*-
'''
$RCSfile: datasource.py,v $
$Revision$
$Author: markus $
$Date$
'''
import os.path, sys, time
# ***** include the biocase.lib directory in the python sys path for importing *****
exec(open(os.path.abspath(os.path.join(os.path.dirname(__file__), os.path.pardir, os.path.pardir, 'lib', 'biocase', 'adjustpath.py'))).read())
exec(open(os.path.abspath(os.path.join(os.path.dirname(__file__), os.path.pardir, os.path.pardir, 'lib', 'biocase', 'appinit.py'))).read())
from biocase.archive.general import inventory_summary, DWCA_SCHEMA_NAME
from biocase.configtool.general import dsaObj, form, dsa, templateDir, log, authorize, action, printOverHTTP
from biocase.configtool.cmfupgrade import cmfUpgrade
from biocase.datasources import Datasource
from biocase.tools.templating import PageMacro
from biocase.tools.htmltools import getDropDownOptionHtml
from biocase.cmfinfo import CMFTemplateListClass
from biocase import __version__
import biocase.configuration
cfg = biocase.configuration.Cfg()
############################################################################################################
#
# MAIN
#
#===========================================================================================================
# check authentication!
if dsaObj is None:
exec(compile(open(os.path.abspath(os.path.join(os.path.dirname(__file__), 'main.cgi')), "rb").read(), os.path.abspath(os.path.join(os.path.dirname(__file__), 'main.cgi')), 'exec'))
sys.exit()
# check authentication!
authorize(form, dsa=dsa)
# use the datasource.html template to get datasource overview
tmpl = PageMacro('Content', PageMacro.DELMODE)
tmpl.load('Content', os.path.join(templateDir, '_datasource.html'))
# PSF
psfObj = dsaObj.getPSFObj(tmp=False)
# upgrade object
upgradeObj = cmfUpgrade()
# Indicate whether a mapping has been removed or recyled
# Required to trigger PSF update later
recyclingOperation = False
def del_schema(schema, dsaObj):
old = os.path.join(dsaObj.getDsaDir(), schema)
new = dsaObj.getBakFileName(schema)
log.debug("Removing CMF %s from datasource" % old)
if os.path.isfile(new):
os.unlink(new)
os.rename(old, new)
#
# ACTIONS
#
if action == 'del':
# "remove" CMF. renames it to a backup file name (= recycle bin), from which it can be restored later
schema = form.getfirst('schema', None)
del_schema(schema, dsaObj)
# refresh dsaObj
dsaObj = Datasource(name=dsa)
recyclingOperation = True
elif action == 'transfer':
# upgrade an existing cmf
oldCmf = os.path.join(dsaObj.getDsaDir(), form.getfirst('schema', None))
newSchema = 'cmf_' + form.getfirst('targetschema') + '.xml'
newCmfObj, missingConcepts, upgradeTuple = upgradeObj.getUpgradedCmfObj(oldCmf, newSchema)
if newCmfObj is None:
log.error("ERROR ! CMF could not be upgraded. Unknown error")
else:
newCmf = os.path.join(dsaObj.getDsaDir(), upgradeTuple[0])
# Check whether there is already a cmf for that schema
existingCmf = dsaObj.getSchemaListObj().getSchemaByNS(newCmfObj.rootCMFElementObj.Namespace)
if existingCmf is not None:
tmpl['updateHint'] = "alert('INFO: A mapping file with the same namespace as the selected schema was already existent (" + existingCmf.name + "). It has been put into the recyling bin if you change your mind.');"
del_schema('cmf_' + existingCmf.name, dsaObj)
newCmfObj.writeCMF(newCmf)
# refresh dsaObj
dsaObj = Datasource(name=dsa)
elif action == 'restore':
schemaFile = form.getfirst('schemafile', None)
schema = schemaFile[5:-8]
old = os.path.join(dsaObj.getDsaDir(), schemaFile)
new = os.path.join(dsaObj.getDsaDir(), "cmf_" + schema)
if os.path.isfile(new):
tmpl['restoreError'] = "alert('A " + schema + " schema is already active. Please remove it first if you want to restore the " + schemaFile + " file');"
else:
os.rename(old, new)
# refresh dsaObj
dsaObj = Datasource(name=dsa)
recyclingOperation = True
elif action == 'purge':
# "purge" CMF.
schemaFile = os.path.join(dsaObj.getDsaDir(), form.getfirst('schemafile', None))
os.unlink(schemaFile)
#
# FILL TEMPLATE
#
# general
tmpl['dsa'] = dsa
tmpl['wrapper_url'] = dsaObj.getBioCASeAccessPoint()
tmpl['ServiceTitle'] = 'BioCASe Provider Software %s' % __version__
# dbconnection status
tmpl['status'] = dsaObj.getDBConnectionStatus()
# number of aliases in PSF
tmpl['num_ta'] = str(len(psfObj.getTableAliasList()))
# list of dsa schemas
slObj = dsaObj.getSchemaListObj()
log.debug("DSA CMFList: %s" % str(slObj))
# list of duplicate dsa schemas with the same NS
origSchemas = {}
duplicateList = []
for sObj in slObj:
if sObj.NS in origSchemas:
duplicateList.append({'schema': sObj.name, 'schemaorig': origSchemas[sObj.NS].name})
else:
origSchemas[sObj.NS] = sObj
tmpl.expand('Content', 'schemaduplicatelist', duplicateList)
#archive
dldPath = os.path.join(cfg.archiveDownloadLocator, dsa)
archivePath = os.path.join(cfg.archiveWorkLocator, dsa)
if not os.path.exists(archivePath):
os.makedirs(archivePath)
if not os.path.exists(dldPath):
os.makedirs(dldPath)
archives = inventory_summary(dsaObj)
# create existing cmf schema list...
DsaSchemaList = []
for sObj in slObj:
entry = {}
entry['schema'] = sObj.name
entry['schema_file'] = os.path.split(sObj.file)[1]
entry['namespace'] = sObj.NS
entry['num_mappings'] = str(sObj.mappings)
entry['num_concepts'] = str(sObj.concepts)
entry['schemalist.upgrades'] = [{'ns': t[0], 'targetschema': t[1][4:-4]} for t in upgradeObj.listPossibleUpgradeTuples(sObj.NS) if t[1][4:] != sObj.name]
if len(entry['schemalist.upgrades']) == 0:
entry['supress_upgrade_start'] = ''
else:
entry['supress_upgrade_start'] = ''
entry['supress_upgrade_end'] = ''
a = archives.get(sObj.name[:-4])
if a is None:
entry['a_hide_s'] = ""
else:
entry['a_hide_s'] = ""
entry['a_hide_e'] = ""
entry['archive_cnt'] = a[0]
entry['archive_mod'] = a[1]
DsaSchemaList.append(entry)
tmpl.expand('Content', 'schemalist', DsaSchemaList)
# UPDATE PSF WITH THESE SCHEMAS ?
CmfUpdates = [sObj.getLastUpdated() for sObj in slObj if sObj is not None]
if recyclingOperation or (len(CmfUpdates) > 0):
if len(CmfUpdates) > 0:
lastCMFupdate = max(CmfUpdates)
else:
lastCMFupdate = None
psfUpdate = psfObj.getPSFUpdatedWhen()
if recyclingOperation or (lastCMFupdate > psfUpdate):
log.debug("Need to update PSF with CMF list. Last PSF update at %s, last CMF update %s" % (str(psfUpdate), str(lastCMFupdate)))
psfObj.delAllSchemas()
for sObj in slObj:
psfObj.addSchema(sObj.NS, sObj.file)
psfObj.writePSFile()
else:
log.debug("No need to update PSF with CMF list. Last PSF update at %s, last CMF update %s" % (str(psfUpdate), str(lastCMFupdate)))
else:
log.debug("No CMFs found. PSF will not be updated")
# list of cmf templates
tmplSlObj = slObj
tmplSlObj = CMFTemplateListClass()
log.debug("Full Template CMFList: %s" % str(tmplSlObj))
# dont show already configured schemas. Do NOT remove schemas with the same namespace, as this might be confusing for the user
for sObj in slObj:
tmplSlObj.removeSchema(name=sObj.name)
dropDown = getDropDownOptionHtml(dict([('--select--', '--select--')] + [(sObj.name, os.path.split(sObj.file)[1])for sObj in tmplSlObj]), '--select--')
tmpl['newschema_options'] = dropDown
# recycle bin
deletedSchemas = dsaObj.getDeletedSchemaListObj()
DsaDeletedSchemaList = []
for ds in deletedSchemas:
s = {}
s['deletedschema'] = ds.name
s['schema_file'] = os.path.split(ds.file)[1]
s['modtime'] = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(os.path.getmtime(ds.file)))
s['num_mappings'] = str(ds.mappings)
s['num_concepts'] = str(ds.concepts)
# if schema with the same NS is already existing, don't allow restoring
if ds.NS in origSchemas:
s['restore'] = ''
else:
s['restore'] = 'Restore'
DsaDeletedSchemaList.append(s)
tmpl.expand('Content', 'recycle', DsaDeletedSchemaList)
if len(DsaDeletedSchemaList) == 0:
tmpl['recycleBinEmptyMessage'] = "Recycle bin is empty."
tmpl['hideRecycleBinStart'] = ""
# Last, DwCA
a = archives.get(DWCA_SCHEMA_NAME)
if a is None:
tmpl['dwca_message'] = "No DarwinCore archives created so far."
else:
tmpl['dwca_message'] = "%s DarwinCore archive(s) for this schema, last modified %s." % (a[0], a[1])
#
# print HTML !
#
printOverHTTP(tmpl)