/**
  * 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;
 }
 public void gotoOther() {
   Object target = getTarget();
   if (target instanceof MAssociationEnd) {
     MAssociationEnd end = (MAssociationEnd) target;
     MAssociation assoc = end.getAssociation();
     Collection connections = assoc.getConnections();
     Iterator iter = connections.iterator();
     Object other = null;
     Object item = null;
     //
     //    always go to the one before match or to end
     //
     while (iter.hasNext()) {
       item = iter.next();
       if (item == end) {
         if (other != null) {
           navigateTo(other);
           return;
         }
       } else {
         other = item;
       }
     }
     //
     //   if previous end was the first, then navigate to the last
     navigateTo(other);
   }
 }
 /**
  * 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;
 }
 protected MNamespace getDisplayNamespace(Object target) {
   MNamespace ns = null;
   if (target instanceof MAssociationEnd) {
     MAssociationEnd end = (MAssociationEnd) target;
     MAssociation assoc = end.getAssociation();
     if (assoc != null) {
       ns = assoc.getNamespace();
     }
   }
   return ns;
 }
 /**
  * Gets the associations between the classifiers from and to. Returns null if from or to is null
  * or if there is no association between them.
  *
  * @param from
  * @param to
  * @return MAssociation
  */
 public Collection getAssociations(MClassifier from, MClassifier to) {
   Set ret = new HashSet();
   if (from == null || to == null) return ret;
   Iterator it = from.getAssociationEnds().iterator();
   while (it.hasNext()) {
     MAssociationEnd end = (MAssociationEnd) it.next();
     MAssociation assoc = end.getAssociation();
     Iterator it2 = assoc.getConnections().iterator();
     while (it2.hasNext()) {
       MAssociationEnd end2 = (MAssociationEnd) it2.next();
       if (end2.getType() == to) {
         ret.add(assoc);
       }
     }
   }
   return ret;
 }
 /**
  * Gets all classifiers that are associated to the given classifier (have an association
  * relationship with the classifier).
  *
  * @param classifier
  * @return Collection
  */
 public Collection getAssociatedClassifiers(MClassifier classifier) {
   if (classifier == null) return new ArrayList();
   List list = new ArrayList();
   Iterator it = classifier.getAssociationEnds().iterator();
   while (it.hasNext()) {
     MAssociationEnd end = (MAssociationEnd) it.next();
     MAssociation assoc = end.getAssociation();
     Iterator it2 = assoc.getConnections().iterator();
     while (it2.hasNext()) {
       MAssociationEnd end2 = (MAssociationEnd) it2.next();
       if (end2 != end) {
         list.add(end2.getType());
       }
     }
   }
   return list;
 }
 /**
  * Returns the associationend between some classifier type and some associaton assoc.
  *
  * @param type
  * @param assoc
  * @return MAssociationEnd
  */
 public MAssociationEnd getAssociationEnd(MClassifier type, MAssociation assoc) {
   if (type == null || assoc == null) return null;
   Iterator it = type.getAssociationEnds().iterator();
   while (it.hasNext()) {
     MAssociationEnd end = (MAssociationEnd) it.next();
     if (assoc.getConnections().contains(end)) return end;
   }
   return null;
 }
 /**
  * Deletes the association end. If the associationend's owner (the association) has one
  * associationend left after this delete, it is also deleted.
  */
 public void removeElement() {
   MAssociationEnd end = (MAssociationEnd) getTarget();
   MAssociation assoc = end.getAssociation();
   Collection ends = assoc.getConnections();
   if (ends.size() > 2) {
     Iterator it =
         ProjectBrowser.TheInstance.getProject()
             .findFigsForMember(end.getAssociation())
             .iterator();
     while (it.hasNext()) {
       // should do here something if the association end is shown
     }
     UmlFactory.getFactory().delete(end);
     navigateTo(assoc);
   } else {
     ProjectBrowser.TheInstance.setDetailsTarget(assoc);
     ActionRemoveFromModel.SINGLETON.actionPerformed(new ActionEvent(this, 0, null));
   }
 }
  /** 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 Enumeration gen(Object o) {
      Vector res = new Vector();
    if (!(o instanceof MClassifier)) return res.elements();
    MClassifier cls = (MClassifier) o;
    Vector ends = new Vector(cls.getAssociationEnds());
    if (ends == null) return res.elements();
    Iterator enum = ends.iterator();
    while (enum.hasNext()) {
      MAssociationEnd ae = (MAssociationEnd) enum.next();
      if (MAggregationKind.COMPOSITE.equals(ae.getAggregation())) {
	MAssociation asc = ae.getAssociation();
	List conn = asc.getConnections();
	if (conn == null || conn.size() != 2) continue;
	Object otherEnd = (ae == conn.get(0)) ?
	  conn.get(1) : conn.get(0);
	MClassifier componentClass = ((MAssociationEnd)otherEnd).getType();
	res.add(componentClass);
      }
    }
    return res.elements();
  }
  public Vector getChildren(Object parent) {
    if (!(parent instanceof MClass)) return null;
    Vector res = new Vector();
    Vector ends = new Vector(((MClass)parent).getAssociationEnds());
    if (ends == null) return null;
    java.util.Enumeration enum = ends.elements();
    while (enum.hasMoreElements()) {
      MAssociationEnd ae = (MAssociationEnd) enum.nextElement();
      MAssociation asc = ae.getAssociation();
      Vector allEnds = new Vector( asc.getConnections());
      MAssociationEnd otherEnd = null;
      if (ae == allEnds.elementAt(0))
	otherEnd = (MAssociationEnd) allEnds.elementAt(1);
      if (ae == allEnds.elementAt(1))
	otherEnd = (MAssociationEnd) allEnds.elementAt(0);
      if (otherEnd == null) continue;
      if (!otherEnd.isNavigable()) continue;
      if (res.contains(otherEnd.getType())) continue;
      res.addElement(otherEnd.getType());
      // needs-more-work: handle n-way Associations
    }
    return res;
  }
 private boolean isValidNamespace(MAssociation assoc, MNamespace ns) {
   Iterator it = assoc.getConnections().iterator();
   List namespaces = new ArrayList();
   while (it.hasNext()) {
     MAssociationEnd end = (MAssociationEnd) it.next();
     namespaces.add(end.getType().getNamespace());
   }
   it = namespaces.iterator();
   while (it.hasNext()) {
     MNamespace ns1 = (MNamespace) it.next();
     if (it.hasNext()) {
       MNamespace ns2 = (MNamespace) it.next();
       if (ns == getFirstSharedNamespace(ns1, ns2)) return true;
     }
   }
   return false;
 }