internal static Adoption ParseAdoption(this ResultContainer resultContainer, GedcomChunk adoptionChunk) { var adoption = new Adoption { DatePlace = resultContainer.ParseDatePlace(adoptionChunk) }; foreach (var chunk in adoptionChunk.SubChunks) { switch (chunk.Type) { case "NOTE": adoption.Note = resultContainer.ParseNote(adoption.Note, chunk); break; case "TYPE": adoption.Type = chunk.Data; break; // Deliberately skipped for now case "DATE": case "FAMC": case "PLAC": case "SOUR": resultContainer.Warnings.Add($"Skipped Adoption Type='{chunk.Type}"); break; default: resultContainer.Errors.Add($"Failed to handle Adoption Type='{chunk.Type}"); break; } } return(adoption); }
internal static Address ParseAddress(this ResultContainer resultContainer, GedcomChunk addressChunk) { // Top level node can also contain a full address or first part of it ... var address = new Address { Street = addressChunk.Data }; foreach (var chunk in addressChunk.SubChunks) { switch (chunk.Type) { case "CONT": case "ADR1": case "ADR2": case "ADR3": address.Street += Environment.NewLine + chunk.Data; break; case "CITY": address.City += chunk.Data; break; case "STAE": address.State += chunk.Data; break; case "POST": address.ZipCode += chunk.Data; break; case "CTRY": address.Country += chunk.Data; break; case "PHON": address.Phone.Add(chunk.Data); break; case "EMAIL": address.Email.Add(chunk.Data); break; case "FAX": address.Fax.Add(chunk.Data); break; case "WWW": address.Web.Add(chunk.Data); break; default: resultContainer.Errors.Add($"Failed to handle Address Type='{chunk.Type}"); break; } } return(address); }
private static HashSet <string> GetType(this GedcomChunk chunk, IDictionary <string, HashSet <string> > types) { if (!types.ContainsKey(chunk.Type)) { types.Add(chunk.Type, new HashSet <string>()); } return(types[chunk.Type]); }
private static void ParseTypeNodes(this GedcomChunk chunk, IDictionary <string, HashSet <string> > types) { var type = chunk.GetType(types); foreach (var subChunk in chunk.SubChunks) { type.Add(subChunk.Type); subChunk.ParseTypeNodes(types); } }
private static int Priority(GedcomChunk chunk) { switch (chunk.Type) { case "NOTE": return(0); case "INDI": return(1); case "FAM": return(2); default: return(0); } }
internal static IEnumerable <GedcomChunk> GetChunks(IEnumerable <GedcomLine> gedcomLines) { var gedcomChunkLevels = new GedcomChunkLevels(); var topChunks = new List <GedcomChunk>(); foreach (var gedcomLine in gedcomLines) { var chunk = new GedcomChunk(gedcomLine); if (gedcomLine.Level == 0) { topChunks.Add(chunk); } else { var parent = gedcomChunkLevels.GetParentChunk(chunk); parent.SubChunks.Add(chunk); } gedcomChunkLevels.Set(chunk); } return(topChunks); }
internal static void ParseFamily(this ResultContainer resultContainer, GedcomChunk famChunk) { DatePlace marriage = null; string relation = null; string note = null; DatePlace divorce = null; var parents = new List <Person>(); var children = new List <Person>(); foreach (var chunk in famChunk.SubChunks) { switch (chunk.Type) { case "CHIL": var child = resultContainer.Persons.SingleOrDefault(p => p.Id == chunk.Reference); if (child != null) { children.Add(child); } break; case "DIV": divorce = resultContainer.ParseDatePlace(chunk); break; case "HUSB": var husband = resultContainer.Persons.SingleOrDefault(p => p.Id == chunk.Reference); if (husband != null) { parents.Add(husband); } break; case "_REL": relation = chunk.Data; break; case "MARR": marriage = resultContainer.ParseDatePlace(chunk); break; case "NOTE": note = resultContainer.ParseNote(note, chunk); break; case "WIFE": var wife = resultContainer.Persons.SingleOrDefault(p => p.Id == chunk.Reference); if (wife != null) { parents.Add(wife); } break; // Deliberately skipped for now case "CHAN": case "DSCR": case "EVEN": case "FAMS": case "FAMC": case "HIST": case "MARS": case "NCHI": case "NMR": case "OBJE": case "PAGE": case "SOUR": resultContainer.Warnings.Add($"Skipped Family Type='{chunk.Type}"); break; default: resultContainer.Errors.Add($"Failed to handle Family Type='{chunk.Type}"); break; } } // Spouses if (parents.Count == 2) { resultContainer.SpouseRelations.Add(new SpouseRelation { FamilyId = famChunk.Id, From = parents[0], To = parents[1], Marriage = marriage, Divorce = divorce, Relation = relation, Note = note }); } // Parents / Children foreach (var parent in parents) { foreach (var child in children) { var childRelation = new ChildRelation { FamilyId = famChunk.Id, From = child, To = parent }; AddStatus(resultContainer, childRelation); resultContainer.ChildRelations.Add(childRelation); } } // Siblings foreach (var child1 in children) { foreach (var child2 in children.Where(c => c.Id != child1.Id)) { resultContainer.SiblingRelations.Add(new SiblingRelation { FamilyId = famChunk.Id, From = child1, To = child2 }); } } }
private static bool IsUnwantedBlob(this GedcomChunk chunk) { // TODO: We should probably make this check more intelligent return(chunk.Data?.Contains("<span") ?? false); }
internal static string ParseNote(this ResultContainer resultContainer, string previousNote, GedcomChunk incomingChunk) { var noteChunk = incomingChunk; if (incomingChunk.Reference.IsSpecified()) { noteChunk = resultContainer.GetIdChunk(noteChunk.Reference); if (noteChunk == null) { throw new Exception($"Unable to find Note with Id='{incomingChunk.Reference}'"); } } var sb = new StringBuilder(); foreach (var chunk in noteChunk.SubChunks) { if (chunk.IsUnwantedBlob()) { sb.AppendLine("(Skipped blob content)"); break; } switch (chunk.Type) { case "CONC": sb.Append(" " + chunk.Data); break; case "CONT": sb.AppendLine(chunk.Data); break; // Deliberately skipped for now case "_PLC": case "DATE": case "PLAC": case "SOUR": resultContainer.Warnings.Add($"Skipped Note Type='{chunk.Type}'"); break; default: resultContainer.Errors.Add($"Failed to handle Note Type='{chunk.Type}'"); break; } } return(previousNote.IsSpecified() ? previousNote + Environment.NewLine + sb : sb.ToString()); }
internal static DatePlace ParseDatePlace(this ResultContainer resultContainer, GedcomChunk chunk) { var datePlace = new DatePlace { Date = chunk.SubChunks.SingleOrDefault(c => c.Type == "DATE")?.Data, Place = chunk.SubChunks.SingleOrDefault(c => c.Type == "PLAC")?.Data }; var map = chunk.SubChunks.SingleOrDefault(c => c.Type == "MAP"); if (map != null) { datePlace.Latitude = map.SubChunks.SingleOrDefault(c => c.Type == "LATI")?.Data; datePlace.Longitude = map.SubChunks.SingleOrDefault(c => c.Type == "LONG")?.Data; } var note = chunk.SubChunks.SingleOrDefault(c => c.Type == "NOTE"); if (note != null) { datePlace.Note = resultContainer.ParseNote(datePlace.Note, note); } return(datePlace); }
internal static string ParseDateTime(this GedcomChunk chunk) { return((chunk.SubChunks.SingleOrDefault(c => c.Type == "DATE")?.Data + " " + chunk.SubChunks.SingleOrDefault(c => c.Type == "TIME")?.Data).Trim()); }
internal static void ParsePerson(this ResultContainer resultContainer, GedcomChunk indiChunk) { var person = new Person { Id = indiChunk.Id }; foreach (var chunk in indiChunk.SubChunks) { switch (chunk.Type) { case "_UID": person.Uid = chunk.Data; break; case "ADOP": person.Adoption = resultContainer.ParseAdoption(chunk); break; case "BAPM": person.Baptized = resultContainer.ParseDatePlace(chunk); break; case "BIRT": person.Birth = resultContainer.ParseDatePlace(chunk); break; case "BURI": person.Buried = resultContainer.ParseDatePlace(chunk); break; case "CHAN": person.Changed = chunk.ParseDateTime(); break; case "CHR": person.Baptized = resultContainer.ParseDatePlace(chunk); break; case "DEAT": person.Death = resultContainer.ParseDatePlace(chunk); break; case "EDUC": person.Education = chunk.Data; break; case "EMIG": person.Emigrated = resultContainer.ParseDatePlace(chunk); break; case "FACT": person.Note = resultContainer.ParseNote(person.Note, chunk); break; case "GRAD": person.Graduation = resultContainer.ParseDatePlace(chunk); break; case "HEAL": person.Health = chunk.Data; break; case "IDNO": person.IdNumber = chunk.Data; break; case "IMMI": person.Immigrated = resultContainer.ParseDatePlace(chunk); break; case "NAME": var nameSections = chunk.Data.Split("/".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); if (nameSections.Length > 0) { person.FirstName = nameSections[0]; } if (nameSections.Length > 1) { person.LastName = nameSections[1]; } break; case "NATU": person.BecomingCitizen = resultContainer.ParseDatePlace(chunk); break; case "NOTE": person.Note = resultContainer.ParseNote(person.Note, chunk); break; case "OCCU": person.Occupation = chunk.Data; break; case "RESI": person.Residence = resultContainer.ParseDatePlace(chunk); break; case "RELI": person.Religion = chunk.Data; break; case "SEX": person.Gender = chunk.Data; break; case "TITL": person.Title = chunk.Data; break; // Deliberately skipped for now case "_GRP": case "CONF": case "DSCR": case "EVEN": case "FAMS": case "FAMC": case "HIST": case "NCHI": case "NMR": case "OBJE": case "PAGE": case "RIN": case "SOUR": resultContainer.Warnings.Add($"Skipped Person Type='{chunk.Type}"); break; default: resultContainer.Errors.Add($"Failed to handle Person Type='{chunk.Type}"); break; } } resultContainer.Persons.Add(person); }