]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/web/js/ui/default/staff/cat/services/tagtable.js
webstaff: improve initialization of egTable.authorityControlSet()
[Evergreen.git] / Open-ILS / web / js / ui / default / staff / cat / services / tagtable.js
1 /*
2  * Retrieve, cache, and query MARC tag tables
3  */
4 angular.module('egCoreMod')
5 .factory('egTagTable', 
6        ['$q', 'egCore', 'egAuth',
7 function($q,   egCore,   egAuth) {
8
9     var service = {
10         defaultTagTableSelector : {
11             marcFormat     : 'marc21',
12             marcRecordType : 'biblio',
13         },
14         fields : { },
15         ff_pos_map : { },
16         ff_value_map : { },
17         authority_control_set : {
18             _controlsets : [ ]
19         }
20     };
21
22     // allow 'bre' and 'biblio' to be synonyms, etc.
23     service.normalizeRecordType = function(recordType) {
24         if (recordType === 'sre') {
25             return 'serial';
26         } else if (recordType === 'bre') {
27             return 'biblio';
28         } else if (recordType === 'are') {
29             return 'authority';
30         } else {
31             return recordType;
32         }
33     };
34
35     service.loadTagTable = function(args) {
36         var fields = service.defaultTagTableSelector;
37         if (args) {
38             if (args.marcFormat) {
39                 fields.marcFormat = args.marcFormat;
40             }
41             if (args.marcRecordType) {
42                 fields.marcRecordType = service.normalizeRecordType(args.marcRecordType);
43             }
44         }
45         var tt_key = 'current_tag_table_' + fields.marcFormat + '_' +
46                      fields.marcRecordType;
47         egCore.hatch.getItem(tt_key).then(function(tt) {
48             if (tt) {
49                 service.fields = tt;
50             } else {
51                 service.loadRemoteTagTable(fields, tt_key);
52             }
53         });
54     };
55
56     service.fetchFFPosTable = function(rtype) {
57         var deferred = $q.defer();
58
59         var hatch_pos_key = 'FFPosTable_'+rtype;
60
61         egCore.hatch.getItem(hatch_pos_key).then(function(cached_table) {
62             if (cached_table) {
63                 service.ff_pos_map[rtype] = cached_table;
64                 deferred.resolve(cached_table);
65
66             } else {
67
68                 egCore.net.request( // First, get the list of FFs (minus 006)
69                     'open-ils.fielder',
70                     'open-ils.fielder.cmfpm.atomic',
71                     { query : { tag : { '!=' : '006' } } }
72                 ).then(function (data)  {
73                     service.ff_pos_map[rtype] = data;
74                     egCore.hatch.setItem(hatch_pos_key, data);
75                     deferred.resolve(data);
76                 });
77             }
78         });
79
80         return deferred.promise;
81     };
82
83     service.fetchFFValueTable = function(rtype) {
84         var deferred = $q.defer();
85
86         var hatch_value_key = 'FFValueTable_'+rtype;
87
88         egCore.hatch.getItem(hatch_value_key).then(function(cached_table) {
89             if (cached_table) {
90                 service.ff_value_map[rtype] = cached_table;
91                 deferred.resolve(cached_table);
92
93             } else {
94
95                 egCore.net.request(
96                         'open-ils.cat',
97                         'open-ils.cat.biblio.fixed_field_values.by_rec_type',
98                         rtype
99                 ).then(function (data)  {
100                     service.ff_value_map[rtype] = data;
101                     egCore.hatch.setItem(hatch_value_key, data);
102                     deferred.resolve(data);
103                 });
104             }
105         });
106
107         return deferred.promise;
108     };
109
110     service.loadRemoteTagTable = function(fields, tt_key) {
111         egCore.net.request(
112             'open-ils.cat',
113             'open-ils.cat.tag_table.all.retrieve.local',
114             egAuth.token(), fields.marcFormat, fields.marcRecordType
115         ).then(
116             function (data)  {
117                 egCore.hatch.setItem(tt_key, service.fields);
118             },
119             function (err)   { console.err('error fetch tag table: ' + err) }, 
120             function (field) {
121                 if (!field) return;
122                 service.fields[field.tag] = field;
123             }
124         );
125     };
126
127     service.getFieldTags = function() {
128         var list = [];
129         angular.forEach(service.fields, function(value, key) {
130             this.push({ 
131                 value: key,
132                 label: key + ': ' + value.name
133             });
134         }, list);
135         return list;
136     }
137
138     service.getSubfieldCodes = function(tag) {
139         var list = [];
140         if (!tag) return;
141         if (!service.fields[tag]) return;
142         angular.forEach(service.fields[tag].subfields, function(value) {
143             this.push({
144                 value: value.code,
145                 label: value.code + ': ' + value.description
146             });
147         }, list);
148         return list;
149     }
150
151     service.getSubfieldValues = function(tag, sf_code) {
152         var list = [];
153         if (!tag) return list;
154         if (!service.fields[tag]) return;
155         if (!service.fields[tag]) return;
156         angular.forEach(service.fields[tag].subfields, function(sf) {
157             if (sf.code == sf_code && sf.hasOwnProperty('value_list')) {
158                 angular.forEach(sf.value_list, function(value) {
159                     var label = (value.code == value.description) ?
160                                 value.code :
161                                 value.code + ': ' + value.description;
162                     this.push({
163                         value: value.code,
164                         label: label
165                     });
166                 }, this);
167             }
168         }, list);
169         return list;
170     }
171
172     service.getIndicatorValues = function(tag, pos) {
173         var list = [];
174         if (!tag) return list;
175         if (!service.fields[tag]) return;
176         if (!service.fields[tag]["ind" + pos]) return;
177         angular.forEach(service.fields[tag]["ind" + pos], function(value) {
178             this.push({
179                 value: value.code,
180                 label: value.code + ': ' + value.description
181             });
182         }, list);
183         return list;
184     }
185
186     service.authorityControlSet = function (kwargs) {
187     
188         kwargs = kwargs || {};
189
190         this._fetch_class = function(hint, cache_key) {
191             return egCore.pcrud.retrieveAll(hint, {}, {atomic : true}).then(
192                 function(list) {
193                     egCore.env.absorbList(list, hint);
194                     service.authority_control_set[cache_key] = list;
195                 }
196             );
197         };
198
199         this._fetch = function(cmap) {
200             var deferred = $q.defer();
201             var promises = [];
202             for (var hint in cmap) {
203                 promises.push(this._fetch_class(hint, cmap[hint]));
204             }
205             $q.all(promises).then(function() {
206                 deferred.resolve();
207             });
208             return deferred.promise;
209         };
210
211         this._parse = function() {
212             service.authority_control_set._browse_axis_by_code = {};
213             service.authority_control_set._browse_axis_list.forEach(function (ba) {
214                 ba.maps(
215                     service.authority_control_set._browse_field_map_list.filter(
216                         function (m) { return m.axis() == ba.code() }
217                     )
218                 );
219                 service.authority_control_set._browse_axis_by_code[ba.code()] = ba;
220             });
221     
222             // loop over each acs
223             service.authority_control_set._control_set_list.forEach(function (cs) {
224                 service.authority_control_set._controlsets[''+cs.id()] = {
225                     id : cs.id(),
226                     name : cs.name(),
227                     description : cs.description(),
228                     authority_tag_map : {},
229                     control_map : {},
230                     bib_fields : [],
231                     raw : cs
232                 };
233     
234                 // grab the authority fields
235                 var acsaf_list = service.authority_control_set._authority_field_list.filter(
236                     function (af) { return af.control_set() == cs.id() }
237                 );
238     
239                 var at_list = service.authority_control_set._thesaurus_list.filter(
240                     function (at) { return at.control_set() == cs.id() }
241                 );
242     
243                 service.authority_control_set._controlsets[''+cs.id()].raw.authority_fields( acsaf_list );
244                 service.authority_control_set._controlsets[''+cs.id()].raw.thesauri( at_list );
245     
246                 // and loop over each
247                 acsaf_list.forEach(function (csaf) {
248                     csaf.axis_maps([]);
249     
250                     // link the main entry if we're subordinate
251                     if (csaf.main_entry()) {
252                         csaf.main_entry(
253                             acsaf_list.filter(function (x) {
254                                 return x.id() == csaf.main_entry();
255                             })[0]
256                         );
257                     }
258     
259                     // link the sub entries if we're main
260                     csaf.sub_entries(
261                         acsaf_list.filter(function (x) {
262                             return x.main_entry() == csaf.id();
263                         })
264                     );
265     
266                     // now, bib fields
267                     var acsbf_list = service.authority_control_set._bib_field_list.filter(
268                         function (b) { return b.authority_field() == csaf.id() }
269                     );
270                     csaf.bib_fields( acsbf_list );
271     
272                     service.authority_control_set._controlsets[''+cs.id()].bib_fields = [].concat(
273                         service.authority_control_set._controlsets[''+cs.id()].bib_fields,
274                         acsbf_list
275                     );
276     
277                     acsbf_list.forEach(function (csbf) {
278                         // link the authority field to the bib field
279                         if (csbf.authority_field()) {
280                             csbf.authority_field(
281                                 acsaf_list.filter(function (x) {
282                                     return x.id() == csbf.authority_field();
283                                 })[0]
284                             );
285                         }
286     
287                     });
288     
289                     service.authority_control_set._browse_axis_list.forEach(
290                         function (ba) {
291                             ba.maps().filter(
292                                 function (m) { return m.field() == csaf.id() }
293                             ).forEach(
294                                 function (fm) { fm.field( csaf ); csaf.axis_maps().push( fm ) } // and set the field
295                             )
296                         }
297                     );
298     
299                 });
300     
301                 // build the authority_tag_map
302                 service.authority_control_set._controlsets[''+cs.id()].bib_fields.forEach(function (bf) {
303     
304                     if (!service.authority_control_set._controlsets[''+cs.id()].control_map[bf.tag()])
305                         service.authority_control_set._controlsets[''+cs.id()].control_map[bf.tag()] = {};
306     
307                     bf.authority_field().sf_list().split('').forEach(function (sf_code) {
308     
309                         if (!service.authority_control_set._controlsets[''+cs.id()].control_map[bf.tag()][sf_code])
310                             service.authority_control_set._controlsets[''+cs.id()].control_map[bf.tag()][sf_code] = {};
311     
312                         service.authority_control_set._controlsets[''+cs.id()].control_map[bf.tag()][sf_code][bf.authority_field().tag()] = sf_code;
313                     });
314                 });
315     
316             });
317     
318             if (this.controlSetList().length > 0)
319                 delete service.authority_control_set._controlsets['-1'];
320     
321         }
322     
323         this.controlSetId = function (x) {
324             if (x) this._controlset = ''+x;
325             return this._controlset;
326         }
327
328         this.controlSetList = function () {
329             var l = [];
330             for (var i in service.authority_control_set._controlsets) {
331                 l.push(i);
332             }
333             return l;
334         }
335     
336     
337         if (!service.authority_control_set._remote_loaded) {
338     
339             // TODO -- push the raw tree into the oils cache for later reuse
340     
341             // fetch everything up front...
342             var parent = this;
343             this._fetch({
344                 "acs": "_control_set_list",
345                 "at": "_thesaurus_list",
346                 "acsaf": "_authority_field_list",
347                 "acsbf": "_bib_field_list",
348                 "aba": "_browse_axis_list",
349                 "abaafm": "_browse_field_map_list"
350             }).then(function() {
351                 service.authority_control_set._remote_loaded = true;
352                 parent._parse();
353                 if (kwargs.controlSet) {
354                     parent.controlSetId( kwargs.controlSet );
355                 } else {
356                     parent.controlSetId( parent.controlSetList().sort(function(a,b){return (a - b)}) );
357                 }
358             });
359         }
360
361         this.controlSet = function (x) {
362             return service.authority_control_set._controlsets[''+this.controlSetId(x)];
363         }
364     
365         this.controlSetByThesaurusCode = function (x) {
366             var thes = service.authority_control_set._thesaurus_list.filter(
367                 function (at) { return at.code() == x }
368             )[0];
369     
370             return this.controlSet(thes.control_set());
371         }
372     
373         this.browseAxisByCode = function(code) {
374             return service.authority_control_set._browse_axis_by_code[code];
375         }
376     
377         this.bibFieldByTag = function (x) {
378             var me = this;
379             return me.controlSet().bib_fields.filter(
380                 function (bf) { if (bf.tag() == x) return true }
381             )[0];
382         }
383     
384         this.bibFields = function (x) {
385             return this.controlSet(x).bib_fields;
386         }
387     
388         this.bibFieldBrowseAxes = function (t) {
389             var blist = [];
390             for (var bcode in service.authority_control_set._browse_axis_by_code) {
391                 service.authority_control_set._browse_axis_by_code[bcode].maps().forEach(
392                     function (m) {
393                         if (m.field().bib_fields().filter(
394                                 function (b) { return b.tag() == t }
395                             ).length > 0
396                         ) blist.push(bcode);
397                     }
398                 );
399             }
400             return blist;
401         }
402     
403         this.authorityFields = function (x) {
404             return this.controlSet(x).raw.authority_fields();
405         }
406     
407         this.thesauri = function (x) {
408             return this.controlSet(x).raw.thesauri();
409         }
410     
411         this.findControlSetsForTag = function (tag) {
412             var me = this;
413             var old_acs = this.controlSetId();
414             var acs_list = me.controlSetList().filter(
415                 function(acs_id) { return (me.controlSet(acs_id).control_map[tag]) }
416             );
417             this.controlSetId(old_acs);
418             return acs_list;
419         }
420     
421         this.findControlSetsForAuthorityTag = function (tag) {
422             var me = this;
423             var old_acs = this.controlSetId();
424     
425             var acs_list = me.controlSetList().filter(
426                 function(acs_id) {
427                     var a = me.controlSet(acs_id);
428                     for (var btag in a.control_map) {
429                         for (var sf in a.control_map[btag]) {
430                             if (a.control_map[btag][sf][tag]) return true;
431                         }
432                     }
433                     return false;
434                 }
435             );
436             this.controlSetId(old_acs);
437             return acs_list;
438         }
439     
440         this.bibToAuthority = function (field) {
441             var b_field = this.bibFieldByTag(field.tag);
442     
443             if (b_field) { // construct an marc authority record
444                 var af = b_field.authority_field();
445     
446                 var sflist = [];                
447                 for (var i = 0; i < field.subfields.length; i++) {
448                     if (af.sf_list().indexOf(field.subfields[i][0]) > -1) {
449                         sflist.push(field.subfields[i]);
450                     }
451                 }
452     
453                 var m = new MARC21.Record ({rtype:'AUT'});
454                 m.appendFields(
455                     new MARC21.Field ({
456                         tag : af.tag(),
457                         ind1: field.ind1,
458                         ind2: field.ind2,
459                         subfields: sflist
460                     })
461                 );
462     
463                 return m.toXmlString();
464             }
465     
466             return null;
467         }
468     
469         this.bibToAuthorities = function (field) {
470             var auth_list = [];
471             var me = this;
472     
473             var old_acs = this.controlSetId();
474             me.controlSetList().forEach(
475                 function (acs_id) {
476                     var acs = me.controlSet(acs_id);
477                     var x = me.bibToAuthority(field);
478                     if (x) { var foo = {}; foo[acs_id] = x; auth_list.push(foo); }
479                 }
480             );
481             this.controlSetId(old_acs);
482     
483             return auth_list;
484         }
485     
486         // This should not be used in an angular world.  Instead, the call
487         // to open-ils.search.authority.simple_heading.from_xml.batch.atomic should
488         // be performed by the code that wants to find matching authorities.
489         this.findMatchingAuthorities = function (field) {
490             return fieldmapper.standardRequest(
491                 [ 'open-ils.search', 'open-ils.search.authority.simple_heading.from_xml.batch.atomic' ],
492                 this.bibToAuthorities(field)
493             );
494         }
495
496     }
497
498     return service;
499 }]);