Package de.chris_soft.fyllgen.menu.extra

Source Code of de.chris_soft.fyllgen.menu.extra.MergeData

/**
* FyLLGen - A Java based tool for collecting and distributing family data
*
* Copyright (C) 2007-2011 Christian Packenius
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
package de.chris_soft.fyllgen.menu.extra;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Properties;

import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.MessageBox;

import de.chris_soft.fyllgen.GUI;
import de.chris_soft.fyllgen.Statics;
import de.chris_soft.fyllgen.data.Family;
import de.chris_soft.fyllgen.data.Person;
import de.chris_soft.fyllgen.data.Relationship;
import de.chris_soft.fyllgen.data.RelationshipParentChild;
import de.chris_soft.fyllgen.data.RelationshipPartners;
import de.chris_soft.fyllgen.ged.GedReader;
import de.chris_soft.fyllgen.ged.GedReaderException;
import de.chris_soft.fyllgen.utilities.SwtUtilities;
import de.chris_soft.fyllgen.widget.dialog.MergeChoiceDialog;
import de.chris_soft.fyllgen.widget.dialog.MergeChoiceRelationshipPersonDialog;
import de.chris_soft.fyllgen.widget.dialog.MergePersonDialog;
import de.chris_soft.fyllgen.widget.dialog.MergeRelationshipDialog;

/**
* Fremddaten �bernehmen. Falls noch keine Fremddaten eingelesen wurden (oder
* die alten schon komplett abgearbeitet sind), kann hier eine weitere Familie
* eingelesen werden. Ansonsten k�nnen die bisherigen Daten weiter �bernommen
* werden.<br>
* Vorgehensweise:<br>
* <code>
* Gibt es schon eingelesene Fremddaten (Consts.mergeFamily != null)?
*   NEIN: Datei-�ffnen-Dialog f�r Genealogie-Dateien.
*   JA:   Beziehung zwischen zwei �bernommenen Personen vorhanden?
*           JA:   Dialog zur Beziehungs�bernahme.
*           NEIN: Beziehung mit einer �bernommenen Person vorhanden?
*                 NEIN: MergeChoiceDialog und dann MergePersonDialog. [1], [2]
*                 JA:   Dialog zur Beziehungs�bernahme und gleichzeitiger Personenwahl. [3]
* [3] Fakt: Eine Person wurde schon �bernommen. Es existiert eine Beziehung zu einem Kind, Elternteil oder Partner,
* das/der noch nicht �bernommen wurde.
* </code>
* @author Christian Packenius, Juli 2008.
*/
public class MergeData implements Listener {
  /**
   * Fremddaten �bernehmen.
   * @param event Ungenutzter Event.
   */
  public void handleEvent(Event event) {
    // Neue Merge-Datei �ffnen?
    if (Statics.mergeFamily == null) {
      FileDialog fd = new FileDialog(GUI.instance.shell, SWT.OPEN);
      fd.setFilterExtensions(new String[] { "*.fgf", "*.ged" });
      fd.setFilterNames(new String[] { "FyLLGenFamily-Datei", "GEDCOM-Datei" });
      fd.setFilterPath(".");
      fd.setText("Datei zum Verkn�pfen w�hlen");
      String result = fd.open();
      if (result != null) {
        // *** FyLLGenFile ***
        if (result.endsWith(".fgf")) {
          Family mergeFamily = new Family();
          try {
            mergeFamily.loader.load(result);
          }
          catch (Exception exception) {
            messageBoxFileProblems(exception);
            return;
          }
          Statics.mergeFamily = mergeFamily;
        }
        // *** GEDCOM ***
        else if (result.endsWith(".ged")) {
          Family mergeFamily = new Family();
          try {
            readGedFile(result, mergeFamily);
          }
          catch (Exception exception) {
            messageBoxFileProblems(exception);
            return;
          }
          Statics.mergeFamily = mergeFamily;
        }
        // *** unknown ***
        else {
          MessageBox mb = new MessageBox(GUI.instance.shell, SWT.OK | SWT.ICON_ERROR);
          mb.setMessage("Dateityp unbekannt!");
          mb.setText("Fehler!");
          mb.open();
          return;
        }
      }
      else {
        // Der User hat die Dateiauswahl abgebrochen.
        return;
      }
    }

    // Personen intern sortieren (einmalig).
    Statics.mergeFamily.sortPersons();

    // Hier das manuelle und automatische Mergen.
    makeMerge();

    // Wenn keine Personen mehr in der Familie sind, diese l�schen.
    if (Statics.mergeFamily != null && Statics.mergeFamily.getPersonsArray().length == 0) {
      Statics.mergeFamily = null;
    }
  }

  private void readGedFile(String result, Family mergeFamily) throws FileNotFoundException, IOException,
      GedReaderException {
    GedReader ged = new GedReader();
    InputStream in = new FileInputStream(result);
    ged.setInputStream(in);
    ged.read();
    in.close();
    ged.fillFamily(mergeFamily);
  }

  private void messageBoxFileProblems(Exception exception) {
    MessageBox mb = new MessageBox(GUI.instance.shell, SWT.OK | SWT.ICON_ERROR);
    mb.setMessage("Problem beim Laden der Datei!\r\n" + exception.getMessage());
    mb.setText("Fehler!");
    mb.open();
  }

  /**
   * F�hrt den n�chsten Merge-Schritt aus.
   */
  private void makeMerge() {
    boolean bNext = true;
    while (bNext && Statics.mergeFamily != null) {
      // Eventuell gibt es Personen, die noch nicht gel�scht wurden. Dies
      // hier pr�fen.
      ArrayList<Person> listRemovedPersons = new ArrayList<Person>();
      for (Person p : Statics.mergeFamily.getPersonsArray()) {
        if (p.isFinishedMerge()) {
          Statics.mergeFamily.removeFinishedMergePersons(listRemovedPersons, p);
        }
      }

      // Zuerst schauen, ob eine Beziehung zu Verkn�pfen ist.
      Relationship rel = getNextFullRelationship();
      if (rel != null) {
        bNext = mergeFullRelationship(rel);
      }

      else {
        // Erst nach einer Beziehung mit nur einer �bernommenen Person suchen.
        rel = getNextHalfRelationship();
        if (rel != null) {
          bNext = mergeHalfRelationship(rel);
        }

        // Dann nach einer Person suchen.
        else {
          // Eventuell gibt es Personen, die noch nicht gel�scht wurden. Dies
          // hier pr�fen.
          listRemovedPersons = new ArrayList<Person>();
          for (Person p : Statics.mergeFamily.getPersonsArray()) {
            if (p.isFinishedMerge()) {
              Statics.mergeFamily.removeFinishedMergePersons(listRemovedPersons, p);
            }
          }

          if (Statics.mergeFamily != null && Statics.mergeFamily.getPersonsCount() > 0) {
            bNext = mergeNextPerson();
          }
          else {
            Statics.mergeFamily = null;
            bNext = false;
          }
        }
      }
    }
  }

  /**
   * �bernahme einer Beziehung zweier Personen, bei der beide Personen schon
   * bekannt sind.
   */
  private boolean mergeFullRelationship(Relationship rel) {
    boolean bNext;
    if (rel instanceof RelationshipParentChild) {
      bNext = mergeParentChildRelation((RelationshipParentChild) rel);
    }
    else {
      bNext = mergePartnerRelation((RelationshipPartners) rel);
    }
    return bNext;
  }

  /**
   * Merge einer Personenbeziehung, bei der eine der beiden Personen schon
   * �bernommen wurde und die andere nicht (daher "Half").
   */
  private boolean mergeHalfRelationship(Relationship rel) {
    // Schauen, ob wir die andere (nicht �bernommene) Person nicht direkt
    // �bernehmen k�nnen.
    Person notMergedPerson = rel.partner1.isFinishedMerge() ? rel.partner2 : rel.partner1;
    Person p2 = Family.instance.getPersonFromXREFID(notMergedPerson.getValue(Person.XREFID));
    if (p2 != null && notMergedPerson.getXREFID().equals(p2.getXREFID())) {
      // Person wurde zwar noch nicht �bernommen, aber es gibt sie schon. Nun
      // schauen, ob sie nicht ohnehin identisch ist.
      if (notMergedPerson.equals(p2)) {
        notMergedPerson.setFinishedMerge(true);
        return true;
      }
    }

    // Eigentlichen Merge-Dialog aufrufen und auswerten.
    boolean bNext;
    MergeChoiceRelationshipPersonDialog mcrpd = new MergeChoiceRelationshipPersonDialog(GUI.instance.shell, rel);
    mcrpd.open();
    bNext = mcrpd.finished;
    if (mcrpd.finished) {
      MergePersonDialog mpd = new MergePersonDialog(GUI.instance.shell, mcrpd.oldPerson, mcrpd.otherPerson);
      mpd.open();
      bNext = mpd.finished;
    }
    else if (mcrpd.finishedNew) {
      MergePersonDialog mpd = new MergePersonDialog(GUI.instance.shell, null, mcrpd.otherPerson);
      mpd.open();
      if (mpd.finished) {
        Person originalPerson = Family.instance.getPersonFromXREFID(mcrpd.mergedPerson.getValue(Person.XREFID));
        Relationship newRelship;
        if (rel instanceof RelationshipParentChild) {
          if (rel.partner1 == mcrpd.mergedPerson) {
            newRelship = new RelationshipParentChild(originalPerson, mpd.oldPerson, rel.cloneProperties());
          }
          else {
            newRelship = new RelationshipParentChild(mpd.oldPerson, originalPerson, rel.cloneProperties());
          }
        }
        else {
          newRelship = new RelationshipPartners(mpd.oldPerson, originalPerson, rel.cloneProperties());
        }
        originalPerson.addRelationship(newRelship);
        Family.instance.setCurrentPerson(mpd.oldPerson, 2);
        mcrpd.otherPerson.removeRelationship(rel);
        Statics.mergeFamily.removeFinishedMergePersons(new ArrayList<Person>(), rel.partner1);
        Statics.mergeFamily.removeFinishedMergePersons(new ArrayList<Person>(), rel.partner2);
      }
      bNext = mpd.finished;
    }
    return bNext;
  }

  /**
   * Noch zu verkn�pfende Beziehung suchen. Ist recht einfach: Es m�ssen nur
   * beide Personen schon verkn�pft sein.
   */
  private Relationship getNextFullRelationship() {
    Relationship relship;
    for (Person person : Statics.mergeFamily.getPersonsArray()) {
      // Eltern und Partner pr�fen (Kind wird indirekt durch Eltern mit
      // gepr�ft).
      Relationship[] relships = person.getRelationships(Relationship.PARENTS);
      if ((relship = getGoodRelationship(relships)) != null) {
        return relship;
      }
      relships = person.getRelationships(Relationship.PARTNERS);
      if ((relship = getGoodRelationship(relships)) != null) {
        return relship;
      }
    }

    // Aktuell keine abzuarbeitende Verbindung.
    return null;
  }

  /**
   * Noch zu verkn�pfende Beziehung suchen. Hier braucht nur eine der beiden
   * Personen �bernommen sein.
   */
  private Relationship getNextHalfRelationship() {
    Relationship relship;
    for (Person person : Statics.mergeFamily.getPersonsArray()) {
      // Eltern und Partner pr�fen (Kind wird indirekt durch Eltern mit
      // gepr�ft).
      Relationship[] relships = person.getRelationships(Relationship.PARENTS);
      if ((relship = getHalfGoodRelationship(relships)) != null) {
        return relship;
      }
      relships = person.getRelationships(Relationship.PARTNERS);
      if ((relship = getHalfGoodRelationship(relships)) != null) {
        return relship;
      }
    }

    // Aktuell keine abzuarbeitende Verbindung.
    return null;
  }

  /**
   * Pr�ft, ob eine der angegebenen Verbindungen geeignet f�r eine �bernahme
   * ist. Dies ist der Fall, sobald beide Personen �bernommen wurden.
   * @param relships
   * @return
   */
  private Relationship getGoodRelationship(Relationship[] relships) {
    for (Relationship relationship : relships) {
      if (relationship.partner1.isFinishedMerge() && relationship.partner2.isFinishedMerge()) {
        return relationship;
      }
    }
    return null;
  }

  /**
   * Pr�ft, ob eine der angegebenen Verbindungen geeignet f�r eine �bernahme
   * ist. Dies ist der Fall, wenn eine der beiden Personen bereits �bernommen
   * worden ist.
   * @param relships
   * @return
   */
  private Relationship getHalfGoodRelationship(Relationship[] relships) {
    for (Relationship relationship : relships) {
      if (relationship.partner1.isFinishedMerge() || relationship.partner2.isFinishedMerge()) {
        return relationship;
      }
    }
    return null;
  }

  /**
   * Macht den Dialog auf, in dem eine Eltern-Kind-Beziehung �bernommen werden
   * kann.
   * @return true, wenn es weiter gehen kann, sonst false.
   */
  private boolean mergeParentChildRelation(RelationshipParentChild mergeRelationship) {
    // Zu dieser Verbindung die Original-Verbindung ermitteln.
    Person p1 = Family.instance.getPersonFromXREFID(mergeRelationship.partner1.getXREFID());
    Person p2 = Family.instance.getPersonFromXREFID(mergeRelationship.partner2.getXREFID());
    Relationship originalRelationship = p1.getRelationship(p2);

    // Falls es bisher keine Beziehung gab, dann fragen, ob man sie �bernehmen
    // soll.
    if (originalRelationship == null) {
      String question = "Soll die Eltern-Kind-Beziehung zwischen\r\n\r\n" + p1 + "\r\nund\r\n" + p2 + "\r\n\r\n";
      question += "mit dem Status \"" + mergeRelationship.getTypeText() + "\" �bernommen werden?";
      int answer = SwtUtilities.askYesNoCancel(GUI.instance.shell, question);
      if (answer == SWT.YES) {
        RelationshipParentChild rpc = p1.addChild(p2);
        rpc.setValue(Relationship.TYPE, mergeRelationship.getType());
        Family.instance.setCurrentPerson(p2, 2);
        Statics.mergeFamily.removeRelationship(mergeRelationship);
      }
      else if (answer == SWT.NO) {
        Statics.mergeFamily.removeRelationship(mergeRelationship);
      }
      return answer != SWT.CANCEL;
    }

    // Falls beide identisch sind, brauchen wir hier keinen Dialog mehr.
    if (compareRelationships(mergeRelationship, originalRelationship)) {
      // SwtUtilities.sayInfo(Consts.getGui().shell,
      // "Identische Beziehung zwischen "
      // + p1 + " und " + p2 + " wird gel�scht.");
      Statics.mergeFamily.removeRelationship(mergeRelationship);
      return true;
    }

    // Fragen, ob der Typ ge�ndert werden soll.
    String question = "Die Eltern-Kind-Beziehung zwischen\r\n\r\n" + originalRelationship.partner1 + "\r\nund\r\n";
    question += originalRelationship.partner2 + "\r\n\r\nhat zur Zeit den Status\r\n\r\n"
        + originalRelationship.getTypeText() + ".";
    question += "\r\n\r\n Soll dieser Status den neuen Daten gem�� auf\r\n\r\n" + mergeRelationship.getTypeText()
        + "\r\n\r\nge�ndert werden?";
    int answer = SwtUtilities.askYesNoCancel(GUI.instance.shell, question);
    if (answer == SWT.YES) {
      originalRelationship.setValue(Relationship.TYPE, mergeRelationship.getType());
    }
    if (answer != SWT.CANCEL) {
      Statics.mergeFamily.removeRelationship(mergeRelationship);
    }
    return answer != SWT.CANCEL;
  }

  /**
   * Pr�ft, ob die angegebene zu verkn�pfende Beziehung identisch zur
   * Original-Beziehung ist (wenn es diese gibt).
   * @param mergeRelationship Beziehung aus der Merge-Family.
   * @param originalRelationship
   * @return true, falls identisch oder Original-Beziehung mit �bergeordneten
   *         Informationen, sonst false.
   */
  private boolean compareRelationships(Relationship mergeRelationship, Relationship originalRelationship) {
    // Daten der beiden Beziehungen ermitteln.
    Properties propMerge = mergeRelationship.cloneProperties();
    Properties propOriginal = originalRelationship.cloneProperties();

    // Falls die neuen Daten leer oder unn�tz sind, braucht keine �bernahme der
    // Daten stattfinden.
    if (propMerge.size() == 0) {
      return true;
    }
    String type = propMerge.getProperty(Relationship.TYPE);
    if (propMerge.size() == 1 && type != null && type.equals("?")) {
      return true;
    }

    // Wenn beide unterschiedlich sind, auf jeden Fall vergleichen.
    if (propMerge.size() != propOriginal.size()) {
      return false;
    }

    // Alles vergleichen.
    Enumeration<Object> en = propMerge.keys();
    while (en.hasMoreElements()) {
      String key = (String) en.nextElement();
      String val2 = propOriginal.getProperty(key);
      if (val2 == null) {
        return false;
      }
      if (!propMerge.getProperty(key).equals(val2)) {
        return false;
      }
    }
    return true;
  }

  /**
   * Macht den Dialog auf, in dem eine Partnerschaft �bernommen werden kann.
   * @return true, wenn der Anwender die Daten �bernommen hat, sonst false.
   */
  private boolean mergePartnerRelation(RelationshipPartners newRelship) {
    Person p1 = Family.instance.getPersonFromXREFID(newRelship.partner1.getXREFID());
    Person p2 = Family.instance.getPersonFromXREFID(newRelship.partner2.getXREFID());
    RelationshipPartners oldRelship = p1.getPartnersRelationship(p2);

    // Fragen, ob Partnerschaft �bernommen werden soll.
    if (oldRelship == null) {
      String question = "Soll die Partnerschaft zwischen\r\n\r\n" + p1 + "\r\nund\r\n" + p2 + "\r\n\r\n";
      question += "mit dem Status \"" + newRelship.getTypeText() + "\" �bernommen werden?";
      int answer = SwtUtilities.askYesNoCancel(GUI.instance.shell, question);
      if (answer == SWT.YES) {
        String type = newRelship.getType();
        RelationshipPartners rpc = p1.addPartner(p2, type);
        rpc.setValue(Relationship.TYPE, type);
        Family.instance.setCurrentPerson(p2, 2);
        Statics.mergeFamily.removeRelationship(newRelship);
      }
      else if (answer == SWT.NO) {
        Statics.mergeFamily.removeRelationship(newRelship);
      }
      return answer != SWT.CANCEL;
    }

    // Vor dem �ffnen des Dialogs erstmal feststellen, ob es �berhaupt einen
    // Unterschied gibt.
    // Falls nicht, kann man sich den Dialog auch sparen.
    if (oldRelship.equals(newRelship)) {
      Statics.mergeFamily.removeRelationship(newRelship);
      return true;
    }

    // SwtUtilities.sayInfo(Consts.getGui().shell,
    // "TO-DO - openAbsorbPartnerRelationDialog!");
    MergeRelationshipDialog mrd = new MergeRelationshipDialog(GUI.instance.shell, oldRelship, newRelship);
    mrd.open();
    if (mrd.finished) {
      Statics.mergeFamily.removeRelationship(newRelship);
    }
    return mrd.finished;
  }

  /**
   * Ermittelt die n�chste Person, die �bernommen werden kann. Sie wird auch
   * direkt �bernommen bzw. es wird eine neue Person erzeugt.
   * @return false, wenn der Anwender einen Dialog abgebrochen hat, sonst true.
   */
  private boolean mergeNextPerson() {
    MergeChoiceDialog npcd = new MergeChoiceDialog(GUI.instance.shell);
    npcd.open();
    if (npcd.finished) {
      MergePersonDialog mpd = new MergePersonDialog(GUI.instance.shell, npcd.oldPerson, npcd.newPerson);
      mpd.open();
      return mpd.finished;
    }
    return false;
  }
}
TOP

Related Classes of de.chris_soft.fyllgen.menu.extra.MergeData

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.