Bug 111593 - Operations of the Interface are not implemented in the class automatically
Summary: Operations of the Interface are not implemented in the class automatically
Status: RESOLVED FIXED
Alias: None
Product: umbrello
Classification: Applications
Component: general (show other bugs)
Version: 1.4.2
Platform: openSUSE Linux
: NOR wishlist
Target Milestone: ---
Assignee: Umbrello Development Group
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-08-27 04:54 UTC by Ujean
Modified: 2007-02-20 22:42 UTC (History)
0 users

See Also:
Latest Commit:
Version Fixed In:
Sentry Crash Report:


Attachments
java class diagram with interface (29.63 KB, image/png)
2007-02-20 15:39 UTC, Antoine Dopffer
Details
java generated code (2.06 KB, text/x-java)
2007-02-20 15:43 UTC, Antoine Dopffer
Details
patch for #111593 (5.32 KB, patch)
2007-02-20 15:49 UTC, Antoine Dopffer
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Ujean 2005-08-27 04:54:03 UTC
Version:           1.4.2 (using KDE KDE 3.4.2)
Installed from:    SuSE RPMs

Bodys of methods defined by an interface should be automatically written in the generated code of an class, which implements the Interface. 

This should happen in the generated file, not in the UML diagram.

With that system, implementation of the methods in the class are not forgoten and done easily by hand.
Comment 1 Antoine Dopffer 2007-02-20 15:39:27 UTC
Created attachment 19756 [details]
java class diagram with interface 

That's an exemple of a class diagram with few interfaces and classes
Comment 2 Antoine Dopffer 2007-02-20 15:43:27 UTC
Created attachment 19757 [details]
java generated code

With the patch in the next attachment, here comes the generated code.
You can notice: 
the method kde4ever is not generated in class_1 because it exists in class_2
the method doStuff is not generated in class_1 because it should be implemented
first in class_2
the method beSmart is only implemented once
Comment 3 Antoine Dopffer 2007-02-20 15:49:07 UTC
Created attachment 19758 [details]
patch for #111593

The difficult part was to not generate methods that exist in super classes and
not to generate twice methods that exist in two super interfaces

Thanks
Comment 4 Oliver Kellogg 2007-02-20 22:42:35 UTC
SVN commit 635782 by okellogg:

Apply attachment 19758 [details] from Antoine Dopffer.
> The difficult part was to not generate methods that exist in super classes
> and not to generate twice methods that exist in two super interfaces 


Many thanks Antoine for your work!
BUG:111593


 M  +2 -0      ChangeLog  
 M  +74 -1     umbrello/codegenerators/javawriter.cpp  
 M  +31 -0     umbrello/codegenerators/javawriter.h  


--- branches/KDE/3.5/kdesdk/umbrello/ChangeLog #635781:635782
@@ -5,6 +5,8 @@
 * Java interface inheritance, abstract classes and generics in code generation
   (53376)
 * %date% and %time% not being parsed (96612)
+* Operations of the Interface are not implemented in the class automatically
+  (111593)
 * Relationships for entities do not live outside of the diagram (125146)
 * Javascript wrong Code Generation (135527)
 * Javascript Code Generation creates bad format methods (135540)
--- branches/KDE/3.5/kdesdk/umbrello/umbrello/codegenerators/javawriter.cpp #635781:635782
@@ -704,6 +704,76 @@
     return l;
 }
 
+
+bool JavaWriter::compareJavaMethod(UMLOperation *op1, UMLOperation *op2)
+{
+    if (op1 == NULL || op2 == NULL)
+        return false;
+    if (op1 == op2)
+        return true;
+    if (op1->getName() != op2->getName())
+        return false;
+    UMLAttributeList atl1 = op1->getParmList();
+    UMLAttributeList atl2 = op2->getParmList();
+    if (atl1.count() != atl2.count())
+        return false;
+    UMLAttribute *at1;
+    UMLAttribute *at2;
+    for (at1  = atl1.first(), at2 = atl2.first(); at1 && at2 ; at1 = atl1.next(),at2 = atl2.next())
+    {
+        if (at1->getTypeName() != at2->getTypeName())
+            return false;
+    }
+    return true;
+    
+}
+
+bool JavaWriter::javaMethodInList(UMLOperation *umlOp, UMLOperationList &opl)
+{
+    for (UMLOperation *op = opl.first(); op; op = opl.next()) {
+        if (JavaWriter::compareJavaMethod(op, umlOp)) {
+            return true;
+        }
+    }
+    return false;
+}
+
+void JavaWriter::getSuperImplementedOperations(UMLClassifier *c, UMLOperationList &yetImplementedOpList ,UMLOperationList &toBeImplementedOpList, bool noClassInPath)
+{
+    UMLClassifierList superClasses = c->findSuperClassConcepts();
+    
+    for (UMLClassifier *concept= superClasses.first(); concept; concept = superClasses.next())
+    {
+        getSuperImplementedOperations(concept, yetImplementedOpList, toBeImplementedOpList, (concept->isInterface() && noClassInPath));
+        UMLOperationList opl = concept->getOpList();
+        for (UMLOperation *op = opl.first(); op; op = opl.next()) {
+            if (concept->isInterface() && noClassInPath) {
+                if (!JavaWriter::javaMethodInList(op,toBeImplementedOpList))
+                    toBeImplementedOpList.append(op);
+            }
+            else
+            {
+                if (!JavaWriter::javaMethodInList(op, yetImplementedOpList))
+                    yetImplementedOpList.append(op);
+            }
+        }
+    }
+    
+}
+
+void JavaWriter::getInterfacesOperationsToBeImplemented(UMLClassifier *c, UMLOperationList &opList )
+{
+    UMLOperationList yetImplementedOpList;
+    UMLOperationList toBeImplementedOpList;
+
+    getSuperImplementedOperations(c,yetImplementedOpList, toBeImplementedOpList);
+    for (UMLOperation *op = toBeImplementedOpList.first(); op; op = toBeImplementedOpList.next())
+    {
+        if ( ! JavaWriter::javaMethodInList(op, yetImplementedOpList) && ! JavaWriter::javaMethodInList(op, opList) )
+            opList.append(op);
+    } 
+}
+
 void JavaWriter::writeOperations(UMLClassifier *c, QTextStream &java) {
     UMLOperationList opl;
     UMLOperationList oppub,opprot,oppriv;
@@ -711,8 +781,11 @@
     opprot.setAutoDelete(false);
     oppriv.setAutoDelete(false);
 
-    //sort operations by scope first and see if there are abstrat methods
+    //sort operations by scope first and see if there are abstract methods
     opl = c->getOpList();
+    if (! c->isInterface()) {
+        getInterfacesOperationsToBeImplemented(c, opl);
+    } 
     for (UMLOperation *op = opl.first(); op; op = opl.next()) {
         switch(op->getVisibility()) {
           case Uml::Visibility::Public:
--- branches/KDE/3.5/kdesdk/umbrello/umbrello/codegenerators/javawriter.h #635781:635782
@@ -76,6 +76,37 @@
     void writeConstructor(UMLClassifier *c, QTextStream &java);
 
     /**
+     * return true if the two operations have the same name and the same parameters
+     * @param op1 first operation to be compared
+     * @param op2 second operation to be compared
+     */
+    static bool compareJavaMethod(UMLOperation *op1, UMLOperation *op2);
+
+    /**
+     * return true if the operation is in the list
+     * @param umlOp operation to be searched 
+     * @param opl list of operations
+     */
+    static bool javaMethodInList(UMLOperation *umlOp, UMLOperationList &opl);
+
+    /**
+     * get all operations which a given class inherit from all its super interfaces and get all operations
+     * which this given class inherit from all its super classes
+     * @param c the class for which we are generating code
+     * @param yetImplementedOpList the list of yet implemented operations
+     * @param toBeImplementedOpList the list of to be implemented operations
+     * @param noClassInPath tells if there is a class between the base class and the current interface 
+     */
+    void getSuperImplementedOperations(UMLClassifier *c, UMLOperationList &yetImplementedOpList ,UMLOperationList &toBeImplementedOpList, bool noClassInPath = true);
+
+    /**
+     * get all operations which a given class inherit from all its super interfaces and that should be implemented
+     * @param c the class for which we are generating code
+     * @param opl the list of operations used to append the operations
+     */
+    void getInterfacesOperationsToBeImplemented(UMLClassifier *c, UMLOperationList &opl);
+
+     /**
      * write all operations for a given class
      * @param c the class for which we are generating code
      * @param j the stream associated with the output file