public void InsertFieldTest() { Record target = new Record(); string tag = "245"; target.Fields.Add(new ControlField("001", "I am data! (But not Data from Star Trek TNG)")); target.Fields.Add(new DataField(tag)); target.Fields.Add(new DataField("521", new List<Subfield>(), ' ', '1')); Field newField = new DataField("300", new List<Subfield>(), '0', '1'); target.InsertField(newField); Assert.AreSame(newField, target.Fields[2]); }
public void CloneTest() { string tag = "100"; List<Subfield> subfields = new List<Subfield>(); Subfield subfield = new Subfield('a', "It's a book!"); subfields.Add(subfield); subfield = new Subfield('b', "Anne Author"); subfields.Add(subfield); Field target = new DataField(tag, subfields); Field actual; actual = target.Clone(); Assert.AreNotEqual(target, actual); target.Tag = "200"; string expectedString = tag; string actualString; actualString = actual.Tag; Assert.AreEqual(expectedString, actualString); ((DataField)target).Indicator1 = '1'; ((DataField)target).Indicator2 = '2'; expectedString = " "; actualString = ((DataField)actual).Indicator1.ToString() + ((DataField)actual).Indicator2.ToString(); Assert.AreEqual(expectedString, actualString); ((DataField)target)['a'].Code = 'c'; ((DataField)target)['c'].Data = "It's a NEW book!"; expectedString = "aIt's a book!"; actualString = ((DataField)actual)['a'].Code.ToString() + ((DataField)actual)['a'].Data; Assert.AreEqual(expectedString, actualString); //This next line will fail as there's no subfield c! ((DataField)actual)['c'].Code = 'a'; }
public void FieldsTest() { Record target = new Record(); ControlField controlField = new ControlField("001", "I am data! (But not Data from Star Trek TNG)"); DataField dataField = new DataField("245"); DataField dataField2 = new DataField("521", new List<Subfield>(), ' ', '1'); target.Fields.Add(controlField); target.Fields.Add(dataField); target.Fields.Add(dataField2); { int expected = 3; int actual; actual = target.Fields.Count; Assert.AreEqual(expected, actual); } { Field expected = controlField; Field actual; actual = target.Fields[0]; Assert.AreSame(expected, actual); expected = dataField; actual = target.Fields[1]; Assert.AreSame(expected, actual); expected = dataField2; actual = target.Fields[2]; Assert.AreSame(expected, actual); } { List<Field> expected = new List<Field>(); expected.Add(controlField); expected.Add(dataField); expected.Add(dataField2); target.Fields = expected; List<Field> actual; actual = target.Fields; Assert.AreSame(expected, actual); } }
public void ToRawTest() { string tag = "100"; List<Subfield> subfields = new List<Subfield>(); Subfield subfield = new Subfield('a', "It's a book!"); subfields.Add(subfield); subfield = new Subfield('b', "Anne Author"); subfields.Add(subfield); DataField target = new DataField(tag, subfields); string expected = " " + FileMARC.SUBFIELD_INDICATOR.ToString() + "aIt's a book!" + FileMARC.SUBFIELD_INDICATOR.ToString() + "bAnne Author" + FileMARC.END_OF_FIELD.ToString(); string actual; actual = target.ToRaw(); Assert.AreEqual(expected, actual); }
public void ToStringTest() { string tag = "100"; List<Subfield> subfields = new List<Subfield>(); Subfield subfield = new Subfield('a', "It's a book!"); subfields.Add(subfield); subfield = new Subfield('b', "Anne Author"); subfields.Add(subfield); DataField target = new DataField(tag, subfields); string expected = "100 [a]: It's a book!" + Environment.NewLine + " [b]: Anne Author"; string actual; actual = target.ToString(); Assert.AreEqual(expected, actual); }
/// <summary> /// Decodes the raw MARC record into a <see cref="MARC.Record"/> at the specified index./// /// </summary> /// <param name="index">The index of the record to retrieve.</param> /// <returns></returns> private Record Decode(int index) { string raw = _rawSource[index]; Record marc = new Record(); Match match = Regex.Match(raw, "^(\\d{5})"); int recordLength = 0; // Store record length if (match.Captures.Count == 0) { marc.AddWarnings("MARC record length is not numeric."); } else { recordLength = Convert.ToInt32(match.Captures[0].Value); } if (recordLength != raw.Length) { marc.AddWarnings("MARC record length does not match actual length."); recordLength = raw.Length; } if (!raw.EndsWith(END_OF_RECORD.ToString())) { throw new InvalidDataException("MARC record ends with an invalid terminator"); } //Store leader marc.Leader = raw.Substring(0, LEADER_LEN); //Bytes 12-16 of leader give offset to the body of the record int dataStart = Convert.ToInt32(raw.Substring(12, 5)); //Immediately after the leader comes the directory (no separator) string directory = raw.Substring(LEADER_LEN, dataStart - LEADER_LEN - 1); //Character after the directory should be END_OF_FIELD if (raw.Substring(dataStart - 1, 1) != END_OF_FIELD.ToString()) { marc.AddWarnings("No directory found."); } //All directory entries must be DIRECTORY_ENTRY_LEN long, so length % DIRECTORY_ENTRY_LEN should be 0 if (directory.Length % DIRECTORY_ENTRY_LEN != 0) { marc.AddWarnings("Invalid directory length."); } //Go through all the fields int fieldCount = directory.Length / DIRECTORY_ENTRY_LEN; for (int i = 0; i < fieldCount; i++) { string tag = directory.Substring(i * DIRECTORY_ENTRY_LEN, DIRECTORY_ENTRY_LEN).Substring(0, 3); int fieldLength = 0; int fieldOffset = 0; try { fieldLength = Convert.ToInt32(directory.Substring(i * DIRECTORY_ENTRY_LEN, DIRECTORY_ENTRY_LEN).Substring(3, 4)); } catch (FormatException) { marc.AddWarnings("Invalid Directory Tag Length for tag " + tag + "."); } try { fieldOffset = Convert.ToInt32(directory.Substring(i * DIRECTORY_ENTRY_LEN, DIRECTORY_ENTRY_LEN).Substring(7, 5)); } catch (FormatException) { marc.AddWarnings("Invalid Directory Offset for tag " + tag + "."); } //Check Directory validity //If a tag isn't valid, default it to ZZZ. This should at least make the record valid enough to be readable and not throw exceptions if (!Field.ValidateTag(tag)) { marc.AddWarnings("Invalid tag " + tag + " in directory."); tag = "ZZZ"; } if (fieldOffset + fieldLength > recordLength) { marc.AddWarnings("Directory entry for tag " + tag + " runs past the end of the record."); } int fieldStart = dataStart + fieldOffset; if (fieldStart > recordLength) { marc.AddWarnings("Directory entry for tag " + tag + " starts past the end of the record. Skipping tag and all proceeding tags."); break; } else if (fieldStart + fieldLength > recordLength) { marc.AddWarnings("Directory entry for tag " + tag + " runs past the end of the record."); fieldLength = recordLength - fieldStart; } string tagData = raw.Substring(fieldStart, fieldLength); if (tagData.Substring(tagData.Length - 1, 1) == END_OF_FIELD.ToString()) { //Get rid of the end of tag character tagData = tagData.Remove(tagData.Length - 1); fieldLength--; } else { marc.AddWarnings("Field for tag " + tag + " does not end with an end of field character."); } match = Regex.Match(tag, "^\\d+$"); if (match.Captures.Count > 0 && Convert.ToInt32(tag) < 10) { marc.Fields.Add(new ControlField(tag, tagData)); } else { List <string> rawSubfields = new List <string>(tagData.Split(SUBFIELD_INDICATOR)); string indicators = rawSubfields[0]; rawSubfields.RemoveAt(0); char ind1; char ind2; if (indicators.Length != 2) { marc.AddWarnings("Invalid indicator length. Forced indicators to blanks for tag " + tag + "."); ind1 = ind2 = ' '; } else { ind1 = char.ToLower(indicators[0]); if (!DataField.ValidateIndicator(ind1)) { ind1 = ' '; marc.AddWarnings("Invalid first indicator. Forced first indicator to blank for tag " + tag + "."); } ind2 = char.ToLower(indicators[1]); if (!DataField.ValidateIndicator(ind2)) { ind2 = ' '; marc.AddWarnings("Invalid second indicator. Forced second indicator to blank for tag " + tag + "."); } } //Split the subfield data into subfield name and data pairs List <Subfield> subfieldData = new List <Subfield>(); foreach (string subfield in rawSubfields) { if (subfield.Length > 0) { subfieldData.Add(new Subfield(subfield[0], subfield.Substring(1))); } else { marc.AddWarnings("No subfield data found in tag " + tag + "."); } } if (subfieldData.Count == 0) { marc.AddWarnings("No subfield data found in tag " + tag + "."); } marc.Fields.Add(new DataField(tag, subfieldData, ind1, ind2)); } } return(marc); }
public void SubfieldsTest() { string tag = "100"; List<Subfield> subfields = new List<Subfield>(); Subfield subfield = new Subfield('a', "It's a book!"); subfields.Add(subfield); subfield = new Subfield('b', "Anne Author"); subfields.Add(subfield); DataField target = new DataField(tag, subfields); List<Subfield> expected = new List<Subfield>(); subfield = new Subfield('a', "It's another book!"); expected.Add(subfield); subfield = new Subfield('b', "Anne Otter Author"); expected.Add(subfield); List<Subfield> actual; target.Subfields = expected; actual = target.Subfields; Assert.AreEqual(expected.Count, actual.Count); for (int i = 0; i < expected.Count; i++) { Assert.AreEqual(expected[i].Code, actual[i].Code); Assert.AreEqual(expected[i].Data, actual[i].Data); } }
public void Indicator2Test() { string tag = "100"; DataField target = new DataField(tag); char expected = '1'; char actual; target.Indicator2 = expected; actual = target.Indicator2; Assert.AreEqual(expected, actual); expected = '%'; target.Indicator2 = expected; //Will throw exception }
public void IsEmptyTest() { string tag = "100"; DataField target = new DataField(tag); bool expected = true; bool actual; actual = target.IsEmpty(); Assert.AreEqual(expected, actual); List<Subfield> subfields = new List<Subfield>(); Subfield subfield = new Subfield('a', "It's a book!"); subfields.Add(subfield); subfield = new Subfield('b', "Anne Author"); subfields.Add(subfield); subfield = new Subfield('b', "Anne Otter Author"); subfields.Add(subfield); target = new DataField(tag, subfields); expected = false; actual = target.IsEmpty(); Assert.AreEqual(expected, actual); }
public void DataFieldConstructorTest3() { string tag = "100"; List<Subfield> subfields = new List<Subfield>(); Subfield subfield = new Subfield('a', "It's a book!"); subfields.Add(subfield); subfield = new Subfield('b', "Anne Author"); subfields.Add(subfield); char ind1 = '1'; DataField target = new DataField(tag, subfields, ind1); { char expected = '1'; char actual = target.Indicator1; Assert.AreEqual(expected, actual); expected = ' '; actual = target.Indicator2; Assert.AreEqual(expected, actual); expected = 'a'; actual = target['a'].Code; Assert.AreEqual(expected, actual); expected = 'b'; actual = target['b'].Code; Assert.AreEqual(expected, actual); } { string expected = "100"; string actual = target.Tag; Assert.AreEqual(expected, actual); expected = "It's a book!"; actual = target['a'].Data; Assert.AreEqual(expected, actual); expected = "Anne Author"; actual = target['b'].Data; Assert.AreEqual(expected, actual); } { int expected = 2; int actual = target.Subfields.Count; Assert.AreEqual(expected, actual); } }
public void FormatFieldTest1() { string tag = "600"; List<Subfield> subfields = new List<Subfield>(); Subfield subfield = new Subfield('a', "It's a book!"); subfields.Add(subfield); subfield = new Subfield('b', "Anne Author"); subfields.Add(subfield); subfield = new Subfield('c', "Some text"); subfields.Add(subfield); subfield = new Subfield('d', "Some more text"); subfields.Add(subfield); subfield = new Subfield('v', "Some fancy text"); subfields.Add(subfield); subfield = new Subfield('z', "Some more fancy text"); subfields.Add(subfield); DataField target = new DataField(tag, subfields); string expected = "It's a book! Anne Author Some text Some more text -- Some fancy text -- Some more fancy text"; string actual; actual = target.FormatField(); Assert.AreEqual(expected, actual); }
public void DataFieldConstructorTest1() { string tag = "100"; DataField target = new DataField(tag); { string expected = "100"; string actual = target.Tag; Assert.AreEqual(expected, actual); } { char expected = ' '; char actual = target.Indicator1; Assert.AreEqual(expected, actual); actual = target.Indicator2; Assert.AreEqual(expected, actual); } { int expected = 0; int actual = target.Subfields.Count; Assert.AreEqual(expected, actual); } }
/// <summary> /// Makes a deep clone of this instance. /// </summary> /// <returns></returns> public override Field Clone() { Field clone = new DataField(Tag, new List<Subfield>(), _ind1, _ind2); foreach (Subfield needsCloned in Subfields) ((DataField)clone).Subfields.Add(needsCloned.Clone()); return clone; }
internal virtual Field CreateDataField() { List<Subfield> subfields = new List<Subfield>(); subfields.Add(new Subfield('a', "It's a book!")); subfields.Add(new Subfield('b', "Anne Author")); Field target = new DataField("100", subfields, '1', ' '); return target; }
public void ItemTest() { Record target = new Record(); string tag = "245"; ControlField controlField = new ControlField("001", "I am data! (But not Data from Star Trek TNG)"); DataField dataField = new DataField(tag); DataField dataField2 = new DataField(tag, new List<Subfield>(), ' ', '1'); target.Fields.Add(controlField); target.Fields.Add(dataField); target.Fields.Add(dataField2); Field expected = dataField; Field actual; actual = target[tag]; }
public void ItemTest() { string tag = "100"; List<Subfield> subfields = new List<Subfield>(); Subfield subfield = new Subfield('a', "It's a book!"); subfields.Add(subfield); subfield = new Subfield('b', "Anne Author"); subfields.Add(subfield); DataField target = new DataField(tag, subfields); char code = 'a'; Subfield expected = new Subfield('a', "It's a book!"); Subfield actual; actual = target[code]; Assert.AreEqual(expected.Code, actual.Code); Assert.AreEqual(expected.Data, actual.Data); }
/// <summary> /// Decodes the raw MARC record into a <see cref="MARC.Record"/> at the specified index./// /// </summary> /// <param name="index">The index of the record to retrieve.</param> /// <returns></returns> private Record Decode(int index) { XElement record = _rawSource[index]; Record marcXml = new Record(); //First we get the leader marcXml.Leader = record.Elements().First(e => e.Name.LocalName == "leader").Value; //Now we get the control fields foreach (XElement controlField in record.Elements().Where(e => e.Name.LocalName == "controlfield")) { ControlField newField = new ControlField(controlField.Attribute("tag").Value, controlField.Value); marcXml.Fields.Add(newField); } //Now we get the data fields foreach (XElement dataField in record.Elements().Where(e => e.Name.LocalName == "datafield")) { DataField newField = new DataField(dataField.Attribute("tag").Value, new List<Subfield>(), dataField.Attribute("ind1").Value[0], dataField.Attribute("ind2").Value[0]); foreach (XElement subfield in dataField.Elements().Where(e => e.Name.LocalName == "subfield")) { Subfield newSubfield = new Subfield(subfield.Attribute("code").Value[0], subfield.Value); newField.Subfields.Add(newSubfield); } marcXml.Fields.Add(newField); } return marcXml; }
//Private utility functions #region Private utility functions /// <summary> /// Decodes the raw MARC record into a <see cref="MARC.Record"/> at the specified index./// /// </summary> /// <param name="index">The index of the record to retrieve.</param> /// <returns></returns> private Record decode(int index) { string raw = rawSource[index]; Record marc = new Record(); Match match = Regex.Match(raw, "^(\\d{5})"); int recordLength = 0; int totalExtraBytesRead = 0; // Store record length if (match.Captures.Count == 0) { marc.AddWarnings("MARC record length is not numeric or incorrect number of characters."); string[] split = Regex.Split(raw, "[^0-9]"); if (Int32.TryParse(split[0], out recordLength)) { string padding = ""; padding = padding.PadLeft(5 - split[0].Length, '0'); raw = padding + raw; } } else { recordLength = Convert.ToInt32(match.Captures[0].Value); } if (recordLength != raw.Length) { //Check if there are multi-byte characters in the string System.Globalization.StringInfo stringInfo = new System.Globalization.StringInfo(raw); int extraBytes = raw.Length - stringInfo.LengthInTextElements; int extraBytes2 = Encoding.UTF8.GetByteCount(raw) - raw.Length; if (recordLength == extraBytes + raw.Length) { recordLength -= extraBytes; } else if (recordLength == extraBytes2 + raw.Length) { recordLength -= extraBytes2; } else { marc.AddWarnings("MARC record length does not match actual length."); recordLength = raw.Length; } } if (!raw.EndsWith(END_OF_RECORD.ToString())) { throw new InvalidDataException("MARC record ends with an invalid terminator"); } //Store leader marc.Leader = raw.Substring(0, LEADER_LEN); //Bytes 12-16 of leader give offset to the body of the record int dataStart = Convert.ToInt32(raw.Substring(12, 5)); //Verify data start matches the first end of field marker if (raw.IndexOf(END_OF_FIELD) + 1 != dataStart) { dataStart = raw.IndexOf(END_OF_FIELD) + 1; marc.AddWarnings("Leader specifies incorrect base address of data."); } //Immediately after the leader comes the directory (no separator) string directory = raw.Substring(LEADER_LEN, dataStart - LEADER_LEN - 1); //Character after the directory should be END_OF_FIELD if (raw.Substring(dataStart - 1, 1) != END_OF_FIELD.ToString()) { marc.AddWarnings("No directory found."); } //All directory entries must be DIRECTORY_ENTRY_LEN long, so length % DIRECTORY_ENTRY_LEN should be 0 if (directory.Length % DIRECTORY_ENTRY_LEN != 0) { marc.AddWarnings("Invalid directory length."); } //Go through all the fields int fieldCount = directory.Length / DIRECTORY_ENTRY_LEN; for (int i = 0; i < fieldCount; i++) { string tag = directory.Substring(i * DIRECTORY_ENTRY_LEN, DIRECTORY_ENTRY_LEN).Substring(0, 3); int fieldLength = 0; int fieldOffset = 0; try { fieldLength = Convert.ToInt32(directory.Substring(i * DIRECTORY_ENTRY_LEN, DIRECTORY_ENTRY_LEN).Substring(3, 4)); } catch (FormatException) { marc.AddWarnings("Invalid Directory Tag Length for tag " + tag + "."); } try { fieldOffset = Convert.ToInt32(directory.Substring(i * DIRECTORY_ENTRY_LEN, DIRECTORY_ENTRY_LEN).Substring(7, 5)) + totalExtraBytesRead; } catch (FormatException) { marc.AddWarnings("Invalid Directory Offset for tag " + tag + "."); } //Check Directory validity //If a tag isn't valid, default it to ZZZ. This should at least make the record valid enough to be readable and not throw exceptions if (!Field.ValidateTag(tag)) { marc.AddWarnings("Invalid tag " + tag + " in directory."); tag = "ZZZ"; } if (fieldOffset + fieldLength > recordLength) { marc.AddWarnings("Directory entry for tag " + tag + " runs past the end of the record."); } int fieldStart = dataStart + fieldOffset - (totalExtraBytesRead * 2); if (fieldStart > recordLength) { marc.AddWarnings("Directory entry for tag " + tag + " starts past the end of the record. Skipping tag and all proceeding tags."); break; } else if (fieldStart + fieldLength > recordLength) { marc.AddWarnings("Directory entry for tag " + tag + " runs past the end of the record."); fieldLength = recordLength - fieldStart; } string tagData = raw.Substring(fieldStart, fieldLength); //Check if there are multi-byte characters in the string System.Globalization.StringInfo stringInfo = new System.Globalization.StringInfo(tagData); int extraBytes = fieldLength - stringInfo.LengthInTextElements; int extraBytes2 = Encoding.UTF8.GetByteCount(tagData) - fieldLength; int endOfFieldIndex = tagData.IndexOf(END_OF_FIELD); if (tagData.Length - 1 != endOfFieldIndex) { int differenceLength = tagData.Length - 1 - endOfFieldIndex; if (differenceLength != extraBytes && differenceLength != extraBytes2) { fieldLength -= differenceLength; totalExtraBytesRead += differenceLength; tagData = raw.Substring(fieldStart, endOfFieldIndex + 1); } else { if (extraBytes > 0) { fieldLength -= extraBytes; totalExtraBytesRead += extraBytes; tagData = raw.Substring(fieldStart, fieldLength); } else if (extraBytes2 > 0) { fieldLength -= extraBytes2; totalExtraBytesRead += extraBytes2; tagData = raw.Substring(fieldStart, fieldLength); } } } if (fieldLength > 0) { string endCharacter = tagData.Substring(tagData.Length - 1, 1); if (endCharacter == END_OF_FIELD.ToString()) { //Get rid of the end of tag character tagData = tagData.Remove(tagData.Length - 1); fieldLength--; } else { marc.AddWarnings("Field for tag " + tag + " does not end with an end of field character."); } } else { marc.AddWarnings("Field for tag " + tag + " has a length of 0."); } match = Regex.Match(tag, "^\\d+$"); if (match.Captures.Count > 0 && Convert.ToInt32(tag) < 10) { marc.Fields.Add(new ControlField(tag, tagData)); } else { List <string> rawSubfields = new List <string>(tagData.Split(SUBFIELD_INDICATOR)); string indicators = rawSubfields[0]; rawSubfields.RemoveAt(0); char ind1; char ind2; if (indicators.Length != 2) { marc.AddWarnings("Invalid indicator length. Forced indicators to blanks for tag " + tag + "."); ind1 = ind2 = ' '; } else { ind1 = char.ToLower(indicators[0]); if (!DataField.ValidateIndicator(ind1)) { ind1 = ' '; marc.AddWarnings("Invalid first indicator. Forced first indicator to blank for tag " + tag + "."); } ind2 = char.ToLower(indicators[1]); if (!DataField.ValidateIndicator(ind2)) { ind2 = ' '; marc.AddWarnings("Invalid second indicator. Forced second indicator to blank for tag " + tag + "."); } } //Split the subfield data into subfield name and data pairs List <Subfield> subfieldData = new List <Subfield>(); foreach (string subfield in rawSubfields) { if (subfield.Length > 0) { subfieldData.Add(new Subfield(subfield[0], subfield.Substring(1))); } else { marc.AddWarnings("No subfield data found in tag " + tag + "."); } } if (subfieldData.Count == 0) { marc.AddWarnings("No subfield data found in tag " + tag + "."); } marc.Fields.Add(new DataField(tag, subfieldData, ind1, ind2)); } } return(marc); }