| 1 | ## Copyright 2005, 2006, 2007 Virginia Polytechnic Institute and State University |
|---|
| 2 | ## |
|---|
| 3 | ## This file is part of the OSSIE Waveform Developer. |
|---|
| 4 | ## |
|---|
| 5 | ## OSSIE Waveform Developer is free software; you can redistribute it and/or modify |
|---|
| 6 | ## it under the terms of the GNU General Public License as published by |
|---|
| 7 | ## the Free Software Foundation; either version 2 of the License, or |
|---|
| 8 | ## (at your option) any later version. |
|---|
| 9 | ## |
|---|
| 10 | ## OSSIE Waveform Developer is distributed in the hope that it will be useful, |
|---|
| 11 | ## but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 12 | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 13 | ## GNU General Public License for more details. |
|---|
| 14 | ## |
|---|
| 15 | ## You should have received a copy of the GNU General Public License |
|---|
| 16 | ## along with OSSIE Waveform Developer; if not, write to the Free Software |
|---|
| 17 | ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|---|
| 18 | |
|---|
| 19 | import os, sys |
|---|
| 20 | import xml.dom.minidom |
|---|
| 21 | from xml.dom.minidom import Node |
|---|
| 22 | import ComponentClass as CC |
|---|
| 23 | from errorMsg import * |
|---|
| 24 | |
|---|
| 25 | availableTypes = ["boolean", "char", "double", "float", "short", "long", |
|---|
| 26 | "objref", "octet", "string", "ulong","ushort"] |
|---|
| 27 | availableKinds = ["allocation", "configure", "test", "execparam", "factoryparam"] |
|---|
| 28 | availableActions = ["eq", "ne", "gt", "lt", "ge", "le", "external"] |
|---|
| 29 | availableModes = ["readonly", "readwrite", "writeonly"] |
|---|
| 30 | |
|---|
| 31 | def getResource(path,Rname,parent): |
|---|
| 32 | scdPath = findFile(path,Rname,".scd.xml") |
|---|
| 33 | if scdPath == None: |
|---|
| 34 | errorMsg(parent,"No scd file found for: " + Rname) |
|---|
| 35 | return |
|---|
| 36 | |
|---|
| 37 | spdPath = findFile(path,Rname,".spd.xml") |
|---|
| 38 | prfPath = findFile(path,Rname,".prf.xml") |
|---|
| 39 | |
|---|
| 40 | prefix = "/sdr/dom" |
|---|
| 41 | if path.startswith("/sdr/dev"): |
|---|
| 42 | prefix = "/sdr/dev" |
|---|
| 43 | # |
|---|
| 44 | # Build the main component or device from the SCD file |
|---|
| 45 | # |
|---|
| 46 | doc_scd = xml.dom.minidom.parse(scdPath) |
|---|
| 47 | try: |
|---|
| 48 | componenttypeNode = doc_scd.getElementsByTagName("componenttype") |
|---|
| 49 | componenttype = componenttypeNode[0].childNodes[0].data |
|---|
| 50 | except: |
|---|
| 51 | errorMsg(parent,"Invalid file: " + scdPath) |
|---|
| 52 | return None |
|---|
| 53 | |
|---|
| 54 | doc_spd = xml.dom.minidom.parse(spdPath) |
|---|
| 55 | |
|---|
| 56 | # get resource description |
|---|
| 57 | # note: this is not the same as the implementation description |
|---|
| 58 | softpkgNode = doc_spd.getElementsByTagName("softpkg")[0] |
|---|
| 59 | Rdescription = '' |
|---|
| 60 | for n in softpkgNode.childNodes: |
|---|
| 61 | if n.nodeName == "description": |
|---|
| 62 | resDescriptionNode = doc_spd.getElementsByTagName("description") |
|---|
| 63 | try: |
|---|
| 64 | Rdescription = resDescriptionNode[0].firstChild.data |
|---|
| 65 | except: |
|---|
| 66 | pass |
|---|
| 67 | break |
|---|
| 68 | |
|---|
| 69 | #Instantiate a new component of the appropriate type |
|---|
| 70 | if componenttype == u'resource': |
|---|
| 71 | newComp = CC.Component(name=Rname,type='resource',description=Rdescription) |
|---|
| 72 | elif componenttype == u'executabledevice': |
|---|
| 73 | newComp = CC.Component(name=Rname,type='executabledevice',description=Rdescription) |
|---|
| 74 | elif componenttype == u'loadabledevice': |
|---|
| 75 | newComp = CC.Component(name=Rname,type='loadabledevice',description=Rdescription) |
|---|
| 76 | elif componenttype == u'device': |
|---|
| 77 | newComp = CC.Component(name=Rname,type='device',description=Rdescription) |
|---|
| 78 | else: |
|---|
| 79 | errorMsg(parent,"Can't identify resource type for: " + Rname) |
|---|
| 80 | return None |
|---|
| 81 | |
|---|
| 82 | # Get the Ports |
|---|
| 83 | portsNodes = doc_scd.getElementsByTagName("ports") |
|---|
| 84 | for node in portsNodes: |
|---|
| 85 | providesPortsNodes = node.getElementsByTagName("provides") |
|---|
| 86 | usesPortsNodes = node.getElementsByTagName("uses") |
|---|
| 87 | |
|---|
| 88 | # Provides ports |
|---|
| 89 | for node in providesPortsNodes: |
|---|
| 90 | tmpName = node.getAttribute("providesname") |
|---|
| 91 | tmpInt = getInterface( node.getAttribute("repid"), tmpName ) |
|---|
| 92 | if tmpInt == None: |
|---|
| 93 | return None |
|---|
| 94 | portTypeNodeList = node.getElementsByTagName("porttype") |
|---|
| 95 | tmpType = portTypeNodeList[0].getAttribute("type") |
|---|
| 96 | newPort = CC.Port(tmpName,tmpInt,type='Provides',portType=tmpType) |
|---|
| 97 | newComp.ports.append(newPort) |
|---|
| 98 | |
|---|
| 99 | # Uses ports |
|---|
| 100 | for node in usesPortsNodes: |
|---|
| 101 | tmpName = node.getAttribute("usesname") |
|---|
| 102 | tmpInt = getInterface( node.getAttribute("repid"), tmpName ) |
|---|
| 103 | if tmpInt == None: |
|---|
| 104 | return None |
|---|
| 105 | portTypeNodeList = node.getElementsByTagName("porttype") |
|---|
| 106 | tmpType = portTypeNodeList[0].getAttribute("type") |
|---|
| 107 | newPort = CC.Port(tmpName,tmpInt,type='Uses',portType=tmpType) |
|---|
| 108 | newComp.ports.append(newPort) |
|---|
| 109 | |
|---|
| 110 | # Make sure that xml and code are not generated for this resource |
|---|
| 111 | newComp.generate = False |
|---|
| 112 | |
|---|
| 113 | # Store the name of the file without the suffix (.scd.xml) |
|---|
| 114 | i = scdPath.rfind("/") |
|---|
| 115 | if i != -1: |
|---|
| 116 | newComp.xmlName = scdPath[i+1:-8] |
|---|
| 117 | else: |
|---|
| 118 | newComp.xmlName = scdPath[:-8] |
|---|
| 119 | |
|---|
| 120 | # |
|---|
| 121 | # Import the properties from the PRF file |
|---|
| 122 | # |
|---|
| 123 | # If there are no properties, just return the component as is |
|---|
| 124 | if prfPath == None: |
|---|
| 125 | return newComp |
|---|
| 126 | doc_prf = xml.dom.minidom.parse(prfPath) |
|---|
| 127 | try: |
|---|
| 128 | propertyNodeList = doc_prf.getElementsByTagName("properties") |
|---|
| 129 | except: |
|---|
| 130 | errorMsg(parent,"Invalid file: " + prfPath) |
|---|
| 131 | return None |
|---|
| 132 | |
|---|
| 133 | # get simple properties |
|---|
| 134 | simplePropertyNodeList = doc_prf.getElementsByTagName("simple") |
|---|
| 135 | props = getSimpleProperties(simplePropertyNodeList, prfPath) |
|---|
| 136 | for prop in props: |
|---|
| 137 | newComp.properties.append(prop) |
|---|
| 138 | |
|---|
| 139 | |
|---|
| 140 | # get simple sequence properties |
|---|
| 141 | simpleSequencePropertyNodeList = doc_prf.getElementsByTagName("simplesequence") |
|---|
| 142 | sequenceProps = getSimpleSequenceProperties(simpleSequencePropertyNodeList, prfPath) |
|---|
| 143 | for prop in sequenceProps: |
|---|
| 144 | newComp.properties.append(prop) |
|---|
| 145 | |
|---|
| 146 | |
|---|
| 147 | # read additional implementations from the spd file if necessary |
|---|
| 148 | |
|---|
| 149 | # example implementation node from an spd file |
|---|
| 150 | #<implementation id="DCE:f559a6a6-a1b3-4acd-b926-d194be1b9930"> |
|---|
| 151 | # <description>Virtex4 FPGA Implementation, Controller Component</description> |
|---|
| 152 | # <propertyfile type="PRF"> |
|---|
| 153 | # <localfile name="/xml/TxDemo/TxDemo_v4.prf.xml"/> |
|---|
| 154 | # </propertyfile> |
|---|
| 155 | # <code type="Executable"> |
|---|
| 156 | # <localfile name="/bin/TxDemo_v4"/> |
|---|
| 157 | # </code> |
|---|
| 158 | # <os name="Linux" version="2.6.27-rc9-xlnx"/> |
|---|
| 159 | # <processor name="powerpc"/> |
|---|
| 160 | # <!-- this id points to the impl ID in the XilinxFPGA SPD --> |
|---|
| 161 | # <dependency type="Device" softpkgref="DCE:e6d7ca42-e4c9-482c-a9ed-23901f15a465"/> |
|---|
| 162 | #</implementation> |
|---|
| 163 | |
|---|
| 164 | simpleProps = [] |
|---|
| 165 | simpleSequenceProps = [] |
|---|
| 166 | implementationNodes = doc_spd.getElementsByTagName("implementation") |
|---|
| 167 | for node in implementationNodes: |
|---|
| 168 | simpleProps = [] |
|---|
| 169 | simpleSequenceProps = [] |
|---|
| 170 | propertyFile = '' |
|---|
| 171 | id = node.getAttribute("id") |
|---|
| 172 | tmp = node.getElementsByTagName("description") |
|---|
| 173 | if len(tmp) > 0: |
|---|
| 174 | descriptionNode = tmp[0] |
|---|
| 175 | description = descriptionNode.firstChild.data |
|---|
| 176 | else: |
|---|
| 177 | description = '' |
|---|
| 178 | tmp = node.getElementsByTagName("propertyfile") |
|---|
| 179 | if len(tmp) > 0: |
|---|
| 180 | propertyFileNode = tmp[0] |
|---|
| 181 | propertyFile = prefix + propertyFileNode.getElementsByTagName("localfile")[0].getAttribute("name") |
|---|
| 182 | propertyDoc = xml.dom.minidom.parse(propertyFile) |
|---|
| 183 | simplePropNodes = propertyDoc.getElementsByTagName("simple") |
|---|
| 184 | simpleProps = getSimpleProperties(simplePropNodes, propertyFile) |
|---|
| 185 | |
|---|
| 186 | simpleSequencePropNodes = propertyDoc.getElementsByTagName("simplesequence") |
|---|
| 187 | simpleSequenceProps = getSimpleSequenceProperties(simpleSequencePropNodes, propertyFile) |
|---|
| 188 | else: |
|---|
| 189 | propertyFile = None |
|---|
| 190 | tmp = node.getElementsByTagName("processor") |
|---|
| 191 | if len(tmp) > 0: |
|---|
| 192 | processorNode = tmp[0] |
|---|
| 193 | processor = processorNode.getAttribute("name") |
|---|
| 194 | else: |
|---|
| 195 | processor = '' |
|---|
| 196 | |
|---|
| 197 | newImplementation = CC.Implementation(id, description, propertyFile, processor) |
|---|
| 198 | for prop in simpleProps: |
|---|
| 199 | newImplementation.properties.append(prop) |
|---|
| 200 | for prop in simpleSequenceProps: |
|---|
| 201 | newImplementation.properties.append(prop) |
|---|
| 202 | |
|---|
| 203 | newComp.implementations.append(newImplementation) |
|---|
| 204 | # print newComp.name + ' summary:' |
|---|
| 205 | # print 'Main properties: ' |
|---|
| 206 | # for prop in newComp.properties: |
|---|
| 207 | # print ' ' + prop.name |
|---|
| 208 | # print 'Implementations:' |
|---|
| 209 | # for imp in newComp.implementations: |
|---|
| 210 | # print imp.processor |
|---|
| 211 | # for prop in imp.properties: |
|---|
| 212 | # print ' ' + prop.name |
|---|
| 213 | return newComp |
|---|
| 214 | |
|---|
| 215 | def getInterface(repid,name): |
|---|
| 216 | try: |
|---|
| 217 | repid = repid.strip('IDL:') |
|---|
| 218 | repid = repid[:repid.rfind(':')] |
|---|
| 219 | tmpNS = repid[:repid.find('/')] |
|---|
| 220 | tmpName = repid[repid.find('/')+1:] |
|---|
| 221 | newInt = CC.Interface(tmpName,nameSpace=tmpNS) |
|---|
| 222 | return newInt |
|---|
| 223 | |
|---|
| 224 | except: |
|---|
| 225 | errorMsg(parent,"Can't read the Interface information for port: " + name) |
|---|
| 226 | return None |
|---|
| 227 | |
|---|
| 228 | |
|---|
| 229 | def findFile(path,Rname,suf): |
|---|
| 230 | tmpf = None |
|---|
| 231 | if os.path.isfile(path + '/' + Rname +'Resource'+suf): |
|---|
| 232 | tmpf = path + '/' + Rname +'Resource' + suf |
|---|
| 233 | elif os.path.isfile(path + '/' + Rname + suf): |
|---|
| 234 | tmpf = path + '/' + Rname + suf |
|---|
| 235 | else: |
|---|
| 236 | tmpFiles = os.listdir(path) |
|---|
| 237 | for f in tmpFiles: |
|---|
| 238 | if len(f)>=8 and f[-8:] == suf: |
|---|
| 239 | tmpf = path + '/' + f |
|---|
| 240 | break |
|---|
| 241 | return tmpf |
|---|
| 242 | |
|---|
| 243 | def stripDoctype(xmlfile): |
|---|
| 244 | """Strips out the DOCTYPE checking because the dtd files are positioned |
|---|
| 245 | in a relative location to the SCA (OSSIE) filesystem, so when Amara |
|---|
| 246 | trys to validate against them, it bails out looking for the file. |
|---|
| 247 | Returns a string representation of the xml file without the DOCTYPE line.""" |
|---|
| 248 | |
|---|
| 249 | file = open(xmlfile, 'r') |
|---|
| 250 | xml = '' |
|---|
| 251 | line = file.readline() |
|---|
| 252 | while len(line) > 0: |
|---|
| 253 | if "DOCTYPE" in line: |
|---|
| 254 | break |
|---|
| 255 | xml += line |
|---|
| 256 | line = file.readline() |
|---|
| 257 | xml += file.read() |
|---|
| 258 | |
|---|
| 259 | return xml |
|---|
| 260 | |
|---|
| 261 | def getSimpleProperties(simplePropertyNodeList, propertyFile): |
|---|
| 262 | props = [] |
|---|
| 263 | for node in simplePropertyNodeList: |
|---|
| 264 | p = getSimpleProperty(node) |
|---|
| 265 | if p == None: |
|---|
| 266 | print "There was an error parsing simple properties in the PRF file " + propertyFile |
|---|
| 267 | continue |
|---|
| 268 | props.append(p) |
|---|
| 269 | |
|---|
| 270 | return props |
|---|
| 271 | |
|---|
| 272 | def getSimpleSequenceProperties(simpleSequencePropertyNodeList, propertyFile): |
|---|
| 273 | props = [] |
|---|
| 274 | for node in simpleSequencePropertyNodeList: |
|---|
| 275 | p = getSimpleSequenceProperty(node, propertyFile) |
|---|
| 276 | if p == None: |
|---|
| 277 | print "There was an error parsing simple sequence properties in the PRF file " + propertyFile |
|---|
| 278 | continue |
|---|
| 279 | props.append(p) |
|---|
| 280 | |
|---|
| 281 | return props |
|---|
| 282 | |
|---|
| 283 | def getSimpleProperty(n): |
|---|
| 284 | tmpName = n.getAttribute("name") |
|---|
| 285 | tmpID = n.getAttribute("id") |
|---|
| 286 | tmpType = n.getAttribute("type") |
|---|
| 287 | tmpMode = n.getAttribute("mode") |
|---|
| 288 | tmpDes = n.getAttribute("description") |
|---|
| 289 | |
|---|
| 290 | if tmpName == "" or tmpID == "" or tmpType == "" or tmpMode == "": |
|---|
| 291 | return None |
|---|
| 292 | if tmpMode not in availableModes: |
|---|
| 293 | return None |
|---|
| 294 | if tmpType not in availableTypes: |
|---|
| 295 | return None |
|---|
| 296 | |
|---|
| 297 | newProp = CC.SimpleProperty(tmpName,tmpMode,tmpType,description=tmpDes) |
|---|
| 298 | |
|---|
| 299 | # Set ID |
|---|
| 300 | #UUID in the sad file will need to match the UUID in the prf (tmpID is from prf) |
|---|
| 301 | newProp.id = tmpID |
|---|
| 302 | |
|---|
| 303 | # Get/set property value |
|---|
| 304 | valueNodeList = n.getElementsByTagName("value") |
|---|
| 305 | value = valueNodeList[0].childNodes[0].data |
|---|
| 306 | newProp.value = newProp.defaultValue = str(value) |
|---|
| 307 | del valueNodeList, value |
|---|
| 308 | |
|---|
| 309 | # Get/set property units |
|---|
| 310 | unitsNodeList = n.getElementsByTagName("units") |
|---|
| 311 | if len(unitsNodeList) > 0: |
|---|
| 312 | units = unitsNodeList[0].childNodes[0].data |
|---|
| 313 | newProp.units = str(s.units) |
|---|
| 314 | #del unitsNodeList, units |
|---|
| 315 | |
|---|
| 316 | # TODO: Get/set min/max values |
|---|
| 317 | # TODO: Get/set enum |
|---|
| 318 | |
|---|
| 319 | # Get/set kind |
|---|
| 320 | kindNodeList = n.getElementsByTagName("kind") |
|---|
| 321 | kindtype = kindNodeList[0].getAttribute("kindtype") |
|---|
| 322 | if kindtype == "": |
|---|
| 323 | return None |
|---|
| 324 | newProp.kind = str(kindtype) |
|---|
| 325 | del kindNodeList, kindtype |
|---|
| 326 | |
|---|
| 327 | # Get/set action |
|---|
| 328 | actionNodeList = n.getElementsByTagName("action") |
|---|
| 329 | if len(actionNodeList) > 0: |
|---|
| 330 | actiontype = actionNodeList[0].getAttribute("type") |
|---|
| 331 | newProp.action = str(actiontype) |
|---|
| 332 | #del actionNodeList, actiontype |
|---|
| 333 | |
|---|
| 334 | return newProp |
|---|
| 335 | |
|---|
| 336 | def getSimpleSequenceProperty(n, prfPath): |
|---|
| 337 | tmpName = n.getAttribute("name") |
|---|
| 338 | tmpID = n.getAttribute("id") |
|---|
| 339 | tmpType = n.getAttribute("type") |
|---|
| 340 | tmpMode = n.getAttribute("mode") |
|---|
| 341 | tmpDes = n.getAttribute("description") |
|---|
| 342 | |
|---|
| 343 | if tmpName == "" or tmpID == "" or tmpType == "" or tmpMode == "": |
|---|
| 344 | return None |
|---|
| 345 | if tmpMode not in availableModes: |
|---|
| 346 | return None |
|---|
| 347 | if tmpType not in availableTypes: |
|---|
| 348 | return None |
|---|
| 349 | |
|---|
| 350 | newProp = CC.SimpleSequenceProperty(tmpName,tmpMode,tmpType,description=tmpDes) |
|---|
| 351 | |
|---|
| 352 | # Set ID |
|---|
| 353 | #UUID in the sad file will need to match the UUID in the prf (tmpID is from prf) |
|---|
| 354 | newProp.id = tmpID |
|---|
| 355 | |
|---|
| 356 | |
|---|
| 357 | # Get/set property values |
|---|
| 358 | newProp.values = [] |
|---|
| 359 | newProp.defaultValues = [] |
|---|
| 360 | valuesNodeList = n.getElementsByTagName("values") |
|---|
| 361 | |
|---|
| 362 | try: |
|---|
| 363 | valueNodeList = valuesNodeList[0].getElementsByTagName("value") |
|---|
| 364 | except: |
|---|
| 365 | valueNodeList = n.getElementsByTagName("value") #cbd |
|---|
| 366 | #print "\nERROR in " + prfPath |
|---|
| 367 | #print "ERROR parsing prf file. You may be missing a values tag in a simple sequence property.\n" |
|---|
| 368 | #sys.exit() |
|---|
| 369 | print "\nWarning in " + prfPath |
|---|
| 370 | print "Warning parsing prf file. You may be missing a values tag in a simple sequence property.\n" |
|---|
| 371 | |
|---|
| 372 | for valueNode in valueNodeList: |
|---|
| 373 | tmpVal = valueNode.childNodes[0].data |
|---|
| 374 | newProp.values.append(str(tmpVal)) |
|---|
| 375 | newProp.defaultValues.append(str(tmpVal)) |
|---|
| 376 | del valueNodeList |
|---|
| 377 | |
|---|
| 378 | # Get/set property units |
|---|
| 379 | unitsNodeList = n.getElementsByTagName("units") |
|---|
| 380 | if len(unitsNodeList) > 0: |
|---|
| 381 | units = unitsNodeList[0].childNodes[0].data |
|---|
| 382 | newProp.units = str(s.units) |
|---|
| 383 | #del unitsNodeList, units |
|---|
| 384 | |
|---|
| 385 | # TODO: Get/set min/max values |
|---|
| 386 | # TODO: Get/set enum |
|---|
| 387 | |
|---|
| 388 | # Get/set kind |
|---|
| 389 | kindNodeList = n.getElementsByTagName("kind") |
|---|
| 390 | kindtype = kindNodeList[0].getAttribute("kindtype") |
|---|
| 391 | if kindtype == "": |
|---|
| 392 | return None |
|---|
| 393 | newProp.kind = str(kindtype) |
|---|
| 394 | del kindNodeList, kindtype |
|---|
| 395 | |
|---|
| 396 | # Get/set action |
|---|
| 397 | actionNodeList = n.getElementsByTagName("action") |
|---|
| 398 | if len(actionNodeList) > 0: |
|---|
| 399 | actiontype = actionNodeList[0].getAttribute("type") |
|---|
| 400 | newProp.action = str(actiontype) |
|---|
| 401 | #del actionNodeList, actiontype |
|---|
| 402 | |
|---|
| 403 | return newProp |
|---|