Passed
Push — 2.x ( 041ff6...87c3c9 )
by Jordi
08:54
created

ReferenceWidgetDataProvider.lookup()   B

Complexity

Conditions 6

Size

Total Lines 29
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 19
dl 0
loc 29
rs 8.5166
c 0
b 0
f 0
cc 6
nop 4
1
# -*- coding: utf-8 -*-
2
3
import json
4
5
import Missing
6
from Acquisition import aq_base
7
from Acquisition import aq_inner
8
from bika.lims import api
9
from Products.CMFPlone.utils import base_hasattr
10
from senaite.core import logger
11
from senaite.core.interfaces import IReferenceWidgetDataProvider
12
from zope.interface import implementer
13
14
_marker = object()
15
MISSING_VALUES = [_marker, Missing.Value]
16
17
18
@implementer(IReferenceWidgetDataProvider)
19
class ReferenceWidgetDataProvider(object):
20
    def __init__(self, context, request):
21
        self.request = request
22
        self.context = context
23
24
    def get_field_name(self):
25
        """Return the field name
26
        """
27
        return self.request.get("field_name", None)
28
29
    def get_columns(self):
30
        """Return the requested columns
31
        """
32
        columns = self.request.get("column_names", [])
33
        if api.is_string(columns):
34
            # seems to be converted to string only if only one column exists.
35
            return [columns]
36
        return columns
37
38
    def lookup(self, brain_or_object, name, default=None):
39
        """Lookup a named attribute on the brain/object
40
        """
41
        if base_hasattr(brain_or_object, name):
42
            value = getattr(aq_base(aq_inner(brain_or_object)), name, _marker)
43
        else:
44
            value = _marker
45
46
        # wake up the object
47
        if value is _marker:
48
            logger.info("No catalog metadata found for '{name}'"
49
                        "in catalog {catalog}. Waking up the object!".format(
50
                            name=name, catalog=brain_or_object.aq_parent.id))
51
            obj = api.get_object(brain_or_object)
52
            value = getattr(obj, name, default)
53
54
        # Fallback to the default value if we do not have a catalog metadata
55
        if value in MISSING_VALUES:
56
            value = default
57
58
        if callable(value):
59
            value = value()
60
61
        try:
62
            json.dumps(value)
63
            return value
64
        except TypeError:
65
            # not JSON serializable
66
            return default
67
68
    def get_base_info(self, brain_or_object):
69
        """Return the base information for the brain or object
70
        """
71
        id = self.lookup(brain_or_object, "getId", "")
72
        title = self.lookup(brain_or_object, "Title", "")
73
        description = self.lookup(brain_or_object, "Description", "")
74
        return {
75
            "id": id,
76
            "getId": id,
77
            "uid": api.get_uid(brain_or_object),
78
            "url": api.get_url(brain_or_object),
79
            "Title": title or id,
80
            "title": title or id,
81
            "Description": description,
82
            "description": description,
83
            "review_state": api.get_review_status(brain_or_object),
84
        }
85
86
    def to_dict(self, reference, data=None, **kw):
87
        """Return the required data for the given object or uid
88
89
        :param reference: Catalog Brain, AT/DX object or UID
90
        :param data: Dictionary of collected data
91
        """
92
        info = {}
93
94
        if isinstance(data, dict):
95
            info.update(data)
96
97
        # Fetch the object if an UID is passed
98
        if api.is_uid(reference):
99
            brain_or_object = api.get_object(reference)
100
        else:
101
            brain_or_object = reference
102
103
        # always include base information
104
        info.update(self.get_base_info(brain_or_object))
105
106
        columns = self.get_columns()
107
108
        # always include all brain metadata
109
        if api.is_brain(brain_or_object):
110
            columns.extend(brain_or_object.schema())
111
112
        for column in columns:
113
            if column not in info:
114
                info[column] = self.lookup(brain_or_object, column, default="")
115
116
        return info
117