@ -1,37 +1,34 @@
package app.navigation ;
import app.components.label.ValidationLabel ;
import app.data.entity.Match ;
import app.data.entity.Matchday ;
import app.data.entity.Season ;
import app.data.service.MatchService ;
import app.data.service.MatchdayService ;
import app.data.service.SeasonService ;
import com.vaadin.flow.component.* ;
import com.vaadin.flow.component.button.Button ;
import com.vaadin.flow.component.html.Label ;
import com.vaadin.flow.component.icon.Icon ;
import com.vaadin.flow.component.icon.VaadinIcon ;
import com.vaadin.flow.component.AbstractField ;
import com.vaadin.flow.component.HasValue ;
import com.vaadin.flow.component.UI ;
import com.vaadin.flow.component.select.Select ;
import com.vaadin.flow.router.BeforeEvent ;
import com.vaadin.flow.router.HasUrlParameter ;
import com.vaadin.flow.router.WildcardParameter ;
import org.springframework.beans.factory.annotation.Autowired ;
import org.springframework.lang.NonNull ;
import org.springframework.lang.Nullable ;
import org.springframework.stereotype.Component ;
import java.util.ArrayList ;
import java.util.List ;
import java.util.Map ;
import java.util.Optional ;
@SuppressWarnings ( "OptionalUsedAsFieldOrParameterType" )
public class Navigation implements HasUrlParameter < String > {
/ / TODO : show dropdown menus also for invalid URLs ( with content that fits the situation )
private final String route ;
private final boolean onlyMatchdaysWithActivity ;
private final List < Runnable > runnablesToBeRunAfterSeasonSelection = new ArrayList < > ( ) ;
private final List < Runnable > runnablesToBeRunAfterMatchdaySelection = new ArrayList < > ( ) ;
private final List < Runnable > runnablesToBeRunAfterMatchSelection = new ArrayList < > ( ) ;
private String route ;
private boolean onlyMatchdaysWithActivity ;
private final List < Runnable > runnablesToBeRunAfterSelection = new ArrayList < > ( ) ;
private final SeasonService seasonService ;
private final MatchdayService matchdayService ;
@ -45,113 +42,148 @@ public class Navigation implements HasUrlParameter<String> {
private final Select < Matchday > matchdaySelect = new Select < > ( ) ;
private final Select < Match > matchSelect = new Select < > ( ) ;
private String seasonParam ;
private String matchdayParam ;
private String matchParam ;
private boolean autoselectSeason = false ;
private boolean autoselectMatchday = false ;
private boolean autoselectMatch = false ;
private boolean seasonEnabled = false ;
private boolean matchdayEnabled = false ;
private boolean matchEnabled = false ;
private final Label invalidUrlLabel = new Label ( ) ;
private final Button prevMatchdayButton = new Button ( new Icon ( VaadinIcon . ARROW_LEFT ) ) ;
private final Button nextMatchdayButton = new Button ( new Icon ( VaadinIcon . ARROW_RIGHT ) ) ;
private final ValidationLabel validationLabel = new ValidationLabel ( ) ;
public Navigation ( String route ,
@Autowired SeasonService seasonService ,
public Navigation ( @Autowired SeasonService seasonService ,
@Autowired MatchdayService matchdayService ,
@Autowired MatchService matchService ) {
this ( route , seasonService , matchdayService , matchService , false ) ;
}
public Navigation ( String route ,
@Autowired SeasonService seasonService ,
@Autowired MatchdayService matchdayService ,
@Autowired MatchService matchService ,
boolean onlyMatchdaysWithActivity ) {
this . route = route ;
this . seasonService = seasonService ;
this . matchdayService = matchdayService ;
this . matchService = matchService ;
this . onlyMatchdaysWithActivity = onlyMatchdaysWithActivity ;
fillSeasonSelectWithData ( ) ;
seasonSelect . addValueChangeListener ( seasonSelectValueChangeListener ( ) ) ;
matchdaySelect . addValueChangeListener ( matchdaySelectValueChangeListener ( ) ) ;
matchSelect . addValueChangeListener ( matchSelectValueChangeListener ( ) ) ;
}
public void setAutoselectSeason ( boolean autoselectSeason ) {
this . autoselectSeason = autoselectSeason ;
public void setRoute ( String route ) {
this . route = route ;
}
public void setOnlyMatchdaysWithActivity ( boolean onlyMatchdaysWithActivity ) {
this . onlyMatchdaysWithActivity = onlyMatchdaysWithActivity ;
}
public void setSeasonEnabled ( boolean seasonEnabled ) {
this . seasonEnabled = seasonEnabled ;
}
public void setMatchdayEnabled ( boolean matchdayEnabled ) {
this . matchdayEnabled = matchdayEnabled ;
}
public void setMatchEnabled ( boolean matchEnabled ) {
this . matchEnabled = matchEnabled ;
}
public void addRunnableToBeRunAfterSelection ( Runnable runnable ) {
runnablesToBeRunAfterSelection . add ( runnable ) ;
}
public boolean isSeasonEnabled ( ) {
return seasonEnabled ;
}
public void setAutoselectMatchday ( boolean autoselectMatchday ) {
this . autoselectMatchday = autoselectMatchday ;
public boolean isMatchdayEnabled ( ) {
return matchdayEnabled ;
}
public void setAutoselectMatch ( boolean autoselectMatch ) {
this . autoselectMatch = autoselectMatch ;
public boolean isMatchEnabled ( ) {
return matchEnabled ;
}
private String getRoute ( ) {
if ( route ! = null ) return route ;
throw new IllegalStateException ( "Route must be set!" ) ;
}
private void updateUrl ( ) {
String seasonParam = null ;
String matchdayParam = null ;
String matchParam = null ;
if ( seasonEnabled ) seasonParam = seasonSelect . getValue ( ) . toString ( ) ;
if ( matchdayEnabled ) matchdayParam = matchdaySelect . getValue ( ) . toString ( ) ;
if ( matchEnabled ) matchParam = matchdaySelect . getValue ( ) . toString ( ) ;
String params = NavigationUtils . getWildcardParam ( seasonParam , matchdayParam , matchParam ) ;
UI . getCurrent ( ) . getPage ( ) . getHistory ( ) . pushState ( null , String . format ( "%s/%s" , route , params ) ) ;
UI . getCurrent ( ) . getPage ( ) . getHistory ( ) . pushState ( null , String . format ( "%s/%s" , getRoute ( ) , params ) ) ;
}
private HasValue . ValueChangeListener < ? super AbstractField . ComponentValueChangeEvent < Select < Season > , Season > > seasonSelectValueChangeListener ( ) {
return seasonChangeEvent - > {
Season newSeason = seasonChangeEvent . getValue ( ) ;
if ( newSeason ! = null ) {
String seasonParam = newSeason . toString ( ) ;
String matchdayParam = null ;
Matchday matchdayInNewSeason = null ;
Matchday matchdayInOldSeason = matchdaySelect . getValue ( ) ;
if ( matchdayInOldSeason ! = null ) {
matchdayParam = matchdayInOldSeason . toString ( ) ;
matchdayInNewSeason = getMatchdayFromParam ( matchdayParam , newSeason ) ;
}
matchdayParam = matchdayInNewSeason = = null ? "1" : matchdayParam ;
this . seasonParam = seasonParam ;
this . matchdayParam = matchdayParam ;
this . matchParam = null ;
return event - > {
if ( ! seasonEnabled ) throw new IllegalStateException ( "Cannot select season when it is not enabled!" ) ;
if ( matchdayEnabled ) {
fillMatchdaySelectWithData ( event . getValue ( ) ) ;
autoselectMatchday ( ) ;
return ;
}
runnablesToBeRunAfterSeasonSelection . forEach ( Runnable : : run ) ;
updateUrl ( ) ;
doPostSelectionStuff ( ) ;
} ;
}
private HasValue . ValueChangeListener < ? super AbstractField . ComponentValueChangeEvent < Select < Matchday > , Matchday > > matchdaySelectValueChangeListener ( ) {
return matchdayChangeEvent - > {
Matchday matchday = matchdayChangeEvent . getValue ( ) ;
if ( matchday = = null ) {
matchParam = null ;
} else {
matchdayParam = matchday . toString ( ) ;
fillMatchSelectWithData ( matchday ) ;
return event - > {
if ( ! matchdayEnabled ) throw new IllegalStateException ( "Cannot select matchday when it is not enabled!" ) ;
if ( matchEnabled ) {
fillMatchSelectWithData ( event . getValue ( ) ) ;
autoselectMatch ( ) ;
return ;
}
configureButtons ( ) ;
matchSelect . setValue ( null ) ;
runnablesToBeRunAfterMatchdaySelection . forEach ( Runnable : : run ) ;
updateUrl ( ) ;
doPostSelectionStuff ( ) ;
} ;
}
private HasValue . ValueChangeListener < ? super AbstractField . ComponentValueChangeEvent < Select < Match > , Match > > matchSelectValueChangeListener ( ) {
return matchChangeEvent - > {
Match match = matchChangeEvent . getValue ( ) ;
if ( match = = null ) {
matchParam = null ;
} else {
matchParam = match . toString ( ) ;
}
runnablesToBeRunAfterMatchSelection . forEach ( Runnable : : run ) ;
updateUrl ( ) ;
return event - > {
if ( ! matchEnabled ) throw new IllegalStateException ( "Cannot select match when it is not enabled!" ) ;
doPostSelectionStuff ( ) ;
} ;
}
private void doPostSelectionStuff ( ) {
validationLabel . setValid ( true ) ;
updateUrl ( ) ;
runnablesToBeRunAfterSelection . forEach ( Runnable : : run ) ;
}
private void autoselectSeason ( ) {
if ( ! seasonEnabled ) throw new IllegalStateException ( "This method should not be called when season is not enabled!" ) ;
if ( seasonList . isEmpty ( ) ) {
validationLabel . setText ( "No Seasons in List!" ) ;
validationLabel . setValid ( false ) ;
return ;
}
seasonSelect . setValue ( seasonList . get ( seasonList . size ( ) - 1 ) ) ;
}
private void autoselectMatchday ( ) { / / TODO : add date stuff and choose depending on date instead !
if ( ! matchdayEnabled ) throw new IllegalStateException ( "This method should not be called when matchday is not enabled!" ) ;
if ( matchdayList . isEmpty ( ) ) {
validationLabel . setText ( "No Matchdays in List!" ) ;
validationLabel . setValid ( false ) ;
return ;
}
Matchday matchdayToSelect = matchdayList . get ( 0 ) ;
for ( Matchday matchday : matchdayList ) if ( matchdayService . hasActivity ( matchday ) ) matchdayToSelect = matchday ;
matchdaySelect . setValue ( matchdayToSelect ) ;
}
private void autoselectMatch ( ) {
if ( ! matchEnabled ) throw new IllegalStateException ( "This method should not be called when match is not enabled!" ) ;
if ( matchList . isEmpty ( ) ) {
validationLabel . setText ( "No Matches in List!" ) ;
validationLabel . setValid ( false ) ;
return ;
}
matchSelect . setValue ( matchList . get ( 0 ) ) ;
}
private void fillSeasonSelectWithData ( ) {
seasonList . clear ( ) ;
seasonList . addAll ( seasonService . getAllSeasonsSorted ( ) ) ;
@ -172,212 +204,82 @@ public class Navigation implements HasUrlParameter<String> {
matchSelect . setItems ( matchList ) ;
}
private boolean isMatchDayParamValid ( @NonNull String matchdayParam ) {
return matchdayList . stream ( ) . anyMatch ( matchday - > matchdayParam . equals ( matchday . toString ( ) ) ) ;
}
@Override
public void setParameter ( BeforeEvent event , @WildcardParameter String param ) {
Map < UrlParameterType , String > map = NavigationUtils . getParameterMap ( param ) ;
setParameter ( map . get ( UrlParameterType . SEASON ) , map . get ( UrlParameterType . MATCHDAY ) , map . get ( UrlParameterType . MATCH ) ) ;
Map < UrlParameterType , Optional < String > > map = NavigationUtils . getParameterMap ( param ) ;
navigate ( map . get ( UrlParameterType . SEASON ) , map . get ( UrlParameterType . MATCHDAY ) , map . get ( UrlParameterType . MATCH ) ) ;
}
private boolean paramInvalid ( @Nullable String param ) {
return param = = null | | param . equals ( "" ) ;
}
private void navigate ( Optional < String > seasonParam , Optional < String > matchdayParam , Optional < String > matchParam ) {
if ( ! seasonEnabled ) return ;
Optional < Season > season = getSeasonFromParam ( seasonParam ) ;
if ( season . isPresent ( ) ) seasonSelect . setValue ( season . get ( ) ) ;
else autoselectSeason ( ) ;
private void noMatchFound ( Season season , Matchday matchday ) {
invalidUrlLabel . setText ( String . format ( "No Match found in Matchday %s in Season %s!" , matchday . toString ( ) , season . toString ( ) ) ) ;
}
if ( ! matchdayEnabled ) return ;
Optional < Matchday > matchday = getMatchdayFromParam ( matchdayParam ) ;
if ( matchday . isPresent ( ) ) matchdaySelect . setValue ( matchday . get ( ) ) ;
else autoselectMatchday ( ) ;
private void matchFound ( Match match ) {
matchSelect . setValue ( match ) ;
if ( ! matchEnabled ) return ;
Optional < Match > match = getMatchFromParam ( matchParam ) ;
if ( match . isPresent ( ) ) matchSelect . setValue ( match . get ( ) ) ;
else autoselectMatch ( ) ;
}
private void noMatchdayFound ( Season season ) {
invalidUrlLabel . setText ( String . format ( "No Matchday found in Season %s!" , season . toString ( ) ) ) ;
}
private void autoselectMatch ( Season season , Matchday matchday ) {
Optional < Match > firstMatch = matchService . getFirstMatch ( matchday ) ;
firstMatch . ifPresentOrElse (
this : : matchFound ,
( ) - > noMatchFound ( season , matchday ) ) ;
}
private void matchdayFound ( Season season , Matchday matchday , String matchParam ) {
matchdaySelect . setValue ( matchday ) ;
fillMatchSelectWithData ( matchday ) ;
if ( paramInvalid ( matchParam ) & & autoselectMatch ) {
autoselectMatch ( season , matchday ) ;
private Optional < Season > getSeasonFromParam ( Optional < String > seasonParam ) {
if ( seasonParam . isEmpty ( ) ) {
return Optional . empty ( ) ;
}
return seasonList . stream ( )
. filter ( season - > season . toString ( ) . equals ( seasonParam . get ( ) ) )
. findFirst ( ) ;
}
private void noSeasonFound ( ) {
invalidUrlLabel . setText ( "No Season found!" ) ;
}
private void autoselectMatchday ( Season season , String matchParam ) {
Optional < Matchday > latestMatchday = matchdayService . getLastMatchdayWithActivityOrElseFirstMatchday ( season ) ;
latestMatchday . ifPresentOrElse (
matchday - > matchdayFound ( season , matchday , matchParam ) ,
( ) - > noMatchdayFound ( season ) ) ;
}
private void seasonFound ( Season season , String matchdayParam , String matchParam ) {
seasonSelect . setValue ( season ) ;
fillMatchdaySelectWithData ( season ) ;
if ( paramInvalid ( matchdayParam ) & & autoselectMatchday ) {
autoselectMatchday ( season , matchParam ) ;
private Optional < Matchday > getMatchdayFromParam ( Optional < String > matchdayParam ) {
if ( matchdayParam . isEmpty ( ) ) {
return Optional . empty ( ) ;
}
return matchdayList . stream ( )
. filter ( matchday - > matchday . toString ( ) . equals ( matchdayParam . get ( ) ) )
. findFirst ( ) ;
}
private void autoselectSeason ( String matchdayParam , String matchParam ) {
Optional < Season > latestSeason = seasonService . getLatestSeason ( ) ;
latestSeason . ifPresentOrElse (
season - > seasonFound ( season , matchdayParam , matchParam ) ,
this : : noSeasonFound ) ;
}
private boolean autoselectIfNecessary ( String seasonParam , String matchdayParam , String matchParam ) {
if ( paramInvalid ( seasonParam ) & & autoselectSeason ) {
autoselectSeason ( matchdayParam , matchParam ) ;
return true ;
}
if ( paramInvalid ( matchdayParam ) & & autoselectMatchday ) {
autoselectMatchday ( seasonSelect . getValue ( ) , matchParam ) ;
return true ;
}
if ( paramInvalid ( matchParam ) & & autoselectMatch ) {
autoselectMatch ( seasonSelect . getValue ( ) , matchdaySelect . getValue ( ) ) ;
return true ;
private Optional < Match > getMatchFromParam ( Optional < String > matchParam ) {
if ( matchParam . isEmpty ( ) ) {
return Optional . empty ( ) ;
}
return false ;
return matchList . stream ( )
. filter ( match - > match . toString ( ) . equals ( matchParam . get ( ) ) )
. findFirst ( ) ;
}
public void setParameter ( String seasonParam , String matchdayParam , String matchParam ) {
if ( autoselectIfNecessary ( seasonParam , matchdayParam , matchParam ) ) {
return ;
}
Season season = getSeasonFromParam ( seasonParam ) ;
if ( season ! = null ) {
seasonSelect . setValue ( season ) ;
this . seasonParam = seasonParam ;
fillMatchdaySelectWithData ( season ) ;
} else if ( autoselectSeason ) {
invalidUrlLabel . setText ( String . format ( "Invalid URL! Season \"%s\" does not exist in the database!" , seasonParam ) ) ;
return ;
}
Matchday matchday = getMatchdayFromParam ( matchdayParam ) ;
if ( matchday ! = null ) {
matchdaySelect . setValue ( matchday ) ;
this . matchdayParam = matchdayParam ;
fillMatchSelectWithData ( matchday ) ;
configureButtons ( ) ;
} else if ( autoselectMatchday ) {
String messageExtra = onlyMatchdaysWithActivity ? " or has no games played yet" : "" ;
invalidUrlLabel . setText ( String . format ( "Invalid URL! Matchday \"%s\" in Season \"%s\" does not exist in the database%s!" , matchdayParam , seasonParam , messageExtra ) ) ;
return ;
}
Match match = getMatchFromParam ( matchParam ) ;
if ( match ! = null ) {
matchSelect . setValue ( match ) ;
this . matchParam = matchParam ;
} else if ( autoselectMatch ) {
invalidUrlLabel . setText ( String . format ( "Invalid URL: Match \"%s\" in Matchday \"%s\" in Season \"%s\" does not exist in the database!" , matchParam , matchdayParam , seasonParam ) ) ;
}
}
@Nullable
private Season getSeasonFromParam ( @Nullable String seasonParam ) {
if ( seasonParam = = null ) {
return null ;
}
for ( Season season : seasonList ) {
if ( seasonParam . equals ( season . toString ( ) ) ) {
return season ;
}
}
return null ;
}
@Nullable
private Matchday getMatchdayFromParam ( @Nullable String matchdayParam ) {
return getMatchdayFromParam ( matchdayParam , null ) ;
}
@Nullable
private Matchday getMatchdayFromParam ( @Nullable String matchdayParam , @Nullable Season season ) {
if ( matchdayParam = = null ) {
return null ;
}
List < Matchday > matchdayList = season = = null ? this . matchdayList : matchdayService . getMatchdaysSorted ( season ) ;
for ( Matchday matchday : matchdayList ) {
if ( matchdayParam . equals ( matchday . toString ( ) ) ) {
return matchday ;
}
}
return null ;
}
@Nullable
private Match getMatchFromParam ( @Nullable String matchParam ) {
if ( matchParam = = null ) {
return null ;
}
for ( Match match : matchList ) {
if ( matchParam . equals ( match . toString ( ) ) ) {
return match ;
}
}
return null ;
}
public void addRunnableToBeRunAfterSeasonSelection ( Runnable runnable ) {
runnablesToBeRunAfterSeasonSelection . add ( runnable ) ;
public ValidationLabel getValidationLabel ( ) {
return validationLabel ;
}
public void addRunnableToBeRunAfterMatchdaySelection ( Runnable runnable ) {
runnablesToBeRunAfterMatchdaySelection . add ( runnable ) ;
public List < Season > getSeasonList ( ) {
return seasonList ;
}
public void addRunnableToBeRunAfterMatchSelection ( Runnable runnable ) {
runnablesToBeRunAfterMatchSelection . add ( runnable ) ;
public List < Matchday > getMatchdayList ( ) {
return matchdayList ;
}
private void configureButtons ( ) {
prevMatchdayButton . setEnabled ( isMatchDayParamValid ( getPrevMatchdayParam ( ) ) ) ;
prevMatchdayButton . addClickListener ( getButtonClickListener ( getPrevMatchdayParam ( ) ) ) ;
nextMatchdayButton . setEnabled ( isMatchDayParamValid ( getNextMatchdayParam ( ) ) ) ;
nextMatchdayButton . addClickListener ( getButtonClickListener ( getNextMatchdayParam ( ) ) ) ;
public List < Match > getMatchList ( ) {
return matchList ;
}
private ComponentEventListener < ClickEvent < Button > > getButtonClickListener ( String matchdayParam ) {
return buttonClickEvent - > matchdayList . stream ( )
. filter ( matchday - > matchdayParam . equals ( matchday . toString ( ) ) )
. findFirst ( ) . ifPresent ( matchdaySelect : : setValue ) ;
public Select < Season > getSeasonSelect ( ) {
return seasonSelect ;
}
private String getPrevMatchdayParam ( ) {
try {
return String . valueOf ( Integer . parseInt ( matchdayParam ) - 1 ) ;
} catch ( NumberFormatException e ) {
return "" ;
}
public Select < Matchday > getMatchdaySelect ( ) {
return matchdaySelect ;
}
private String getNextMatchdayParam ( ) {
try {
return String . valueOf ( Integer . parseInt ( matchdayParam ) + 1 ) ;
} catch ( NumberFormatException e ) {
return "" ;
}
public Select < Match > getMatchSelect ( ) {
return matchSelect ;
}
public Optional < Matchday > getSelectedMatchday ( ) {
@ -391,32 +293,4 @@ public class Navigation implements HasUrlParameter<String> {
public Optional < Match > getSelectedMatch ( ) {
return matchSelect . getOptionalValue ( ) ;
}
public Button getPrevMatchdayButton ( ) {
return prevMatchdayButton ;
}
public Button getNextMatchdayButton ( ) {
return nextMatchdayButton ;
}
public Label getInvalidUrlLabel ( ) {
return invalidUrlLabel ;
}
public Select < Season > getSeasonSelect ( ) {
return seasonSelect ;
}
public Select < Matchday > getMatchdaySelect ( ) {
return matchdaySelect ;
}
public Select < Match > getMatchSelect ( ) {
return matchSelect ;
}
public void selectMatch ( Match match ) {
matchSelect . setValue ( match ) ;
}
}