Automatisches einfügen von Variablen

Hallo zusammen,

Ich versuche in meinem Projekt Variablen aus dem Klassendiagramm zu entfernen und Zwecks der Übersichtlichkeit mittels XPAND Templates zu generieren. Die Tutorials habe ich bereits durchgearbeitet aber komme nun leider nicht weiter.

Ich habe zuerst versucht einfach ein Kommentar hinzuzufügen. Die Xpand Template wurde aber nicht aufgerufen.

«DEFINE additionalMember FOR ShoppingCart»
    //Hello World
«ENDDEFINE»


Nach mehreren Versuchen konnte ich schließlich mit folgendem Code die myInteger Variable hinzufügen.
Leider kann ich nicht nachvollziehen was genau die DEFINE in diesem Fall aufruft und warum dieser Code angenommen wird.


«DEFINE additionalMember1 (LoggerStyledElement style, Classifier parent) FRAGMENT Single FOR Classifier»
   «IF Class.isInstance(parent)»
       private static final Integer myInteger = new Integer(1);
   «ENDIF»
«ENDDEFINE»

Jedoch entsteht beim Reparsen ein Mergekonflikt bei welchem entweder die gleiche Variable nochmal hinzugefügt oder sie komplett gelöscht wird. Zudem wird sie dem Klassendiagramm hinzugefügt wenn sie nochmal hinzugefügt wird. Sowohl die File.xpt als auch die Attribute.xpt haben nicht funktioniert.

Ist es irgendwie möglich die Variable in der File.xpt so einzubauen das sie generiert wird, nicht im erstellen Klassendiagramm angezeigt wird und das kein Mergeerror beim Reparsen auftritt?


Vielen Dank schon im Voraus

LarsAlex

Comments

  • edited May 2013

    «DEFINE additionalMember (LoggerStyledElement style, Classifier parent) FRAGMENT Single FOR Classifier»
       «REM»
       This template is a placeholder for other styles that contribute additional member to the classifier's children.
       «ENDREM»
       «IF class.isInstance(parent)»
          private static final Logger log = Logger
           .getLogger("«getQualifiedName(".")»");
          «addImport("java.util.logging.Logger")»
       «ENDIF»
       «IF class.isInstance(parent)»
           «IF class.name == 'Person'»
              private Address address;
              private String name;
              private int age;
              private String gender;
           «ENDIF»
       «ENDIF»
    «ENDDEFINE»


    Anhand von dem Logger Style example habe ich nun einfach mal versucht ob sich die Attribute so aus dem Diagramm ausblenden lassen. Dies funktioniert leider nicht. Was müsste ich an obigem Beispiel ändern um die Attribute adress, name, age und gender bei der Klasse Person ausblenden zu lassen.

    Vielen Dank
  • edited May 2013
    Hi,

    ich versuche mal ein wenig Licht ins Dunkel zu bringen ;).

    In der Kurzfassung hast Du fast alles richtig gemacht. Folgende beiden Fehler sind allerdings in Deinem Template:

    «IF class.isInstance(parent)»
    Mit class ist hier die UML Klasse Class gemeint - sie muss groß geschrieben werden:

    «IF Class.isInstance(parent)»
    «IF class.name == 'Person'»
    Hier meinst Du ja den Namen der aktuell zu generierenden Klasse - das muss deshalb

    «IF this.name == 'Person'»
    heißen.

    Das wars, dann funktioniert alles :).

    ---

    Ich möchte nun noch auf Deine prinzipiellen Fragen eingehen:

    Leider kann ich nicht nachvollziehen was genau die DEFINE in diesem Fall aufruft und warum dieser Code angenommen wird.
    Wir haben uns für das Generieren von Elementen, die über den Code in beliebiger Reihenfolge verstreut sein können, das Konzept der Fragmente überlegt. Wenn Du also mehrere Attribute für eine Klasse mitgenerieren möchtest, solltest Du dies in einzelnen Fragment-Templates tun. Diese haben alle die gleiche Signatur und unterscheiden sich in unserem Xpand++ Editor nur durch den jeweiligen Zusatz hinter dem Schlüsselwort FRAGMENT.

    Technisch ist es nun so, dass Xpand++ unsere Erweiterung des existierenden Xpand ist. Öffnest Du das Template mit dem normalen Xpand Editor siehst Du was ich meine: Es gibt ein sogenanntes Dispatcher-Template, dass an die einzelnen Fragment-Templates delegiert.

    Ich habe Dein Beispiel nachgebaut und angehängt. Hier mal das Template mit dem Xpand++ Editor angeschaut...

    «IMPORT uml»
    «IMPORT UMLLabProfile»
    «IMPORT myExampleStyle»

    «EXTENSION Utility»
    «EXTENSION java::standard::classDiag::classifier::ClassifierExtensions»


    «DEFINE additionalMember (MyExampleStyleStyledElement style, Classifier parent) FRAGMENT Single FOR Classifier»
       «IF Class.isInstance(parent)»
          «IF this.name == 'NewClass1'»
              private Address address;
              private String name;
              private int age;
              private String gender;
          «ENDIF»
       «ENDIF»
    «ENDDEFINE»

    ... und hier das selbe Template mit dem Standard Xpand Editor:

    «IMPORT uml»
    «IMPORT UMLLabProfile»
    «IMPORT myExampleStyle»

    «EXTENSION Utility»
    «EXTENSION java::standard::classDiag::classifier::ClassifierExtensions»


    «DEFINE additionalMember (MyExampleStyleStyledElement style,Classifier parent,MemberFragmentTuple fragment) FOR Classifier»
    «IF fragment.partId==0»
    «EXPAND java::standard::classDiag::classifier::File::additionalMember_FRG_Single(style, parent) FOR this»
    «ENDIF»
    «ENDDEFINE»

    «DEFINE additionalMember_FRG_Single (MyExampleStyleStyledElement style, Classifier parent) FOR Classifier»
    «IF Class.isInstance(parent)»
    «IF this.name == 'NewClass1'»
    private Address address;
    private String name;
    private int age;
    private String gender;
    «ENDIF»
    «ENDIF»
    «ENDDEFINE»

    Hier fällt auf, dass es eben das Dispatcher Template gibt, und das eigentliche Template nun additionalMember_FRG_Single heißt.

    (Der CodeStyle heißt bei mir "MyEmampleStyle", daher heißt der Typ des ersten Parameters auch MyExampleStyleStyledElement und nicht LoggerStyledElement).

    Ich hoffe ich konnte Dir weiterhelfen!

    Viele Grüße
    Manuel


  • Hallo Herr Bork

    Vielen Dank für die Erklärung :) Ich habe gleich mal versucht dies umzusetzen bin jedoch leider bei der Generierung hängen geblieben.
    Einige Attribute und Setter/Getter bleiben bei der Generierung trotzdem im Code stehen, während andere Attribute, Setter/Getter entfernt werden.
    Habe einen Screenshot angehängt.
    Mein Code ist folgender, wobei der Logger nur als Referenz enhalten ist:
    «DEFINE additionalMember (LoggerundPersonStyledElement style, Classifier parent) FRAGMENT Single FOR Classifier»
        «IF Class.isInstance(parent)»
           private static final Logger log =
           Logger.getLogger("«getQualifiedName(".")»");
           «addImport("java.util.logging.Logger")»
        «ENDIF»
       
        «IF Class.isInstance(parent)»
           «FOREACH this.getAllAttributes() AS curAttr-»
              «IF curAttr.association.endType.size == null»
                private «curAttr.type.name» «curAttr.name»;
              «ENDIF»
           «ENDFOREACH»
       «ENDIF»
       «IF Class.isInstance(parent)»
           «FOREACH this.getAllAttributes() AS curAttr-»
              «IF curAttr.association.endType.size == null»
                public «curAttr.type.name» get«curAttr.name.toFirstUpper()»() {
                 return this.«curAttr.name»;
                }
              «ENDIF»
           «ENDFOREACH»
       «ENDIF»
       «IF Class.isInstance(parent)»
           «FOREACH this.getAllAttributes() AS curAttr-»
              «IF curAttr.association.endType.size == null»
                public void set«curAttr.name.toFirstUpper()»(«curAttr.type.name» value) {
                 log.log(Level.FINE, "change «curAttr.name»");
                 this.«curAttr.name» = value;
                }
              «ENDIF»
           «ENDFOREACH»
        «ENDIF»
    «ENDDEFINE»

    Einige Attribute und die dazugehörigen Getter/Setter werden mehrmals in die Klasse geschrieben oder komplett gelöscht.
    Hier habe ich auch noch ein paar Fragen:
    Wann werden die Attribute(auch Getter/Setter) aus den Klassen gelöscht und wann werden die Attribute(auch Getter/Setter) in die Klasse geschrieben?(Habe bei der Codegenerierung einige Inkonsistenzen)
    Gibt es eine Möglichkeit das Roundtripengineering zu deaktivieren, da der Code momentan nach jeder Generierung ersetzt werden muss?

    Vielen Dank und viele Grüße

    Lars
    UML-Attributes.jpg
    1595 x 721 - 272K
  • edited May 2013
    Hallo Herr Bork,

    ich habe weiter versucht Attribute ausblenden zu lassen. Nun habe ich folgendes Template versucht.

    «DEFINE additionalMember (LoggerundPersonStyledElement style, Classifier parent) FRAGMENT Single FOR Classifier»
       «IF Class.isInstance(parent)»
          «IF this.attribute.contains(this.name == 'name')»
             private String name;
          «ENDIF»
          «IF this.attribute.contains(this.name == 'zipCode')»
             private Integer zipCode;
          «ENDIF»
       «ENDIF»

    Ich muss das Template 2 mal durchlaufen lassen damit jeweils aus der Addresse name und zipCode entfernt werden.
    Wie müsste ich mein Template abändern wenn ich name und zipCode in 1 Reparse verändern möchte?

    Vielen Dank und viele Grüße

    Lars
  • Hi Lars,

    das Problem mit Deinen letzten beiden Ansätzen ist, dass die Templates einerseits dafür sorgen sollen, dass die Attribute nicht im Modell sind. Andererseits setzen sie aber das Attribut im Modell voraus, um den entsprechenden Code zu generieren:

    «IF this.attribute.contains ...

    Was jetzt passiert, ist dass im ersten Durchlauf noch kein Attribut existiert, dein Template - das ein Attribut voraussetzt - daher nicht passt, dann die normalen Attribut-Templates zum Zuge kommen, die ein Attribut anlegen. Im zweiten Durchgang ist dann ein Attribut da, dein Template passt also, und da dies von allen Möglichkeiten das kompakteste (Modell-)Ergebnis liefert, wird es verwendet und das Modell entsprechend angepasst.

    Generell nutzt UML Lab ja dieselben Templates für Codegenerierung und Reverse Engineering. Um aber passende Templates für das Reverse Engineering zu schreiben, die das Modell liefern, das man will, ist es häufig hilfreich, gedanklich anders herum heranzugehen: Stell dir das Modell vor, das Du gern als Ergebnis hättest, dann schreib dafür Templates, die daraus den Code generieren, den Du haben willst.

    Wenn Du dabei merkst, dass das nicht hinhaut, weil Dir z.B. notwendige Informationen fehlen, kann es im Einzelfall sicherlich Kniffe geben, mit denen man doch zum Ziel kommt. Häufig ist es aber auch ein gutes Indiz, dass der gewählte Weg hier vielleicht nicht richtig passt.

    Ich würde vorschlagen wir gehen vielleicht kurz einen Schritt zurück und reden losgelöst von konkreten Template-Formulierungen erst nochmal darüber, was eigentlich das Ziel eurer Anpassungen sein soll, um zu sehen, wie man das am besten erreicht. Das können wir hier tun, oder gerne auch nochmal kurz dazu telefonieren.

    Viele Grüße,
    Carsten
  • Hi Carsten,

    Vielen Dank für die Erklärung.

    Unser Ziel der Anpassung ist ein UML Diagramm aus einem Java Projekt zu erzeugen, welches um gewisse Architekturspezifika angereichert ist. Die Ausgangssituation ist ein Projekt in dem verschiedene Typen von Klassen existieren(hauptsächlich Entities, Business Functions und Business Services).
    Im ersten Schritt sollen abhängig vom Typen der Klasse Attribute und/oder Methoden im Modell angezeigt oder ausgeblendet werden.

    Viele Grüße,
    Lars
Sign In or Register to comment.