/// <summary> /// writes the given object to the StreamWriter /// /// throws /// - ArgumentException if the gedcomLine is a GedcomLine and no tagStr (gedcomLine.tagStr) is given /// </summary> /// <param name="gedcomLine">the gedcom line that should be written</param> /// <param name="tagStr"></param> /// <param name="streamWriter">the stream writer that the line should be written to</param> /// <param name="level">the level of the line</param> /// <param name="path">the path for the current object</param> private void WriteObject(object gedcomLine, string tagStr, StreamWriter streamWriter, int level, string path) { var lineV = new Line { Level = level, TagName = tagStr }; if (gedcomLine is GedcomLine) { try { var lineValueProperty = TagUtil.GetMember(gedcomLine, "", true, false); var obj = lineValueProperty.GetValue(gedcomLine, null); if (obj == null) { lineV.LineValue = ""; } else { lineV.LineValue = obj.ToString(); } if (lineV.LineValue.Length > LengthUtil.GetMaximumLength(lineValueProperty)) { reporting.Warn("line-value too long"); } if (lineV.LineValue.Length < LengthUtil.GetMinimumLength(lineValueProperty)) { reporting.Warn("line-value too short"); } } catch (MemberNotFoundException) { lineV.LineValue = ""; } if (gedcomLine is Record record) { lineV.XRefId = record.XRef; } } else if (gedcomLine.GetType().IsEnum) { lineV.LineValue = EnumTagUtil.GetFirstTagName(gedcomLine as ValueType); } else { lineV.LineValue = gedcomLine.ToString(); } WriteLine(lineV, streamWriter); foreach (var type in TagUtil.GetTags(gedcomLine.GetType())) { var prop = type.Key; var defaultTag = TagUtil.GetTagName(prop); if (!prop.CanRead) { continue; } var minOccur = QuantityUtil.GetMinimum(prop); var maxOccur = QuantityUtil.GetMaximum(prop); var obj = prop.GetValue(gedcomLine, null); if (TagUtil.IsDefaultValue(prop, obj)) { if (minOccur > 0) { reporting.Warn( $"object {prop.Name} in {path} must occur at least {minOccur} time(s), but was not set"); } continue; } // use a loop, event its just a single object to avoid redundant code var tmpList = ImplementsIList(prop.PropertyType) ? obj as IList : new[] { obj }; var occurrences = 0; foreach (var o in tmpList) { occurrences++; string tag; if (o is GedcomLine) { var line = o as GedcomLine; line.Tag = GetTag(type.Value, line); tag = line.Tag; } else { tag = defaultTag; } if (tag == "") { continue; } try { WriteObject(o, tag, streamWriter, level + 1, path + "/" + tag); } catch (Exception) { continue; } } if (occurrences < minOccur) { reporting.Warn( $"object {prop.Name} in {path} must occur at least {minOccur} time(s), but occured only {occurrences} time(s)"); } if (occurrences > maxOccur) { reporting.Warn( $"object {prop.Name} in {path} can only occur {maxOccur} time(s), but occured {occurrences} time(s)"); } } }