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