# ALMA - Atacama Large Millimeter Array
# (c) European Southern Observatory, 2024
# (c) Associated Universities Inc., 2024
# Copyright by ESO (in the framework of the ALMA collaboration),
# Copyright by AUI (in the framework of the ALMA collaboration),
# All rights reserved.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
# MA 02111-1307 USA
#
# File EntityRef.py
# adapted from the original c++ and Java
from .PartId import PartId
from .EntityId import EntityId
from xml.dom import minidom
import pyasdm.utils
[docs]class EntityRef:
"""
The EntityRef class is an identification of a persistent
entity in the ALMA archive. It wasily maps onto an EntiyREfT
object in ACS system entities.
"""
_entityId = EntityId()
_partId = None # a PartId when not null
_entityTypeName = None # the entityTypeName string
_instanceVersion = None # the instanceVersion string
def __init__(self, *args):
"""
Construct an EntityRef.
If args is empty, the default EntityRef whose internal parameters are null.
If args is 1 it may be either a string (XML as produced by toXML) or
another EntityRef (copy constructor).
If there are 4 args they are, in order, entityId, partId,
entityTypeName, and instanceVersion. All strings that express the
4 components of an EntityRef.
"""
_entityId = EntityId()
_partId = None
_entityTypeName = None
_instanceVersion = None
if len(args) == 0:
# default, nothing to do
pass
elif len(args) == 1 and isinstance(args[0], str):
self.setFromXML(args[0])
elif len(args) == 1 and isinstance(args[0], EntityRef):
otherRef = args[0]
self._entityId = EntityId(otherRef._entityId)
if otherRef._partId is None:
# preserve it as unset
self._partId = None
else:
self._partId = PartId(otherRef._partId)
self._entityTypeName = otherRef._entityTypeName
self._instanceVersion = otherRef._instanceVersion
elif len(args) == 4:
self._entityId = EntityId(args[0])
self._partId = PartId(args[1])
self._entityTypeName = str(args[2])
self._instanceVersion = str(args[3])
else:
raise ValueError("unrecognized arguments to EntityRef constructor")
def __str__(self):
"""
Return the entityId as a string. Equivalent to toXML.
"""
return self.toXML()
[docs] def toBin(self, eos):
"""
Write the binary representation of this into a DataOutput stream.
"""
self._entityId.toBin(eos)
self._partId.toBin(eos)
eos.writeString(self._entityTypeName)
eos.writeString(self._instanceVersion)
[docs] @staticmethod
def listToBin(entityRefList, eos):
"""
Write a list of EntityRef to the EndianOutput.
Only lists of 1D are supported.
"""
if not isinstance(entityRefList, list):
raise ValueError("entityRefList is not a list")
listDims = pyasdm.utils.getListDims(entityRefList)
if len(listDims) != 1:
raise ValueError("only 1D lists of EntityRef are supported.")
EntityRef.listTo1DBin(entityRefList, eos)
[docs] @staticmethod
def listTo1DBin(entityRefList, eos):
"""
Write a 1D list of EntityRef to the EndianOutput
"""
if not isinstance(entityRefList, list):
raise ValueError("entityRefList is not a list")
# ndim is always written, even for 0-element lists
eos.writeInt(len(entityRefList))
# only check the first value
if (len(entityRefList) > 0) and not isinstance(entityRefList[0], EntityRef):
raise (ValueError("entityRefList is not a list of EntityRef"))
for thisEntityRef in entityRefList:
thisEntityRef.toBin(eos)
[docs] @staticmethod
def fromBin(eis):
"""
Read the binary representation of an EntityRef from an EndianInput
instance and use the read values to set an EntityRef.
return an EntityRef
"""
# I don't trust the order that these might be evaluated if done in
# the EntityRef constructor
entityId = EntityId.fromBin(eis)
partId = PartId.fromBin(eis)
typeName = eis.readString()
instanceVersion = eis.readString()
return EntityRef(str(entityId), str(partId), typeName, instanceVersion)
[docs] @staticmethod
def from1DBin(eis):
"""
Read a list of EntityRef from an EndianInput instance and return
the resulting list.
"""
dim1 = eis.readInt()
result = []
for i in range(dim1):
result.append(EntityRef.fromBin(eis))
return result
[docs] def toXML(self):
"""
Return the values of this EntityRef as an XML-formatted string.
"""
# checks for valid values first
msg = self.validXML()
if msg is not None:
raise RuntimeError(msg)
result = ""
result = '<EntityRef entityId="' + str(self._entityId)
if self._partId is not None:
result += '" partId="' + str(self._partId)
result += '" entityTypeName="' + self._entityTypeName
result += '" documentVersion="' + self._instanceVersion + '"/>'
return result
[docs] def setFromXML(self, xmlstr):
"""
Set the values of this EntityRef from an XML formatted as produced by toXML
"""
if not isinstance(xmlstr, str):
raise ValueError(
"EntityRef.setFromXML argument is not a string. type="
+ str(type(xmlstr))
)
try:
xmldom = minidom.parseString(xmlstr)
# requires that there's at least one EntityRef here and that the one that's desired is the first one
entityRefEl = xmldom.getElementsByTagName("EntityRef")[0]
self._entityId = EntityId(entityRefEl.getAttribute("entityId"))
# partId may be missing if None
partIdStr = entityRefEl.getAttribute("partId")
if len(partIdStr) == 0:
self._partId = None
else:
self._partId = PartId(partIdStr)
self._entityTypeName = entityRefEl.getAttribute("entityTypeName")
self._instanceVersion = entityRefEl.getAttribute("documentVersion")
except Exception as exc:
msg = "EntityRef.setFromXML() invalid EntityRef XML string." + str(exc)
raise ValueError(msg) from None
# and validate it
msg = self.validXML()
if msg is not None:
raise ValueError(msg)
[docs] def validXML(self):
"""
Used internally to validate this EntityRef for conversion to or after
conversion from an XML string
If this is invalid a string message is returned, otherwise None is returned.
"""
# null values, except for partId, are invalid in XML
if (
self._entityId.isNull()
or len(self._entityTypeName) == 0
or len(self._instanceVersion) == 0
):
return "Null values detected in EntityRef " + str(self._entityId)
# I think this isn't necessary the way these python classes work - caught elsewhere
msg = EntityId.validate(str(self._entityId))
if msg is not None:
return msg
# if partId is set, it must have the correct format
if self._partId is not None:
return PartId.validate(str(self._partId))
return None
[docs] def equals(self, other):
"""
Returns True if and only if other is an EntityRef and it's values are all equal to this
EntityRef.
"""
if not isinstance(other, EntityRef):
return False
# if they're both null then they're equal, but if only one is they're not equal
if self.isNull():
if other.isNull():
return True
# only one is Null
return False
elif other.isNull():
# only one is Null
return False
# a null EntityId has already been dealt with
result = self._entityId.equals(other._entityId)
# partId can be null, must be null in both
if self._partId is None:
result = result and (other._partId is None)
else:
# equals here will return False of other._partId is None
result = result and self._partId.equals(other._partId)
result = result and (self._entityTypeName == other._entityTypeName)
result = result and (self._instanceVersion == other._instanceVersion)
return result
[docs] def isNull(self):
"""
Returns True if and only if the entityId is Null
"""
return self._entityId.isNull()
# getters and setters
[docs] def getEntityId(self):
"""
Returns the entityId as a string
"""
if self.isNull():
return ""
return str(self._entityId)
[docs] def setEntityId(self, entityId):
"""
Sets the entityId to this string, which must be a valid EntityId string
"""
self._entityId = EntityId(entityId)
[docs] def getPartId(self):
"""
Returns the partId as a string. If unset, returns None
"""
if self._partId is None:
return None
return str(self._partId)
[docs] def setPartId(self, partId):
"""
Sets the part to the given string
"""
self._partId = PartId(partId)
[docs] def getEntityTypeName(self):
"""
returns the entityTypeName string
"""
return self._entityTypeName
[docs] def setEntityTypeName(self, entityTypeName):
"""
sets the entityTypeName to the given string
"""
self._entityTypeName = entityTypeName
[docs] def getInstanceVersion(self):
"""
returns the instanceVersion string
"""
return self._instanceVersion
[docs] def setInstanceVersion(self, instanceVersion):
"""
sets the instanceVersion to the given string
"""
self._instanceVersion = instranceVersion
[docs] @staticmethod
def getInstance(stringList):
"""
This mirrors similar functions in the other types.
This should not be used to construct an EntityRef because of the
complexity of that object. It is included here in case
the translation from java includes such a use. If used it
will raise a RuntimeError.
"""
raise RuntimeError("Entity.getEntityRef called, not supported in pyasdm.")