f7e54d3f3abc4ca2974b0b46f547cb8f1928d32b
[evergreen-equinox.git] / Open-ILS / src / eg2 / src / app / share / catalog / bib-record.service.ts
1 import {Injectable} from '@angular/core';
2 import {Observable, from} from 'rxjs';
3 import {mergeMap, map, tap} from 'rxjs/operators';
4 import {OrgService} from '@eg/core/org.service';
5 import {UnapiService} from '@eg/share/catalog/unapi.service';
6 import {IdlService, IdlObject} from '@eg/core/idl.service';
7 import {NetService} from '@eg/core/net.service';
8 import {PcrudService} from '@eg/core/pcrud.service';
9
10 export const NAMESPACE_MAPS = {
11     'mods':     'http://www.loc.gov/mods/v3',
12     'biblio':   'http://open-ils.org/spec/biblio/v1',
13     'holdings': 'http://open-ils.org/spec/holdings/v1',
14     'indexing': 'http://open-ils.org/spec/indexing/v1'
15 };
16
17 export const HOLDINGS_XPATH =
18     '/holdings:holdings/holdings:counts/holdings:count';
19
20 interface EResourceUrl {
21     href: string;
22     note: string;
23     label: string;
24 }
25
26 export class BibRecordSummary {
27     id: number; // == record.id() for convenience
28     metabibId: number; // If present, this is a metabib summary
29     metabibRecords: number[]; // all constituent bib records
30     orgId: number;
31     orgDepth: number;
32     record: IdlObject;
33     display: any;
34     attributes: any;
35     holdingsSummary: any;
36     holdCount: number;
37     bibCallNumber: string;
38     firstCallNumber: string;
39     net: NetService;
40     displayHighlights: {[name: string]: string | string[]} = {};
41     eResourceUrls: EResourceUrl[] = [];
42     copies: any[];
43
44     constructor(record: IdlObject, orgId: number, orgDepth?: number) {
45         this.id = Number(record.id());
46         this.record = record;
47         this.orgId = orgId;
48         this.orgDepth = orgDepth;
49         this.display = {};
50         this.attributes = {};
51         this.bibCallNumber = null;
52         this.metabibRecords = [];
53     }
54
55     // Get -> Set -> Return bib-level call number
56     getBibCallNumber(): Promise<string> {
57
58         if (this.bibCallNumber !== null) {
59             return Promise.resolve(this.bibCallNumber);
60         }
61
62         return this.net.request(
63             'open-ils.cat',
64             'open-ils.cat.biblio.record.marc_cn.retrieve',
65             this.id, null, this.orgId
66         ).toPromise().then(cnArray => {
67             if (cnArray && cnArray.length > 0) {
68                 const key1 = Object.keys(cnArray[0])[0];
69                 this.bibCallNumber = cnArray[0][key1];
70             } else {
71                 this.bibCallNumber = '';
72             }
73             return this.bibCallNumber;
74         });
75     }
76 }
77
78 @Injectable()
79 export class BibRecordService {
80
81     // Cache of bib editor / creator objects
82     // Assumption is this list will be limited in size.
83     userCache: {[id: number]: IdlObject};
84
85     constructor(
86         private idl: IdlService,
87         private net: NetService,
88         private org: OrgService,
89         private unapi: UnapiService,
90         private pcrud: PcrudService
91     ) {
92         this.userCache = {};
93     }
94
95     getBibSummary(id: number,
96         orgId?: number, isStaff?: boolean): Observable<BibRecordSummary> {
97         return this.getBibSummaries([id], orgId, isStaff);
98     }
99
100     getBibSummaries(bibIds: number[], orgId?: number,
101         isStaff?: boolean, options?: any): Observable<BibRecordSummary> {
102
103         if (bibIds.length === 0) { return from([]); }
104         if (!orgId) { orgId = this.org.root().id(); }
105
106         let method = 'open-ils.search.biblio.record.catalog_summary';
107         if (isStaff) { method += '.staff'; }
108
109         return this.net.request('open-ils.search', method, orgId, bibIds, options)
110         .pipe(map(bibSummary => {
111             const summary = new BibRecordSummary(bibSummary.record, orgId);
112             summary.net = this.net; // inject
113             summary.display = bibSummary.display;
114             summary.attributes = bibSummary.attributes;
115             summary.holdCount = bibSummary.hold_count;
116             summary.holdingsSummary = bibSummary.copy_counts;
117             summary.eResourceUrls = bibSummary.urls;
118             summary.copies = bibSummary.copies;
119             summary.firstCallNumber = bibSummary.first_call_number;
120
121             return summary;
122         }));
123     }
124
125     getMetabibSummaries(metabibIds: number[],
126         orgId?: number, isStaff?: boolean, options?: any): Observable<BibRecordSummary> {
127
128         if (metabibIds.length === 0) { return from([]); }
129         if (!orgId) { orgId = this.org.root().id(); }
130
131         let method = 'open-ils.search.biblio.metabib.catalog_summary';
132         if (isStaff) { method += '.staff'; }
133
134         return this.net.request('open-ils.search', method, orgId, metabibIds, options)
135         .pipe(map(metabibSummary => {
136             const summary = new BibRecordSummary(metabibSummary.record, orgId);
137             summary.net = this.net; // inject
138             summary.metabibId = Number(metabibSummary.metabib_id);
139             summary.metabibRecords = metabibSummary.metabib_records;
140             summary.display = metabibSummary.display;
141             summary.attributes = metabibSummary.attributes;
142             summary.holdCount = metabibSummary.hold_count;
143             summary.holdingsSummary = metabibSummary.copy_counts;
144             summary.copies = metabibSummary.copies;
145             summary.firstCallNumber = metabibSummary.first_call_number;
146
147             return summary;
148         }));
149     }
150 }
151
152