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