]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/src/eg2/src/app/staff/share/marc-edit/marcrecord.ts
LP1852782 MARC editor and related lint repairs
[working/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     isControlfield(): boolean;
23
24     deleteExactSubfields(...subfield: MarcSubfield[]): number;
25 }
26
27 export class MarcRecord {
28
29     id: number; // Database ID when known.
30     deleted: boolean;
31     record: any; // MARC21.Record object
32     breakerText: string;
33
34     // Let clients know some fixed field shuffling may have occured.
35     // Emits the fixed field code.
36     fixedFieldChange: EventEmitter<string>;
37
38     get leader(): string {
39         return this.record.leader;
40     }
41
42     set leader(l: string) {
43         this.record.leader = l;
44     }
45
46     get fields(): MarcField[] {
47        return this.record.fields;
48     }
49
50     set fields(f: MarcField[]) {
51         this.record.fields = f;
52     }
53
54     constructor(xml: string) {
55         this.record = new MARC21.Record({marcxml: xml, delimiter: DELIMITER});
56         this.breakerText = this.record.toBreaker();
57         this.fixedFieldChange = new EventEmitter<string>();
58     }
59
60     toXml(): string {
61         return this.record.toXmlString();
62     }
63
64     toBreaker(): string {
65         return this.record.toBreaker();
66     }
67
68     recordType(): string {
69         return this.record.recordType();
70     }
71
72     absorbBreakerChanges() {
73         this.record = new MARC21.Record(
74             {marcbreaker: this.breakerText, delimiter: DELIMITER});
75     }
76
77     extractFixedField(fieldCode: string): string {
78         return this.record.extractFixedField(fieldCode);
79     }
80
81     setFixedField(fieldCode: string, fieldValue: string): string {
82         const response = this.record.setFixedField(fieldCode, fieldValue);
83         this.fixedFieldChange.emit(fieldCode);
84         return response;
85     }
86
87     // Give each field an identifier so it may be referenced later.
88     stampFieldIds() {
89         this.fields.forEach(f => this.stampFieldId(f));
90     }
91
92     stampFieldId(field: MarcField) {
93         if (!field.fieldId) {
94             field.fieldId = Math.floor(Math.random() * 10000000);
95         }
96     }
97
98     field(spec: string, wantArray?: boolean): MarcField | MarcField[] {
99         return this.record.field(spec, wantArray);
100     }
101
102     insertFieldsBefore(field: MarcField, ...newFields: MarcField[]) {
103         this.record.insertFieldsBefore.apply(
104             this.record, [field].concat(newFields));
105         this.stampFieldIds();
106     }
107
108     insertFieldsAfter(field: MarcField, ...newFields: MarcField[]) {
109         this.record.insertFieldsAfter.apply(
110             this.record, [field].concat(newFields));
111         this.stampFieldIds();
112     }
113
114     insertOrderedFields(...newFields: MarcField[]) {
115         this.record.insertOrderedFields.apply(this.record, newFields);
116         this.stampFieldIds();
117     }
118
119     generate008(): MarcField {
120         return this.record.generate008();
121     }
122
123
124     deleteFields(...fields: MarcField[]) {
125         this.record.deleteFields.apply(this.record, fields);
126     }
127
128     getField(id: number): MarcField {
129         return this.fields.filter(f => f.fieldId === id)[0];
130     }
131
132     getPreviousField(id: number): MarcField {
133         for (let idx = 0; idx < this.fields.length; idx++) {
134             if (this.fields[idx].fieldId === id) {
135                 return this.fields[idx - 1];
136             }
137         }
138     }
139
140     getNextField(id: number): MarcField {
141         for (let idx = 0; idx < this.fields.length; idx++) {
142             if (this.fields[idx].fieldId === id) {
143                 return this.fields[idx + 1];
144             }
145         }
146     }
147
148     // Turn an field-ish object into a proper MARC.Field
149     newField(props: any): MarcField {
150         const field = new MARC21.Field(props);
151         this.stampFieldId(field);
152         return field;
153     }
154
155     cloneField(field: any): MarcField {
156         const props: any = {tag: field.tag};
157
158         if (field.isControlfield()) {
159             props.data = field.data;
160
161         } else {
162             props.ind1 = field.ind1;
163             props.ind2 = field.ind2;
164             props.subfields = this.cloneSubfields(field.subfields);
165         }
166
167         return this.newField(props);
168     }
169
170     cloneSubfields(subfields: MarcSubfield[]): MarcSubfield[] {
171         const root = [];
172         subfields.forEach(sf => root.push([].concat(sf)));
173         return root;
174     }
175 }
176