Folgende Abfrage dynamisch programmieren?

Bitte aktiviere JavaScript!
Hallo zusammen,

ich habe folgenden Code. Dieser Code prüft das Feld von einem RuleConditionComponent-Objekt ab (ConditionState).
1) Heißt ruleConditionComponent.getFieldName() dem Feldname (in diesem Fall "NAME")
2) Danach welchen (ConditionState) das Feld hat.

Derzeit habe ich von einer Klasse diese Abfrage zig Mal (für jedes Feld), also statt "NAME", dann "EMAIL" usw.
Die Frage ist nun, kann man diesen Code irgendwie dynamisch programmieren?
Also:
a) eine Schleife über alle Felder einer Klasse
b) Prüfen, ob das Feld so heißt, wie ruleConditionComponent.getFieldName()
c) ruleConditionComponent.getState().equals(RuleConditionComponent.ConditionState.EQUAL.toString() -> Dieser Code bleibt dann eben bestehen für jeden Zustand...
c) Wenn b) richtig ist, dann von diesem Feld den Wert nehmen und mit dem Wert von ruleConditionComponent.getValue() vergleichen

-> Also was ich bräuchte:
a) Von newObjectForCheck.getRequest().getName() -> Den getName dynamisch halten und bei Schleifendurchlauf die nächste Property der Klasse nehmen...
b) Request.EntityField.NAME.getFieldName() -> Hier habe ich für jede Propertie einen String angelegt bisher, der den Namen der Property in einen String schreibt. Dies müsste ebenfalls irgendwie automatisch gehalten werden. Gibt es hier nicht Annotationen über der Property selbst? (sowas habe ich schon Mal gesehn)


Java:
    ///////////////////
        // NAME
        ///////////////////
        if (ruleConditionComponent.getFieldName()
                .equals(Request.ENTITY_NAME_SPACE + Request.EntityField.NAME.getFieldName())) {

            if (newObjectForCheck.getRequest().getName() == null)
                return false;

            if (ruleConditionComponent.getState().equals(RuleConditionComponent.ConditionState.EQUAL.toString())) {
                if (newObjectForCheck.getRequest().getName().equalsIgnoreCase(ruleConditionComponent.getValue())) {
                    return true;
                }
            }

            if (ruleConditionComponent.getState().equals(RuleConditionComponent.ConditionState.NOT_EQUAL.toString())) {
                if (!newObjectForCheck.getRequest().getName().equalsIgnoreCase(ruleConditionComponent.getValue())) {
                    return true;
                }
            }

            if (ruleConditionComponent.getState().equals(RuleConditionComponent.ConditionState.CONTAINS.toString())) {
                if (newObjectForCheck.getRequest().getName().toLowerCase()
                        .contains(ruleConditionComponent.getValue().toLowerCase())) {
                    return true;
                }
            }

            if (ruleConditionComponent.getState()
                    .equals(RuleConditionComponent.ConditionState.NOT_CONTAINS.toString())) {
                if (!newObjectForCheck.getRequest().getName().toLowerCase()
                        .contains(ruleConditionComponent.getValue().toLowerCase())) {
                    return true;
                }
            }
        }
Danke für die Hilfe
 
Also generell ist dies über Reflection denkbar. Aber das sehe ich nicht als so Sinnvoll an.

Ich hatte in der Vergangenheit schon Lösungen, bei denen ich die Daten selbst dynamisch halten musste und da habe ich dann Daten z.B. in einer Map abgelegt. Dies wäre aber ein komplett anderes Design, das schon recht speziell ist und das wird bei dir auch nicht unbedingt passen.

Was evtl. bei Dir helfen könnte, wäre ggf. eine Map, welche zu jedem feld Namen dann den Getter speichert (Oder was Du sonst noch so brauchst). Ein kleines, minimales Beispiel dafür wäre:
Code:
import java.util.HashMap;
import java.util.Map;
import java.util.function.Supplier;

public class Example {
    private String someField;
    public String getSomeField() { return someField; }
    public void setSomeField(String someField) {this.someField = someField; }


    public static void main(String[] args) {
        Example test = new Example();
        test.setSomeField("Test Value");

        Map<String, Supplier<String>> fields = new HashMap<>();
        fields.put("someField", test::getSomeField);

        System.out.println(fields.get("someField").get());
    }
}
Also Example soll einfach par Felder mit Getter/Setter haben, hier nur ein einziges "someField".
Zugriff auf Properties über den Namen:
a) Map, in dem die Getter zu jedem Feld gespeichert werden (Supplier<T>).
b) Die Map muss natürlich gefüllt werden, das schreibt man dann an eine Stelle.
c) Da, wo es gebraucht wird, kann dann auf die Getter zugegriffen werden.

Es lohnt sich, java.util.function näher anzusehen, denn da gibt es viele nützliche Dinge, denn ggf. will man ja nicht nur den Getter sondern auch den Setter oder eine andere Funktion speichern...
 
Aus ConditionState machst du ein Predicate, dann reduzieren sich die vier ifs schon mal auf eins.

ruleConditionComponent kannst du eine Function<DeinObject, IrgendeinTyp> geben, die dir aus dem Object das Feld zurückgibt.


Ergibt dann etwa:
Java:
T field = ruleConditionComponent.getter.apply(newObjectForCheck); //Entspricht dem Getter-Aufruf
return ruleConditionComponent.state.test(field); entspricht deinen 4 ifs
Das ganze kann man dann noch in ruleConditionComponent auslagern, sodass man am Ende ein einzelnen ruleConditionComponent.test(newObjectForCheck) hat.


EDIT: das ganze kombiniert man sinnvollerweise mit @kneitzel's Map, falls man das ganze irgendwie serialisieren muss, damit hast du dann noch die Abbildung String<->Getter, die du brauchst, um ruleConditionComponent in Menschenlesbarer Form zu speichern.
 
Danke...

Map<String, Supplier<String>> fields = new HashMap<>();
fields.put("someField", test::getSomeField);
}
}
[/code]
Was macht denn "test::getSomeField" ? Kenne diese Syntax nicht...

Also im Moment habe ich mir ein Enum angelegt für die verschiedenen Properties:

Java:
public enum EntityField {

        NAME("NAME", "Name"), //
        
        ; //

        /////////////////////////

        private String fieldName;
        private String languageName;

        /////////////////////////

        private EntityField(String fieldName, String languageName) {
            this.fieldName = fieldName;
            this.languageName = languageName;
        }

        public String getFieldName() {
            return fieldName;
        }

        public void setFieldName(String fieldName) {
            this.fieldName = fieldName;
        }

        public String getLanguageName() {
            return languageName;
        }

        public void setLanguageName(String languageName) {
            this.languageName = languageName;
        }

    }
 
Ich kann nicht verstehen welches Konzept hinter so etwas stehen soll. Ich habe noch nie so etwas gebraucht. Klar kann man alles machen aber ich sehe bei sowas immer ein grundsätzliches Designproblem der Software viel weiter vorher.
 
Ich kann nicht verstehen welches Konzept hinter so etwas stehen soll. Ich habe noch nie so etwas gebraucht. Klar kann man alles machen aber ich sehe bei sowas immer ein grundsätzliches Designproblem der Software viel weiter vorher.
z.B. Filtern nach vom Benutzer ausgewählten Bedingungen.
Im einfachsten Fall kann der Nutzer das Feld angeben und den Inhalt vergleichen, schon ist man bei dem da oben.
 
Tolle Useability. Da würde ich ein Popup machen mit allen Feldern zum selektieren.
Meine Aussage ist keine zur Usabiility oder zur konkreten Umsetzung.
Deine Umsetzung mit Popup und Feld selektieren ist einfach nur eine Umsetzung von "Nutzer kann das Feld angeben", eben das passendes Feld selektieren.
Für sinnvolles Filtern ist das aber zu wenig, das erlaubt nur sowas wie "Alle Nutzer mit Nutzernamen"

Im Hinterkopf hatte ich dabei Dropdown für Feld, Dropdown für Art des Vergleichs (!=, ==, contains, ...) und Feld für die Eingabe, womit verglichen werden soll. Erlaubt Abfragen wie "Alle Nutzer mit Nutzername gleich Thallius".
Dafür braucht man mindestens diese drei Möglichkeiten auch irgendwie in der UI, Umsetzungen gibt es da viele, eine andere wäre zB, das der Nutzer das direkt als String eingibt, in SQL-ähnlicher Syntax, wie zb google oder github das erlauben.
In jedem Fall muss man aber irgendwie drei Dinge angeben können (wobei sich das Einschränken lässt auf ein oder zwei, je nach Datentyp, zB bei Booleans).


Schon biste das Problem wieder los....
Mit einem "Popup, in dem man Felder selektieren kann", hast du in keinster Weise die Logik dahinter modelliert und umgesetzt - das Problem ist also noch genauso vorhanden.

Wie würdest du das ganze denn modellieren? Ich würde mich wirklich über eine einfachere Variante als die bisherigen drei hier im Thread freuen...
 
Passende Stellenanzeigen aus deiner Region:

Oben