@Override
  public RelationSchema getClone() {
    RelationSchema clone;

    ArrayList<Attribute> clonesAttributes = new ArrayList<>();
    ArrayList<FunctionalDependency> clonesFunctionalDependencies = new ArrayList<>();

    for (Attribute attribute : attributes) {
      clonesAttributes.add((Attribute) attribute.getClone());
    }

    for (FunctionalDependency dependency : functionalDependencies) {
      clonesFunctionalDependencies.add(dependency.getClone());
    }

    clone = new RelationSchema(name, clonesAttributes, clonesFunctionalDependencies);

    clone.setOwnId(ownId);

    clone.restoreReferences();
    clone.initPropertyChangeListeners();

    clone.setDirty(super.isDirty());

    return clone;
  }
 public boolean addFunctionalDependency(FunctionalDependency dependency) {
   for (FunctionalDependency fd : functionalDependencies) {
     if (fd.equals(dependency)) {
       return false;
     }
   }
   changeSupport.fireBeforeChange();
   functionalDependencies.add(dependency);
   changeSupport.fireAfterChange();
   return true;
 }
  public void updateFunctionalDependencies() {
    ArrayList<FunctionalDependency> toDelete = new ArrayList<>();

    for (FunctionalDependency fd : functionalDependencies) {
      cleanReferences(fd.getSourceAttributes());
      cleanReferences(fd.getTargetAttributes());

      if (fd.getSourceAttributes().isEmpty() || fd.getTargetAttributes().isEmpty()) {
        toDelete.add(fd);
      }
    }

    for (FunctionalDependency fd : toDelete) {
      removeFunctionalDependency(fd);
    }
  }
 /**
  * Restores the References between the FunctionalDependencies and the Attributes of the relation
  */
 public void restoreReferences() {
   for (FunctionalDependency fd : getFunctionalDependencies()) {
     for (int i = 0; i < fd.getSourceAttributes().size(); i++) {
       fd.getSourceAttributes()
           .set(i, getAttributeByName(fd.getSourceAttributes().get(i).getName()));
     }
     for (int i = 0; i < fd.getTargetAttributes().size(); i++) {
       fd.getTargetAttributes()
           .set(i, getAttributeByName(fd.getTargetAttributes().get(i).getName()));
     }
   }
 }