#!/usr/bin/python3
# -*- coding: utf-8 -*-
from lxml import etree
from xml.sax.expatreader import AttributesImpl
import sys, urllib
objectTypes = dict();
dataTypes = dict();
primitiveTypes = dict();
imports = dict();
parsedImports = dict();
nbPassOnRoot= 0;
rootObjectId = None
indent = 1;
print("==============")
class vodmlObjectType:
def __init__(self, vomdlid, name, superclass, attributes):
self.vodmlid = vomdlid
self.name = name
self.superclass = superclass
self.attributes = attributes
def __str__(self):
retour = "OBJECT "
if self.superclass != '':
retour += "(extends " + self.superclass + ") "
retour += self.name + " " + self.vodmlid +"\n"
for attribute in self.attributes:
retour += attribute.__str__()
return retour
def __repr__(self):
return self.__str__()
class vodmlDataType:
def __init__(self, vodmlid, name, ref, attributes):
self.vodmlid = vodmlid
self.ref = ref
self.name = name
self.attributes = attributes
def __str__(self):
retour = "DATATYPE " + self.name + " " + self.vodmlid + " " + self.ref +"\n"
for attribute in self.attributes:
retour += attribute.__str__()
return retour
def __repr__(self):
retour = "DATATYPE " + self.name + " " + self.vodmlid + " " + self.ref +"\n"
for attribute in self.attributes:
retour += attribute.__str__()
return retour
class vodmlAttribute:
def __init__(self, vomdlid, name, datatype, arraySize):
self.vodmlid = vomdlid
self.name = name
self.datatype = datatype
self.arraySize = arraySize
def __str__(self):
retour = "ATTRIBUTE "
retour += "(arraySize " + str(self.arraySize) + ") "
retour += self.name + " " + self.vodmlid +"\n"
retour += self.datatype.__str__()
return retour
def __repr__(self):
return self.__str__()
class vodmlImport:
def __init__(self, name, url):
self.name = name
self.url = url
def __str__(self):
retour = "IMPORT " + self.name + " " + self.url +"\n"
return retour
def __repr__(self):
retour = "IMPORT " + self.name + " " + self.url +"\n"
return retour
def readPackage(modelName, packageNode):
if packageNode.tag == 'package':
packageName = packageNode.find("name").text
print (">>>>>>>>>> PACKAGE " + packageName)
for child in packageNode.findall('*'):
if child.tag == "objectType":
ot = readObjectType(modelName, child)
logMsg("ADD OBJECT " , ot.vodmlid)
objectTypes[ot.vodmlid] = ot
elif child.tag == 'primitiveType' or child.tag == 'enumeration':
dt = readDataType(modelName, child)
logMsg("ADD TYPE " , dt.vodmlid)
primitiveTypes[dt.vodmlid] = dt
elif child.tag == "dataType" :
ot = readDataType(modelName, child)
logMsg("ADD DATA " , ot.vodmlid)
dataTypes[ot.vodmlid] = ot
elif child.tag == 'package':
readPackage(modelName, child)
def readDataType(modelName,datatypeTag):
vodmlid = ''
name = ''
ref = ''
attributes = []
for datatypeTagChild in datatypeTag.findall('*'):
if datatypeTagChild.tag == "vodml-id":
vodmlid = modelName + ":" + datatypeTagChild.text
elif datatypeTagChild.tag == "name":
name = datatypeTagChild.text
elif datatypeTagChild.tag == "vodml-ref":
ref = datatypeTagChild.text
elif datatypeTagChild.tag == "constraint":
pass
# attributes.append(readConstraint(modelName,datatypeTagChild))
elif datatypeTagChild.tag == "attribute":
attributes.append(readAttribute(modelName,datatypeTagChild))
elif datatypeTagChild.tag == "reference":
attributes.append(readReference(modelName,datatypeTagChild))
return vodmlDataType(vodmlid, name, ref, attributes)
def readAttribute(modelName,attributeTag):
dataType = ''
arraySize = 2
for attributeTagChild in attributeTag.findall('*'):
if attributeTagChild.tag == "vodml-id":
vodmlid = modelName + ":" + attributeTagChild.text
elif attributeTagChild.tag == "name":
name = attributeTagChild.text
elif attributeTagChild.tag == "multiplicity":
for multiplicityTagChild in attributeTagChild.findall('maxOccurs'):
arraySize = int(multiplicityTagChild.text)
elif attributeTagChild.tag == "datatype" or attributeTagChild.tag == 'reference':
dataType = readDataType(modelName,attributeTagChild)
return vodmlAttribute(vodmlid, name, dataType, arraySize)
def readReference(modelName,ReferenceTag):
for ReferenceTagChild in ReferenceTag.findall('*'):
if ReferenceTagChild.tag == "vodml-id":
vodmlid = modelName + ":" + ReferenceTagChild.text
elif ReferenceTagChild.tag == "name":
name = ReferenceTagChild.text
elif ReferenceTagChild.tag == "datatype":
dataType = readDataType(modelName,ReferenceTagChild)
return vodmlAttribute(vodmlid, name, dataType, 1)
def readObjectType(modelName, objectTypeTag):
attributes = []
superclass = ''
for objectTypeChild in objectTypeTag.findall('*'):
if objectTypeChild.tag == "vodml-id":
vodmlid = modelName + ":" + objectTypeChild.text
elif objectTypeChild.tag == "name":
name = objectTypeChild.text
elif objectTypeChild.tag == "composition":
for multiplicityTagChild in objectTypeChild.findall('maxOccurs'):
arraySize = int(multiplicityTagChild.text)
att = readAttribute(modelName,objectTypeChild)
attributes.append(att)
elif objectTypeChild.tag == "extends":
for superTypeChild in objectTypeChild.findall('vodml-ref'):
superclass = superTypeChild.text
break
elif objectTypeChild.tag == "attribute":
attributes.append(readAttribute(modelName,objectTypeChild))
elif objectTypeChild.tag == "reference":
attributes.append(readReference(modelName,objectTypeChild))
obj = vodmlObjectType(vodmlid, name, superclass, attributes)
return obj
''' if vodmlid.endswith('PolarizationSpace'):
print( obj)
print( "EXIT")
sys.exit()
'''
def parseVodmlFile(filename='', model=None):
print( "Reading FILE " + filename + " for model ", model)
if filename.startswith("http://") or filename.startswith("https://") :
tree = etree.ElementTree(file=urllib.request.urlopen(filename))
else :
tree = etree.parse(filename)
root = tree.getroot()
ns = {"vo-dml": "http://www.ivoa.net/xml/VODML/v1"}
if model == None:
modelName = root.find("name").text
else :
modelName = model
print( "PARSE FILE " + filename + " for model ", model)
for node in tree.xpath("import"):
name = node.find('name').text
url = node.find('url').text
if not name in imports:
# Let's take the import name as VODML prefix
modelName = name
print ("PARSE IMPORT " + name)
parseVodmlFile(filename=url, model=modelName)
print ("END PARSE " + name)
imports[name]=url
if model == None:
modelName = root.find("name").text
else :
modelName = model
print (model , " " , modelName)
for node in tree.xpath("*"):
if node.tag == 'package':
readPackage(modelName, node)
elif node.tag == 'primitiveType' or node.tag == 'enumeration':
dt = readDataType(modelName, node)
logMsg("ADD TYPE " , dt.vodmlid)
primitiveTypes[dt.vodmlid] = dt
elif node.tag == 'dataType' or node.tag == 'reference':
dt = readDataType(modelName, node)
logMsg("ADD DATA " , dt.vodmlid)
dataTypes[dt.vodmlid] = dt
elif node.tag == 'objectType':
dt = readObjectType(modelName, node)
logMsg("ADD OBJECT " , dt.vodmlid)
objectTypes[dt.vodmlid] = dt
def generateSingleAttributeMapping(attribute):
ref = attribute.datatype.ref
if ref in primitiveTypes:
appendOuput( "")
appendOuput( "")
elif ref in dataTypes :
dt = dataTypes[ref]
generateDataMapping(dt, attribute.vodmlid, attribute.arraySize)
elif ref in objectTypes :
generateObjectMapping(objectTypes[ref], attribute.vodmlid, attribute.arraySize)
else:
print("REF NOT FOUND " + ref)
print ("PRIM ", primitiveTypes.keys())
print ("TYPE ", dataTypes.keys())
print ("OBJ ",objectTypes.keys())
sys.exit()
def generateAttributeMapping(attribute):
if attribute.arraySize == 0 :
return
elif attribute.arraySize == 1:
generateSingleAttributeMapping(attribute)
elif attribute.arraySize == -1:
appendOuput( "")
generateSingleAttributeMapping(attribute)
appendOuput( "")
else:
appendOuput( "")
for num in range(0, attribute.arraySize):
generateSingleAttributeMapping(attribute)
appendOuput( "")
def generateDataMapping(objectType, attrId, arraySize):
appendOuput( "")
for attribute in objectType.attributes:
generateAttributeMapping(attribute)
appendOuput( "")
def generateObjectMapping(objectType, attrId, arraySize):
appendOuput( "")
readAttributes = []
for attribute in objectType.attributes:
if attribute.vodmlid not in readAttributes:
generateAttributeMapping(attribute)
readAttributes.append(attribute.vodmlid)
else:
print( "SKIPPP " + attribute.vodmlid )
appendOuput( "")
def appendOuput(string):
space = " "
global indent
blank = ''
if string.startswith("") :
for i in range(0, (indent-1)):
blank += space
else :
for i in range(0, indent):
blank += space
print(blank + string)
if string.startswith("") :
indent -= 1
else:
indent += 1
if indent > 10:
sys.exit()
def logMsg(label, msg):
#if( msg.endswith("SpatialCoord")):
print(label + " " + msg)
def resolveInheritance():
for obj in objectTypes.values():
if obj.superclass != '':
if obj.superclass in objectTypes :
sc = objectTypes[obj.superclass]
obj.attributes = sc.attributes + obj.attributes
elif obj.superclass in dataTypes:
sc = objectTypes[obj.superclass]
obj.attributes = sc.attributes + obj.attributes
else:
print( obj.vodmlid + ": Neither dataType or objectType with key " + obj.superclass + " found")
sys.exit(1)
def generateMapping():
print(rootObjectId)
rootObjectType = objectTypes[rootObjectId]
generateObjectMapping(rootObjectType, 'root', 1)
def main():
global rootObjectId
parseVodmlFile(filename="../models/timeseries.vo-dml.xml", model='timeseries')
resolveInheritance();
rootObjectId = 'timeseries:TimeSerie'
generateMapping()
#parseVodmlFile(filename="/home/michel/workspace/vo-datamodels/provenance/vo-dml/xml/ProvenanceDM.vo-dml.xml", model='provenance')
#rootObjectId = 'provenance:provenance.Entity'
#print(rootObjectId)
#generateMapping()
if __name__ == "__main__":
main()