Dynamiczne metody?

0

Witam,

Mam następujący problem:

Mam model dto, który wygląda mniej więcej tak:

public class Something {

	private Integer id;
	private String name;
	private List<SomeObject> someObjects;
}

I ten ta lista w środku zawiera kolejny model z kolejną listą kolejnego obiektu, który też ma jakąś listę.

Mam 3 poziomy na których odbywa się mapowanie pól z entities, dociąganie danych itp.
Więc mam konwerter, który zawiera konwerter, który zawiera kolejny konwerter.

I teraz klucz programu.
Chciałbym jakoś dynamicznie zmieniać jedną metodę, która jest wywoływana w tym najniższym konwerterze, konkretnie jest to spring repository.
W zależności od odpowiedniego pparametru/requestu cokolwiek chcialbym wywolywac inną metodę spring repository np. findById, findByName, cokolwiek itp.

Do konwertowania używam interfacu Guava Function:
Function<A, B>, which has the single method B apply(A input).

0

Musisz jako parametr wysyłać funkcje T->E a zwracać z konwertera E i wszystko mieć na genericach, inaczej nie da rady.

0

O takie coś Tobie chodzi? Z opisu trochę ciężko wywnioskować:

import javafx.util.Pair;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Predicate;

public class RequestDispatchingService {

    private Map<Pair<Class, Class>, Function> handlersMap;

    public void initialize(){
        handlersMap = new HashMap<Pair<Class, Class>, Function>();
        Function<String, Integer> stringToIntegerMapper = (s -> Integer.parseInt(s));
        Function<Double, Integer> doubleIntegerMapper = (d -> d.intValue());

        handlersMap.put(new Pair<>(String.class, Integer.class), stringToIntegerMapper);
        handlersMap.put(new Pair<>(Double.class, Integer.class), doubleIntegerMapper);
    }

    public <T, R> R map(T source, Class<R> resultClass){
        Optional<Pair<Class, Class>> optionalResult = handlersMap.keySet()
                .stream()
                .filter(pair ->
                        pair.getKey().equals(source.getClass()) &&
                                pair.getValue().equals(resultClass))
                .findAny();

        Function function = handlersMap.get(
                optionalResult.orElseThrow(
                        () -> new IllegalArgumentException("No handler found")));

        Object result = function.apply(source);

        return (R) result;
    }

    public static void main(String[] args){
        RequestDispatchingService service = new RequestDispatchingService();
        service.initialize();

        Integer doubleResult = service.map(2.0, Integer.class);
        Integer stringResult = service.map("3", Integer.class);

        System.out.println(doubleResult);
        System.out.println(stringResult);
    }
}
0

Dzieki. Pomysle jak do tego zowu usiade. Ale czuje, ze to bedzie najsensowniejsze rozwiazanie.

Ja myslalem o tym czy nie powinienem jakos zrefaktoryzowac tego kodu.

Inne pomysly jakie mialem to:

  • pomyslec czy daloby rade wykotzystac tu aspekty
  • przerobic te konwertery na 'puste' a newralgiczne pozycje ustawic jakimis seterami
  • na pewno nie da sie tego jakos elegancko wstrzykiwac ? ;)
0

Jest jeszcze składanie funkcji, tj:

        Function<Double, String> doubleStringFunction = (d -> d.toString());
        Function<String, Integer> stringIntegerFunction = (s -> Integer.parseInt(s));
        
        Function<Double, Integer> doubleIntegerFunction = doubleStringFunction.andThen(stringIntegerFunction);
        
        Integer i = doubleIntegerFunction.apply(2.0);

I w teorii mógłbyś zrobić coś w ten deseń:

private Map<String, Function<OddObject, ResultObject>> konwerter3Map;

public ResultObject convert(SomeObject object, String request){
	Function<SomeObject, SomeOtherObject> konwerter1 = // zakładam, że wiesz co z tym chcesz zrobić
	Function<SomeOtherObject, OddObject> konwerter2 = // tutaj też powinieneś wiedzieć, co chcesz osiągnąć

	Function<OddObject, ResultObject> konwerter3 = map.get(request);
	
	return konwerter1.andThen(konwerter2).andThen(konwerter3).apply(object);
}

Zakładam oczywiście, że znasz typ wejściowy i wynikowy obiektu.

0

Ogólnie to wszystkie konwertery są ok, tylko na samym spodzie jest jeden predykat powinien sie zmieniac.
Wszystko będzie mapowane na ten sam model danych, tyle, że metoda wyszukujaca dane w bazie będzie zwracać odpowiednie wartości, w zależności od jakiegoś ifa.
Takie filtrowanie, które chcialbym zrobic na bazie danych, zamiast np. filtrowac to za pomoca guavy.

Nie wiem czy rozsądniejszym i czytelniejszym rozwiązanie nie byłoby przerobić te konwertery na 'puste' i będą one ustawiac tylko rzeczy, które będą stałe.
A pozsotałe rzeczy uzupelniac dodatkowym serwisem.

1 użytkowników online, w tym zalogowanych: 0, gości: 1