]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/eg2/src/app/staff/share/marc-edit/marcrecord.ts
493eaadcbe18d23d32cc5a603fd5c5deabf85a30
[Evergreen.git] / Open-ILS / src / eg2 / src / app / staff / share / marc-edit / marcrecord.ts
1 import {EventEmitter} from '@angular/core';
2
3 /* Wrapper class for our external MARC21.Record JS library. */
4
5 declare var MARC21;
6
7 // MARC breaker delimiter
8 const DELIMITER = '$';
9
10 export interface MarcSubfield    // code, value, position
11     extends Array<string|number> { 0: string; 1: string; 2: number; }
12
13 // Only contains the attributes/methods we need so far.
14 export interface MarcField {
15     fieldId?: number;
16     data?: string;
17     tag?: string;
18     ind1?: string;
19     ind2?: string;
20     subfields?: MarcSubfield[];
21
22     // For authority validation
23     authValid: boolean;
24     authChecked: boolean;
25
26     // Fields are immutable when it comes to controlfield vs.
27     // data field.  Stamp the value when stamping field IDs.
28     isCtrlField: boolean;
29
30     // Pass-through to marcrecord.js
31     isControlfield(): boolean;
32
33     deleteExactSubfields(...subfield: MarcSubfield[]): number;
34 }
35
36 export class MarcRecord {
37
38     id: number; // Database ID when known.
39     deleted: boolean;
40     record: any; // MARC21.Record object
41     breakerText: string;
42
43     // Let clients know some fixed field shuffling may have occured.
44     // Emits the fixed field code.
45     fixedFieldChange: EventEmitter<string>;
46
47     get leader(): string {
48         return this.record.leader;
49     }
50
51     set leader(l: string) {
52         this.record.leader = l;
53     }
54
55     get fields(): MarcField[] {
56        return this.record.fields;
57     }
58
59     set fields(f: MarcField[]) {
60         this.record.fields = f;
61     }
62
63     constructor(xml?: string) {
64         this.record = new MARC21.Record({marcxml: xml, delimiter: DELIMITER});
65         this.breakerText = this.record.toBreaker();
66         this.fixedFieldChange = new EventEmitter<string>();
67     }
68
69     toXml(): string {
70         return this.record.toXmlString();
71     }
72
73     toBreaker(): string {
74         return this.record.toBreaker();
75     }
76
77     recordType(): string {
78         return this.record.recordType();
79     }
80
81     absorbBreakerChanges() {
82         this.record = new MARC21.Record(
83             {marcbreaker: this.breakerText, delimiter: DELIMITER});
84     }
85
86     extractFixedField(fieldCode: string): string {
87         return this.record.extractFixedField(fieldCode);
88     }
89
90     setFixedField(fieldCode: string, fieldValue: string): string {
91         const response = this.record.setFixedField(fieldCode, fieldValue);
92         this.fixedFieldChange.emit(fieldCode);
93         return response;
94     }
95
96     // Give each field an identifier so it may be referenced later.
97     stampFieldIds() {
98         this.fields.forEach(f => this.stampFieldId(f));
99     }
100
101     // Stamp field IDs the the initial isCtrlField state.
102     stampFieldId(field: MarcField) {
103         if (!field.fieldId) {
104             field.fieldId = Math.floor(Math.random() * 10000000);
105         }
106
107         if (field.isCtrlField === undefined) {
108             field.isCtrlField = field.isControlfield();
109         }
110     }
111
112     field(spec: string, wantArray?: boolean): MarcField | MarcField[] {
113         return this.record.field(spec, wantArray);
114     }
115
116     appendFields(...newFields: MarcField[]) {
117         this.record.appendFields.apply(this.record, newFields);
118         this.stampFieldIds();
119     }
120
121     insertFieldsBefore(field: MarcField, ...newFields: MarcField[]) {
122         this.record.insertFieldsBefore.apply(
123             this.record, [field].concat(newFields));
124         this.stampFieldIds();
125     }
126
127     insertFieldsAfter(field: MarcField, ...newFields: MarcField[]) {
128         this.record.insertFieldsAfter.apply(
129             this.record, [field].concat(newFields));
130         this.stampFieldIds();
131     }
132
133     insertOrderedFields(...newFields: MarcField[]) {
134         this.record.insertOrderedFields.apply(this.record, newFields);
135         this.stampFieldIds();
136     }
137
138     generate008(): MarcField {
139         return this.record.generate008();
140     }
141
142
143     deleteFields(...fields: MarcField[]) {
144         this.record.deleteFields.apply(this.record, fields);
145     }
146
147     getField(id: number): MarcField {
148         return this.fields.filter(f => f.fieldId === id)[0];
149     }
150
151     getPreviousField(id: number): MarcField {
152         for (let idx = 0; idx < this.fields.length; idx++) {
153             if (this.fields[idx].fieldId === id) {
154                 return this.fields[idx - 1];
155             }
156         }
157     }
158
159     getNextField(id: number): MarcField {
160         for (let idx = 0; idx < this.fields.length; idx++) {
161             if (this.fields[idx].fieldId === id) {
162                 return this.fields[idx + 1];
163             }
164         }
165     }
166
167     // Turn an field-ish object into a proper MARC.Field
168     newField(props: any): MarcField {
169         const field = new MARC21.Field(props);
170         this.stampFieldId(field);
171         return field;
172     }
173
174     cloneField(field: any): MarcField {
175         const props: any = {tag: field.tag};
176
177         if (field.isControlfield()) {
178             props.data = field.data;
179
180         } else {
181             props.ind1 = field.ind1;
182             props.ind2 = field.ind2;
183             props.subfields = this.cloneSubfields(field.subfields);
184         }
185
186         return this.newField(props);
187     }
188
189     cloneSubfields(subfields: MarcSubfield[]): MarcSubfield[] {
190         const root = [];
191         subfields.forEach(sf => root.push([].concat(sf)));
192         return root;
193     }
194
195     // Returns a list of values for the tag + subfield combo
196     subfield(tag: string, subfield: string): string {
197         return this.record.subfield(tag, subfield);
198     }
199 }
200