3

Resolved

GedcomImport logic problem in ImportChildren method

description

BUG REPORT:
 
There are at least two errors in the way that spouse relationships are adding during GEDCOM import. Specifically, cases where only one parent is known have problems. Also, I have cases where a person with multiple spouses with multiple children do not import properly.
 
In the ImportChildren method, there is some flawed logic. I grabbed the FamilyShow code to help me generate the XML for a seperate purpose and encountered this problem. I do not know the code to fix FamilyShow, but here is my modification that worked for my purpose. Please look at this method.
 
By the way, GREAT PROGRAM. This is honestly one of the coolest applications I've seen in a long time. Thank you several time over for putting this together.
 
Here is the code i modified in GedcomImport.cs in the ImportChildren method, changes are at the end:
 
foreach (string child in children)
{
// Get the Person object for the child.
Person childPerson = people.Find(child);
 
// Calling RelationshipHelper.AddChild hooks up all of the
// child relationships for the husband and wife. Also hooks up
// the sibling relationships.
if (husbandPerson != null && wifePerson != null && childPerson != null)
{
RelationshipHelper.AddChild(people, husbandPerson, childPerson);
RelationshipHelper.AddChild(people, wifePerson, childPerson);
}
 
if (husbandPerson == null && wifePerson != null && childPerson != null)
RelationshipHelper.AddChild(people, wifePerson, childPerson);
 
if (husbandPerson != null && wifePerson == null && childPerson != null)
RelationshipHelper.AddChild(people, husbandPerson, childPerson);

file attachments

comments

elyoh wrote Apr 9, 2009 at 11:44 PM

I agree the current code misses adding relationships for multiple spouses. However, your code here:

RelationshipHelper.AddChild(people, husbandPerson, childPerson);
RelationshipHelper.AddChild(people, wifePerson, childPerson);

correctly adds the parent but the sideeffect is that child gets added to its brothers and sisters again. If I have one brother, his relationship text say brother to me and me!

There is no way to fix this in version 3.0. You need a method to add a child to a parent but not create all the other relationships aswell!

wrote Apr 9, 2009 at 11:46 PM

elyoh wrote Apr 25, 2009 at 5:05 PM

This code fixes the issue you describe but prevents muliple identical sibling relationships from being generated:

if (husbandPerson == null && wifePerson != null & childPerson != null)
                    RelationshipHelper.AddChild(people, wifePerson, childPerson);

                if (husbandPerson != null && wifePerson == null & childPerson != null)
                    RelationshipHelper.AddChild(people, husbandPerson, childPerson);

                if (husbandPerson != null && wifePerson != null & childPerson != null)
                {

                    if (husbandPerson.Spouses.Contains(wifePerson))
                        RelationshipHelper.AddChild(people, husbandPerson, childPerson);
                    else
                        RelationshipHelper.AddChild(people, wifePerson, childPerson);

                    if(!wifePerson.Spouses.Contains(husbandPerson))
                        RelationshipHelper.AddChild(people, wifePerson, childPerson);
                    if (!husbandPerson.Spouses.Contains(wifePerson))
                        RelationshipHelper.AddChild(people, husbandPerson, childPerson);
                }

josephskeller wrote Aug 14, 2009 at 9:41 PM

I've got a fix for this which I've thoroughly tested. Four files are affected.

1) GedcomImport.cs line 126:
            // Import the children.
            foreach (string child in children)
            {
                // Get the Person object for the child.
                Person childPerson = people.Find(child);

                // Calling RelationshipHelper.AddChild hooks up all of the
                // child relationships for the parent. Also hooks up
                // the sibling relationships.
                if (husbandPerson != null && childPerson != null)
                    RelationshipHelper.AddChild(people, husbandPerson, childPerson);

                // ** We need to do this for each parent...
                //if (husbandPerson == null && wifePerson != null & childPerson != null)
                //    RelationshipHelper.AddChild(people, wifePerson, childPerson);

                if (wifePerson != null & childPerson != null)
                    RelationshipHelper.AddChild(people, wifePerson, childPerson);
            }
2) RelationshipHelper.cs line 15:
    /// <summary>
    /// Performs the business logic for adding the Child relationship between the person and the child.
    /// </summary>
    public static void AddChild(PeopleCollection family, Person person, Person child)
    {
        // Add the new child as a sibling to any existing children
        foreach (Person existingSibling in person.Children)
        {
            family.AddSibling(existingSibling, child);
        }

        // **** If there are multiple spouses, this code will prevent this child from being added.

        //switch (person.Spouses.Count)
        //{
        //    // Single parent, add the child to the person
        //    case 0:
        //        family.AddChild(person, child, ParentChildModifier.Natural);
        //        break;

        //    // Has existing spouse, add the child to the person's spouse as well.
        //    case 1:
        //        family.AddChild(person, child, ParentChildModifier.Natural);
        //        family.AddChild(person.Spouses[0], child, ParentChildModifier.Natural);
        //        break;
        //}

        family.AddChild(person, child, ParentChildModifier.Natural);
    }
3) People.cs line 516:
    /// <summary>
    /// Adds sibling relation between the person and the sibling
    /// </summary>
    public void AddSibling(Person person, Person sibling)
    {
        //assign sibling to each other    
        if (!person.Relationships.Contains(sibling))
            person.Relationships.Add(new SiblingRelationship(sibling));
        if (!sibling.Relationships.Contains(person))
            sibling.Relationships.Add(new SiblingRelationship(person));

        //add the sibling to the main people list
        if (!this.Contains(sibling))
            this.Add(sibling);
    }
4) Relationship.cs line 184:
/// <summary>
/// Collection of relationship for a person object
/// </summary>
[Serializable]
public class RelationshipCollection : ObservableCollection<Relationship>
{
    //----------------------------------------------------------------------
    /// <summary>
    /// Determines whether the person is part of any existing relationship.
    /// </summary>
    public bool Contains(Person person)
    {
        // Only add the item if it doesn't already exist.
        foreach (Relationship relationship in this)
        {
            if (relationship.RelationTo.Id == person.Id)
                return true;
        }
        return false;
    }
}
There you go!

Joseph

elyoh wrote Aug 21, 2009 at 10:11 PM

A bit after my April post, which I later realised is not the correct code, I noticed that the problem was not at all with the Gedcom Import logic at all but the switch in the AddChild method in RelationshipHelper.cs

I'll try to explain my reasoning:

The problem is when you have a parent with 2 spouses, the AddChild method doesn't do anything. It contains a switch on spouses count and looks at 2 cases, spouse count = 0 and =1 therefore when a person has greater than 2 spouses, no child is added to the parent. I'm pretty sure now that the original Gedcom Import logic is sound. In fact it becomes a nightmare to use the RelationshipHelper.AddChild method to do this once number of spouses becomes greater than 1.

Since we know the family members explicitly from the gedcom file, we don't need to use RelationshipHelper.cs methods we can use the People.cs methods for adding relationships directly.

The somewhat elusive solution is to use this code:
                //case both parents specified
                if (husbandPerson != null && wifePerson != null & childPerson != null)
                {
                    people.AddChild(husbandPerson, childPerson, ParentChildModifier.Natural);
                    people.AddChild(wifePerson, childPerson, ParentChildModifier.Natural);
                }

                //case only wifePerson specified
                if (husbandPerson == null && wifePerson != null & childPerson != null)
                    people.AddChild(wifePerson, childPerson, ParentChildModifier.Natural);

                //case only husbandPerson specifed
                if (husbandPerson != null && wifePerson == null & childPerson != null)
                    people.AddChild(husbandPerson, childPerson, ParentChildModifier.Natural);

                //connect each sibling to the childPerson
               foreach (String child1 in children)
                {
                    Person sibling = people.Find(child1);

                    if (sibling != childPerson && !childPerson.Siblings.Contains(sibling))
                        people.AddSibling(sibling, childPerson);
                }
I'll upload a sample file familyx file and it's gedcom clone which may highlight the point further.

elyoh wrote Aug 22, 2009 at 1:16 PM

The gedcom file.

wrote Aug 22, 2009 at 1:16 PM

elyoh wrote Aug 22, 2009 at 1:17 PM

And the familyx equivilent.

wrote Aug 22, 2009 at 1:17 PM

wrote Dec 7, 2009 at 8:43 PM

wrote Dec 28, 2009 at 10:17 AM

wrote Feb 21, 2013 at 10:59 PM

wrote May 16, 2013 at 10:35 AM

wrote May 16, 2013 at 10:35 AM

wrote Jun 14, 2013 at 7:23 AM