/**
  * Returns the source of a relation. The source of a relation is defined as the modelelement that
  * propagates this relation. If there are more then 1 sources, only the first is returned. If
  * there is no source, null is returned. Examples of sources include classifiers that are types to
  * associationends, usecases that are bases to extend and include relations and so on.
  *
  * @param relation
  * @return MModelElement
  */
 public MModelElement getSource(MRelationship relation) {
   if (relation instanceof MAssociation) {
     MAssociation assoc = (MAssociation) relation;
     List conns = assoc.getConnections();
     if (conns.isEmpty()) return null;
     return ((MAssociationEnd) conns.get(0)).getType();
   }
   if (relation instanceof MGeneralization) {
     MGeneralization gen = (MGeneralization) relation;
     return gen.getParent();
   }
   if (relation instanceof MDependency) {
     MDependency dep = (MDependency) relation;
     Collection col = dep.getSuppliers();
     if (col.isEmpty()) return null;
     return (MModelElement) (col.toArray())[0];
   }
   if (relation instanceof MFlow) {
     MFlow flow = (MFlow) relation;
     Collection col = flow.getSources();
     if (col.isEmpty()) return null;
     return (MModelElement) (col.toArray())[0];
   }
   if (relation instanceof MExtend) {
     MExtend extend = (MExtend) relation;
     return extend.getExtension(); // we have to follow the arrows..
   }
   if (relation instanceof MInclude) {
     MInclude include = (MInclude) relation;
     return include.getBase();
   }
   return null;
 }
 /**
  * Returns the destination of a relation. The destination of a relation is defined as the
  * modelelement that receives this relation. If there are more then 1 destinations, only the first
  * is returned. If there is no destination, null is returned. Examples of sources include
  * classifiers that are types to associationends, usecases that are bases to extend and include
  * relations and so on. In the case of an association, the destination is defined as the type of
  * the second element in the connections list.
  *
  * @param relation
  * @return MModelElement
  */
 public MModelElement getDestination(MRelationship relation) {
   if (relation instanceof MAssociation) {
     MAssociation assoc = (MAssociation) relation;
     List conns = assoc.getConnections();
     if (conns.size() <= 1) return null;
     return ((MAssociationEnd) conns.get(1)).getType();
   }
   if (relation instanceof MGeneralization) {
     MGeneralization gen = (MGeneralization) relation;
     return gen.getChild();
   }
   if (relation instanceof MDependency) {
     MDependency dep = (MDependency) relation;
     Collection col = dep.getClients();
     if (col.isEmpty()) return null;
     return (MModelElement) (col.toArray())[0];
   }
   if (relation instanceof MFlow) {
     MFlow flow = (MFlow) relation;
     Collection col = flow.getTargets();
     if (col.isEmpty()) return null;
     return (MModelElement) (col.toArray())[0];
   }
   if (relation instanceof MExtend) {
     MExtend extend = (MExtend) relation;
     return extend.getBase();
   }
   if (relation instanceof MInclude) {
     MInclude include = (MInclude) relation;
     return include.getAddition();
   }
   return null;
 }
  /**
   * Returns all Interfaces of which this class is a realization.
   *
   * @param cls the class you want to have the interfaces for
   * @return a collection of the Interfaces
   */
  public Collection getSpecifications(MClassifier cls) {
    Collection result = new Vector();
    Collection deps = cls.getClientDependencies();
    Iterator depIterator = deps.iterator();

    while (depIterator.hasNext()) {
      MDependency dep = (MDependency) depIterator.next();
      if ((dep instanceof MAbstraction)
          && dep.getStereotype() != null
          && dep.getStereotype().getName() != null
          && dep.getStereotype().getName().equals("realize")) {
        MInterface i = (MInterface) dep.getSuppliers().toArray()[0];
        result.add(i);
      }
    }
    return result;
  }
  /** Return a Fig that can be used to represent the given edge */
  public FigEdge getFigEdgeFor(GraphModel gm, Layer lay, Object edge) {
    if (edge instanceof MDependency) {

      MDependency dep = (MDependency) edge;
      FigDependency depFig = new FigDependency(dep);

      MModelElement supplier = (MModelElement) ((dep.getSuppliers().toArray())[0]);
      MModelElement client = (MModelElement) ((dep.getClients().toArray())[0]);

      FigNode supFN = (FigNode) lay.presentationFor(supplier);
      FigNode cliFN = (FigNode) lay.presentationFor(client);

      depFig.setSourcePortFig(cliFN);
      depFig.setSourceFigNode(cliFN);
      depFig.setDestPortFig(supFN);
      depFig.setDestFigNode(supFN);
      depFig.getFig().setLayer(lay);
      depFig.getFig().setDashed(true);
      return depFig;
    }

    if (edge instanceof MAssociation) {
      MAssociation asc = (MAssociation) edge;
      FigAssociation ascFig = new FigAssociation(asc, lay);
      Collection connections = asc.getConnections();
      if (connections == null) System.out.println("null connections....");
      Object[] connArray = connections.toArray();
      MAssociationEnd fromEnd = (MAssociationEnd) connArray[0];
      MClassifier fromCls = (MClassifier) fromEnd.getType();
      MAssociationEnd toEnd = (MAssociationEnd) connArray[1];
      MClassifier toCls = (MClassifier) toEnd.getType();
      FigNode fromFN = (FigNode) lay.presentationFor(fromCls);
      FigNode toFN = (FigNode) lay.presentationFor(toCls);
      ascFig.setSourcePortFig(fromFN);
      ascFig.setSourceFigNode(fromFN);
      ascFig.setDestPortFig(toFN);
      ascFig.setDestFigNode(toFN);
      ascFig.getFig().setLayer(lay);
      return ascFig;
    }
    return null;
  }
  public void setOwner(Object own) {
    Object oldOwner = getOwner();
    super.setOwner(own);

    if (own instanceof MDependency) {
      MDependency newDep = (MDependency) own;
      for (int i = 0; i < newDep.getSuppliers().size(); i++) {
        ((MModelElement) ((Object[]) newDep.getSuppliers().toArray())[i])
            .removeMElementListener(this);
        ((MModelElement) ((Object[]) newDep.getSuppliers().toArray())[i]).addMElementListener(this);
      }
      for (int i = 0; i < newDep.getClients().size(); i++) {
        ((MModelElement) ((Object[]) newDep.getClients().toArray())[i])
            .removeMElementListener(this);
        ((MModelElement) ((Object[]) newDep.getClients().toArray())[i]).addMElementListener(this);
      }
      newDep.removeMElementListener(this);
      newDep.addMElementListener(this);
      MModelElement supplier = (MModelElement) ((newDep.getSuppliers().toArray())[0]);
      MModelElement client = (MModelElement) ((newDep.getClients().toArray())[0]);

      FigNode supFN = (FigNode) getLayer().presentationFor(supplier);
      FigNode cliFN = (FigNode) getLayer().presentationFor(client);

      if (cliFN != null) {
        setSourcePortFig(cliFN);
        setSourceFigNode(cliFN);
      }
      if (supFN != null) {
        setDestPortFig(supFN);
        setDestFigNode(supFN);
      }
    }
  }