"""
This file is part of the everest project.
See LICENSE.txt for licensing, CONTRIBUTORS.txt for contributor information.
Resource attribute handling classes.
Created on Dec 2, 2011.
"""
from collections import OrderedDict
from everest.resources.descriptors import CARDINALITY
from everest.resources.descriptors import attribute_base
from everest.resources.descriptors import collection_attribute
from everest.resources.descriptors import member_attribute
from everest.resources.descriptors import terminal_attribute
from everest.resources.kinds import ResourceKinds
from everest.resources.utils import get_member_class
__docformat__ = 'reStructuredText en'
__all__ = ['CollectionResourceAttribute',
'MemberResourceAttribute',
'MetaResourceAttributeCollector',
'ResourceAttributeControllerMixin',
'ResourceAttributeKinds',
'TerminalResourceAttribute',
'get_resource_class_attribute_names',
'get_resource_class_attributes',
'is_collection_attribute',
'is_member_attribute',
'is_terminal_attribute',
]
[docs]class ResourceAttributeKinds(object):
"""
Static container for resource attribute kind constants.
We have three kinds of resource attribute:
MEMBER :
a member resource attribute
COLLECTION :
a collection resource attribute
TERMINAL :
an attribute that is not a resource
"""
MEMBER = ResourceKinds.MEMBER
COLLECTION = ResourceKinds.COLLECTION
TERMINAL = 'TERMINAL'
class _ResourceAttribute(object):
"""
Value object holding information about a resource attribute.
"""
#: The kind of the attribute. Set to one of the constants defined in the
#: :class: `ResourceAttributeKinds` class in derived classes.
kind = None
def __init__(self, name, value_type, cardinality, entity_name=None):
#: The name of the attribute in the resource.
self.name = name
#: The type or interface of the attribute in the underlying entity.
self.value_type = value_type
#: For non-terminal attributes, indicates the cardinality of the
#: relationship.
self.cardinality = cardinality
#: The name of the attribute in the underlying entity.
self.entity_name = entity_name
[docs]class TerminalResourceAttribute(_ResourceAttribute):
"""
Resource attribute class for terminal attribute declarations.
"""
kind = ResourceAttributeKinds.TERMINAL
def __init__(self, name, value_type, entity_name=None):
_ResourceAttribute.__init__(self, name, value_type, None,
entity_name=entity_name)
class _ResourceResourceAttribute(_ResourceAttribute):
def __init__(self, name, value_type, cardinality,
entity_name=None, is_nested=False):
_ResourceAttribute.__init__(self, name, value_type, cardinality,
entity_name=entity_name)
#: If this is set, URLs for this resource attribute will be relative
#: to the parent resource.
self.is_nested = is_nested
[docs]class MemberResourceAttribute(_ResourceResourceAttribute):
"""
Resource attribute class for member attribute declarations.
"""
kind = ResourceAttributeKinds.MEMBER
def __init__(self, name, value_type, cardinality=CARDINALITY.MANYTOONE,
entity_name=None, is_nested=False):
_ResourceResourceAttribute.__init__(self, name, value_type,
cardinality,
entity_name=entity_name,
is_nested=is_nested)
[docs]class CollectionResourceAttribute(_ResourceResourceAttribute):
"""
Resource attribute class for collection attribute declarations.
"""
kind = ResourceAttributeKinds.COLLECTION
def __init__(self, name, value_type, cardinality=CARDINALITY.ONETOMANY,
entity_name=None, is_nested=False):
_ResourceResourceAttribute.__init__(self, name, value_type,
cardinality,
entity_name=entity_name,
is_nested=is_nested)
class ResourceAttributeControllerMixin(object):
__metaclass__ = MetaResourceAttributeCollector
# Populated by the meta class.
_attributes = None
@classmethod
def is_terminal(cls, attr):
"""
Checks if the given resource class attribute is a terminal resource
attribute.
"""
return cls._attributes[attr].kind == ResourceAttributeKinds.TERMINAL
@classmethod
def is_member(cls, attr):
"""
Checks if the given resource class attribute is a member resource
attribute.
"""
return cls._attributes[attr].kind == ResourceAttributeKinds.MEMBER
@classmethod
def is_collection(cls, attr):
"""
Checks if the given resource class attribute is a collection resource
attribute.
"""
return cls._attributes[attr].kind == ResourceAttributeKinds.COLLECTION
@classmethod
def is_resource(cls, attr):
"""
Checks if the given resource class attribute is a member or collection
resource attribute.
"""
return cls._attributes[attr].kind \
in [ResourceAttributeKinds.MEMBER,
ResourceAttributeKinds.COLLECTION]
@classmethod
def get_attribute_names(cls):
"""
Returns all attribute names of the given resource class.
"""
return cls._attributes.keys()
@classmethod
def get_attributes(cls):
"""
Returns a dictionary mapping the attribute names of the given
resource class to :class:`ResourceAttribute` instances.
"""
return cls._attributes
def is_terminal_attribute(rc, attr_name):
mb_cls = get_member_class(rc)
return mb_cls.is_terminal(attr_name)
def is_member_attribute(rc, attr_name):
mb_cls = get_member_class(rc)
return mb_cls.is_member(attr_name)
def is_collection_attribute(rc, attr_name):
mb_cls = get_member_class(rc)
return mb_cls.is_collection(attr_name)
def get_resource_class_attribute_names(rc):
mb_cls = get_member_class(rc)
return mb_cls.get_attribute_names()
def get_resource_class_attributes(rc):
mb_cls = get_member_class(rc)
return mb_cls.get_attributes()