/** * Should be called after all classes have been parsed. This generates the different arrow types. * connecting the classes in the UML. * * @param classes A list of all classes in the UML. */ public void generateArrows(ArrayList<UMLClass> classes) { for (UMLClass secondClass : classes) { // Check for implements arrows for (String implementation : this.implementations) { if (secondClass.getName().equals(implementation)) { this.addArrow(secondClass, "onormal", "dashed"); } } // Check for extends arrows if (secondClass.getName().equals(this.extension)) { this.addArrow(secondClass, "onormal", ""); } // Check for association arrows // Keep in mind, if we do the diamonds this is technically // backwards. for (UMLField field : this.fields) { String type = field.getType().getFullBaseDataType(); if (secondClass.getName().equals(type)) { this.addArrow(secondClass, "vee", "solid"); // System.out.println("association from " + this.getName() + " " + type ); } } } // Check for uses arrows for (UMLMethod meth : this.methods) { ArrayList<UMLClass> classUsedList = new ArrayList<UMLClass>(); for (TypeData d : meth.getClassesUsed()) { for (UMLClass c : classes) { if (c.getName().equals(d.getFullBaseDataType())) { classUsedList.add(c); } } } for (UMLClass cls : classUsedList) { this.addArrow(cls, "vee", "dashed"); } } }
// TODO Move these methods into UMLGraph where it makes more sense? // TODO Have a seperate array stored for all of the arrows? public void removeRedundantUsesArrows() { ArrayList<UMLClass> extendsOrImplements = this.getAllExtendsOrImplements(); ArrayList<UMLClass> thisUsed = this.getAllUsedClasses(); // Go through everything this class extends or implements (directly or // indirectly) for (UMLClass extendedClass : extendsOrImplements) { ArrayList<UMLClass> otherUsed = extendedClass.getAllUsedClasses(); // Go through all of the classes that this class uses for (UMLClass usedClass : thisUsed) { boolean removeArrow = true; // If the other class uses the same thing as this class, check // to see // if all instances where that is used is the same in both // classes // or not used in this class. If so, remove the arrow from this // class. if (otherUsed.contains(usedClass)) { // Check if the used class is within a field boolean foundField = false; for (UMLField field : this.getFields()) { if (field.getType().getFullBaseDataType().equals(usedClass.getName())) { foundField = true; removeArrow = false; } } // If the used class is in a field, don't remove the arrow, // so skip the arrow checks. if (!foundField) { // Check everything for type, and if they are the same // in the two // If everything is the same, remove this class' used // arrow for that thing for (UMLMethod thisMethod : this.methods) { boolean wasUsed = false; // Check to see if this method uses the used class // at all for (TypeData d : thisMethod.getClassesUsed()) { if (d.getFullBaseDataType().equals(usedClass.getName())) { wasUsed = true; break; } } // The class was used in the method. Check to see if // there is an identical method in the other. if (wasUsed) { boolean isSame = false; for (UMLMethod extendedMethod : extendedClass.getMethods()) { // If the methods have the same signature if (thisMethod.sameSignature(extendedMethod)) { isSame = true; break; } } if (!isSame) { removeArrow = false; break; } } } } if (removeArrow) { for (UMLArrow arrow : new ArrayList<UMLArrow>(this.arrows)) { if (arrow.isUsesArrow() && arrow.getEndClass().getName().equals(usedClass.getName())) { this.arrows.remove(arrow); break; } } } } } } }