--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/p4l/mapping/serializers.py Fri Sep 20 00:03:31 2013 +0200
@@ -0,0 +1,182 @@
+# -*- coding: utf-8 -*-
+'''
+Created on Sep 19, 2013
+
+@author: ymh
+'''
+import logging
+
+from rdflib.namespace import RDF
+from rdflib.term import URIRef, Literal, BNode
+from collections import OrderedDict
+
+
+logger = logging.getLogger(__name__)
+
+class BaseSerializer(object):
+
+ creation_counter = 0
+
+ def __init__(self, predicate=None, many=False):
+ self.predicate = predicate
+ self.creation_counter = BaseSerializer.creation_counter
+ self.many = many
+ BaseSerializer.creation_counter += 1
+ if self.predicate and not isinstance(self.predicate, URIRef):
+ self.predicate = URIRef(predicate)
+
+
+class FieldSerializer(BaseSerializer):
+
+ def __init__(self, predicate=None, convert=None, source=None, many=False):
+ super(FieldSerializer, self).__init__(predicate=predicate, many=many)
+ self.convert = convert or (lambda x: Literal(unicode(x)) if x else None)
+ self.source = source
+
+
+ def get_rdf_object(self, obj, fieldname):
+ raise NotImplemented()
+
+ def to_graph(self, subject, obj, fieldname, graph):
+ o = self.get_rdf_object(obj, fieldname)
+ if o:
+ graph.add((subject, self.predicate, o))
+
+
+class SimpleFieldSerializer(FieldSerializer):
+
+ def __init__(self, predicate=None, convert=None, source=None, lang_field=None):
+ super(SimpleFieldSerializer, self).__init__(predicate=predicate, convert=convert, source=source, many=False)
+ self.lang_field = lang_field
+
+ def get_rdf_object(self, obj, fieldname):
+ res = self.convert(getattr(obj, self.source or fieldname))
+ if res is None:
+ return
+ if not isinstance(res, Literal):
+ res = Literal(unicode(res))
+ lang = getattr(obj, self.lang_field, None) if self.lang_field else None
+
+ return Literal(res.value, lang) if lang else res
+
+class BooleanFieldSerializer(SimpleFieldSerializer):
+
+ def bool_convert(self, value):
+ return (Literal('TRUE') if value else Literal('FALSE')) if value is not None else None
+
+ def __init__(self, predicate=None, convert=None, source=None, lang_field=None):
+ super(BooleanFieldSerializer, self).__init__( predicate, convert=convert, source=source, lang_field=lang_field)
+ self.convert = lambda x: self.bool_convert(x)
+
+
+class RelatedFieldSerializer(SimpleFieldSerializer):
+
+ def __init__(self, value_field, predicate=None, convert=None, source=None, many=False, lang_field=None):
+ super(RelatedFieldSerializer, self).__init__(predicate, convert, source, lang_field=lang_field)
+ self.many = many
+ self.value_field = value_field
+
+ def to_graph(self, subject, obj, fieldname, graph):
+ value = getattr(obj, fieldname, None)
+ if not value:
+ return
+
+ values_to_add = []
+ if self.many:
+ for related_obj in value.all():
+ values_to_add.append(self.get_rdf_object(related_obj, self.value_field))
+ else:
+ values_to_add.append(self.get_rdf_object(value, self.value_field))
+ for o in values_to_add:
+ if o:
+ graph.add((subject, self.predicate, o))
+
+
+
+# Directly adapted from serializers in rest_framework
+def _get_declared_fields(bases, attrs):
+ """
+ Create a list of serializer field instances from the passed in 'attrs',
+ plus any fields on the base classes (in 'bases').
+
+ Note that all fields from the base classes are used.
+ """
+ fields = [(field_name, attrs.pop(field_name))
+ for field_name, obj in list(attrs.iteritems())
+ if isinstance(obj, BaseSerializer)]
+ fields.sort(key=lambda x: x[1].creation_counter)
+
+ # If this class is subclassing another Serializer, add that Serializer's
+ # fields. Note that we loop over the bases in *reverse*. This is necessary
+ # in order to maintain the correct order of fields.
+ for base in bases[::-1]:
+ if hasattr(base, 'base_serializers'):
+ fields = list(base.base_serializers.items()) + fields
+
+ return OrderedDict(fields)
+
+
+class SerializerMetaclass(type):
+ def __new__(cls, name, bases, attrs):
+ attrs['base_serializers'] = _get_declared_fields(bases, attrs)
+ return super(SerializerMetaclass, cls).__new__(cls, name, bases, attrs)
+
+
+class ModelSerializerOptions(object):
+
+ def __init__(self, meta):
+ self.type = getattr(meta, 'type', None)
+ if self.type and not isinstance(self.type, URIRef):
+ self.type = URIRef(self.type)
+ self.uri_fieldname = getattr(meta, 'uri_fieldname', None)
+
+class ModelSerializer(BaseSerializer):
+
+ __metaclass__ = SerializerMetaclass
+
+ class Meta(object):
+ pass
+
+ def get_serializers(self):
+ return []
+
+ def get_uri(self, obj):
+ uri = None
+ if self.opts.uri_fieldname:
+ uri = getattr(obj, self.opts.uri_fieldname, None)
+ return URIRef(uri) if uri else None
+
+ def object_to_graph(self, subject, uri, obj, graph):
+
+ if self.predicate:
+ graph.add((subject, self.predicate, uri))
+
+ for serializer_fieldname, field_serializer in self.base_serializers.iteritems():
+ field_serializer.to_graph(uri, obj, serializer_fieldname, graph)
+
+
+ def to_graph(self, subject, obj, fieldname, graph):
+
+ uri = self.get_uri(obj)
+ if self.opts.type:
+ graph.add((uri, RDF.type, self.opts.type))
+
+ obj_to_add = []
+ if fieldname:
+ field_value = getattr(obj, fieldname, None)
+ if field_value:
+ if self.many:
+ obj_to_add = [(nested_obj, BNode()) for nested_obj in field_value.all()]
+ else:
+ obj_to_add = [(field_value, BNode())]
+ else:
+ obj_to_add = [(obj, uri)]
+
+ for nested_obj, nested_uri in obj_to_add:
+ self.object_to_graph( subject, nested_uri, nested_obj, graph)
+
+
+ def __init__(self, predicate=None, many=False):
+ BaseSerializer.__init__(self, predicate=predicate, many=many)
+ self.opts = ModelSerializerOptions(self.Meta)
+