Coverage for portality/models/v1/bibjson.py: 82%
144 statements
« prev ^ index » next coverage.py v6.4.2, created at 2022-07-22 15:59 +0100
« prev ^ index » next coverage.py v6.4.2, created at 2022-07-22 15:59 +0100
1from portality.lib import dataobj
2from portality.models.v1 import shared_structs
4class GenericBibJSON(dataobj.DataObj):
5 # vocab of known identifier types
6 P_ISSN = "pissn"
7 E_ISSN = "eissn"
8 DOI = "doi"
10 # allowable values for the url types
11 HOMEPAGE = "homepage"
12 WAIVER_POLICY = "waiver_policy"
13 EDITORIAL_BOARD = "editorial_board"
14 AIMS_SCOPE = "aims_scope"
15 AUTHOR_INSTRUCTIONS = "author_instructions"
16 OA_STATEMENT = "oa_statement"
17 FULLTEXT = "fulltext"
19 # constructor
20 def __init__(self, bibjson=None, **kwargs):
21 self._add_struct(shared_structs.SHARED_BIBJSON.get("structs", {}).get("bibjson"))
22 # construct_maintain_reference is enforced here, don't allow override with kwargs
23 kwargs.pop('construct_maintain_reference', None)
24 super(GenericBibJSON, self).__init__(raw=bibjson, construct_maintain_reference=True, **kwargs)
26 ####################################################
27 # shared simple property getter and setters
29 @property
30 def title(self):
31 return self._get_single("title")
33 @title.setter
34 def title(self, val):
35 self._set_with_struct("title", val)
37 #####################################################
38 # complex getters and setters
41 ## work with the identifiers
43 def add_identifier(self, idtype, value):
44 self._delete_from_list("identifier", matchsub={"type": idtype})
45 idobj = {"type" : idtype, "id" : self._normalise_identifier(idtype, value)}
46 self._add_to_list_with_struct("identifier", idobj)
48 def get_identifiers(self, idtype=None):
49 if idtype is None:
50 return self._get_list("identifier")
52 ids = []
53 for identifier in self._get_list("identifier"):
54 if identifier.get("type") == idtype and identifier.get("id") not in ids:
55 ids.append(identifier.get("id"))
56 return ids
58 def get_one_identifier(self, idtype=None):
59 results = self.get_identifiers(idtype=idtype)
60 if len(results) > 0:
61 return results[0]
62 else:
63 return None
65 def remove_identifiers(self, idtype=None, id=None):
66 # if we are to remove all identifiers, this is easy
67 if idtype is None and id is None:
68 self._delete("identifier")
69 return
71 match = {}
72 if idtype is not None:
73 match["type"] = idtype
74 if id is not None:
75 match["id"] = id
76 self._delete_from_list("identifier", matchsub=match)
78 def _normalise_identifier(self, idtype, value):
79 if idtype in [self.P_ISSN, self.E_ISSN]:
80 return self._normalise_issn(value)
81 return value
83 def _normalise_issn(self, issn):
84 issn = issn.upper()
85 if len(issn) > 8: return issn
86 if len(issn) == 8:
87 if "-" in issn: return "0" + issn
88 else: return issn[:4] + "-" + issn[4:]
89 if len(issn) < 8:
90 if "-" in issn: return ("0" * (9 - len(issn))) + issn
91 else:
92 issn = ("0" * (8 - len(issn))) + issn
93 return issn[:4] + "-" + issn[4:]
95 ## work with keywords
97 @property
98 def keywords(self):
99 return self._get_list("keywords")
101 def add_keyword(self, keyword):
102 if keyword is not None:
103 self._add_to_list_with_struct("keywords", keyword.lower())
105 def set_keywords(self, keywords):
106 if type(keywords) is list:
107 keywords = [w.lower() for w in keywords]
108 self._set_with_struct("keywords", keywords)
109 else:
110 if keywords is not None:
111 self._set_with_struct("keywords", keywords.lower())
113 ## work with urls
115 def add_url(self, url, urltype=None, content_type=None):
116 if url is None:
117 # do not add empty URL-s
118 return
120 urlobj = {"url": url}
121 if urltype is not None:
122 urlobj["type"] = urltype
123 if content_type is not None:
124 urlobj["content_type"] = content_type
126 self._add_to_list_with_struct("link", urlobj)
128 def get_urls(self, urltype=None, unpack_urlobj=True):
129 if urltype is None:
130 return self._get_list("link")
132 urls = []
133 for link in self._get_list("link"):
134 if link.get("type") == urltype:
135 if unpack_urlobj:
136 urls.append(link.get("url"))
137 else:
138 urls.append(link)
139 return urls
141 def get_single_url(self, urltype, unpack_urlobj=True):
142 urls = self.get_urls(urltype=urltype, unpack_urlobj=unpack_urlobj)
143 if len(urls) > 0:
144 return urls[0]
145 return None
147 def remove_urls(self, urltype=None, url=None):
148 # if we are to remove all urls, this is easy
149 if urltype is None and url is None:
150 self._delete("link")
151 return
153 match = {}
154 if urltype is not None:
155 match["type"] = urltype
156 if url is not None:
157 match["url"] = id
158 self._delete_from_list("link", matchsub=match)
160 ## work with subjects
162 def add_subject(self, scheme, term, code=None):
163 sobj = {"scheme" : scheme, "term" : term}
164 if code is not None:
165 sobj["code"] = code
166 self._add_to_list_with_struct("subject", sobj)
168 def subjects(self):
169 return self._get_list("subject")
171 def set_subjects(self, subjects):
172 self._set_with_struct("subject", subjects)
174 def remove_subjects(self):
175 self._delete("subject")
177 def lcc_paths(self):
178 classification_paths = []
180 # calculate the classification paths
181 from portality.lcc import lcc # inline import since this hits the database
182 for subs in self.subjects():
183 scheme = subs.get("scheme")
184 term = subs.get("term")
185 if scheme == "LCC":
186 p = lcc.pathify(term)
187 if p is not None:
188 classification_paths.append(p)
190 # normalise the classification paths, so we only store the longest ones
191 classification_paths = lcc.longest(classification_paths)
193 return classification_paths
195 def issns(self):
196 issns = []
197 issns += self.get_identifiers(self.P_ISSN)
198 issns += self.get_identifiers(self.E_ISSN)
199 return issns
201 @property
202 def first_pissn(self):
203 return self.get_identifiers(self.P_ISSN)[0]
205 @property
206 def first_eissn(self):
207 return self.get_identifiers(self.E_ISSN)[0]