2 * Retrieve, cache, and query MARC tag tables
4 angular.module('egCoreMod')
6 ['$q', 'egCore', 'egAuth',
7 function($q, egCore, egAuth) {
10 defaultTagTableSelector : {
11 marcFormat : 'marc21',
12 marcRecordType : 'biblio',
17 phys_char_type_map : null,
18 phys_char_sf_map : { },
19 phys_char_value_map : { },
20 authority_control_set : {
21 _remote_loaded : false,
24 _active_control_set : undefined
27 service.initialized = function() {
28 return service.authority_control_set._remote_loaded;
31 // allow 'bre' and 'biblio' to be synonyms, etc.
32 service.normalizeRecordType = function(recordType) {
33 if (recordType === 'sre') {
35 } else if (recordType === 'bre') {
37 } else if (recordType === 'are') {
44 service.loadTagTable = function(args) {
45 var fields = service.defaultTagTableSelector;
47 if (args.marcFormat) {
48 fields.marcFormat = args.marcFormat;
50 if (args.marcRecordType) {
51 fields.marcRecordType = service.normalizeRecordType(args.marcRecordType);
54 var tt_key = 'current_tag_table_' + fields.marcFormat + '_' +
55 fields.marcRecordType;
56 egCore.hatch.getItem(tt_key).then(function(tt) {
60 service.loadRemoteTagTable(fields, tt_key);
65 var _ffpos_promises = {};
66 service.fetchFFPosTable = function(rtype) {
67 if (!(rtype in _ffpos_promises)) {
68 _ffpos_promises[rtype] = $q.defer();
70 var hatch_pos_key = 'FFPosTable_'+rtype;
72 egCore.hatch.getItem(hatch_pos_key).then(function(cached_table) {
74 service.ff_pos_map[rtype] = cached_table;
75 _ffpos_promises[rtype].resolve(cached_table);
79 egCore.net.request( // First, get the list of FFs (minus 006)
81 'open-ils.fielder.cmfpm.atomic',
82 { query : { tag : { '!=' : '006' } } }
83 ).then(function (data) {
84 service.ff_pos_map[rtype] = data;
85 egCore.hatch.setItem(hatch_pos_key, data);
86 _ffpos_promises[rtype].resolve(data);
92 return _ffpos_promises[rtype].promise;
95 var _ffval_promises = {};
96 service.fetchFFValueTable = function(rtype) {
97 if (!(rtype in _ffval_promises)) {
98 _ffval_promises[rtype] = $q.defer();
100 var hatch_value_key = 'FFValueTable_'+rtype;
102 egCore.hatch.getItem(hatch_value_key).then(function(cached_table) {
104 service.ff_value_map[rtype] = cached_table;
105 _ffval_promises[rtype].resolve(cached_table);
111 'open-ils.cat.biblio.fixed_field_values.by_rec_type',
113 ).then(function (data) {
114 service.ff_value_map[rtype] = data;
115 egCore.hatch.setItem(hatch_value_key, data);
116 _ffval_promises[rtype].resolve(data);
122 return _ffval_promises[rtype].promise;
125 service.loadRemoteTagTable = function(fields, tt_key) {
128 'open-ils.cat.tag_table.all.retrieve.local',
129 egAuth.token(), fields.marcFormat, fields.marcRecordType
132 egCore.hatch.setItem(tt_key, service.fields);
134 function (err) { console.err('error fetch tag table: ' + err) },
137 service.fields[field.tag] = field;
142 service.getFieldTags = function() {
144 angular.forEach(service.fields, function(value, key) {
147 label: key + ': ' + value.name
153 service.getSubfieldCodes = function(tag) {
156 if (!service.fields[tag]) return;
157 angular.forEach(service.fields[tag].subfields, function(value) {
160 label: value.code + ': ' + value.description
166 service.getSubfieldValues = function(tag, sf_code) {
168 if (!tag) return list;
169 if (!service.fields[tag]) return;
170 if (!service.fields[tag]) return;
171 angular.forEach(service.fields[tag].subfields, function(sf) {
172 if (sf.code == sf_code && sf.hasOwnProperty('value_list')) {
173 angular.forEach(sf.value_list, function(value) {
174 var label = (value.code == value.description) ?
176 value.code + ': ' + value.description;
187 service.getIndicatorValues = function(tag, pos) {
189 if (!tag) return list;
190 if (!service.fields[tag]) return;
191 if (!service.fields[tag]["ind" + pos]) return;
192 angular.forEach(service.fields[tag]["ind" + pos], function(value) {
195 label: value.code + ': ' + value.description
201 service.authorityControlSet = function (kwargs) {
203 kwargs = kwargs || {};
205 this._fetch_class = function(hint, cache_key) {
206 return egCore.pcrud.retrieveAll(hint, {}, {atomic : true}).then(
208 egCore.env.absorbList(list, hint);
209 service.authority_control_set[cache_key] = list;
214 this._fetch = function(cmap) {
215 var deferred = $q.defer();
217 for (var hint in cmap) {
218 promises.push(this._fetch_class(hint, cmap[hint]));
220 $q.all(promises).then(function() {
223 return deferred.promise;
226 this._parse = function() {
227 service.authority_control_set._browse_axis_by_code = {};
228 service.authority_control_set._browse_axis_list.forEach(function (ba) {
230 service.authority_control_set._browse_field_map_list.filter(
231 function (m) { return m.axis() == ba.code() }
234 service.authority_control_set._browse_axis_by_code[ba.code()] = ba;
237 // loop over each acs
238 service.authority_control_set._control_set_list.forEach(function (cs) {
239 service.authority_control_set._controlsets[''+cs.id()] = {
242 description : cs.description(),
243 authority_tag_map : {},
249 // grab the authority fields
250 var acsaf_list = service.authority_control_set._authority_field_list.filter(
251 function (af) { return af.control_set() == cs.id() }
254 var at_list = service.authority_control_set._thesaurus_list.filter(
255 function (at) { return at.control_set() == cs.id() }
258 service.authority_control_set._controlsets[''+cs.id()].raw.authority_fields( acsaf_list );
259 service.authority_control_set._controlsets[''+cs.id()].raw.thesauri( at_list );
261 // and loop over each
262 acsaf_list.forEach(function (csaf) {
265 // link the main entry if we're subordinate
266 if (csaf.main_entry()) {
268 acsaf_list.filter(function (x) {
269 return x.id() == csaf.main_entry();
274 // link the sub entries if we're main
276 acsaf_list.filter(function (x) {
277 return x.main_entry() == csaf.id();
282 var acsbf_list = service.authority_control_set._bib_field_list.filter(
283 function (b) { return b.authority_field() == csaf.id() }
285 csaf.bib_fields( acsbf_list );
287 service.authority_control_set._controlsets[''+cs.id()].bib_fields = [].concat(
288 service.authority_control_set._controlsets[''+cs.id()].bib_fields,
292 acsbf_list.forEach(function (csbf) {
293 // link the authority field to the bib field
294 if (csbf.authority_field()) {
295 csbf.authority_field(
296 acsaf_list.filter(function (x) {
297 return x.id() == csbf.authority_field();
304 service.authority_control_set._browse_axis_list.forEach(
307 function (m) { return m.field() == csaf.id() }
309 function (fm) { fm.field( csaf ); csaf.axis_maps().push( fm ) } // and set the field
316 // build the authority_tag_map
317 service.authority_control_set._controlsets[''+cs.id()].bib_fields.forEach(function (bf) {
319 if (!service.authority_control_set._controlsets[''+cs.id()].control_map[bf.tag()])
320 service.authority_control_set._controlsets[''+cs.id()].control_map[bf.tag()] = {};
322 bf.authority_field().sf_list().split('').forEach(function (sf_code) {
324 if (!service.authority_control_set._controlsets[''+cs.id()].control_map[bf.tag()][sf_code])
325 service.authority_control_set._controlsets[''+cs.id()].control_map[bf.tag()][sf_code] = {};
327 service.authority_control_set._controlsets[''+cs.id()].control_map[bf.tag()][sf_code][bf.authority_field().tag()] = sf_code;
333 if (this.controlSetList().length > 0)
334 delete service.authority_control_set._controlsets['-1'];
338 this.controlSetId = function (x) {
339 if (x) this._controlset = ''+x;
340 return this._controlset;
343 this.controlSetList = function () {
345 for (var i in service.authority_control_set._controlsets) {
352 if (!service.authority_control_set._remote_loaded) {
354 // TODO -- push the raw tree into the oils cache for later reuse
356 // fetch everything up front...
359 "acs": "_control_set_list",
360 "at": "_thesaurus_list",
361 "acsaf": "_authority_field_list",
362 "acsbf": "_bib_field_list",
363 "aba": "_browse_axis_list",
364 "abaafm": "_browse_field_map_list"
366 service.authority_control_set._remote_loaded = true;
368 if (kwargs.controlSet) {
369 parent.controlSetId( kwargs.controlSet );
371 parent.controlSetId( parent.controlSetList().sort(function(a,b){return (a - b)}) );
376 this.controlSet = function (x) {
377 return service.authority_control_set._controlsets[''+this.controlSetId(x)];
380 this.controlSetByThesaurusCode = function (x) {
381 var thes = service.authority_control_set._thesaurus_list.filter(
382 function (at) { return at.code() == x }
385 return this.controlSet(thes.control_set());
388 this.browseAxisByCode = function(code) {
389 return service.authority_control_set._browse_axis_by_code[code];
392 this.bibFieldByTag = function (x) {
394 return me.controlSet().bib_fields.filter(
395 function (bf) { if (bf.tag() == x) return true }
399 this.bibFields = function (x) {
400 return this.controlSet(x).bib_fields;
403 this.bibFieldBrowseAxes = function (t) {
405 for (var bcode in service.authority_control_set._browse_axis_by_code) {
406 service.authority_control_set._browse_axis_by_code[bcode].maps().forEach(
408 if (m.field().bib_fields().filter(
409 function (b) { return b.tag() == t }
418 this.authorityFields = function (x) {
419 return this.controlSet(x).raw.authority_fields();
422 this.thesauri = function (x) {
423 return this.controlSet(x).raw.thesauri();
426 this.findControlSetsForTag = function (tag) {
428 var old_acs = this.controlSetId();
429 var acs_list = me.controlSetList().filter(
430 function(acs_id) { return (me.controlSet(acs_id).control_map[tag]) }
432 this.controlSetId(old_acs);
436 this.findControlSetsForAuthorityTag = function (tag) {
438 var old_acs = this.controlSetId();
440 var acs_list = me.controlSetList().filter(
442 var a = me.controlSet(acs_id);
443 for (var btag in a.control_map) {
444 for (var sf in a.control_map[btag]) {
445 if (a.control_map[btag][sf][tag]) return true;
451 this.controlSetId(old_acs);
455 this.bibToAuthority = function (field) {
456 var b_field = this.bibFieldByTag(field.tag);
458 if (b_field) { // construct an marc authority record
459 var af = b_field.authority_field();
462 for (var i = 0; i < field.subfields.length; i++) {
463 if (af.sf_list().indexOf(field.subfields[i][0]) > -1) {
464 if (typeof(field.subfields[i][1]) != 'undefined'
465 && field.subfields[i][1] !== null
466 && field.subfields[i][1].length > 0
468 sflist.push(field.subfields[i]);
472 if (sflist.length == 0) return null;
474 var m = new MARC21.Record ({rtype:'AUT'});
484 return m.toXmlString();
490 this.bibToAuthorities = function (field) {
494 var old_acs = this.controlSetId();
495 me.controlSetList().forEach(
497 var acs = me.controlSet(acs_id);
498 var x = me.bibToAuthority(field);
499 if (x) { var foo = {}; foo[acs_id] = x; auth_list.push(foo); }
502 this.controlSetId(old_acs);
509 service.getAuthorityControlSet = function() {
510 if (!service._active_control_set) {
511 service.authority_control_set._remote_loaded = false;
512 service._active_control_set = new service.authorityControlSet();
514 return service._active_control_set;
517 // fetches and caches the full set of values from
518 // config.marc21_physical_characteristic_type_map
519 service.getPhysCharTypeMap = function() {
521 if (service.phys_char_type_map) {
522 return $q.when(service.phys_char_type_map);
525 return egCore.pcrud.retrieveAll('cmpctm', {}, {atomic : true})
526 .then(function(map) {return service.phys_char_type_map = map});
529 // Fetch+caches the config.marc21_physical_characteristic_subfield_map
530 // values for the requested ptype_key (i.e. type_map.ptype_key).
531 // Values are sorted by start_pos
532 service.getPhysCharSubfieldMap = function(ptype_key) {
534 if (service.phys_char_sf_map[ptype_key]) {
535 return $q.when(service.phys_char_sf_map[ptype_key]);
538 return egCore.pcrud.search('cmpcsm',
539 {ptype_key : ptype_key},
540 {order_by : {cmpcsm : ['start_pos']}},
542 ).then(function(maps) {
543 return service.phys_char_sf_map[ptype_key] = maps;
547 // Fetches + caches the config.marc21_physical_characteristic_value_map
548 // for the requested ptype_subfield (subfield_map.id).
549 // Maps are ordered by value.
550 service.getPhysCharValueMap = function(ptype_subfield) {
551 if (service.phys_char_value_map[ptype_subfield]) {
552 return $q.when(service.phys_char_value_map[ptype_subfield]);
555 return egCore.pcrud.search('cmpcvm',
556 {ptype_subfield : ptype_subfield},
557 {order_by : {cmpcsm : ['value']}},
559 ).then(function(maps) {
560 return service.phys_char_sf_map[ptype_subfield] = maps;