Bug 53374 - Java interface inheritance, abstract classes and generics in code generation
Summary: Java interface inheritance, abstract classes and generics in code generation
Status: RESOLVED FIXED
Alias: None
Product: umbrello
Classification: Applications
Component: general (show other bugs)
Version: unspecified
Platform: unspecified Linux
: NOR wishlist
Target Milestone: ---
Assignee: Umbrello Development Group
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2003-01-24 19:23 UTC by Jonathan Riddell
Modified: 2007-02-21 19:19 UTC (History)
0 users

See Also:
Latest Commit:
Version Fixed In:


Attachments
patch for #53374 (4.38 KB, patch)
2007-02-18 07:10 UTC, Antoine Dopffer
Details
patch for handling the case where a generic extends an existing class (692 bytes, patch)
2007-02-21 15:50 UTC, Antoine Dopffer
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Jonathan Riddell 2003-01-24 19:23:44 UTC
Version:            (using KDE Devel)
Compiler:          gcc 2.95 
OS:          Linux

The java code generation should support the use of interfaces,
generics, and the abstract keyword.

1) The interface keyword creates classes where the methods are
specified without any implementation. Java allows [0..n] interfaces per
class, where java may only extend 1 class (inherited functionality)

2) Additionally this should not effect the abstract classes. In java a
class may be declared as abstract. In this instance implementation of
part or all of the class is possible. It could be extended like any other
class but cannot be instanciated directly.

3) Finally it should support parameterized types (aka generics).
Generic templates are being added to java in the next major release of
java; most likely version 1.5 of the JDK.

This request is being submitted anonymously; my e-mail address is:
steven.green30@verizon.net
Comment 1 vittor 2003-10-31 16:37:52 UTC
2) seems to be OK

1) How should an interface be declared ? By putting an "interface" stereotype on a class ?
Comment 2 Jonathan Riddell 2003-10-31 17:05:32 UTC
In Umbrello 1.2 interfaces are a separate widget and UML object.
Comment 3 Harald Wallus 2003-11-26 13:29:10 UTC
To 1) 
Yes. Java do not need the keyword abstract:

interface Material
{
  int HART      = 0,
      WEICH     = HART + 1,
      FLAUSCHIG = WEICH + 1;
  int berechneGewicht();
}
class Wolle implements Material
{
  public int berechneGewicht() { return 234; }
}
class Synthetik implements Material
{
  public int berechneGewicht() { return 452; }
}
abstract class Stahl implements Material
{
  boolean glänzend;
}
 

Some more special in java:

If java have an abstract class, it can be extends

abstract class Tier
{
  int alter = -1;
  void alterSetzen( int a ) { alter = a; }
  abstract boolean istSäuger();
  abstract void ausgabe();
}
abstract class Säugetier extends Tier
{
  boolean istSäuger() { return true; }
}
class Mensch extends Säugetier
{
  void ausgabe() {
    System.out.println( "Ich bin ein Mensch" );
  }
}
class Delfin extends Säugetier
{
  void ausgabe() {
    System.out.println( "Ich bin ein Delfin" );
  }
}


And Java can be implements and extends:
Which means, you can implement an Interface and extend a abstract class.
This is used e.g. in ejb or ozone (for serializing objects)

package srv;
import ozoneDB.OzoneRemote;
abstract public interface Car implements OzoneRemote {
  public String getCarBez ( );
  public boolean setCarBez ( String CarBez);
  public boolean setCarColor ( String CarColor);
  public String getCarColor ( );
  public boolean setMonthKm ( int Month, int Km);
  public int getMonthKm ( int Month);
}

and (I cut the methodscoding off):

package srv;
import ozoneDB.OzoneObject;
public class CarImpl implements Car extends OzoneObject {
  static public long serialVersionUID = 1L;
  private String m_CarBez;
  private String m_CarColor;
  private int m_MonthKm[];
  public String getCarBez ( ) {
  }
  public boolean setCarBez ( String CarBez) {
  }
  public String getCarColor ( ) {
  }
  public boolean setCarColor ( String CarColor) {
  }
  public boolean setMonthKm ( int Month, int Km) {
  }
  public int getMonthKm ( int Month) {
  }  

May this helps.
Oh, one think:
at the moment (tarball vom 11/23/03) the package and import 
statements are written at the bottom of the source code!
Comment 4 Antoine Dopffer 2007-02-18 07:10:43 UTC
Created attachment 19724 [details]
patch for #53374

This patch succeeds (I hope so) to handle java interface and java abstract
class.
I think we could also wish to generate the methods of a interface that a class
should implement.

The work for handling generics is not quite finished.
Only the generic classes work.
In java, you can have generic classes but also generic methods.
For example, the class A is generic and the method returnMe is also generic:
class A<T> 
{
private T param;
public T getParam() {return param;}
public void setParam(T p) {param = p;}
public static  <Y> Y returnMe (Y p) { return p;}
}

Ok, this class is dumb.
But I couldn't manage to design a generic methods with umbrello (I don't even
know if generics methods are part of the UML specifications) so I couldn't
update the java generator for handling generic method.

I hope it can help anyway

Have a nice day !
PS : According to me, the new java code generator (javacodegenerator.cpp)
managed the interfaces and the abstract classes
Comment 5 Oliver Kellogg 2007-02-19 21:54:10 UTC
SVN commit 635329 by okellogg:

Apply attachment 19724 [details] from Antoine Dopffer.

> I couldn't manage to design a generic method with umbrello [...]
> so I couldn't update the java generator for handling generic method.
> 

If anybody needs this they should open a new wish.

BUG:53374


 M  +4 -1      ChangeLog  
 M  +4 -2      umbrello/classifier.cpp  
 M  +47 -9     umbrello/codegenerators/javawriter.cpp  


--- branches/KDE/3.5/kdesdk/umbrello/ChangeLog #635328:635329
@@ -2,6 +2,8 @@
 
 * Bugs/wishes from http://bugs.kde.org:
 * C# Code Generation and export (53368)
+* Java interface inheritance, abstract classes and generics in code generation
+  (53376)
 * %date% and %time% not being parsed (96612)
 * Relationships for entities do not live outside of the diagram (125146)
 * Javascript wrong Code Generation (135527)
@@ -10,7 +12,8 @@
 * Associations not updated during move of class on diagram (140709)
 * Crash when deleting the link between a package and a class (141602)
 * Ada95 Code Generation Errors for Aggregation (141644)
-* Unable to delete multiplicity information or lable from an association (141813)
+* Unable to delete multiplicity information or lable from an association
+  (141813)
 
 Version 1.5.61
 
--- branches/KDE/3.5/kdesdk/umbrello/umbrello/classifier.cpp #635328:635329
@@ -381,7 +381,8 @@
             UMLObject* obj = a->getObject(A);
             UMLClassifier *concept = dynamic_cast<UMLClassifier*>(obj);
             if (concept && (type == ALL || (!concept->isInterface() && type == CLASS)
-                            || (concept->isInterface() && type == INTERFACE)))
+                            || (concept->isInterface() && type == INTERFACE))
+                        && (inheritingConcepts.findRef(concept) == -1))
                 inheritingConcepts.append(concept);
         }
     }
@@ -409,7 +410,8 @@
             UMLObject* obj = a->getObject(B);
             UMLClassifier *concept = dynamic_cast<UMLClassifier*>(obj);
             if (concept && (type == ALL || (!concept->isInterface() && type == CLASS)
-                            || (concept->isInterface() && type == INTERFACE)))
+                            || (concept->isInterface() && type == INTERFACE))
+                        && (parentConcepts.findRef(concept) == -1))
                 parentConcepts.append(concept);
         }
     }
--- branches/KDE/3.5/kdesdk/umbrello/umbrello/codegenerators/javawriter.cpp #635328:635329
@@ -31,6 +31,8 @@
 #include "../operation.h"
 #include "../attribute.h"
 #include "../association.h"
+#include "../template.h"
+#include "../umltemplatelist.h"
 
 JavaWriter::JavaWriter() {
     startline = m_endl + m_indentation;
@@ -280,7 +282,7 @@
     } else
         scope = "public ";
 
-    java<<(c->getAbstract()?QString("abstract "):QString(""))<<scope;
+    java<<((c->getAbstract() && !isInterface) ? QString("abstract ") : QString(""))<<scope;
     if(isInterface)
         java<<"interface ";
     else
@@ -288,23 +290,59 @@
 
     java<<classname;
 
+    // Generics 
+    UMLTemplateList template_params = c->getTemplateList();
+    if (template_params.count()) {
+        java << "<";
+        for (UMLTemplate *t = template_params.first(); t; ) {
+            QString formalName = t->getName();
+            java <<  formalName;
+            if ((t = template_params.next()) != NULL)
+                java << ", ";
+        }
+        java << ">" << m_endl;
+    }
 
     // write inheritances out
     UMLClassifier *concept;
-    UMLClassifierList superclasses = c->findSuperClassConcepts();
+    UMLClassifierList superclasses = c->findSuperClassConcepts(UMLClassifier::CLASS);
 
-    if(superclasses.count()>0)
-        java<<" extends ";
-
-    // Q: Where is 'implements' ??
-
     int i = 0;
     for (concept= superclasses.first(); concept; concept = superclasses.next())
     {
-        java<<cleanName(concept->getName())<<(i>0?", ":"");
+        if (i == 0)
+        {
+            java<< " extends ";
+        }
+        else
+        {
+            //The java generated code is wrong ! : No multiple inheritence of class 
+            java<< ", " ;
+        }
+        java<< cleanName(concept->getName());
         i++;
     }
 
+    UMLClassifierList superInterfaces = c->findSuperClassConcepts(UMLClassifier::INTERFACE);
+    i = 0;
+    for (concept= superInterfaces.first(); concept; concept = superInterfaces.next())
+    {
+        if (i == 0)
+        {
+            if (isInterface)
+                java<< " extends ";
+            else
+                java<< " implements ";
+        }
+        else
+        {
+            //The java generated code is OK ! : multiple inheritence of interface 
+            java<< ", " ;
+        }
+        java<< cleanName(concept->getName());
+        i++;
+    }
+
 }
 
 void JavaWriter::writeAttributeDecls(UMLAttributeList &atpub, UMLAttributeList &atprot,
@@ -740,7 +778,7 @@
             returnStr += "@return       "+methodReturnType+"\n";
 
         str = ""; // reset for next method
-        str += ((op->getAbstract() || isInterface) ? "abstract ":"");
+        str += ((op->getAbstract() && !isInterface) ? "abstract ":"");
         str += scopeToJavaDecl(op->getVisibility()) + ' ';
         str += (op->getStatic() ? "static ":"");
         str += methodReturnType + ' ' +cleanName(op->getName()) + "( ";
Comment 6 Antoine Dopffer 2007-02-21 15:50:18 UTC
Created attachment 19771 [details]
patch for handling the case where a generic extends an existing class

Here comes a new patch that handles the case where the generics extends a type
that is not "Object" .
So we can have
class Foo<T extends Bar>
{
}
By default, a generic extends Object, so you can't have something really
interesting (see http://www.mindview.net/WebLog/log-0050)

So, if the user lets the type "class" when designing the template in umbrello,
the generated code will be:
class Foo<T> {...}
Il the user chooses another type, say "Bar", the generated code will be:
class Foo<T extends Bar> {...}

This patch completes but do not replace the previous one.
Thanks
Comment 7 Oliver Kellogg 2007-02-21 19:19:16 UTC
SVN commit 636032 by okellogg:

writeClassDecl(): Attachment 19771 [details] from Antoine Dopffer adds "extends"
 for a generic formal parameter that is not of type Object. Cool!
CCBUG:53374


 M  +4 -0      javawriter.cpp  


--- branches/KDE/3.5/kdesdk/umbrello/umbrello/codegenerators/javawriter.cpp #636031:636032
@@ -297,6 +297,10 @@
         for (UMLTemplate *t = template_params.first(); t; ) {
             QString formalName = t->getName();
             java <<  formalName;
+            QString typeName = t->getTypeName();
+            if (typeName != "class") {
+                java << " extends " << typeName;
+            }
             if ((t = template_params.next()) != NULL)
                 java << ", ";
         }