source: lliurex-abies2pmb/trunk/fuentes/lliurex-abies2pmb-core.install/abies2pmb.py @ 4167

Last change on this file since 4167 was 4167, checked in by Juanma, 3 years ago

Added tmp workdir for csv tables generation

  • Property svn:executable set to *
File size: 15.7 KB
Line 
1#!/usr/bin/python3
2import os
3import datetime
4import subprocess
5import sys
6import tempfile
7# -*- coding: utf-8 -*-
8class abiesToPmb():
9        def __init__(self,mdbFile):
10                self.dbg=0
11               
12                #Dict with relations between pmb and abies
13                self.pmb_abies={}
14                self.pmb_abies["empr_categ"]=["TiposLector"]
15                self.pmb_abies["docs_location"]=["Ubicaciones"]
16                self.pmb_abies["authors"]=["Autores"]
17                self.pmb_abies["exemplaires"]=["Ejemplares"]
18                self.pmb_abies["notices"]=["Fondos"]
19                self.pmb_abies["collections"]=["Series"]
20                self.pmb_abies["notices_langues"]=["Fondos-Idiomas"]
21                self.pmb_abies["publishers"]=["Editoriales"]
22                self.pmb_abies["groupe"]=["Cursos"]
23                self.pmb_abies["indexint"]=["CDUs"]
24                self.pmb_abies["notices_tmp"]=["Fondos_all"]
25
26                #Blacklist pmb_abies tables.
27                self.blacklist=['notices_tmp']
28
29                #Dict with abies source fields for pmb
30                #Numbers are the indexes of the source data table
31                self.pmb_tables={}
32                self.pmb_tables["docs_location"]=[0,1,'','','','','','','','','','','','','','','','','','','','','','','']
33                self.pmb_tables["empr_categ"]=[0,1,'','','','']
34                self.pmb_tables["authors"]=[0,1,2,'','','','','','','','','','','','']
35                self.pmb_tables["publishers"]=[0,1,'','','','','','','','']
36                self.pmb_tables["groupe"]=[0,1,'','','','']
37                self.pmb_tables["exemplaires"]=[0,4,1,'','',13,'','',6,'','','','','','','','',9,'','','','','','','','','']
38                self.pmb_tables["collections"]=[0,1,'','','','','','']
39                self.pmb_tables["indexint"]=[0,1,'','','']
40                self.pmb_tables["notices_tmp"]=[0,1,2]
41                self.pmb_tables["notices"]=[0,1,14,15,16,13,'','',19,'',24,'',20,17,25,11,21,22,'',23,'','','','','',26,'','','','','','','','','','','','','','',6,'','','','','','','','','','','','','','']
42
43                #dict with needed virtual tables
44                #Only load one column using a 'get', any other column must be charged with formatTables or formatFields
45                self.virtual_tables={}
46                self.virtual_tables["CDUs"]={}
47                self.virtual_tables["CDUs"].update({'index 0':''})
48                self.virtual_tables["CDUs"].update({'index 1':'get Fondos_CDUs.1'})
49                self.virtual_tables['Series']={}
50                self.virtual_tables['Series'].update({'index 0':''})
51                self.virtual_tables['Series'].update({'index 1':'get Fondos.24'})
52                self.virtual_tables['Fondos_all']={'index 0':'get Fondos.0'}
53                self.virtual_tables['Fondos_all'].update({'index 1':''})
54                self.virtual_tables['Fondos_all'].update({'index 2':''})
55
56                #Dict whith field transformations
57                self.formatFields={}
58                self.formatFields['TiposLector']={'index 0':'add index 0 7'}
59                self.formatFields['Autores']={'index 1':'value 100=70,value 110=71,value 120=72,value 700=70'}
60                self.formatFields['Ejemplares']={'index 13':'concat 13,14,15'}
61                self.formatFields['Ejemplares'].update({'index 9':'date %m/%d/%y %H:%M:%S %Y-%m-%d %H:%M:%S'})
62                self.formatFields['CDUs']={'index 0':'inc 1 1000'}
63                self.formatFields['Series']={'index 0':'inc 1 1000'}
64                self.formatFields['Fondos']={'index 1':'value 1="a",value 2="g",value 3="m",value4="j",value 5="k",value 6="a",value 7="l"'}
65                self.formatFields['Fondos'].update({'index 13':'from Autores.2 on 13=0'})
66                self.formatFields['Fondos'].update({'index 24':'from Series.0 on 24=0'})
67                self.formatFields['Fondos'].update({'index 26':'from Fondos_all.2 on 0=1'})
68                self.formatFields['Fondos_all']={'index 2':'from CDUs.0 on 0=1'}
69
70                #Dict whith special columns
71                self.formatTables={}
72                self.formatTables['CDUs']={'index 1':'uniq'}
73                self.formatTables['Series']={'index 1':'uniq'}
74                self.formatTables['Fondos_all']={'index 1':'from Fondos_CDUs.1 on 0=0'}
75
76                #Dict with temp results
77                self.pmb_result={}
78
79                #Array with process order
80                self.executionOrder=['Ubicaciones','TiposLector','Autores','Editoriales','Cursos','Ejemplares','Series','CDUs','Fondos_all','Fondos']
81                #Tmp variables
82                self.workDir='/tmp/.abiesToPmb/'
83                self.tmpTableDict={}
84                self.tableValuesDict={}
85                self.tmpInc=0
86                #Mdb file
87                self.mdb=mdbFile
88        #def _init
89
90        def _debug(self,msg):
91                if self.dbg:
92                        print('Migrator: '+str(msg))
93        #def _debug
94
95        def _error(self,e):
96                print(str(e))
97        #def _error
98
99        ###
100        #Process array executionOrder
101        ###
102        def beginMigration(self):
103                returnValue=False
104                if self.exportMdb():
105                        for abiesTable in self.executionOrder:
106                                self.tmpInc=0
107                                self._debug("Processing "+abiesTable)
108                                self._loadTable(abiesTable)
109                                pmbTable=self._getTableEquivalence(abiesTable)
110                                self._generateSql(pmbTable,abiesTable)
111                        returnValue=True
112                        self._debug("Files generated for tables "+str(self.executionOrder))
113                return returnValue
114        #def beginMigration
115
116        def exportMdb(self):
117                returnValue=None
118                if os.path.exists(self.mdb):
119                        try:
120                                cmdOut=subprocess.check_output(['mdb-tables',self.mdb],universal_newlines=True)
121                                if cmdOut:
122                                        self.workDir=tempfile.mkdtemp()+"/"
123                                        tables=cmdOut.strip("\n")
124                                        listTables=tables.split(' ')
125                                        for table in listTables:
126                                                if table!='':
127                                                        cmdOut=subprocess.check_output(['mdb-export','-H','-d|||',self.mdb,table],universal_newlines=True)
128                                                        if cmdOut:
129                                                                f=open (self.workDir+table+".csv",'w')
130                                                                f.writelines(cmdOut)
131                                                                f.close()
132                                returnValue=True
133                        except Exception as e:
134                                self._error(e)
135                                returnValue=False
136                return returnValue
137        #def exportMdb
138
139        ###
140        #Generates the sql
141        #Input: pmb tableName
142        #Output: Array of sql sentences
143        ###
144        def _generateSql(self,destTable,abiesTable):
145                transformDict=self._checkTransformField(abiesTable)
146                origData=self.tableValuesDict[abiesTable]
147                fileName=destTable+".sql"
148                if destTable not in self.blacklist:
149                        f=open (fileName,'w')
150                for line in origData:
151                        strInsertValues=''
152                        for index in self.pmb_tables[destTable]:
153                                if index!='':
154                                        if transformDict:
155                                                if index in transformDict.keys():
156                                                        strTransform=transformDict[index]
157#                                                       self._debug("Transforming value "+str(line[index])+" index "+str(index)+" with "+strTransform)
158                                                        line[index]=eval(strTransform)
159                                        tmp=str(line[index]).strip("\n")
160                                        #Clean tmp field
161                                        tmp=tmp.replace('"',' ')
162                                        try:
163                                                int(tmp)
164                                        except:
165                                                tmp=tmp.lstrip(' ')
166                                                tmp=tmp.rstrip(' ')
167                                                tmp='"'+tmp+'"'
168                                                pass
169                                else:
170                                        tmp='""'
171                                strInsertValues=strInsertValues+tmp+','
172                        strInsertValues=strInsertValues[:-1]
173                        if destTable not in self.blacklist:
174                                f.write("Insert into "+destTable+" values ("+strInsertValues+");\n")
175                if destTable not in self.blacklist:
176                        f.close()
177        #def _generateSql
178
179        ###
180        #Loads a table from a file or a virtual table from a bunch of tables
181        #Input: Table name
182        ###
183        def _loadTable(self,tableName):
184                fileName=self.workDir+tableName+'.csv'
185                data=[]
186                if os.path.exists(fileName):
187                        try:
188                                f=open(fileName,'r')
189                                lines=f.readlines()
190                                f.close()
191                                for line in lines:
192                                        array=line.split('|||')
193                                        data.append(array)
194                        except Exception as e:
195                                self._error(e)
196                else: #Check in virtual dict
197                        if tableName in self.virtual_tables.keys():
198                                data=self._loadVirtualTable(tableName)
199                        else:
200                                self._error("Table "+tableName+" not found")
201
202                self.tableValuesDict[tableName]=data
203                if tableName in self.formatTables.keys():
204                        self.tableValuesDict[tableName]=self._checkTransformTables(tableName)
205        #def _loadTable
206
207        ###
208        #Loads a virtual table as described by virtual table's dict
209        #Input: Table name
210        #Output: Dataset (array of arrays) with the virtual table
211        ###
212        def _loadVirtualTable(self,tableName):
213                self._debug("Loading virtual table "+tableName)
214                data=[]
215                dataDict={}
216                if tableName in self.virtual_tables.keys():
217                        proceed=False
218                        for key,line in self.virtual_tables[tableName].items():
219#                               print (s)ourceData)
220#                               for key,line in sourceData.items():
221                                        if line.startswith('get'):
222                                                proceed=True
223                                                sourceIndex=key.split(' ')[1]
224                                                getFrom=line.split(' ')[1]
225                                                sourceIndex=getFrom.split('.')[1]
226                                                sourceTable=getFrom.split('.')[0]
227                                                dataDict[key]=self._funcGetValueFromTable(sourceTable,sourceIndex)
228                        if proceed:
229                                #Data is charged on the dataDict, time to populate data array
230                                maxLen=0
231                                for key in dataDict.keys():
232                                        columnLen=len(dataDict[key])
233                                        if columnLen>maxLen:
234                                                maxLen=columnLen
235                                index=0
236                                while index<maxLen:
237                                        dataLine=[]
238                                        for key in self.virtual_tables[tableName].keys():
239                                                arrayIndex=int(key.split(' ')[-1])
240                                                if key in dataDict.keys():
241                                                        dataLine.insert(arrayIndex,dataDict[key][index])
242                                                else:
243                                                        dataLine.insert(arrayIndex,'')
244                                        data.append(dataLine)
245                                        index=index+1
246                else:
247                        self._error("No source for virtual table "+tableName)
248                return(data)
249
250        ###
251        #Finds the pmb table related with an abies table
252        #Input: Table name in abies
253        #Output: pmb table
254        ###
255        def _getTableEquivalence(self,tableName):
256                pmbTable=None
257                for key in self.pmb_abies.keys():
258                        if tableName in self.pmb_abies[key]:
259                                pmbTable=key
260                                break
261                return pmbTable
262        #def _getTableEquivalence
263
264        ###
265        #Check if there's any transformation to apply to the fields of a table
266        #Input: Abies table name
267        #Output: Dict with field indexes as keys and transformations to apply as values
268        def     _checkTransformField(self,abiesTable):
269                transformDict={}
270                if abiesTable in self.formatFields.keys():
271                        transform=self.formatFields[abiesTable]
272                        self._debug("Transforming fields "+str(transform)+" in "+abiesTable)
273                        for key,line in transform.items():
274                                index=int(key.split(' ')[-1])
275                                if line.startswith('add'):
276                                        transformDict[index]=self._transformAdd(line,index)
277                                elif line.startswith('value'):
278                                        transformDict[index]=self._transformValue(line,index)
279                                elif line.startswith('concat'):
280                                        transformDict[index]=self._transformConcat(line,index)
281                                elif line.startswith('date'):
282                                        transformDict[index]=self._transformDate(line,index)
283                                elif line.startswith('inc'):
284                                        transformDict[index]=self._transformInc(line,index)
285                                elif line.startswith('get'):
286                                        transformDict[index]=self._transformGet(line,index)
287                                elif line.startswith('from'):
288                                        transformDict[index]=self._transformQuery(line,index,abiesTable)
289
290                self._debug("TransformDict: "+str(transformDict))
291                return transformDict
292        #def _checkTransformField
293
294        ###
295        #Transform routines, self-explaining
296        ###
297        def _transformAdd(self,line,index):
298                sourceIndex=line.split(' ')[1]
299                increment=line.split(' ')[-1]
300                returnValue='int(line['+sourceIndex+'])+'+increment
301                return(returnValue)
302
303        def _transformValue(self,line,index):
304                values=line.split(',')
305                tmpStr=''
306                for value in values:
307                        relation=value.split('=')
308                        sourceValue=relation[0].split(' ')[-1]
309                        destValue=relation[-1]
310                        tmpStr=tmpStr+str(destValue)+' if line['+str(index)+']=="'+str(sourceValue)+'" else '
311                try:
312                        int(destValue)
313                        returnValue='('+tmpStr+ '"'+str(destValue)+'")'
314                except:
315                        returnValue='('+tmpStr+ ''+str(destValue)+')'
316                return(returnValue)
317
318        def _transformConcat(self,line,index):
319                concat=line.split(' ')[-1]
320                concatArray=concat.split(',')
321                tmpStr=''
322                for concatField in concatArray:
323                        tmpStr=tmpStr+'line['+str(concatField)+']+'
324                returnValue=tmpStr[:-1]
325                return(returnValue)
326
327        def _transformDate(self,line,index):
328                dates=line.split(' ')
329                sourceFormat=dates[1]+' '+dates[2]
330                destFormat=dates[3]+' '+dates[4]
331                returnValue='self._funcDateTransform(line['+str(index)+'],"'+sourceFormat+'","'+destFormat+'")'
332                return(returnValue)
333
334        def _funcDateTransform(self,date,origFormat,destFormat):
335                date=date.replace('"','')
336                destFormat=destFormat.replace('"','')
337                returnValue=(datetime.datetime.strptime(date, origFormat).strftime(destFormat))
338                return(returnValue)
339               
340        def _transformInc(self,line,index):
341                increment=line.split(' ')
342                inc=increment[1]
343                base=0
344                if len(increment)==3:
345                        base=int(increment[2])
346                if self.tmpInc<base:
347                        self.tmpInc=base
348                returnValue='self._funcIncrementField('+inc+')'
349                return(returnValue)
350        ###
351        #Some values need a special transformation that requires a helper function.
352        #Those helper functions are the _func...
353        ###
354        def _funcIncrementField(self,inc):
355                self.tmpInc=self.tmpInc+int(inc)
356                returnValue=self.tmpInc
357                return(returnValue)
358
359        def _transformGet(self,line,index):
360                getFrom=line.split(' ')[-1]
361                getFromTable=getFrom.split('.')[0]
362                getFromIndex=getFrom.split('.')[-1]
363                returnValue='self._funcGetValueFromTable('+getFromTable+','+getFromIndex+')'
364                return(returnValue)
365
366        def _funcGetValueFromTable(self,table,index):
367                fileName=self.workDir+table+'.csv'
368                data=[]
369                index=int(index)
370                if os.path.exists(fileName):
371                        try:
372                                f=open(fileName,'r')
373                                lines=f.readlines()
374                                f.close()
375                                for line in lines:
376                                        array=line.split('|||')
377                                        data.append(array[index])
378                        except Exception as e:
379                                self._error(e)
380                else:
381                        self._error("No source table "+fileName+" available")
382                return(data)
383
384        def _transformQuery(self,line,index,tableName):
385                self._debug("Join field "+line)
386                transformDict=[]
387                arrayLine=line.split(' ')
388                sourceTableField=arrayLine[1]
389                joinFromTo=arrayLine[-1]
390                sourceTable=sourceTableField.split('.')[0]
391                sourceField=int(sourceTableField.split('.')[1])
392                joinFrom=joinFromTo.split('=')[0]
393                joinTo=joinFromTo.split('=')[1]
394                returnValue='self._funcGetValueFromQuery("'+tableName+'","'+sourceTable+'",line['+str(joinFrom)+'],'+str(joinTo)+','+str(sourceField)+')'
395                return(returnValue)
396
397        def _funcGetValueFromQuery(self,abiesTable,sourceTable,valueFrom,fieldTo,reqFieldIndex):
398                returnValue=''
399                valueFrom=valueFrom.strip("\n")
400                if sourceTable not in self.tableValuesDict:
401                        self._loadTable(sourceTable)
402                for row in self.tableValuesDict[sourceTable]:
403                                #                       print ("Comparing "+str(valueFrom)+" with "+str(row[fieldTo]))
404                        if valueFrom==str(row[fieldTo]).strip("\n"):
405                                returnValue=row[reqFieldIndex]
406                                break
407                return returnValue
408        #Transform fields functions
409
410        ###
411        #Check if there's any Transform to apply to a whole table
412        #Input: abies table
413        #Output: Dataset with the table
414        ###
415        def _checkTransformTables(self,tableName):
416                transformDict={}
417                if tableName in self.formatTables.keys():
418                        transform=self.formatTables[tableName]
419                        for key,line in transform.items():
420                                index=int(key.split(' ')[-1])
421                                if line.startswith('uniq'):
422                                        transformDict=self._transformTableUniq(tableName,index)
423                                if line.startswith('from'):
424                                        transformDict=self._transformTableJoin(tableName,index,line)
425                return transformDict
426        #def _checkTransformTamble
427
428        ###
429        #Function helpers for table transformation. Self-explaining
430        ###
431        def _transformTableUniq(self,tableName,index):
432                self._debug("Uniq items from index "+str(index))
433                transformDict=[]
434                for item in self.tableValuesDict[tableName]:
435                        if item not in transformDict:
436                                transformDict.append(item)
437                return transformDict
438
439        def _transformTableJoin(self,tableName,index,line):
440                self._debug("Join "+line)
441                transformDict=[]
442                arrayLine=line.split(' ')
443                sourceTableField=arrayLine[1]
444                joinFromTo=arrayLine[-1]
445                sourceTable=sourceTableField.split('.')[0]
446                sourceField=int(sourceTableField.split('.')[1])
447                joinFrom=joinFromTo.split('=')[0]
448                joinTo=joinFromTo.split('=')[1]
449                if sourceTable not in self.tableValuesDict:
450                        self._loadTable(sourceTable)
451                #Generate a dict with joinTo as index and required field as value
452                tmpDict={}
453                tmpIndex=int(joinTo)
454                for row in self.tableValuesDict[sourceTable]:
455                        rowIndex=row[tmpIndex]
456                        rowValue=row[sourceField]
457                        tmpDict.update({rowIndex:rowValue})
458
459                #Walk through origin table and insert values from sourceTableDict
460                tmpIndex=int(joinFrom)
461                for row in self.tableValuesDict[tableName]:
462                        rowIndex=row[tmpIndex]
463                        if rowIndex in tmpDict:
464                                row.insert(tmpIndex,tmpDict[rowIndex])
465                        else:
466                                row.insert(tmpIndex,'')
467                        transformDict.append(row)
468                return transformDict
469        #Table transformation function helpers
470
471### MAIN PROGRAM ###
472
473migration=abiesToPmb(sys.argv[1])
474result=migration.beginMigration()
475print(result)
476
477
478'''                             #-------------------#
479#Abrimos fichero csv
480#FICHERO se alimenta desde el array de ficheros
481f=open("TiposLector.csv","r")
482#Cargamos el array
483array=f.readlines()
484#Recorremos
485x=0
486#Diccionario nombre_tabla_pmb->array con inserts
487dictResult={"empr_categ":[]}
488for line in array:
489        campos=line.split('|||')
490        x=x+1
491        if x==1:
492                pass
493        else:
494                dictResult['empr_categ'].append('insert into empr_categ values('+campos[0]+','+campos[1])
495
496print (dictResult)
497'''
498
Note: See TracBrowser for help on using the repository browser.