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