1 import {EventEmitter} from '@angular/core';
3 /* Wrapper class for our external MARC21.Record JS library. */
7 // MARC breaker delimiter
10 export interface MarcSubfield // code, value, position
11 extends Array<string|number> { 0: string; 1: string; 2: number; }
13 // Only contains the attributes/methods we need so far.
14 export interface MarcField {
20 subfields?: MarcSubfield[];
22 isControlfield(): boolean;
24 deleteExactSubfields(...subfield: MarcSubfield[]): number;
27 export class MarcRecord {
29 id: number; // Database ID when known.
31 record: any; // MARC21.Record object
34 // Let clients know some fixed field shuffling may have occured.
35 // Emits the fixed field code.
36 fixedFieldChange: EventEmitter<string>;
38 get leader(): string {
39 return this.record.leader;
42 set leader(l: string) {
43 this.record.leader = l;
46 get fields(): MarcField[] {
47 return this.record.fields;
50 set fields(f: MarcField[]) {
51 this.record.fields = f;
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>();
61 return this.record.toXmlString();
65 return this.record.toBreaker();
68 recordType(): string {
69 return this.record.recordType();
72 absorbBreakerChanges() {
73 this.record = new MARC21.Record(
74 {marcbreaker: this.breakerText, delimiter: DELIMITER});
77 extractFixedField(fieldCode: string): string {
78 return this.record.extractFixedField(fieldCode);
81 setFixedField(fieldCode: string, fieldValue: string): string {
82 const response = this.record.setFixedField(fieldCode, fieldValue);
83 this.fixedFieldChange.emit(fieldCode);
87 // Give each field an identifier so it may be referenced later.
89 this.fields.forEach(f => this.stampFieldId(f));
92 stampFieldId(field: MarcField) {
94 field.fieldId = Math.floor(Math.random() * 10000000);
98 field(spec: string, wantArray?: boolean): MarcField | MarcField[] {
99 return this.record.field(spec, wantArray);
102 insertFieldsBefore(field: MarcField, ...newFields: MarcField[]) {
103 this.record.insertFieldsBefore.apply(
104 this.record, [field].concat(newFields));
105 this.stampFieldIds();
108 insertFieldsAfter(field: MarcField, ...newFields: MarcField[]) {
109 this.record.insertFieldsAfter.apply(
110 this.record, [field].concat(newFields));
111 this.stampFieldIds();
114 insertOrderedFields(...newFields: MarcField[]) {
115 this.record.insertOrderedFields.apply(this.record, newFields);
116 this.stampFieldIds();
119 generate008(): MarcField {
120 return this.record.generate008();
124 deleteFields(...fields: MarcField[]) {
125 this.record.deleteFields.apply(this.record, fields);
128 getField(id: number): MarcField {
129 return this.fields.filter(f => f.fieldId === id)[0];
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];
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];
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);
155 cloneField(field: any): MarcField {
156 const props: any = {tag: field.tag};
158 if (field.isControlfield()) {
159 props.data = field.data;
162 props.ind1 = field.ind1;
163 props.ind2 = field.ind2;
164 props.subfields = this.cloneSubfields(field.subfields);
167 return this.newField(props);
170 cloneSubfields(subfields: MarcSubfield[]): MarcSubfield[] {
172 subfields.forEach(sf => root.push([].concat(sf)));