2016-04-04 9 views
14

Per mappare un certo oggetto con mapstruct ho bisogno di un po 'di post-elaborazione personalizzato che ha bisogno di un ulteriore parametro per fare è un lavoro:Mappa una collezione con il parametro con mapstruct

@Mapper 
public abstract class AlertConfigActionMapper { 

    @Mappings({ @Mapping(target = "label", ignore = true)}) 
    public abstract AlertConfigActionTO map (AlertConfigAction action, Locale userLanguage); 

    @AfterMapping 
    public void setLabel (AlertConfigAction action, @MappingTarget AlertConfigActionTO to, Locale userLanguage) { 
     for (AlertConfigActionLabel label : action.getAlertConfigActionLabels()) { 
      if (label.getLanguage().equals(userLanguage)) { 
       to.setLabel(label.getLabel()); 
       break; 
      } else if (label.getLanguage().equals(Locale.ENGLISH)) { 
       to.setLabel(label.getLabel()); 
      } 
     } 

    } 
} 

Questo funziona bene. Il problema inizia quando aggiungo seguente metodo a questo mapper:

public abstract ArrayList<AlertConfigActionTO> mapList (List<AlertConfigAction> actions, Locale userLanguage); 

ho bisogno di passare questo parametro (LinguaUtente) così, ma mapstruct sembra 'abbattere', in questo caso: mi genera seguente codice per questa parte (che dà naturalmente un errore di compilazione):

@Override 
public List<AlertConfigActionTO> mapList(List<AlertConfigAction> actions, Locale userLanguage) { 
    if (actions == null && userLanguage == null) { 
     return null; 
    } 

    List<AlertConfigActionTO> list = new List<AlertConfigActionTO>(); 

    return list; 
} 

sono sicuro che è legato al parametro poiché se lo cancello (da tutti i metodi di mappatura), allora il metodo di lista mappe viene generato correttamente.

Cosa è necessario fare per consentire i parametri personalizzati in questo caso?

risposta

7

Quello che descrivi non è possibile (ancora). Potresti aprire una richiesta di funzionalità nel nostro issue tracker? Dovremmo fornire i mezzi per indicare i parametri come una sorta di "contesto" che viene trasmesso allo stack delle chiamate.

Come soluzione per il momento, è possibile dare un'occhiata all'utilizzo di uno ThreadLocal che è stato impostato prima di richiamare la routine di mappatura e a cui si accede nella personalizzazione after-mapping. Non è elegante - e devi assicurarti di pulire il thread locale per evitare perdite di memoria - ma dovrebbe fare il trucco.

+0

Grazie, creato https://github.com/mapstruct/mapstruct/issues/809 –

+0

FYI: Poiché avevo già creato una facciata come wrapper per i mappatori effettivi (per disaccoppiare il codice più dall'attuale implementazione del mapper) Ho semplicemente scorrere l'elenco di singoli elementi (AlertConfigAction) e mapparli singolarmente. Ogni volta che questa funzione è supportata, posso semplicemente aggiornare la facciata. –

1

Non credo sia possibile. Almeno non così. Il problema è che si prepara l'interfaccia/classe astratta - e il resto è fatto dal motore. E quel motore si aspetta metodi con un parametro ... Ci sono decoratori, ma vanno allo stesso modo. Proverò ad iniettare il linguaggio. Crea bean, contrassegnalo come sessione con scope e scoprilo. Con Spring, dovresti usare ScopedProxyMode per quello ... Non sono sicuro di quello che va con CDI.

Un'altra opzione è più soluzione, quindi soluzione - forse che AlertConfigAction può passare tali informazioni?

Problemi correlati