synergy-service/synergy/common/serializer.py

165 lines
5.1 KiB
Python

import datetime
from json import JSONEncoder
from synergy.common import utils
__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 Exception("it seems not a Synergy object!")
synergy_object = entity["synergy_object"]
if "namespace" not in synergy_object:
raise Exception("synergy_object.namespace not defined!")
if "name" not in synergy_object:
raise Exception("synergy_object.name not defined!")
if "version" not in synergy_object:
raise Exception("synergy_object.version mismatch!")
if synergy_object["version"] != cls.VERSION:
raise Exception("synergy_object.version mis!")
if synergy_object["namespace"] != "synergy":
raise Exception("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 Exception("error on deserializing the object %r: %s"
% (objName, ex))
del entity["synergy_object"]
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.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()
else:
return JSONEncoder.default(self, obj)