From 7176df0ca97ab64e7f13b34602874c06c15285a9 Mon Sep 17 00:00:00 2001 From: encrypTimM Date: Fri, 17 Jun 2022 10:57:30 +0200 Subject: [PATCH] Speicherentlastung --- .../basis/projekt/EditierBefehl.java | 1 + .../basis/projekt/EditierBeobachter.java | 57 ++++--- .../basis/projekt/EditierbarBasis.java | 8 +- .../basis/projekt/EinfacherEditierBefehl.java | 30 +++- .../basis/projekt/ListenUeberwacher.java | 29 +++- .../basis/projekt/ProjektBasis.java | 22 ++- .../basis/projekt/SammelEditierung.java | 80 ++++++++- .../basis/projekt/WertEditierBefehl.java | 38 +++++ .../classifier/gui/HauptKontrolle.java | 49 +++--- .../classifier/gui/ProjektAnsicht.java | 14 +- .../classifier/gui/ProjektKontrolle.java | 53 +++--- .../classifier/gui/ProjekteAnsicht.java | 1 + .../classifier/gui/ProjekteKontrolle.java | 15 +- .../UMLKlassifiziererBearbeitenDialog.java | 156 ++++++++++-------- .../gui/UMLKommentarBearbeitenDialog.java | 7 +- .../gui/elemente/ListenAnsicht.java | 23 ++- .../gui/elemente/UMLElementBasisAnsicht.java | 8 +- .../elemente/UMLKlassifiziererAnsicht.java | 24 +-- .../classifier/main/LoggingEinstellung.java | 1 + .../aid_labor/classifier/uml/UMLProjekt.java | 24 +++ .../uml/eigenschaften/Attribut.java | 38 ++++- .../uml/eigenschaften/Datentyp.java | 22 ++- .../classifier/uml/eigenschaften/Methode.java | 142 ++++++++-------- .../uml/eigenschaften/Parameter.java | 41 +++-- .../uml/klassendiagramm/UMLBasisElement.java | 59 ++++--- .../klassendiagramm/UMLDiagrammElement.java | 2 +- .../klassendiagramm/UMLKlassifizierer.java | 50 +++++- .../uml/klassendiagramm/UMLKommentar.java | 5 +- 28 files changed, 683 insertions(+), 316 deletions(-) create mode 100644 src/main/java/io/github/aid_labor/classifier/basis/projekt/WertEditierBefehl.java diff --git a/src/main/java/io/github/aid_labor/classifier/basis/projekt/EditierBefehl.java b/src/main/java/io/github/aid_labor/classifier/basis/projekt/EditierBefehl.java index 0fce817..e462e9f 100644 --- a/src/main/java/io/github/aid_labor/classifier/basis/projekt/EditierBefehl.java +++ b/src/main/java/io/github/aid_labor/classifier/basis/projekt/EditierBefehl.java @@ -24,4 +24,5 @@ public interface EditierBefehl { */ @Override public String toString(); + } \ No newline at end of file diff --git a/src/main/java/io/github/aid_labor/classifier/basis/projekt/EditierBeobachter.java b/src/main/java/io/github/aid_labor/classifier/basis/projekt/EditierBeobachter.java index 5139771..72d859a 100644 --- a/src/main/java/io/github/aid_labor/classifier/basis/projekt/EditierBeobachter.java +++ b/src/main/java/io/github/aid_labor/classifier/basis/projekt/EditierBeobachter.java @@ -7,6 +7,7 @@ package io.github.aid_labor.classifier.basis.projekt; import java.lang.ref.WeakReference; +import java.util.List; import java.util.Objects; import java.util.logging.Logger; @@ -14,6 +15,7 @@ import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.collections.ObservableList; +import javafx.collections.WeakListChangeListener; /** @@ -24,7 +26,7 @@ * @author Tim Muehle * */ -public interface EditierBeobachter { +public interface EditierBeobachter extends AutoCloseable { public static final Logger log = Logger.getLogger(EditierBeobachter.class.getName()); @@ -39,6 +41,8 @@ public interface EditierBeobachter { */ public void verarbeiteEditierung(EditierBefehl editierung); + public List getBeobachterListe(); + /** * Installiert einen {@code ChangeListener}, der diesen {@code EditierBeobachter} bei * Aenderung der uebergebenen Eigenschaft mit einem entsprechenden {@link EditierBefehl} @@ -46,9 +50,12 @@ public interface EditierBeobachter { * * @param Typparameter des Uebergabeparameters * @param property Eigenschaft, die ueber Anderungen informiert + * @param id ID zur eindeutigen Identifizierung von Editierungen */ - public default void ueberwachePropertyAenderung(Property property) { - property.addListener(new PropertyUeberwachung<>(this, property)); + public default void ueberwachePropertyAenderung(Property property, String id) { + var beobachter = new PropertyUeberwachung<>(this, property, id); + getBeobachterListe().add(beobachter); + property.addListener(beobachter); } public static class PropertyUeberwachung implements ChangeListener { @@ -56,37 +63,46 @@ public static class PropertyUeberwachung implements ChangeListener { private boolean wiederhole; private final WeakReference beobachterRef; private final WeakReference> propertyRef; + private final String id; - private PropertyUeberwachung(EditierBeobachter beobachter, Property property) { + private PropertyUeberwachung(EditierBeobachter beobachter, Property property, String id) { this.wiederhole = false; this.beobachterRef = new WeakReference<>(beobachter); this.propertyRef = new WeakReference<>(property); + this.id = id; } @Override public void changed(ObservableValue aufrufer, T alterWert, T neuerWert) { if (!Objects.equals(alterWert, neuerWert) && !wiederhole) { - beobachterRef.get().verarbeiteEditierung(new EditierBefehl() { + beobachterRef.get().verarbeiteEditierung(new WertEditierBefehl() { @Override - public void wiederhole() { - wiederhole = true; - propertyRef.get().setValue(neuerWert); - wiederhole = false; + public String toString() { + return "EditierBefehl: %s -> %s { alt: %s neu: %s }".formatted(beobachterRef.get(), + propertyRef.get(), alterWert, neuerWert); } @Override - public void macheRueckgaengig() { - wiederhole = true; - propertyRef.get().setValue(alterWert); - wiederhole = false; + public String id() { + return id; } @Override - public String toString() { - return "EditierBefehl: %s -> %s { alt: %s neu: %s }" - .formatted(beobachterRef.get(), propertyRef.get(), - alterWert, neuerWert); + public T getVorher() { + return alterWert; + } + + @Override + public T getNachher() { + return neuerWert; + } + + @Override + public void set(T wert) { + wiederhole = true; + propertyRef.get().setValue(wert); + wiederhole = false; } }); } @@ -94,9 +110,10 @@ public String toString() { } - public default void ueberwacheListenAenderung( - ObservableList liste) { - liste.addListener(new ListenUeberwacher<>(liste, this)); + public default void ueberwacheListenAenderung(ObservableList liste) { + var beobachter = new ListenUeberwacher<>(liste, this); + getBeobachterListe().add(beobachter); + liste.addListener(new WeakListChangeListener<>(beobachter)); } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * diff --git a/src/main/java/io/github/aid_labor/classifier/basis/projekt/EditierbarBasis.java b/src/main/java/io/github/aid_labor/classifier/basis/projekt/EditierbarBasis.java index 252488a..9da644c 100644 --- a/src/main/java/io/github/aid_labor/classifier/basis/projekt/EditierbarBasis.java +++ b/src/main/java/io/github/aid_labor/classifier/basis/projekt/EditierbarBasis.java @@ -95,7 +95,13 @@ public final void meldeAn(EditierBeobachter beobachter) { @Override public final void meldeAb(EditierBeobachter beobachter) { while (this.beobachterListe.contains(beobachter)) { - log.config(() -> this + " -- Melde Beobachter ab: " + beobachter); + log.config(() -> { + try { + return this + " -- Melde Beobachter ab: " + beobachter; + } catch (Exception e) { + return ""; + } + }); this.beobachterListe.remove(beobachter); } } diff --git a/src/main/java/io/github/aid_labor/classifier/basis/projekt/EinfacherEditierBefehl.java b/src/main/java/io/github/aid_labor/classifier/basis/projekt/EinfacherEditierBefehl.java index 4b12661..2087259 100644 --- a/src/main/java/io/github/aid_labor/classifier/basis/projekt/EinfacherEditierBefehl.java +++ b/src/main/java/io/github/aid_labor/classifier/basis/projekt/EinfacherEditierBefehl.java @@ -18,7 +18,7 @@ * * @param */ -public class EinfacherEditierBefehl implements EditierBefehl { +public class EinfacherEditierBefehl implements WertEditierBefehl { private static final Logger log = Logger.getLogger(EinfacherEditierBefehl.class.getName()); // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * @@ -40,6 +40,7 @@ public class EinfacherEditierBefehl implements EditierBefehl { // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * private String quelle; + private final String id; private final T alterWert; private final T neuerWert; private final Consumer setter; @@ -48,7 +49,7 @@ public class EinfacherEditierBefehl implements EditierBefehl { // * Konstruktoren * // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - public EinfacherEditierBefehl(T alterWert, T neuerWert, Consumer setter) { + public EinfacherEditierBefehl(T alterWert, T neuerWert, Consumer setter, String id) { try { var aufrufer = Thread.currentThread().getStackTrace()[1]; quelle = "%s.%s[%d]".formatted(aufrufer.getClassName(), aufrufer.getMethodName(), @@ -61,6 +62,7 @@ public EinfacherEditierBefehl(T alterWert, T neuerWert, Consumer setter) { this.alterWert = alterWert; this.neuerWert = neuerWert; this.setter = setter; + this.id = id; } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * @@ -82,18 +84,28 @@ public EinfacherEditierBefehl(T alterWert, T neuerWert, Consumer setter) { // public ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## @Override - public void wiederhole() { - setter.accept(neuerWert); + public String toString() { + return alterWert + " -> " + neuerWert + "\n -> Quelle: " + quelle; } @Override - public void macheRueckgaengig() { - setter.accept(alterWert); + public String id() { + return id; } - + @Override - public String toString() { - return alterWert + " -> " + neuerWert + "\n -> Quelle: " + quelle; + public T getVorher() { + return alterWert; + } + + @Override + public T getNachher() { + return neuerWert; + } + + @Override + public void set(T wert) { + setter.accept(wert); } // protected ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## diff --git a/src/main/java/io/github/aid_labor/classifier/basis/projekt/ListenUeberwacher.java b/src/main/java/io/github/aid_labor/classifier/basis/projekt/ListenUeberwacher.java index ff094f2..a90cb49 100644 --- a/src/main/java/io/github/aid_labor/classifier/basis/projekt/ListenUeberwacher.java +++ b/src/main/java/io/github/aid_labor/classifier/basis/projekt/ListenUeberwacher.java @@ -6,6 +6,7 @@ package io.github.aid_labor.classifier.basis.projekt; +import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -46,7 +47,7 @@ public class ListenUeberwacher implements ListChangeListen // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * private final List liste; - private final EditierBeobachter beobachter; + private final WeakReference beobachter; // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // * Konstruktoren * @@ -61,7 +62,7 @@ public class ListenUeberwacher implements ListChangeListen */ public ListenUeberwacher(List liste, EditierBeobachter beobachter) { this.liste = liste; - this.beobachter = beobachter; + this.beobachter = new WeakReference(beobachter); } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * @@ -107,7 +108,7 @@ public void onChanged(Change aenderung) { for (EditierBefehl editierBefehl : befehle) { sammelEditierung.speicherEditierung(editierBefehl); } - beobachter.verarbeiteEditierung(sammelEditierung); + beobachter.get().verarbeiteEditierung(sammelEditierung); } // protected ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## @@ -149,10 +150,16 @@ public String toString() { private void behandleEntfernung(Change aenderung, List befehle) { - log.finer(() -> "%s: -> entfernt [%s]".formatted(beobachter, - Arrays.toString(aenderung.getRemoved().toArray()))); + log.finer(() -> { + try { + return "%s: -> entfernt [%s]".formatted(beobachter, Arrays.toString(aenderung.getRemoved().toArray())); + } catch (Exception e) { + return ""; + } + }); + for (E entfernt : aenderung.getRemoved()) { - entfernt.meldeAb(beobachter); + entfernt.meldeAb(beobachter.get()); } var befehl = new EditierBefehl() { @@ -172,8 +179,12 @@ public void macheRueckgaengig() { @Override public String toString() { - return "%s: -> entfernt %s".formatted(beobachter, startIndex, - Arrays.toString(entfernteAttribute.toArray())); + try { + return "%s: -> entfernt %s".formatted(beobachter, startIndex, + Arrays.toString(entfernteAttribute.toArray())); + } catch (Exception e) { + return ""; + } } }; befehle.add(befehl); @@ -184,7 +195,7 @@ private void behandleHinzugefuegt(Change aenderung, log.finer(() -> "%s: -> hinzugefuegt [%s]".formatted(beobachter, Arrays.toString(aenderung.getAddedSubList().toArray()))); for (E hinzu : aenderung.getAddedSubList()) { - hinzu.meldeAn(beobachter); + hinzu.meldeAn(beobachter.get()); } var befehl = new EditierBefehl() { diff --git a/src/main/java/io/github/aid_labor/classifier/basis/projekt/ProjektBasis.java b/src/main/java/io/github/aid_labor/classifier/basis/projekt/ProjektBasis.java index be3204e..fb3aada 100644 --- a/src/main/java/io/github/aid_labor/classifier/basis/projekt/ProjektBasis.java +++ b/src/main/java/io/github/aid_labor/classifier/basis/projekt/ProjektBasis.java @@ -8,6 +8,8 @@ import java.io.IOException; import java.nio.file.Path; +import java.util.LinkedList; +import java.util.List; import java.util.Objects; import java.util.logging.Level; import java.util.logging.Logger; @@ -114,6 +116,8 @@ public abstract class ProjektBasis implements Projekt { private UeberwachungsStatus ueberwachungsStatus; @JsonIgnore private long gespeicherterHash; + @JsonIgnore + private final List beobachterListe; // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // * Konstruktoren * @@ -149,8 +153,9 @@ public ProjektBasis(String name, boolean automatischSpeichern) Einstellungen.getBenutzerdefiniert().verlaufAnzahl.get()); this.wiederholenVerlauf = VerketteterVerlauf.synchronisierterVerlauf( Einstellungen.getBenutzerdefiniert().verlaufAnzahl.get()); + this.beobachterListe = new LinkedList<>(); - this.ueberwachePropertyAenderung(this.name); + this.ueberwachePropertyAenderung(this.name, "projektname"); this.istGespeichertProperty.addListener((__, ___, istGespeichert) -> { if (istGespeichert) { int neuerHash = hashCode(); @@ -185,6 +190,11 @@ public static T ausDateiOeffnen(Path datei, Class ty // public ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## + @Override + public List getBeobachterListe() { + return beobachterListe; + } + /** * {@inheritDoc} */ @@ -493,6 +503,16 @@ public boolean equals(Object obj) { return istGleich; } + @Override + public void close() throws Exception { + log.fine(() -> "Raueme Projekt " + this.getName() + " auf und schliesse"); + this.setUeberwachungsStatus(UeberwachungsStatus.IGNORIEREN); + rueckgaengigVerlauf.leeren(); + wiederholenVerlauf.leeren(); + beobachterListe.clear(); + sammelEditierung = null; + } + // protected ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## // package ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## diff --git a/src/main/java/io/github/aid_labor/classifier/basis/projekt/SammelEditierung.java b/src/main/java/io/github/aid_labor/classifier/basis/projekt/SammelEditierung.java index acdbf96..0d3d0f9 100644 --- a/src/main/java/io/github/aid_labor/classifier/basis/projekt/SammelEditierung.java +++ b/src/main/java/io/github/aid_labor/classifier/basis/projekt/SammelEditierung.java @@ -8,7 +8,10 @@ import java.util.Arrays; import java.util.Deque; +import java.util.HashMap; import java.util.LinkedList; +import java.util.Map; +import java.util.function.Consumer; import java.util.logging.Logger; @@ -24,6 +27,59 @@ public class SammelEditierung implements EditierBefehl { // * Klassenmethoden * // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + private static class AenderbareWertEditierung implements WertEditierBefehl { + + private final String id; + private T vorher; + private T nachher; + private Consumer setter; + + public AenderbareWertEditierung(WertEditierBefehl wertEditierung) { + this(wertEditierung.id(), wertEditierung.getVorher(), wertEditierung.getNachher(), wertEditierung::set); + } + + public AenderbareWertEditierung(String id, T vorher, T nachher, Consumer setter) { + this.id = id; + this.vorher = vorher; + this.nachher = nachher; + this.setter = setter; + } + + @Override + public String id() { + return id; + } + + @Override + public T getVorher() { + return vorher; + } + + @Override + public T getNachher() { + return nachher; + } + + @SuppressWarnings("unused") + public void setVorher(T vorher) { + this.vorher = vorher; + } + + public void setNachher(T nachher) { + this.nachher = nachher; + } + + @Override + public void set(T wert) { + setter.accept(wert); + } + + @Override + public String toString() { + return "%s {%s -> %s}".formatted(id, vorher, nachher); + } + } + // ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## // # # // # Instanzen # @@ -35,6 +91,7 @@ public class SammelEditierung implements EditierBefehl { // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * private Deque befehle; + private final Map> wertEditierungen; // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // * Konstruktoren * @@ -42,6 +99,7 @@ public class SammelEditierung implements EditierBefehl { public SammelEditierung() { this.befehle = new LinkedList<>(); + this.wertEditierungen = new HashMap<>(); } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * @@ -50,9 +108,25 @@ public SammelEditierung() { // public ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## - public void speicherEditierung(EditierBefehl editierung) { + public void speicherEditierung(EditierBefehl editierung) { log.finest(() -> "sammel + " + editierung); - befehle.add(editierung); + + if (WertEditierBefehl.class.isAssignableFrom(editierung.getClass())) { + @SuppressWarnings("unchecked") + WertEditierBefehl wertEditierung = (WertEditierBefehl) editierung; + @SuppressWarnings("unchecked") + AenderbareWertEditierung vorherigeEditierung = (AenderbareWertEditierung) this.wertEditierungen + .get(wertEditierung.id()); + if (vorherigeEditierung != null) { + vorherigeEditierung.setNachher(wertEditierung.getNachher()); + } else { + vorherigeEditierung = new AenderbareWertEditierung<>(wertEditierung); + wertEditierungen.put(wertEditierung.id(), vorherigeEditierung); + befehle.add(vorherigeEditierung); + } + } else { + befehle.add(editierung); + } } // protected ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## @@ -91,7 +165,7 @@ public void wiederhole() { public String toString() { return "Sammeleditierung: \n " + Arrays.toString(befehle.toArray()); } - + // protected ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## // package ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## diff --git a/src/main/java/io/github/aid_labor/classifier/basis/projekt/WertEditierBefehl.java b/src/main/java/io/github/aid_labor/classifier/basis/projekt/WertEditierBefehl.java new file mode 100644 index 0000000..192f1b0 --- /dev/null +++ b/src/main/java/io/github/aid_labor/classifier/basis/projekt/WertEditierBefehl.java @@ -0,0 +1,38 @@ +/* + * Dieser Quellcode steht unter der MIT-License. + * Copyright (c) 2022 - Tim Muehle (GitHub: @encrypTimM) + * + */ +package io.github.aid_labor.classifier.basis.projekt; + + +public interface WertEditierBefehl extends EditierBefehl { + + /** + * Macht eine Editierung rueckgaengig + */ + @Override + public default void macheRueckgaengig() { + set(getVorher()); + } + + /** + * Wendet eine Editierung erneut an + */ + @Override + public default void wiederhole() { + set(getNachher()); + } + + public T getVorher(); + + public T getNachher(); + + public void set(T wert); + + /** + * eindeutige ID, um Editierungen an gleichen Attributen festzustellen + * @return eindeutige ID, um Editierungen an gleichen Attributen festzustellen + */ + public String id(); +} \ No newline at end of file diff --git a/src/main/java/io/github/aid_labor/classifier/gui/HauptKontrolle.java b/src/main/java/io/github/aid_labor/classifier/gui/HauptKontrolle.java index d4cf2dc..5b426e9 100644 --- a/src/main/java/io/github/aid_labor/classifier/gui/HauptKontrolle.java +++ b/src/main/java/io/github/aid_labor/classifier/gui/HauptKontrolle.java @@ -13,6 +13,7 @@ import java.io.File; import java.io.IOException; +import java.lang.ref.WeakReference; import java.nio.file.Files; import java.nio.file.Path; import java.text.MessageFormat; @@ -65,7 +66,7 @@ class HauptKontrolle { // * Attribute * // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - private HauptAnsicht ansicht; + private WeakReference ansicht; private Sprache sprache; // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * @@ -73,7 +74,7 @@ class HauptKontrolle { // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * HauptKontrolle(HauptAnsicht ansicht, Sprache sprache) { - this.ansicht = ansicht; + this.ansicht = new WeakReference(ansicht); this.sprache = sprache; } @@ -93,9 +94,9 @@ class HauptKontrolle { void konigurationsordnerOeffnen(Event event) { Path ordner = OS.getDefault() - .getKonfigurationsOrdnerPath(ansicht.getProgrammDetails()); + .getKonfigurationsOrdnerPath(ansicht.get().getProgrammDetails()); try { - ansicht.getRechnerService().showDocument(ordner.toUri().toString()); + ansicht.get().getRechnerService().showDocument(ordner.toUri().toString()); } catch (Exception e) { log.log(Level.WARNING, e, () -> "Ordner %s konnte nicht angezeigt werden".formatted(ordner)); @@ -113,7 +114,7 @@ void konigurationsordnerBereinigen(Event event) { .formatted(oe, oe, AE))); beschreibung.setWrapText(true); beschreibung.setId("NEUSTART_WARNUNG"); - this.ansicht.getOverlayDialog().showNode(Type.WARNING, dialogTitel, + this.ansicht.get().getOverlayDialog().showNode(Type.WARNING, dialogTitel, new StackPane(beschreibung), false, List.of(ButtonType.OK, ButtonType.CANCEL)) .thenAccept(buttonTyp -> { if (buttonTyp.equals(ButtonType.OK)) { @@ -145,7 +146,7 @@ void neuesProjektErzeugen(Event event) { new ButtonType(sprache.getText("ok", "Ok"), ButtonData.OK_DONE)); Platform.runLater(() -> eingabeName.requestFocus()); - ansicht.getOverlayDialog() + ansicht.get().getOverlayDialog() .showNode(Type.INPUT, sprache.getText("neuesProjekt", "Neues Projekt"), dialog, false, buttons, true) .thenAccept(button -> { @@ -157,12 +158,12 @@ void neuesProjektErzeugen(Event event) { .getSelectionModel().getSelectedItem(); if (name.isBlank()) { - ansicht.zeigeAnlegenFehlerDialog(sprache.getText( + ansicht.get().zeigeAnlegenFehlerDialog(sprache.getText( "anlegenFehlerName", "Es muss ein g%cltiger Projektname angegeben werden" .formatted(ue))); } else if (programmiersprache == null) { - ansicht.zeigeAnlegenFehlerDialog(sprache.getText( + ansicht.get().zeigeAnlegenFehlerDialog(sprache.getText( "anlegenFehlerProgrammiersprache", "Es muss eine Programmiersprache ausgew%chlt werden" .formatted(ae))); @@ -170,7 +171,7 @@ void neuesProjektErzeugen(Event event) { UMLProjekt projekt = new UMLProjekt(name, programmiersprache, false); try { - ansicht.zeigeProjekt(projekt); + ansicht.get().zeigeProjekt(projekt); } catch (Exception e) { log.log(Level.SEVERE, e, () -> "Fehler beim Anlegen eins Projektes"); @@ -186,17 +187,17 @@ void neuesProjektErzeugen(Event event) { } void projektSpeichern(Event event) { - UMLProjekt projekt = ansicht.getProjektAnsicht().getAngezeigtesProjektProperty().get(); + UMLProjekt projekt = ansicht.get().getProjektAnsicht().getAngezeigtesProjektProperty().get(); if (projekt.getSpeicherort() == null) { projektSpeichernUnter(event); } - ansicht.getProjektAnsicht().angezeigtesProjektSpeichern(); + ansicht.get().getProjektAnsicht().angezeigtesProjektSpeichern(); } void projektSpeichernUnter(Event event) { - ansicht.getProjektAnsicht().angezeigtesProjektSpeicherUnter(); + ansicht.get().getProjektAnsicht().angezeigtesProjektSpeicherUnter(); } void projektOeffnen(Event event) { @@ -206,14 +207,14 @@ void projektOeffnen(Event event) { Einstellungen.getBenutzerdefiniert().letzterSpeicherortEinstellung.get())); dateiDialog.getExtensionFilters() - .addAll(ansicht.getProgrammDetails().dateiZuordnung()); + .addAll(ansicht.get().getProgrammDetails().dateiZuordnung()); String titel = sprache.getText("oeffnenDialogTitel", "Projekt %cffnen".formatted(Umlaute.OE)); dateiDialog.setTitle(titel); List dateien = dateiDialog - .showOpenMultipleDialog(ansicht.getWurzelknoten().getScene().getWindow()); + .showOpenMultipleDialog(ansicht.get().getWurzelknoten().getScene().getWindow()); if (dateien != null && !dateien.isEmpty()) { Einstellungen.getBenutzerdefiniert().letzterSpeicherortEinstellung @@ -231,7 +232,7 @@ void projektOeffnen(DragEvent event) { Dragboard db = event.getDragboard(); boolean akzeptieren = false; if (db.hasFiles()) { - for (ExtensionFilter erweiterungen : this.ansicht.getProgrammDetails() + for (ExtensionFilter erweiterungen : this.ansicht.get().getProgrammDetails() .dateiZuordnung()) { for (String erweiterung : erweiterungen.getExtensions()) { akzeptieren |= db.getFiles().stream() @@ -276,11 +277,11 @@ void projektOeffnen(File datei) { } if (projekt == null) { - ansicht.zeigeOeffnenFehlerDialog(datei); + ansicht.get().zeigeOeffnenFehlerDialog(datei); } else { String projektName = projekt.getName(); try { - this.ansicht.zeigeProjekt(projekt); + this.ansicht.get().zeigeProjekt(projekt); DatumWrapper dateiEintrag = new DatumWrapper(datei.toPath()); if (!Einstellungen.getBenutzerdefiniert().letzteDateien.add(dateiEintrag)) { Einstellungen.getBenutzerdefiniert().letzteDateien.remove(dateiEintrag); @@ -289,19 +290,19 @@ void projektOeffnen(File datei) { } catch (Exception e) { log.log(Level.INFO, e, () -> "Projekt %s wurde nicht geoeffnet".formatted(projektName)); - ansicht.zeigeOeffnenWarnungDialog(datei); + ansicht.get().zeigeOeffnenWarnungDialog(datei); } } } void projektUmbenennen(Event event) { - UMLProjekt projekt = ansicht.getProjektAnsicht().getAngezeigtesProjektProperty().get(); + UMLProjekt projekt = ansicht.get().getProjektAnsicht().getAngezeigtesProjektProperty().get(); MessageFormat format = new MessageFormat(sprache.getText("umbenennenTitel", "Neuen Namen f%cr Projekt {0} festlegen".formatted(ue))); String titel = format.format(new Object[] { projekt.getName() }); - Dialog eingabeDialog = this.ansicht.getOverlayDialog().showTextInput(titel, + Dialog eingabeDialog = this.ansicht.get().getOverlayDialog().showTextInput(titel, projekt.getName()); TextField eingabe = findeElement(eingabeDialog.getContent(), TextField.class); @@ -317,17 +318,17 @@ void projektUmbenennen(Event event) { } void zoomeGroesser(Event event) { - var projekt = ansicht.getProjektAnsicht().getProjektAnsichtProperty().get(); + var projekt = ansicht.get().getProjektAnsicht().getProjektAnsichtProperty().get(); projekt.skaliere(projekt.getSkalierung() + 0.1); } void zoomeKleiner(Event event) { - var projekt = ansicht.getProjektAnsicht().getProjektAnsichtProperty().get(); + var projekt = ansicht.get().getProjektAnsicht().getProjektAnsichtProperty().get(); projekt.skaliere(projekt.getSkalierung() - 0.1); } void resetZoom(Event event) { - var projekt = ansicht.getProjektAnsicht().getProjektAnsichtProperty().get(); + var projekt = ansicht.get().getProjektAnsicht().getProjektAnsichtProperty().get(); projekt.skaliere(projekt.getStandardSkalierung()); } @@ -335,7 +336,7 @@ void resetZoom(Event event) { private void bereinigeKonfigurationsOrdner() { var konfigurationsordner = OS.getDefault() - .getKonfigurationsOrdnerPath(ansicht.getProgrammDetails()); + .getKonfigurationsOrdnerPath(ansicht.get().getProgrammDetails()); var ausgeschlossen = Ressourcen.get().KONFIGURATIONSORDNER.alsPath(); log.info(() -> "Bereinige Konfigurationsordner " + konfigurationsordner); diff --git a/src/main/java/io/github/aid_labor/classifier/gui/ProjektAnsicht.java b/src/main/java/io/github/aid_labor/classifier/gui/ProjektAnsicht.java index 730dd46..d8f35ff 100644 --- a/src/main/java/io/github/aid_labor/classifier/gui/ProjektAnsicht.java +++ b/src/main/java/io/github/aid_labor/classifier/gui/ProjektAnsicht.java @@ -12,6 +12,7 @@ import java.util.Map; import java.util.function.BiConsumer; import java.util.function.Supplier; +import java.util.logging.Level; import java.util.logging.Logger; import com.dlsc.gemsfx.DialogPane; @@ -69,7 +70,7 @@ public class ProjektAnsicht extends Tab { // private ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## - private final UMLProjekt projekt; + private UMLProjekt projekt; private final ProjektKontrolle controller; private final DialogPane overlayDialog; private final ProgrammDetails programm; @@ -202,6 +203,17 @@ public void entferneAuswahl() { // package ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## + void schliesse() { + try { + projekt.close(); + } catch (Exception e1) { + log.log(Level.WARNING, e1, () -> "Fehler beim Schliessen des Projektes"); + } + projekt = null; + selektion.clear(); + ansichten.clear(); + } + // private ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## private void initialisiereInhalt() { diff --git a/src/main/java/io/github/aid_labor/classifier/gui/ProjektKontrolle.java b/src/main/java/io/github/aid_labor/classifier/gui/ProjektKontrolle.java index 8ce98c6..3f49e6e 100644 --- a/src/main/java/io/github/aid_labor/classifier/gui/ProjektKontrolle.java +++ b/src/main/java/io/github/aid_labor/classifier/gui/ProjektKontrolle.java @@ -10,6 +10,7 @@ import static io.github.aid_labor.classifier.basis.sprachverwaltung.Umlaute.sz; import java.io.File; +import java.lang.ref.WeakReference; import java.nio.file.Path; import java.text.MessageFormat; import java.util.logging.Logger; @@ -42,7 +43,7 @@ class ProjektKontrolle { // * Attribute * // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - private final ProjektAnsicht ansicht; + private final WeakReference ansicht; private final Sprache sprache; // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * @@ -50,7 +51,7 @@ class ProjektKontrolle { // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ProjektKontrolle(ProjektAnsicht ansicht, Sprache sprache) { - this.ansicht = ansicht; + this.ansicht = new WeakReference(ansicht); this.sprache = sprache; } @@ -69,25 +70,22 @@ class ProjektKontrolle { // package ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## void checkSchliessen(Event event) { - if (!ansicht.getProjekt().istGespeichertProperty().get()) { + if (!ansicht.get().getProjekt().istGespeichertProperty().get()) { MessageFormat nachricht = new MessageFormat(sprache.getText("schliessenAbfrage", "Projekt \"{0}\" vor dem Schlie%cen speichern?".formatted(sz))); - String abfrage = nachricht.format(new Object[] { ansicht.getProjekt().getName() }); - ButtonType abbrechenButton = new ButtonType(sprache.getText("abbrechen", - "Abbrechen"), + String abfrage = nachricht.format(new Object[] { ansicht.get().getProjekt().getName() }); + ButtonType abbrechenButton = new ButtonType(sprache.getText("abbrechen", "Abbrechen"), ButtonData.CANCEL_CLOSE); - ButtonType verwerfenButton = new ButtonType(sprache.getText("verwerfen", - "%cnderungen verwerfen".formatted(AE)), - ButtonData.NO); - ButtonType speichernSchliessenButton = new ButtonType(sprache.getText( - "speichernSchliessen", "Speichern und Schlie%cen".formatted(sz)), - ButtonData.APPLY); + ButtonType verwerfenButton = new ButtonType( + sprache.getText("verwerfen", "%cnderungen verwerfen".formatted(AE)), ButtonData.NO); + ButtonType speichernSchliessenButton = new ButtonType( + sprache.getText("speichernSchliessen", "Speichern und Schlie%cen".formatted(sz)), ButtonData.APPLY); // @formatter:off Alert dialog = new Alert(AlertType.CONFIRMATION, "", new ButtonType[] {abbrechenButton, verwerfenButton, speichernSchliessenButton}); dialog.setHeaderText(abfrage); - Window hauptfenster = ansicht.getTabPane().getScene().getWindow(); + Window hauptfenster = ansicht.get().getTabPane().getScene().getWindow(); FensterUtil.initialisiereElternFenster(hauptfenster, dialog); dialog.setOnShowing(e -> { @@ -98,21 +96,25 @@ void checkSchliessen(Event event) { switch (button.getButtonData()) { case NO -> { log.info(() -> "Verwerfe %cnderungen am Projekt [%s] und Schlie%ce" - .formatted(AE, ansicht.getProjekt(), sz)); + .formatted(AE, ansicht.get().getProjekt(), sz)); + this.ansicht.get().schliesse(); } case APPLY -> { log.info(() -> "Speichere %cnderungen am Projekt [%s] und Schlie%ce" - .formatted(AE, ansicht.getProjekt(), sz)); - projektSpeichern(this.ansicht.getProjekt()); + .formatted(AE, ansicht.get().getProjekt(), sz)); + projektSpeichern(this.ansicht.get().getProjekt()); + this.ansicht.get().schliesse(); } default -> { log.info(() -> "Schlie%cen von Projekt [%s] abgebrochen" - .formatted(sz, ansicht.getProjekt())); + .formatted(sz, ansicht.get().getProjekt())); event.consume(); } } }); // @formatter:on + } else { + this.ansicht.get().schliesse(); } } @@ -121,7 +123,7 @@ boolean projektSpeichern(UMLProjekt projekt) { return projektSpeichernUnter(projekt); } - return ansicht.getProjekt().speichern(); + return ansicht.get().getProjekt().speichern(); } boolean projektSpeichernUnter(UMLProjekt projekt) { @@ -131,21 +133,18 @@ boolean projektSpeichernUnter(UMLProjekt projekt) { dateiDialog.setInitialDirectory(projekt.getSpeicherort().getParent().toFile()); dateiDialog.setInitialFileName(projekt.getSpeicherort().getFileName().toString()); } else { - dateiDialog.setInitialDirectory(new File( - Einstellungen.getBenutzerdefiniert().letzterSpeicherortEinstellung.get())); + dateiDialog.setInitialDirectory( + new File(Einstellungen.getBenutzerdefiniert().letzterSpeicherortEinstellung.get())); dateiDialog.setInitialFileName(projekt.getName()); } - dateiDialog.getExtensionFilters() - .addAll(ansicht.getProgrammDetails().dateiZuordnung()); + dateiDialog.getExtensionFilters().addAll(ansicht.get().getProgrammDetails().dateiZuordnung()); - String format = sprache.getText("speichernDialogTitel", - "Projekt \"{1}\" speichern als..."); + String format = sprache.getText("speichernDialogTitel", "Projekt \"{1}\" speichern als..."); String titel = MessageFormat.format(format, projekt.getName()); dateiDialog.setTitle(titel); - File speicherOrt = dateiDialog - .showSaveDialog(ansicht.getTabPane().getScene().getWindow()); + File speicherOrt = dateiDialog.showSaveDialog(ansicht.get().getTabPane().getScene().getWindow()); if (speicherOrt == null) { // @formatter:off log.info(() -> @@ -158,7 +157,7 @@ boolean projektSpeichernUnter(UMLProjekt projekt) { Einstellungen.getBenutzerdefiniert().letzterSpeicherortEinstellung .set(speicherOrt.getParentFile().getAbsolutePath()); - boolean gespeichert = ansicht.getProjekt().speichern(speicherOrt.toPath()); + boolean gespeichert = ansicht.get().getProjekt().speichern(speicherOrt.toPath()); if (gespeichert) { DatumWrapper dateiEintrag = new DatumWrapper(speicherOrt.toPath()); diff --git a/src/main/java/io/github/aid_labor/classifier/gui/ProjekteAnsicht.java b/src/main/java/io/github/aid_labor/classifier/gui/ProjekteAnsicht.java index fb0bfeb..f40887f 100644 --- a/src/main/java/io/github/aid_labor/classifier/gui/ProjekteAnsicht.java +++ b/src/main/java/io/github/aid_labor/classifier/gui/ProjekteAnsicht.java @@ -347,6 +347,7 @@ private void setzeListener() { if (aenderung.getElementRemoved() != null) { log.fine( () -> "Projekt entfernt: %s".formatted(aenderung.getElementRemoved())); + } log.fine(() -> "%cnderung der angezeigten Projekte < < < < < < < < < < < < < < <" .formatted(Umlaute.AE)); diff --git a/src/main/java/io/github/aid_labor/classifier/gui/ProjekteKontrolle.java b/src/main/java/io/github/aid_labor/classifier/gui/ProjekteKontrolle.java index d11ba00..ea74b2c 100644 --- a/src/main/java/io/github/aid_labor/classifier/gui/ProjekteKontrolle.java +++ b/src/main/java/io/github/aid_labor/classifier/gui/ProjekteKontrolle.java @@ -6,6 +6,7 @@ package io.github.aid_labor.classifier.gui; +import java.lang.ref.WeakReference; import java.util.function.Supplier; import java.util.logging.Logger; @@ -40,7 +41,7 @@ class ProjekteKontrolle { // private ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## - private final ProjekteAnsicht ansicht; + private final WeakReference ansicht; private final Sprache sprache; // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * @@ -48,7 +49,7 @@ class ProjekteKontrolle { // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ProjekteKontrolle(ProjekteAnsicht ansicht, Sprache sprache) { - this.ansicht = ansicht; + this.ansicht = new WeakReference(ansicht); this.sprache = sprache; } @@ -75,13 +76,13 @@ class ProjekteKontrolle { // package ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## void legeNeuenKlassifiziererAn(KlassifiziererTyp typ) { - var projekt = this.ansicht.getAngezeigtesProjektProperty().get(); + var projekt = this.ansicht.get().getAngezeigtesProjektProperty().get(); legeNeuenKlassifiziererAn( new UMLKlassifizierer(typ, projekt.getProgrammiersprache(), "")); } void legeNeuenKlassifiziererAn(UMLKlassifizierer klassifizierer) { - var projekt = this.ansicht.getAngezeigtesProjektProperty().get(); + var projekt = this.ansicht.get().getAngezeigtesProjektProperty().get(); legeDiagrammElementAn(klassifizierer, () -> { var dialog = new UMLKlassifiziererBearbeitenDialog(klassifizierer, projekt); @@ -99,7 +100,7 @@ void legeKommentarAn() { } void legeKommentarAn(UMLKommentar kommentar) { - var projekt = this.ansicht.getAngezeigtesProjektProperty().get(); + var projekt = this.ansicht.get().getAngezeigtesProjektProperty().get(); legeDiagrammElementAn(kommentar, () -> { var dialog = new UMLKommentarBearbeitenDialog(kommentar); @@ -114,14 +115,14 @@ void legeKommentarAn(UMLKommentar kommentar) { private void legeDiagrammElementAn(UMLDiagrammElement element, Supplier dialogKonstruktor) { - var projekt = this.ansicht.getAngezeigtesProjektProperty().get(); + var projekt = this.ansicht.get().getAngezeigtesProjektProperty().get(); var alterStatus = projekt.getUeberwachungsStatus(); projekt.setUeberwachungsStatus(UeberwachungsStatus.ZUSAMMENFASSEN); projekt.getDiagrammElemente().add(element); var dialog = dialogKonstruktor.get(); - dialog.initOwner(this.ansicht.getAnsicht().getScene().getWindow()); + dialog.initOwner(this.ansicht.get().getAnsicht().getScene().getWindow()); dialog.showAndWait().ifPresent(button -> { switch (button.getButtonData()) { case BACK_PREVIOUS -> { diff --git a/src/main/java/io/github/aid_labor/classifier/gui/UMLKlassifiziererBearbeitenDialog.java b/src/main/java/io/github/aid_labor/classifier/gui/UMLKlassifiziererBearbeitenDialog.java index 5878dbc..a95b34b 100644 --- a/src/main/java/io/github/aid_labor/classifier/gui/UMLKlassifiziererBearbeitenDialog.java +++ b/src/main/java/io/github/aid_labor/classifier/gui/UMLKlassifiziererBearbeitenDialog.java @@ -6,6 +6,7 @@ package io.github.aid_labor.classifier.gui; +import java.lang.ref.WeakReference; import java.util.LinkedList; import java.util.List; import java.util.Objects; @@ -42,6 +43,7 @@ import javafx.beans.binding.StringBinding; import javafx.beans.binding.StringExpression; import javafx.beans.binding.When; +import javafx.beans.property.Property; import javafx.beans.value.ChangeListener; import javafx.beans.value.WeakChangeListener; import javafx.collections.ListChangeListener; @@ -103,8 +105,7 @@ public class UMLKlassifiziererBearbeitenDialog extends Alert { // * Attribute * // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - private final UMLKlassifizierer klassifizierer; - private final UMLKlassifizierer sicherungskopie; + private final WeakReference klassifiziererRef; private final Sprache sprache; private final SegmentedButton buttonBar; private final ToggleButton allgemein; @@ -115,6 +116,7 @@ public class UMLKlassifiziererBearbeitenDialog extends Alert { private final List> validierungsBeobachter; private final List> listenBeobachter; private final List vorhandeneElementNamen; + private final List loeseBindungen; // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // * Konstruktoren * @@ -122,13 +124,13 @@ public class UMLKlassifiziererBearbeitenDialog extends Alert { public UMLKlassifiziererBearbeitenDialog(UMLKlassifizierer klassifizierer, UMLProjekt projekt) { super(AlertType.NONE); - this.klassifizierer = klassifizierer; - this.sicherungskopie = klassifizierer.erzeugeTiefeKopie(); + this.klassifiziererRef = new WeakReference<>(klassifizierer); this.sprache = new Sprache(); this.eingabeValidierung = new ValidationSupport(); this.typBeobachterListe = new LinkedList<>(); this.validierungsBeobachter = new LinkedList<>(); this.listenBeobachter = new LinkedList<>(); + this.loeseBindungen = new LinkedList<>(); this.vorhandeneElementNamen = projekt.getDiagrammElemente().parallelStream() .filter(element -> element.getId() != klassifizierer.getId()).map(UMLDiagrammElement::getName).toList(); @@ -166,6 +168,13 @@ public UMLKlassifiziererBearbeitenDialog(UMLKlassifizierer klassifizierer, UMLPr entferneAlleBeobachter(n); } listenBeobachter.clear(); + for (var c : eingabeValidierung.getRegisteredControls()) { + eingabeValidierung.registerValidator(c, Validator.createPredicateValidator(x -> true, "")); + } + for (var prop : loeseBindungen) { + prop.run(); + } + loeseBindungen.clear(); }); } @@ -185,16 +194,16 @@ private void entferneAlleBeobachter(Node n) { // public ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## - public UMLKlassifizierer getSicherungskopie() { - return sicherungskopie; - } - // protected ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## // package ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## // private ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## + private UMLKlassifizierer getKlassifizierer() { + return klassifiziererRef.get(); + } + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // * Methoden * // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * @@ -227,25 +236,25 @@ private HBox initialisiereButtonBar() { private void erzeugeInhalt(BorderPane wurzel) { var allgemeinAnzeige = erzeugeAllgemeinAnzeige(); var attributeAnzeige = erzeugeTabellenAnzeige(new String[] { "Sichtbarkeit", "Attributname", "Datentyp", - "Initialwert", "Getter", "Setter", "static" }, this.klassifizierer.getAttribute(), + "Initialwert", "Getter", "Setter", "static" }, this.getKlassifizierer().getAttribute(), this::erstelleAttributZeile, event -> { - var programmierEigenschaften = klassifizierer.getProgrammiersprache().getEigenschaften(); - this.klassifizierer.getAttribute() + var programmierEigenschaften = getKlassifizierer().getProgrammiersprache().getEigenschaften(); + this.getKlassifizierer().getAttribute() .add(new Attribut( - programmierEigenschaften.getStandardAttributModifizierer(klassifizierer.getTyp()), + programmierEigenschaften.getStandardAttributModifizierer(getKlassifizierer().getTyp()), programmierEigenschaften.getLetzerDatentyp())); }); var methodenAnzeige = erzeugeTabellenAnzeige(new String[] { "Sichtbarkeit", "Methodenname", "Parameterliste", - "Rueckgabetyp", "abstrakt", "final", "static" }, this.klassifizierer.getMethoden(), + "Rueckgabetyp", "abstrakt", "final", "static" }, this.getKlassifizierer().getMethoden(), this::erstelleMethodenZeile, event -> { - var programmierEigenschaften = klassifizierer.getProgrammiersprache().getEigenschaften(); + var programmierEigenschaften = getKlassifizierer().getProgrammiersprache().getEigenschaften(); var methode = new Methode( - programmierEigenschaften.getStandardMethodenModifizierer(klassifizierer.getTyp()), - programmierEigenschaften.getLetzerDatentyp(), klassifizierer.getProgrammiersprache()); - if (klassifizierer.getTyp().equals(KlassifiziererTyp.Interface)) { + programmierEigenschaften.getStandardMethodenModifizierer(getKlassifizierer().getTyp()), + programmierEigenschaften.getLetzerDatentyp(), getKlassifizierer().getProgrammiersprache()); + if (getKlassifizierer().getTyp().equals(KlassifiziererTyp.Interface)) { methode.setzeAbstrakt(true); } - this.klassifizierer.getMethoden().add(methode); + this.getKlassifizierer().getMethoden().add(methode); }); StackPane container = new StackPane(allgemeinAnzeige, attributeAnzeige, methodenAnzeige); @@ -278,30 +287,30 @@ private GridPane erzeugeAllgemeinAnzeige() { ComboBox typ = new ComboBox<>(); typ.getItems().addAll(KlassifiziererTyp.values()); - typ.getSelectionModel().select(this.klassifizierer.getTyp()); + typ.getSelectionModel().select(this.getKlassifizierer().getTyp()); tabelle.add(typ, 1, 0); - TextField paket = new TextField(this.klassifizierer.getPaket()); + TextField paket = new TextField(this.getKlassifizierer().getPaket()); tabelle.add(paket, 1, 1); - TextField name = new TextField(this.klassifizierer.getName()); + TextField name = new TextField(this.getKlassifizierer().getName()); tabelle.add(name, 1, 2); var sichtbarkeit = erzeugeSichtbarkeit(); tabelle.add(sichtbarkeit, 1, 3); - TextField superklasse = new TextField(this.klassifizierer.getSuperklasse()); + TextField superklasse = new TextField(this.getKlassifizierer().getSuperklasse()); tabelle.add(superklasse, 1, 4); // TODO nutze GemsFX Tags Field - TextField interfaces = new TextField(this.klassifizierer.getInterfaces()); + TextField interfaces = new TextField(this.getKlassifizierer().getInterfaces()); tabelle.add(interfaces, 1, 5); - NodeUtil.beobachteSchwach(typ, typ.getSelectionModel().selectedItemProperty(), klassifizierer::setTyp); - this.klassifizierer.getPaketProperty().bindBidirectional(paket.textProperty()); - this.klassifizierer.nameProperty().bindBidirectional(name.textProperty()); - this.klassifizierer.superklasseProperty().bindBidirectional(superklasse.textProperty()); - this.klassifizierer.interfacesProperty().bindBidirectional(interfaces.textProperty()); + NodeUtil.beobachteSchwach(typ, typ.getSelectionModel().selectedItemProperty(), getKlassifizierer()::setTyp); + bindeBiderektional(getKlassifizierer().getPaketProperty(), paket.textProperty()); + bindeBiderektional(getKlassifizierer().nameProperty(), name.textProperty()); + bindeBiderektional(getKlassifizierer().superklasseProperty(), superklasse.textProperty()); + bindeBiderektional(getKlassifizierer().interfacesProperty(), interfaces.textProperty()); tabelle.setHgap(5); tabelle.setVgap(15); @@ -318,7 +327,7 @@ private GridPane erzeugeAllgemeinAnzeige() { setzePlatzhalter(name); }); - updateSuperklasse(superklasse, klassifizierer.getTyp()); + updateSuperklasse(superklasse, getKlassifizierer().getTyp()); ChangeListener typBeobachter = (p, alteWahl, neueWahl) -> updateSuperklasse(superklasse, neueWahl); this.typBeobachterListe.add(typBeobachter); @@ -354,6 +363,7 @@ private Pane erzeugeTabellenAnzeige(String[] labelBezeichnungen, ObservableL var vBar = ((ScrollPaneSkin) scrollContainer.getSkin()).getVerticalScrollBar(); scrollContainer.prefWidthProperty().bind(tabelle.widthProperty() .add(new When(vBar.visibleProperty()).then(vBar.widthProperty()).otherwise(0))); + loeseBindungen.add(scrollContainer.prefWidthProperty()::unbind); }); NodeUtil.beobachteSchwach(tabelle, tabelle.widthProperty(), @@ -402,40 +412,40 @@ private void fuelleListenInhalt(GridPane tabelle, ObservableList inhalt, private Node[] erstelleAttributZeile(Attribut attribut, int zeile) { ComboBox sichtbarkeit = new ComboBox<>(); - sichtbarkeit.getItems().addAll(klassifizierer.getProgrammiersprache().getEigenschaften() - .getAttributModifizierer(klassifizierer.getTyp())); + sichtbarkeit.getItems().addAll(getKlassifizierer().getProgrammiersprache().getEigenschaften() + .getAttributModifizierer(getKlassifizierer().getTyp())); sichtbarkeit.getSelectionModel().select(attribut.getSichtbarkeit()); NodeUtil.beobachteSchwach(sichtbarkeit, sichtbarkeit.getSelectionModel().selectedItemProperty(), attribut::setSichtbarkeit); TextField name = new TextField(); - name.textProperty().bindBidirectional(attribut.getNameProperty()); + bindeBiderektional(name.textProperty(), attribut.getNameProperty()); TextField datentyp = new TextField(attribut.getDatentyp().getTypName()); - datentyp.textProperty().bindBidirectional(attribut.getDatentyp().getTypNameProperty()); + bindeBiderektional(datentyp.textProperty(), attribut.getDatentyp().getTypNameProperty()); TextField initialwert = new TextField(attribut.getInitialwert()); - initialwert.textProperty().bindBidirectional(attribut.getInitialwertProperty()); + bindeBiderektional(initialwert.textProperty(),attribut.getInitialwertProperty()); CheckBox getter = new CheckBox(); - getter.selectedProperty().bindBidirectional(attribut.getHatGetterProperty()); + bindeBiderektional(getter.selectedProperty(), attribut.getHatGetterProperty()); GridPane.setHalignment(getter, HPos.CENTER); CheckBox setter = new CheckBox(); - setter.selectedProperty().bindBidirectional(attribut.getHatSetterProperty()); + bindeBiderektional(setter.selectedProperty(), attribut.getHatSetterProperty()); GridPane.setHalignment(setter, HPos.CENTER); CheckBox statisch = new CheckBox(); - statisch.selectedProperty().bindBidirectional(attribut.getIstStatischProperty()); + bindeBiderektional(statisch.selectedProperty(), attribut.getIstStatischProperty()); GridPane.setHalignment(statisch, HPos.CENTER); Label loeschen = new Label(); NodeUtil.erzeugeIconNode(loeschen, CarbonIcons.DELETE, 15); - loeschen.setOnMouseClicked(e -> klassifizierer.getAttribute().remove(attribut)); + loeschen.setOnMouseClicked(e -> getKlassifizierer().getAttribute().remove(attribut)); Label hoch = new Label(); NodeUtil.erzeugeIconNode(hoch, BootstrapIcons.CARET_UP_FILL, 15); - hoch.setOnMouseClicked(e -> tausche(klassifizierer.getAttribute(), zeile, zeile - 1)); + hoch.setOnMouseClicked(e -> tausche(getKlassifizierer().getAttribute(), zeile, zeile - 1)); if (zeile == 0) { hoch.setDisable(true); @@ -443,9 +453,9 @@ private Node[] erstelleAttributZeile(Attribut attribut, int zeile) { Label runter = new Label(); NodeUtil.erzeugeIconNode(runter, BootstrapIcons.CARET_DOWN_FILL, 15); - runter.setOnMouseClicked(e -> tausche(klassifizierer.getAttribute(), zeile, zeile + 1)); + runter.setOnMouseClicked(e -> tausche(getKlassifizierer().getAttribute(), zeile, zeile + 1)); - if (zeile == klassifizierer.getAttribute().size() - 1) { + if (zeile == getKlassifizierer().getAttribute().size() - 1) { runter.setDisable(true); } @@ -455,7 +465,7 @@ private Node[] erstelleAttributZeile(Attribut attribut, int zeile) { Validator.combine( Validator.createEmptyValidator(sprache.getText("nameValidierung", "Name angeben")), Validator.createPredicateValidator( - tf -> klassifizierer.getAttribute().stream() + tf -> getKlassifizierer().getAttribute().stream() .filter(a -> Objects.equals(a.getName(), name.getText())).count() <= 1, sprache.getText("nameValidierung2", "Ein Attribut mit diesem Namen ist bereits vorhanden")))); @@ -471,11 +481,11 @@ private Node[] erstelleAttributZeile(Attribut attribut, int zeile) { setzePlatzhalter(datentyp); }); - updateStatischAttribut(statisch, klassifizierer.getTyp()); + updateStatischAttribut(statisch, getKlassifizierer().getTyp()); ChangeListener typBeobachter = (p, alteWahl, neueWahl) -> updateStatischAttribut(statisch, neueWahl); this.typBeobachterListe.add(typBeobachter); - klassifizierer.typProperty().addListener(typBeobachter); + getKlassifizierer().typProperty().addListener(typBeobachter); return new Node[] { sichtbarkeit, name, datentyp, initialwert, getter, setter, statisch, hoch, runter, loeschen }; @@ -489,11 +499,11 @@ private HBox erzeugeSichtbarkeit() { for (Modifizierer m : modifizierer) { RadioButton rb = new RadioButton(m.toString()); rb.setUserData(m); - rb.setDisable(!ProgrammierEigenschaften.get(klassifizierer.getProgrammiersprache()) - .istTypModifiziererErlaubt(klassifizierer.getTyp(), m)); + rb.setDisable(!ProgrammierEigenschaften.get(getKlassifizierer().getProgrammiersprache()) + .istTypModifiziererErlaubt(getKlassifizierer().getTyp(), m)); sichtbarkeitGruppe.getToggles().add(rb); sichtbarkeit.getChildren().add(rb); - if (m.equals(klassifizierer.getSichtbarkeit())) { + if (m.equals(getKlassifizierer().getSichtbarkeit())) { sichtbarkeitGruppe.selectToggle(rb); } } @@ -501,7 +511,7 @@ private HBox erzeugeSichtbarkeit() { ChangeListener beobachter = (property, alteWahl, neueWahl) -> { if (neueWahl.getUserData() instanceof Modifizierer m) { - klassifizierer.setSichtbarkeit(m); + getKlassifizierer().setSichtbarkeit(m); } }; sichtbarkeit.getProperties().put(this, beobachter); @@ -512,14 +522,14 @@ private HBox erzeugeSichtbarkeit() { private Node[] erstelleMethodenZeile(Methode methode, int zeile) { ComboBox sichtbarkeit = new ComboBox<>(); - sichtbarkeit.getItems().addAll(klassifizierer.getProgrammiersprache().getEigenschaften() - .getMethodenModifizierer(klassifizierer.getTyp())); + sichtbarkeit.getItems().addAll(getKlassifizierer().getProgrammiersprache().getEigenschaften() + .getMethodenModifizierer(getKlassifizierer().getTyp())); sichtbarkeit.getSelectionModel().select(methode.getSichtbarkeit()); NodeUtil.beobachteSchwach(sichtbarkeit, sichtbarkeit.getSelectionModel().selectedItemProperty(), methode::setSichtbarkeit); TextField name = new TextField(); - name.textProperty().bindBidirectional(methode.getNameProperty()); + bindeBiderektional(name.textProperty(), methode.getNameProperty()); TextField parameter = new TextField(); parameter.textProperty().bind(Bindings.concat("(").concat(new StringBinding() { @@ -554,36 +564,38 @@ protected String computeValue() { return stringExpr.get(); } }).concat(")")); + loeseBindungen.add(parameter.textProperty()::unbind); parameter.setEditable(false); parameter.prefColumnCountProperty().bind( new When(parameter.textProperty().length().greaterThanOrEqualTo(TextField.DEFAULT_PREF_COLUMN_COUNT)) .then(parameter.textProperty().length()).otherwise(TextField.DEFAULT_PREF_COLUMN_COUNT)); + loeseBindungen.add(parameter.prefColumnCountProperty()::unbind); parameter.setOnMousePressed(e -> bearbeiteParameter(parameter, methode)); parameter.setOnAction(e -> bearbeiteParameter(parameter, methode)); TextField rueckgabetyp = new TextField(methode.getRueckgabeTyp().getTypName()); - rueckgabetyp.textProperty().bindBidirectional(methode.getRueckgabeTyp().getTypNameProperty()); + bindeBiderektional(rueckgabetyp.textProperty(), methode.getRueckgabeTyp().getTypNameProperty()); rueckgabetyp.setPrefWidth(70); CheckBox abstrakt = new CheckBox(); - abstrakt.selectedProperty().bindBidirectional(methode.getIstAbstraktProperty()); + bindeBiderektional(abstrakt.selectedProperty(), methode.getIstAbstraktProperty()); GridPane.setHalignment(abstrakt, HPos.CENTER); CheckBox istFinal = new CheckBox(); - istFinal.selectedProperty().bindBidirectional(methode.getIstFinalProperty()); + bindeBiderektional(istFinal.selectedProperty(), methode.getIstFinalProperty()); GridPane.setHalignment(istFinal, HPos.CENTER); CheckBox statisch = new CheckBox(); - statisch.selectedProperty().bindBidirectional(methode.getIstStatischProperty()); + bindeBiderektional(statisch.selectedProperty(), methode.getIstStatischProperty()); GridPane.setHalignment(statisch, HPos.CENTER); Label loeschen = new Label(); NodeUtil.erzeugeIconNode(loeschen, CarbonIcons.DELETE, 15); - loeschen.setOnMouseClicked(e -> klassifizierer.getMethoden().remove(methode)); + loeschen.setOnMouseClicked(e -> getKlassifizierer().getMethoden().remove(methode)); Label hoch = new Label(); NodeUtil.erzeugeIconNode(hoch, BootstrapIcons.CARET_UP_FILL, 15); - hoch.setOnMouseClicked(e -> tausche(klassifizierer.getMethoden(), zeile, zeile - 1)); + hoch.setOnMouseClicked(e -> tausche(getKlassifizierer().getMethoden(), zeile, zeile - 1)); if (zeile == 0) { hoch.setDisable(true); @@ -591,9 +603,9 @@ protected String computeValue() { Label runter = new Label(); NodeUtil.erzeugeIconNode(runter, BootstrapIcons.CARET_DOWN_FILL, 15); - runter.setOnMouseClicked(e -> tausche(klassifizierer.getMethoden(), zeile, zeile + 1)); + runter.setOnMouseClicked(e -> tausche(getKlassifizierer().getMethoden(), zeile, zeile + 1)); - if (zeile == klassifizierer.getMethoden().size() - 1) { + if (zeile == getKlassifizierer().getMethoden().size() - 1) { runter.setDisable(true); } @@ -601,7 +613,7 @@ protected String computeValue() { if (Einstellungen.getBenutzerdefiniert().erweiterteValidierungAktivieren.get()) { eingabeValidierung.registerValidator(parameter, Validator.createPredicateValidator( - tf -> klassifizierer.getMethoden().stream() + tf -> getKlassifizierer().getMethoden().stream() .filter(m -> Objects.equals(m.getName(), methode.getName()) && Objects .deepEquals(m.getParameterListe(), methode.getParameterListe())) .count() <= 1, @@ -620,11 +632,11 @@ protected String computeValue() { setzePlatzhalter(rueckgabetyp); }); - updateMethode(abstrakt, statisch, klassifizierer.getTyp(), methode); + updateMethode(abstrakt, statisch, getKlassifizierer().getTyp(), methode); ChangeListener typBeobachter = (p, alteWahl, neueWahl) -> updateMethode(abstrakt, statisch, neueWahl, methode); this.typBeobachterListe.add(typBeobachter); - klassifizierer.typProperty().addListener(typBeobachter); + getKlassifizierer().typProperty().addListener(typBeobachter); if (methode.istGetter() || methode.istSetter()) { rueckgabetyp.setDisable(true); @@ -654,10 +666,10 @@ private void bearbeiteParameter(TextField parameter, Methode methode) { var parameterListe = erzeugeTabellenAnzeige(new String[] { "Parametername", "Datentyp" }, methode.getParameterListe(), (param, zeile) -> { TextField name = new TextField(); - name.textProperty().bindBidirectional(param.getNameProperty()); + bindeBiderektional(name.textProperty(), param.getNameProperty()); TextField datentyp = new TextField(param.getDatentyp().getTypName()); - datentyp.textProperty().bindBidirectional(param.getDatentyp().getTypNameProperty()); + bindeBiderektional(datentyp.textProperty(), param.getDatentyp().getTypNameProperty()); Label loeschen = new Label(); NodeUtil.erzeugeIconNode(loeschen, CarbonIcons.DELETE, 15); @@ -700,7 +712,7 @@ private void bearbeiteParameter(TextField parameter, Methode methode) { return new Node[] { name, datentyp, loeschen, hoch, runter }; }, event -> { if (!methode.istGetter() && !methode.istSetter()) { - var programmierEigenschaften = klassifizierer.getProgrammiersprache().getEigenschaften(); + var programmierEigenschaften = getKlassifizierer().getProgrammiersprache().getEigenschaften(); methode.getParameterListe().add(new Parameter(programmierEigenschaften.getLetzerDatentyp())); } }); @@ -716,6 +728,7 @@ private void initialisiereButtons() { new ButtonType(sprache.getText("CANCEL_CLOSE", "Abbrechen"), ButtonData.BACK_PREVIOUS) }; this.getDialogPane().getButtonTypes().addAll(buttons); this.getDialogPane().lookupButton(buttons[0]).disableProperty().bind(eingabeValidierung.invalidProperty()); + loeseBindungen.add(this.getDialogPane().lookupButton(buttons[0]).disableProperty()::unbind); } private void setzePlatzhalter(TextInputControl eingabefeld) { @@ -747,7 +760,7 @@ private void tausche(List liste, int indexA, int indexB) { } private void updateSuperklasse(TextField superklasse, KlassifiziererTyp typ) { - boolean superklasseErlaubt = klassifizierer.getProgrammiersprache().getEigenschaften().erlaubtSuperklasse(typ); + boolean superklasseErlaubt = getKlassifizierer().getProgrammiersprache().getEigenschaften().erlaubtSuperklasse(typ); if (!superklasseErlaubt) { superklasse.setText(""); } @@ -755,7 +768,7 @@ private void updateSuperklasse(TextField superklasse, KlassifiziererTyp typ) { } private void updateStatischAttribut(CheckBox statisch, KlassifiziererTyp typ) { - boolean instanzAttributeErlaubt = klassifizierer.getProgrammiersprache().getEigenschaften() + boolean instanzAttributeErlaubt = getKlassifizierer().getProgrammiersprache().getEigenschaften() .erlaubtInstanzAttribute(typ); if (!instanzAttributeErlaubt) { statisch.setSelected(true); @@ -767,9 +780,9 @@ private void updateStatischAttribut(CheckBox statisch, KlassifiziererTyp typ) { } private void updateMethode(CheckBox abstrakt, CheckBox statisch, KlassifiziererTyp typ, Methode methode) { - boolean abstraktErlaubt = klassifizierer.getProgrammiersprache().getEigenschaften() + boolean abstraktErlaubt = getKlassifizierer().getProgrammiersprache().getEigenschaften() .erlaubtAbstrakteMethode(typ); - boolean abstraktErzwungen = !klassifizierer.getProgrammiersprache().getEigenschaften() + boolean abstraktErzwungen = !getKlassifizierer().getProgrammiersprache().getEigenschaften() .erlaubtNichtAbstrakteMethode(typ); if (abstraktErzwungen) { @@ -792,4 +805,9 @@ private void updateMethode(CheckBox abstrakt, CheckBox statisch, KlassifiziererT statisch.setDisable(true); } } + + private void bindeBiderektional(Property p1, Property p2) { + p1.bindBidirectional(p2); + loeseBindungen.add(() -> p1.unbindBidirectional(p2)); + } } \ No newline at end of file diff --git a/src/main/java/io/github/aid_labor/classifier/gui/UMLKommentarBearbeitenDialog.java b/src/main/java/io/github/aid_labor/classifier/gui/UMLKommentarBearbeitenDialog.java index 7c05463..ac1e5a1 100644 --- a/src/main/java/io/github/aid_labor/classifier/gui/UMLKommentarBearbeitenDialog.java +++ b/src/main/java/io/github/aid_labor/classifier/gui/UMLKommentarBearbeitenDialog.java @@ -6,6 +6,7 @@ package io.github.aid_labor.classifier.gui; +import java.lang.ref.WeakReference; import java.util.logging.Logger; import io.github.aid_labor.classifier.basis.io.Ressourcen; @@ -50,7 +51,7 @@ public class UMLKommentarBearbeitenDialog extends Alert { // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * private final Sprache sprache; - private final UMLKommentar kommentar; + private final WeakReference kommentar; private final HTMLEditor inhalt; // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * @@ -60,7 +61,7 @@ public class UMLKommentarBearbeitenDialog extends Alert { public UMLKommentarBearbeitenDialog(UMLKommentar kommentar) { super(AlertType.NONE); this.sprache = new Sprache(); - this.kommentar = kommentar; + this.kommentar = new WeakReference<>(kommentar); boolean spracheGesetzt = SprachUtil.setUpSprache(sprache, Ressourcen.get().SPRACHDATEIEN_ORDNER.alsPath(), @@ -120,7 +121,7 @@ public UMLKommentarBearbeitenDialog(UMLKommentar kommentar) { // private ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## private void updateKommentar(Event event) { - kommentar.setInhalt(inhalt.getHtmlText().replace(" contenteditable=\"true\"", "")); + kommentar.get().setInhalt(inhalt.getHtmlText().replace(" contenteditable=\"true\"", "")); if (event != null) { log.finest(() -> """ potentielle Aenderung festgestellt diff --git a/src/main/java/io/github/aid_labor/classifier/gui/elemente/ListenAnsicht.java b/src/main/java/io/github/aid_labor/classifier/gui/elemente/ListenAnsicht.java index a6d5faa..517ead8 100644 --- a/src/main/java/io/github/aid_labor/classifier/gui/elemente/ListenAnsicht.java +++ b/src/main/java/io/github/aid_labor/classifier/gui/elemente/ListenAnsicht.java @@ -10,6 +10,7 @@ import javafx.collections.ListChangeListener; import javafx.collections.ObservableList; +import javafx.collections.WeakListChangeListener; import javafx.scene.Node; import javafx.scene.layout.GridPane; @@ -35,7 +36,8 @@ public abstract class ListenAnsicht extends GridPane { // * Attribute * // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - protected final ObservableList inhaltListe; + protected final WeakReference> inhaltListeRef; + private ListChangeListener listenBeobachter; // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // * Konstruktoren * @@ -43,20 +45,17 @@ public abstract class ListenAnsicht extends GridPane { public ListenAnsicht(ObservableList inhaltListe) { this.setMinSize(0, 0); - this.setVisible(inhaltListe.size() > 0); - this.inhaltListe = inhaltListe; + this.setVisible(!inhaltListe.isEmpty()); + this.inhaltListeRef = new WeakReference>(inhaltListe); this.getStyleClass().add("attribut-liste"); WeakReference> ref = new WeakReference>( this); - inhaltListe.addListener(new ListChangeListener() { - @Override - public void onChanged(Change aenderung) { - ref.get().setVisible(inhaltListe.size() > 0); - - fuelleListe(); - } - }); + listenBeobachter = aenderung -> { + ref.get().setVisible(!ref.get().inhaltListeRef.get().isEmpty()); + fuelleListe(); + }; + inhaltListe.addListener(new WeakListChangeListener<>(listenBeobachter)); } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * @@ -80,7 +79,7 @@ public void onChanged(Change aenderung) { protected final void fuelleListe() { this.getChildren().clear(); int zeile = 0; - for (var attribut : inhaltListe) { + for (var attribut : inhaltListeRef.get()) { var inhalt = erstelleZeile(attribut); this.addRow(zeile, inhalt); zeile++; diff --git a/src/main/java/io/github/aid_labor/classifier/gui/elemente/UMLElementBasisAnsicht.java b/src/main/java/io/github/aid_labor/classifier/gui/elemente/UMLElementBasisAnsicht.java index 0121592..3c3ef5c 100644 --- a/src/main/java/io/github/aid_labor/classifier/gui/elemente/UMLElementBasisAnsicht.java +++ b/src/main/java/io/github/aid_labor/classifier/gui/elemente/UMLElementBasisAnsicht.java @@ -6,6 +6,8 @@ package io.github.aid_labor.classifier.gui.elemente; +import java.lang.ref.WeakReference; + import io.github.aid_labor.classifier.uml.klassendiagramm.UMLDiagrammElement; import javafx.scene.layout.Region; import javafx.scene.layout.StackPane; @@ -32,14 +34,14 @@ public class UMLElementBasisAnsicht extends StackP // * Attribute * // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - protected final E umlElementModel; + protected final WeakReference umlElementModel; // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // * Konstruktoren * // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * public UMLElementBasisAnsicht(E umlElementModel) { - this.umlElementModel = umlElementModel; + this.umlElementModel = new WeakReference<>(umlElementModel); this.translateXProperty() .bindBidirectional(umlElementModel.getPosition().getXProperty()); this.translateYProperty() @@ -66,7 +68,7 @@ public UMLElementBasisAnsicht(E umlElementModel) { // public ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## public E getUmlElement() { - return umlElementModel; + return umlElementModel.get(); } // protected ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## diff --git a/src/main/java/io/github/aid_labor/classifier/gui/elemente/UMLKlassifiziererAnsicht.java b/src/main/java/io/github/aid_labor/classifier/gui/elemente/UMLKlassifiziererAnsicht.java index 615990d..adba357 100644 --- a/src/main/java/io/github/aid_labor/classifier/gui/elemente/UMLKlassifiziererAnsicht.java +++ b/src/main/java/io/github/aid_labor/classifier/gui/elemente/UMLKlassifiziererAnsicht.java @@ -8,7 +8,9 @@ import io.github.aid_labor.classifier.uml.klassendiagramm.KlassifiziererTyp; import io.github.aid_labor.classifier.uml.klassendiagramm.UMLKlassifizierer; +import javafx.beans.InvalidationListener; import javafx.beans.Observable; +import javafx.beans.WeakInvalidationListener; import javafx.beans.binding.StringBinding; import javafx.beans.binding.When; import javafx.geometry.Insets; @@ -51,6 +53,7 @@ public class UMLKlassifiziererAnsicht extends UMLElementBasisAnsicht { + umlElementModel.get().typProperty().addListener((property, alterTyp, neuerTyp) -> { updateStereotyp(neuerTyp); }); } @@ -166,8 +170,8 @@ private void updateStereotyp(KlassifiziererTyp neuerTyp) { } private void checkeTrenner(Observable o) { - boolean hatAttributOderMethode = umlElementModel.getAttribute().size() > 0 - || umlElementModel.getMethoden().size() > 0; + boolean hatAttributOderMethode = !umlElementModel.get().getAttribute().isEmpty() + || !umlElementModel.get().getMethoden().isEmpty(); if (hatAttributOderMethode) { if (!this.inhalt.getChildren().contains(this.eigenschaften)) { this.inhalt.getChildren().add(eigenschaften); diff --git a/src/main/java/io/github/aid_labor/classifier/main/LoggingEinstellung.java b/src/main/java/io/github/aid_labor/classifier/main/LoggingEinstellung.java index 7c62480..3442b64 100644 --- a/src/main/java/io/github/aid_labor/classifier/main/LoggingEinstellung.java +++ b/src/main/java/io/github/aid_labor/classifier/main/LoggingEinstellung.java @@ -60,6 +60,7 @@ static void initialisiereLogging(ProgrammDetails programm) { logProperties.setProperty("java.util.logging.ConsoleHandler.level", "WARNING"); logProperties.setProperty("javafx.level", "INFO"); logProperties.setProperty("com.sun.level", "OFF"); + logProperties.setProperty("com.sun.jmx.level", "OFF"); // Einstellungen Anwenden wendeLoggingEinstellungenAn(); diff --git a/src/main/java/io/github/aid_labor/classifier/uml/UMLProjekt.java b/src/main/java/io/github/aid_labor/classifier/uml/UMLProjekt.java index 13f2502..1b3becb 100644 --- a/src/main/java/io/github/aid_labor/classifier/uml/UMLProjekt.java +++ b/src/main/java/io/github/aid_labor/classifier/uml/UMLProjekt.java @@ -7,6 +7,7 @@ package io.github.aid_labor.classifier.uml; import java.io.IOException; +import java.lang.reflect.Modifier; import java.nio.file.Path; import java.util.List; import java.util.Objects; @@ -20,6 +21,7 @@ import io.github.aid_labor.classifier.basis.ClassifierUtil; import io.github.aid_labor.classifier.basis.projekt.ListenUeberwacher; import io.github.aid_labor.classifier.basis.projekt.ProjektBasis; +import io.github.aid_labor.classifier.basis.projekt.UeberwachungsStatus; import io.github.aid_labor.classifier.uml.eigenschaften.Programmiersprache; import io.github.aid_labor.classifier.uml.klassendiagramm.UMLDiagrammElement; import javafx.collections.FXCollections; @@ -209,6 +211,28 @@ public boolean equals(Object obj) { return istGleich; } + @Override + public void close() throws Exception { + log.finest(() -> this + " leere diagrammelemente"); + this.setUeberwachungsStatus(UeberwachungsStatus.IGNORIEREN); + for (var element : getDiagrammElemente()) { + element.close(); + } + getDiagrammElemente().clear(); + super.close(); + + for(var attribut : this.getClass().getDeclaredFields()) { + try { + if (!Modifier.isStatic(attribut.getModifiers())) { + attribut.setAccessible(true); + attribut.set(this, null); + } + } catch (Exception e) { + // ignore + } + } + } + // protected ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## // package ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## diff --git a/src/main/java/io/github/aid_labor/classifier/uml/eigenschaften/Attribut.java b/src/main/java/io/github/aid_labor/classifier/uml/eigenschaften/Attribut.java index 913e07a..96a87f9 100644 --- a/src/main/java/io/github/aid_labor/classifier/uml/eigenschaften/Attribut.java +++ b/src/main/java/io/github/aid_labor/classifier/uml/eigenschaften/Attribut.java @@ -6,6 +6,8 @@ package io.github.aid_labor.classifier.uml.eigenschaften; +import java.util.LinkedList; +import java.util.List; import java.util.Objects; import com.fasterxml.jackson.annotation.JsonBackReference; @@ -30,7 +32,9 @@ public class Attribut extends EditierbarBasis implements EditierbarerBeobachter // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // * Klassenattribute * // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - + + private static long naechsteId = 0; + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // * Klassenmethoden * // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * @@ -57,6 +61,9 @@ public class Attribut extends EditierbarBasis implements EditierbarerBeobachter private Methode getter; @JsonBackReference("setterAttribut") private Methode setter; + @JsonIgnore + private final List beobachterListe; + @JsonIgnore private final long id; // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // * Konstruktoren * @@ -82,14 +89,16 @@ public Attribut( this.istStatisch = new JsonBooleanProperty(this, "istStatisch", istStatisch); this.getter = getter; this.setter = setter; + this.beobachterListe = new LinkedList<>(); + this.id = naechsteId++; - this.ueberwachePropertyAenderung(this.sichtbarkeit); - this.ueberwachePropertyAenderung(this.datentyp.getTypNameProperty()); - this.ueberwachePropertyAenderung(this.name); - this.ueberwachePropertyAenderung(this.initialwert); - this.ueberwachePropertyAenderung(this.hatGetter); - this.ueberwachePropertyAenderung(this.hatSetter); - this.ueberwachePropertyAenderung(this.istStatisch); + this.ueberwachePropertyAenderung(this.sichtbarkeit, id + "_attribut_sichtbarkeit"); + this.ueberwachePropertyAenderung(this.datentyp.getTypNameProperty(), id + "_attribut_datentyp"); + this.ueberwachePropertyAenderung(this.name, id + "_attribut_name"); + this.ueberwachePropertyAenderung(this.initialwert, id + "_attribut_initialwert"); + this.ueberwachePropertyAenderung(this.hatGetter, id + "_attribut_getter"); + this.ueberwachePropertyAenderung(this.hatSetter, id + "_attribut_setter"); + this.ueberwachePropertyAenderung(this.istStatisch, id + "_attribut_statisch"); } public Attribut(Modifizierer sichtbarkeit, Datentyp datentyp, boolean istStatisch) { @@ -106,6 +115,11 @@ public Attribut(Modifizierer sichtbarkeit, Datentyp datentyp) { // public ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## + @Override + public List getBeobachterListe() { + return beobachterListe; + } + public Modifizierer getSichtbarkeit() { return sichtbarkeit.get(); } @@ -277,6 +291,14 @@ public Attribut erzeugeTiefeKopie() { return kopie; } + @Override + public void close() throws Exception { + getter = null; + setter = null; + log.finest(() -> this + " leere listeners"); + beobachterListe.clear(); + } + // protected ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## // package ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## diff --git a/src/main/java/io/github/aid_labor/classifier/uml/eigenschaften/Datentyp.java b/src/main/java/io/github/aid_labor/classifier/uml/eigenschaften/Datentyp.java index 1b6796a..47e1b2b 100644 --- a/src/main/java/io/github/aid_labor/classifier/uml/eigenschaften/Datentyp.java +++ b/src/main/java/io/github/aid_labor/classifier/uml/eigenschaften/Datentyp.java @@ -6,11 +6,14 @@ package io.github.aid_labor.classifier.uml.eigenschaften; +import java.util.LinkedList; +import java.util.List; import java.util.Objects; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import io.github.aid_labor.classifier.basis.ClassifierUtil; @@ -29,14 +32,26 @@ //@formatter:on public class Datentyp extends EditierbarBasis implements EditierbarerBeobachter { + private static long naechsteId = 0; private final JsonStringProperty typName; + @JsonIgnore + private final List beobachterListe; + @JsonIgnore + private final long id; @JsonCreator public Datentyp(@JsonProperty("typName") String typName) { this.typName = new JsonStringProperty(this, "typName", typName); + this.beobachterListe = new LinkedList<>(); + this.id = naechsteId++; - this.ueberwachePropertyAenderung(this.typName); + this.ueberwachePropertyAenderung(this.typName, id + "_datentyp_name"); + } + + @Override + public List getBeobachterListe() { + return beobachterListe; } public void set(Datentyp datentyp) { @@ -83,5 +98,10 @@ public boolean equals(Object obj) { Datentyp other = (Datentyp) obj; return Objects.equals(typName, other.typName); } + + @Override + public void close() throws Exception { + beobachterListe.clear(); + } } diff --git a/src/main/java/io/github/aid_labor/classifier/uml/eigenschaften/Methode.java b/src/main/java/io/github/aid_labor/classifier/uml/eigenschaften/Methode.java index 409d4cf..4533cc1 100644 --- a/src/main/java/io/github/aid_labor/classifier/uml/eigenschaften/Methode.java +++ b/src/main/java/io/github/aid_labor/classifier/uml/eigenschaften/Methode.java @@ -13,6 +13,7 @@ import java.util.stream.Collectors; import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonManagedReference; import com.fasterxml.jackson.annotation.JsonProperty; @@ -36,6 +37,8 @@ public class Methode extends EditierbarBasis implements EditierbarerBeobachter { // * Klassenattribute * // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + private static long naechsteId = 0; + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // * Klassenmethoden * // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * @@ -64,36 +67,38 @@ public class Methode extends EditierbarBasis implements EditierbarerBeobachter { @JsonManagedReference("setterAttribut") private Attribut setterAttribut; private final Programmiersprache programmiersprache; + @JsonIgnore + private final List beobachterListe; + @JsonIgnore + private final long id; // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // * Konstruktoren * // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - public Methode(Modifizierer sichtbarkeit, Datentyp rueckgabeTyp, - Programmiersprache programmiersprache) { + public Methode(Modifizierer sichtbarkeit, Datentyp rueckgabeTyp, Programmiersprache programmiersprache) { this(sichtbarkeit, rueckgabeTyp, false, programmiersprache); } public Methode(Modifizierer sichtbarkeit, Datentyp rueckgabeTyp, boolean istStatisch, Programmiersprache programmiersprache) { - this(sichtbarkeit, rueckgabeTyp, istStatisch, false, false, null, null, - programmiersprache); + this(sichtbarkeit, rueckgabeTyp, istStatisch, false, false, null, null, programmiersprache); } - protected Methode(Modifizierer sichtbarkeit, Datentyp rueckgabeTyp, boolean istStatisch, - boolean istGetter, boolean istSetter, Attribut getterAttribut, - Attribut setterAttribut, Programmiersprache programmiersprache) { + protected Methode(Modifizierer sichtbarkeit, Datentyp rueckgabeTyp, boolean istStatisch, boolean istGetter, + boolean istSetter, Attribut getterAttribut, Attribut setterAttribut, + Programmiersprache programmiersprache) { if (istGetter && istSetter) { throw new IllegalStateException("Kann nur getter oder setter sein, nicht beides!"); } + this.id = naechsteId++; + this.beobachterListe = new LinkedList<>(); this.name = new JsonStringProperty(this, "methodenname", ""); this.istStatisch = new JsonBooleanProperty(this, "istStatisch", istStatisch); if (istGetter) { - this.rueckgabeTyp = Objects - .requireNonNull(getterAttribut.getDatentyp().erzeugeTiefeKopie()); - this.rueckgabeTyp.getTypNameProperty() - .bind(getterAttribut.getDatentyp().getTypNameProperty()); + this.rueckgabeTyp = Objects.requireNonNull(getterAttribut.getDatentyp().erzeugeTiefeKopie()); + this.rueckgabeTyp.getTypNameProperty().bind(getterAttribut.getDatentyp().getTypNameProperty()); this.istStatisch.bindBidirectional(getterAttribut.getIstStatischProperty()); this.name.set("get" + Character.toUpperCase(getterAttribut.getName().charAt(0)) + getterAttribut.getName().substring(1)); @@ -104,19 +109,16 @@ protected Methode(Modifizierer sichtbarkeit, Datentyp rueckgabeTyp, boolean istS this.istStatisch.bindBidirectional(setterAttribut.getIstStatischProperty()); this.name.set("set" + Character.toUpperCase(setterAttribut.getName().charAt(0)) + setterAttribut.getName().substring(1)); - var param = new Parameter(setterAttribut.getDatentyp().erzeugeTiefeKopie(), - setterAttribut.getName()); + var param = new Parameter(setterAttribut.getDatentyp().erzeugeTiefeKopie(), setterAttribut.getName()); param.getNameProperty().bind(setterAttribut.getNameProperty()); - param.getDatentyp().getTypNameProperty() - .bind(setterAttribut.getDatentyp().getTypNameProperty()); - this.parameterListe = FXCollections - .unmodifiableObservableList(FXCollections.observableArrayList(param)); + param.getDatentyp().getTypNameProperty().bind(setterAttribut.getDatentyp().getTypNameProperty()); + this.parameterListe = FXCollections.unmodifiableObservableList(FXCollections.observableArrayList(param)); setterAttribut.setSetter(this); } else { this.rueckgabeTyp = Objects.requireNonNull(rueckgabeTyp); - this.ueberwachePropertyAenderung(this.rueckgabeTyp.getTypNameProperty()); + this.ueberwachePropertyAenderung(this.rueckgabeTyp.getTypNameProperty(), id + "_methode_rueckgabetyp"); this.parameterListe = FXCollections.observableList(new LinkedList<>()); - this.ueberwachePropertyAenderung(this.istStatisch); + this.ueberwachePropertyAenderung(this.istStatisch, id + "_methode_statisch"); } this.sichtbarkeit = new JsonObjectProperty<>(this, "sichtbarkeit", sichtbarkeit); @@ -128,30 +130,25 @@ protected Methode(Modifizierer sichtbarkeit, Datentyp rueckgabeTyp, boolean istS this.setterAttribut = setterAttribut; this.programmiersprache = programmiersprache; - this.ueberwachePropertyAenderung(this.sichtbarkeit); - this.ueberwachePropertyAenderung(this.name); - this.ueberwachePropertyAenderung(this.istAbstrakt); - this.ueberwachePropertyAenderung(this.istFinal); + this.ueberwachePropertyAenderung(this.sichtbarkeit, id + "_methode_sichtbarkeit"); + this.ueberwachePropertyAenderung(this.name, id + "_methode_name"); + this.ueberwachePropertyAenderung(this.istAbstrakt, id + "_methode_abstrakt"); + this.ueberwachePropertyAenderung(this.istFinal, id + "_methode_final"); this.ueberwacheListenAenderung(this.parameterListe); } @JsonCreator - protected Methode( - @JsonProperty("sichtbarkeit") Modifizierer sichtbarkeit, - @JsonProperty("name") String name, + protected Methode(@JsonProperty("sichtbarkeit") Modifizierer sichtbarkeit, @JsonProperty("name") String name, @JsonProperty("rueckgabeTyp") Datentyp rueckgabeTyp, @JsonProperty("parameterListe") List parameterListe, @JsonProperty("getterAttribut") Attribut getterAttribut, - @JsonProperty("setterAttribut") Attribut setterAttribut, - @JsonProperty("istAbstrakt") boolean istAbstrakt, - @JsonProperty("istFinal") boolean istFinal, - @JsonProperty("istStatisch") boolean istStatisch, - @JsonProperty("istGetter") boolean istGetter, - @JsonProperty("istSetter") boolean istSetter, + @JsonProperty("setterAttribut") Attribut setterAttribut, @JsonProperty("istAbstrakt") boolean istAbstrakt, + @JsonProperty("istFinal") boolean istFinal, @JsonProperty("istStatisch") boolean istStatisch, + @JsonProperty("istGetter") boolean istGetter, @JsonProperty("istSetter") boolean istSetter, @JsonProperty("programmiersprache") Programmiersprache programmiersprache) { - this(sichtbarkeit, rueckgabeTyp, istStatisch, istGetter, istSetter, getterAttribut, - setterAttribut, programmiersprache); + this(sichtbarkeit, rueckgabeTyp, istStatisch, istGetter, istSetter, getterAttribut, setterAttribut, + programmiersprache); if (!istGetter && !istSetter && parameterListe != null) { this.parameterListe.addAll(parameterListe); } @@ -166,9 +163,10 @@ protected Methode( // public ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## -// public int getId() { -// return id; -// } + @Override + public List getBeobachterListe() { + return beobachterListe; + } public Modifizierer getSichtbarkeit() { return sichtbarkeit.get(); @@ -273,21 +271,16 @@ public BooleanProperty getIstStatischProperty() { @Override public String toString() { - return "Methode <%s %s %s(%s) {%s %s}>".formatted( - getSichtbarkeit(), - getRueckgabeTyp().getTypName(), - getName(), - getParameterListe().stream() - .map(p -> String.join(" ", p.getDatentyp().getTypName(), p.getName())) + return "Methode <%s %s %s(%s) {%s %s}>".formatted(getSichtbarkeit(), getRueckgabeTyp().getTypName(), getName(), + getParameterListe().stream().map(p -> String.join(" ", p.getDatentyp().getTypName(), p.getName())) .collect(Collectors.joining(", ")), - istAbstrakt() ? " abstract" : "", - istFinal() ? "final " : ""); + istAbstrakt() ? " abstract" : "", istFinal() ? "final " : ""); } @Override public int hashCode() { - return ClassifierUtil.hashAlle(istAbstrakt(), istFinal(), getName(), getParameterListe(), - getRueckgabeTyp(), getSichtbarkeit(), istStatisch(), istGetter(), istSetter()); + return ClassifierUtil.hashAlle(istAbstrakt(), istFinal(), getName(), getParameterListe(), getRueckgabeTyp(), + getSichtbarkeit(), istStatisch(), istGetter(), istSetter()); } @Override @@ -306,19 +299,17 @@ public boolean equals(Object obj) { boolean istAbstraktGleich = istAbstrakt() == m.istAbstrakt(); boolean istFinalGleich = istFinal() == m.istFinal(); boolean nameGleich = Objects.equals(getName(), m.getName()); - boolean parameterListeGleich = ClassifierUtil.pruefeGleichheit( - this.getParameterListe(), m.getParameterListe()); + boolean parameterListeGleich = ClassifierUtil.pruefeGleichheit(this.getParameterListe(), m.getParameterListe()); boolean rueckgabeTypGleich = Objects.equals(getRueckgabeTyp(), m.getRueckgabeTyp()); boolean sichtbarkeitGleich = Objects.equals(getSichtbarkeit(), m.getSichtbarkeit()); boolean statischGleich = this.istStatisch() == m.istStatisch(); boolean getterGleich = this.istGetter() == m.istGetter(); boolean setterGleich = this.istSetter() == m.istSetter(); - boolean programmierspracheGleich = Objects.equals(this.programmiersprache, - m.programmiersprache); + boolean programmierspracheGleich = Objects.equals(this.programmiersprache, m.programmiersprache); - boolean istGleich = istAbstraktGleich && istFinalGleich && nameGleich - && parameterListeGleich && rueckgabeTypGleich && sichtbarkeitGleich - && getterGleich && statischGleich && statischGleich && programmierspracheGleich; + boolean istGleich = istAbstraktGleich && istFinalGleich && nameGleich && parameterListeGleich + && rueckgabeTypGleich && sichtbarkeitGleich && getterGleich && statischGleich && statischGleich + && programmierspracheGleich; log.finest(() -> """ istGleich: %s @@ -331,10 +322,9 @@ public boolean equals(Object obj) { |-- getterGleich: %s |-- setterGleich: %s |-- statischGleich: %s - ╰-- programmierspracheGleich: %s""" - .formatted(istGleich, istAbstraktGleich, istFinalGleich, nameGleich, - parameterListeGleich, rueckgabeTypGleich, sichtbarkeitGleich, - getterGleich, setterGleich, statischGleich, programmierspracheGleich)); + ╰-- programmierspracheGleich: %s""".formatted(istGleich, istAbstraktGleich, istFinalGleich, + nameGleich, parameterListeGleich, rueckgabeTypGleich, sichtbarkeitGleich, getterGleich, setterGleich, + statischGleich, programmierspracheGleich)); return istGleich; } @@ -349,9 +339,8 @@ public Methode erzeugeTiefeKopie() { setterAttributKopie = setterAttribut.erzeugeTiefeKopie(); } - var kopie = new Methode(getSichtbarkeit(), getRueckgabeTyp().erzeugeTiefeKopie(), - istStatisch(), istGetter(), istSetter(), getterAttributKopie, - setterAttributKopie, programmiersprache); + var kopie = new Methode(getSichtbarkeit(), getRueckgabeTyp().erzeugeTiefeKopie(), istStatisch(), istGetter(), + istSetter(), getterAttributKopie, setterAttributKopie, programmiersprache); kopie.setName(getName()); kopie.setzeAbstrakt(istAbstrakt()); kopie.setzeFinal(istFinal()); @@ -365,16 +354,31 @@ public Methode erzeugeTiefeKopie() { return kopie; } - public static Methode erstelleGetter(Attribut attribut, - Programmiersprache programmiersprache) { - return new Methode(Modifizierer.PUBLIC, attribut.getDatentyp(), attribut.istStatisch(), - true, false, attribut, null, programmiersprache); + public static Methode erstelleGetter(Attribut attribut, Programmiersprache programmiersprache) { + return new Methode(Modifizierer.PUBLIC, attribut.getDatentyp(), attribut.istStatisch(), true, false, attribut, + null, programmiersprache); } - public static Methode erstelleSetter(Attribut attribut, - Programmiersprache programmiersprache) { - return new Methode(Modifizierer.PUBLIC, attribut.getDatentyp(), attribut.istStatisch(), - false, true, null, attribut, programmiersprache); + public static Methode erstelleSetter(Attribut attribut, Programmiersprache programmiersprache) { + return new Methode(Modifizierer.PUBLIC, attribut.getDatentyp(), attribut.istStatisch(), false, true, null, + attribut, programmiersprache); + } + + @Override + public void close() throws Exception { + log.finest(() -> this + " leere Parameter"); + for(var param : parameterListe) { + param.close(); + } + try { + parameterListe.clear(); + } catch (Exception e) { + // ignorieren fuer Empty List + } + log.finest(() -> this + " leere listeners"); + beobachterListe.clear(); + getterAttribut = null; + setterAttribut = null; } // protected ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## diff --git a/src/main/java/io/github/aid_labor/classifier/uml/eigenschaften/Parameter.java b/src/main/java/io/github/aid_labor/classifier/uml/eigenschaften/Parameter.java index b0adf70..52a3968 100644 --- a/src/main/java/io/github/aid_labor/classifier/uml/eigenschaften/Parameter.java +++ b/src/main/java/io/github/aid_labor/classifier/uml/eigenschaften/Parameter.java @@ -6,9 +6,12 @@ package io.github.aid_labor.classifier.uml.eigenschaften; +import java.util.LinkedList; +import java.util.List; import java.util.Objects; import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import io.github.aid_labor.classifier.basis.ClassifierUtil; @@ -24,23 +27,29 @@ public class Parameter extends EditierbarBasis implements EditierbarerBeobachter // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // * Klassenattribute * // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - + + private static long naechsteId = 0; + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // * Klassenmethoden * // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - + // ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## // # # // # Instanzen # // # # // ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## - + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // * Attribute * // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * private final JsonStringProperty name; private final Datentyp datentyp; + @JsonIgnore + private final List beobachterListe; + @JsonIgnore + private final long id; // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // * Konstruktoren * @@ -50,22 +59,28 @@ public class Parameter extends EditierbarBasis implements EditierbarerBeobachter public Parameter(@JsonProperty("datentyp") Datentyp datentyp, @JsonProperty("name") String name) { this.datentyp = Objects.requireNonNull(datentyp); this.name = new JsonStringProperty(name); + this.beobachterListe = new LinkedList<>(); + this.id = naechsteId++; - this.ueberwachePropertyAenderung(datentyp.getTypNameProperty()); - this.ueberwachePropertyAenderung(this.name); + this.ueberwachePropertyAenderung(datentyp.getTypNameProperty(), id + "_parameter_typ"); + this.ueberwachePropertyAenderung(this.name, id + "_parameter_name"); } public Parameter(Datentyp datentyp) { this(datentyp, ""); } - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // * Getter und Setter * // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // public ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## + @Override + public List getBeobachterListe() { + return beobachterListe; + } + public String getName() { return name.get(); } @@ -113,13 +128,17 @@ public boolean equals(Object obj) { return false; } Parameter other = (Parameter) obj; - return Objects.equals(getDatentyp(), other.getDatentyp()) - && Objects.equals(getName(), other.getName()); + return Objects.equals(getDatentyp(), other.getDatentyp()) && Objects.equals(getName(), other.getName()); } - + public Parameter erzeugeTiefeKopie() { - var kopie = new Parameter(getDatentyp().erzeugeTiefeKopie(), getName()); - return kopie; + return new Parameter(getDatentyp().erzeugeTiefeKopie(), getName()); + } + + @Override + public void close() throws Exception { + log.finest(() -> this + " leere listener"); + beobachterListe.clear(); } // protected ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## diff --git a/src/main/java/io/github/aid_labor/classifier/uml/klassendiagramm/UMLBasisElement.java b/src/main/java/io/github/aid_labor/classifier/uml/klassendiagramm/UMLBasisElement.java index 1390fb1..e70c287 100644 --- a/src/main/java/io/github/aid_labor/classifier/uml/klassendiagramm/UMLBasisElement.java +++ b/src/main/java/io/github/aid_labor/classifier/uml/klassendiagramm/UMLBasisElement.java @@ -6,6 +6,9 @@ package io.github.aid_labor.classifier.uml.klassendiagramm; +import java.lang.reflect.Modifier; +import java.util.LinkedList; +import java.util.List; import java.util.Objects; import com.fasterxml.jackson.annotation.JsonCreator; @@ -31,12 +34,8 @@ * @author Tim Muehle * */ -@JsonSubTypes({ - @JsonSubTypes.Type(value = UMLKlassifizierer.class), - @JsonSubTypes.Type(value = UMLKommentar.class) -}) -abstract class UMLBasisElement extends EditierbarBasis - implements UMLDiagrammElement, EditierBeobachter { +@JsonSubTypes({ @JsonSubTypes.Type(value = UMLKlassifizierer.class), @JsonSubTypes.Type(value = UMLKommentar.class) }) +abstract class UMLBasisElement extends EditierbarBasis implements UMLDiagrammElement, EditierBeobachter { // private static final Logger log = Logger.getLogger(UMLBasisElement.class.getName()); public static class Position { @@ -136,12 +135,12 @@ public void set(Position position) { this.setBreite(position.getBreite()); this.setHoehe(position.getHoehe()); } - + @Override public int hashCode() { return ClassifierUtil.hashAlle(breite, hoehe, x, y); } - + @Override public boolean equals(Object obj) { if (this == obj) { @@ -178,7 +177,10 @@ public boolean equals(Object obj) { // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * private final Position position; - @JsonIgnore private long id; + @JsonIgnore + private long id; + @JsonIgnore + private final List beobachterListe; // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // * Konstruktoren * @@ -186,20 +188,17 @@ public boolean equals(Object obj) { public UMLBasisElement() { this.position = new Position(10, 10, -1, -1, this); - this.ueberwachePropertyAenderung(this.position.x); - this.ueberwachePropertyAenderung(this.position.y); - this.ueberwachePropertyAenderung(this.position.hoehe); - this.ueberwachePropertyAenderung(this.position.breite); + this.beobachterListe = new LinkedList<>(); + this.ueberwachePropertyAenderung(this.position.x, getId() + "_x_position"); + this.ueberwachePropertyAenderung(this.position.y, getId() + "_y_position"); + this.ueberwachePropertyAenderung(this.position.hoehe, getId() + "_hoehe"); + this.ueberwachePropertyAenderung(this.position.breite, getId() + "_breite"); } @JsonCreator public UMLBasisElement(Position position) { - this.position = new Position(position.getX(), position.getY(), position.getHoehe(), - position.getBreite(), this); - this.ueberwachePropertyAenderung(this.position.x); - this.ueberwachePropertyAenderung(this.position.y); - this.ueberwachePropertyAenderung(this.position.hoehe); - this.ueberwachePropertyAenderung(this.position.breite); + this(); + position.set(position); } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * @@ -223,6 +222,11 @@ public void setId(long id) { this.id = id; } + @Override + public List getBeobachterListe() { + return beobachterListe; + } + // protected ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## // package ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## @@ -245,6 +249,23 @@ public void verarbeiteEditierung(EditierBefehl editierung) { informiere(editierung); } + @Override + public void close() throws Exception { + log.finest(() -> this + " leere editierBeobachter"); + beobachterListe.clear(); + + for(var attribut : this.getClass().getDeclaredFields()) { + try { + if (!Modifier.isStatic(attribut.getModifiers())) { + attribut.setAccessible(true); + attribut.set(this, null); + } + } catch (Exception e) { + // ignore + } + } + } + // protected ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## // package ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## diff --git a/src/main/java/io/github/aid_labor/classifier/uml/klassendiagramm/UMLDiagrammElement.java b/src/main/java/io/github/aid_labor/classifier/uml/klassendiagramm/UMLDiagrammElement.java index 17f71a9..83eed35 100644 --- a/src/main/java/io/github/aid_labor/classifier/uml/klassendiagramm/UMLDiagrammElement.java +++ b/src/main/java/io/github/aid_labor/classifier/uml/klassendiagramm/UMLDiagrammElement.java @@ -32,7 +32,7 @@ fieldVisibility = Visibility.ANY ) // @formatter:on -public interface UMLDiagrammElement extends Editierbar { +public interface UMLDiagrammElement extends Editierbar, AutoCloseable { String getName(); diff --git a/src/main/java/io/github/aid_labor/classifier/uml/klassendiagramm/UMLKlassifizierer.java b/src/main/java/io/github/aid_labor/classifier/uml/klassendiagramm/UMLKlassifizierer.java index bf45344..c3639ac 100644 --- a/src/main/java/io/github/aid_labor/classifier/uml/klassendiagramm/UMLKlassifizierer.java +++ b/src/main/java/io/github/aid_labor/classifier/uml/klassendiagramm/UMLKlassifizierer.java @@ -6,6 +6,7 @@ package io.github.aid_labor.classifier.uml.klassendiagramm; +import java.lang.reflect.Modifier; import java.util.LinkedList; import java.util.List; import java.util.Objects; @@ -84,11 +85,11 @@ public UMLKlassifizierer(KlassifiziererTyp typ, Programmiersprache programmiersp this.attribute.addListener(new ListenUeberwacher<>(this.attribute, this)); this.methoden.addListener(new ListenUeberwacher<>(this.methoden, this)); - this.ueberwachePropertyAenderung(this.name); - this.ueberwachePropertyAenderung(this.paket); - this.ueberwachePropertyAenderung(this.typ); - this.ueberwachePropertyAenderung(this.superklasse); - this.ueberwachePropertyAenderung(this.interfaces); + this.ueberwachePropertyAenderung(this.name, getId() + "_klassifizierername"); + this.ueberwachePropertyAenderung(this.paket, getId() + "_paket"); + this.ueberwachePropertyAenderung(this.typ, getId() + "_klassifizierertyp"); + this.ueberwachePropertyAenderung(this.superklasse, getId() + "_superklasse"); + this.ueberwachePropertyAenderung(this.interfaces, getId() + "_interfaces"); ueberwacheGetterUndSetter(); } @@ -126,6 +127,13 @@ protected UMLKlassifizierer( attribut.setGetter(getter); int index = methoden.indexOf(methode); methoden.set(index, getter); + for (var m : mList) { + try { + m.close(); + } catch (Exception e) { + // + } + } } } if (attribut.hatSetter()) { @@ -142,6 +150,13 @@ protected UMLKlassifizierer( attribut.setSetter(setter); int index = methoden.indexOf(methode); methoden.set(index, setter); + for (var m : mList) { + try { + m.close(); + } catch (Exception e) { + // + } + } } } } @@ -329,6 +344,31 @@ public UMLKlassifizierer erzeugeTiefeKopie() { return kopie; } + @Override + public void close() throws Exception { + log.finest(() -> this + " leere inhalt"); + for (var attribut : attribute) { + attribut.close(); + } + for (var methode : methoden) { + methode.close(); + } + methoden.clear(); + attribute.clear(); + super.close(); + + for(var attribut : this.getClass().getDeclaredFields()) { + try { + if (!Modifier.isStatic(attribut.getModifiers())) { + attribut.setAccessible(true); + attribut.set(this, null); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + } + // protected ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## // package ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## diff --git a/src/main/java/io/github/aid_labor/classifier/uml/klassendiagramm/UMLKommentar.java b/src/main/java/io/github/aid_labor/classifier/uml/klassendiagramm/UMLKommentar.java index 93810fe..9b4f361 100644 --- a/src/main/java/io/github/aid_labor/classifier/uml/klassendiagramm/UMLKommentar.java +++ b/src/main/java/io/github/aid_labor/classifier/uml/klassendiagramm/UMLKommentar.java @@ -65,12 +65,11 @@ public class UMLKommentar extends UMLBasisElement { public UMLKommentar() { super(new Position()); this.inhaltProperty = new JsonStringProperty(this, "inhalt", ""); - this.ueberwachePropertyAenderung(this.inhaltProperty); + this.ueberwachePropertyAenderung(this.inhaltProperty, getId() + "_inhalt"); } @JsonCreator - public UMLKommentar(@JsonProperty("inhalt") String inhalt, - @JsonProperty("position") Position position) { + public UMLKommentar(@JsonProperty("inhalt") String inhalt, @JsonProperty("position") Position position) { this(); this.inhaltProperty.set(inhalt); this.getPosition().set(position);