synergy-service/synergy/common/serializer.py

170 lines
5.3 KiB
Python

from datetime import datetime
from json import JSONEncoder
from synergy.common import utils
from synergy.exception import SynergyError
__author__ = "Lisa Zangrando"
__email__ = "lisa.zangrando[AT]pd.infn.it"
__copyright__ = """Copyright (c) 2015 INFN - INDIGO-DataCloud
All Rights Reserved
Licensed under the Apache License, Version 2.0;
you may not use this file except in compliance with the
License. You may obtain a copy of the License at:
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
either express or implied.
See the License for the specific language governing
permissions and limitations under the License."""
class SynergyObject(object):
"""Base class and object factory.
This forms the base of all objects that can be remoted or instantiated
via RPC. Simply defining a class that inherits from this base class
will make it remotely instantiatable. Objects should implement the
necessary "get" classmethod routines as well as "set" object methods
as appropriate.
"""
VERSION = "1.0"
def __init__(self):
super(SynergyObject, self).__init__()
self.attributes = {}
def getId(self):
return self.get("id")
def setId(self, id):
self.set("id", id)
def getName(self):
return self.get("name")
def setName(self, name):
self.set("name", name)
def get(self, field):
return self.attributes.get(field, None)
def set(self, field, value):
if isinstance(value, unicode):
self.attributes[field] = str(value)
else:
self.attributes[field] = value
def setAttributes(self, attributes):
if attributes:
self.attributes = attributes
@classmethod
def deserialize(cls, entity):
if "synergy_object" not in entity:
raise SynergyError("it seems not a Synergy object!")
synergy_object = entity["synergy_object"]
if "namespace" not in synergy_object:
raise SynergyError("synergy_object.namespace not defined!")
if "name" not in synergy_object:
raise SynergyError("synergy_object.name not defined!")
if "version" not in synergy_object:
raise SynergyError("synergy_object.version mismatch!")
if synergy_object["version"] != cls.VERSION:
raise SynergyError("synergy_object.version mis!")
if synergy_object["namespace"] != "synergy":
raise SynergyError("unsupported object objtype='%s.%s"
% (synergy_object["namespace"],
synergy_object["name"]))
objInstance = None
try:
objName = synergy_object["name"]
objClass = utils.import_class(objName)
objInstance = objClass()
except Exception as ex:
raise SynergyError("error on deserializing the object %r: %s"
% (objName, ex))
del entity["synergy_object"]
entity = utils.objectHookHandler(entity)
for key, value in entity.items():
if isinstance(value, dict):
if "synergy_object" in value:
objInstance.set(key, SynergyObject.deserialize(value))
else:
objInstance.set(key, value)
elif isinstance(value, list):
l = []
objInstance.set(key, l)
for item in value:
if isinstance(item, dict) and "synergy_object" in item:
l.append(SynergyObject.deserialize(item))
else:
l.append(item)
else:
objInstance.set(key, value)
return objInstance
def serialize(self):
name = self.__class__.__module__ + "." + self.__class__.__name__
result = {"synergy_object": {}}
result["synergy_object"]["name"] = name
result["synergy_object"]["version"] = self.VERSION
result["synergy_object"]["namespace"] = "synergy"
for key, value in self.attributes.items():
if isinstance(value, SynergyObject):
result[key] = value.serialize()
elif isinstance(value, dict):
result[key] = {}
for k, v in value.items():
if isinstance(v, SynergyObject):
result[key][k] = v.serialize()
else:
result[key][k] = v
elif isinstance(value, list):
result[key] = []
for item in value:
if isinstance(item, SynergyObject):
result[key].append(item.serialize())
else:
result[key].append(item)
elif isinstance(value, datetime):
result[key] = value.isoformat()
else:
result[key] = value
return result
class SynergyEncoder(JSONEncoder):
def default(self, obj):
if isinstance(obj, SynergyObject):
return obj.serialize()
elif isinstance(obj, datetime):
return obj.isoformat()
else:
return JSONEncoder.default(self, obj)