diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/shared/leaderboard/LeaderboardWithHeaderPerspective.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/shared/leaderboard/LeaderboardWithHeaderPerspective.java index fe9a328e8d9..ae48943778e 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/shared/leaderboard/LeaderboardWithHeaderPerspective.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/shared/leaderboard/LeaderboardWithHeaderPerspective.java @@ -30,8 +30,8 @@ import com.sap.sse.gwt.client.shared.components.Component; import com.sap.sse.gwt.client.shared.components.SettingsDialogComponent; import com.sap.sse.gwt.client.shared.perspective.AbstractPerspectiveComposite; import com.sap.sse.gwt.client.shared.perspective.PerspectiveCompositeSettings; -import com.sap.sse.gwt.client.shared.settings.ComponentContextWithSettingsStorage; import com.sap.sse.security.ui.client.UserService; +import com.sap.sse.security.ui.settings.ComponentContextWithSettingsStorage; /** * A perspective managing a header with a single leaderboard filling the rest of the screen. diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/regatta/SharedLeaderboardRegattaTabView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/regatta/SharedLeaderboardRegattaTabView.java index 716225c91e0..ce2a2c499de 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/regatta/SharedLeaderboardRegattaTabView.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/regatta/SharedLeaderboardRegattaTabView.java @@ -14,12 +14,10 @@ import com.sap.sailing.gwt.ui.leaderboard.LeaderboardPanel; import com.sap.sse.gwt.client.mutationobserver.ElementSizeMutationObserver; import com.sap.sse.gwt.client.mutationobserver.ElementSizeMutationObserver.DomMutationCallback; import com.sap.sse.gwt.client.shared.settings.ComponentContext; -import com.sap.sse.gwt.client.shared.settings.ComponentContextWithSettingsStorage; import com.sap.sse.gwt.client.shared.settings.DefaultOnSettingsLoadedCallback; -import com.sap.sse.gwt.client.shared.settings.SettingsStorageManager; import com.sap.sse.gwt.shared.GwtHttpRequestUtils; import com.sap.sse.security.ui.client.UserService; -import com.sap.sse.security.ui.settings.PlaceBasedUserSettingsStorageManager; +import com.sap.sse.security.ui.settings.PlaceBasedComponentContextWithSettingsStorage; import com.sap.sse.security.ui.settings.StorageDefinitionId; /** @@ -82,13 +80,11 @@ public abstract class SharedLeaderboardRegattaTabView createLeaderboardComponentContext(String leaderboardName, UserService userService, String placeToken) { - final LeaderboardPanelLifecycle lifeCycle = new LeaderboardPanelLifecycle(null, StringMessages.INSTANCE); + final LeaderboardPanelLifecycle lifecycle = new LeaderboardPanelLifecycle(null, StringMessages.INSTANCE); final StorageDefinitionId storageDefinitionId = StorageDefinitionIdFactory.createStorageDefinitionIdForEventRegattaLeaderboard(leaderboardName); - final SettingsStorageManager settingsStorageManager = new PlaceBasedUserSettingsStorageManager<>( - userService, storageDefinitionId, placeToken); - final ComponentContext componentContext = new ComponentContextWithSettingsStorage<>( - lifeCycle, settingsStorageManager); + final ComponentContext componentContext = new PlaceBasedComponentContextWithSettingsStorage<>( + lifecycle, userService, storageDefinitionId, placeToken); return componentContext; } } \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/fakeseries/SharedLeaderboardEventSeriesTabView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/fakeseries/SharedLeaderboardEventSeriesTabView.java index 536f063cd2c..751634274f4 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/fakeseries/SharedLeaderboardEventSeriesTabView.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/fakeseries/SharedLeaderboardEventSeriesTabView.java @@ -12,12 +12,10 @@ import com.sap.sailing.gwt.ui.client.LeaderboardUpdateListener; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.leaderboard.LeaderboardPanel; import com.sap.sse.gwt.client.shared.settings.ComponentContext; -import com.sap.sse.gwt.client.shared.settings.ComponentContextWithSettingsStorage; import com.sap.sse.gwt.client.shared.settings.DefaultOnSettingsLoadedCallback; -import com.sap.sse.gwt.client.shared.settings.SettingsStorageManager; import com.sap.sse.gwt.shared.GwtHttpRequestUtils; import com.sap.sse.security.ui.client.UserService; -import com.sap.sse.security.ui.settings.PlaceBasedUserSettingsStorageManager; +import com.sap.sse.security.ui.settings.PlaceBasedComponentContextWithSettingsStorage; import com.sap.sse.security.ui.settings.StorageDefinitionId; /** @@ -64,13 +62,11 @@ public abstract class SharedLeaderboardEventSeriesTabView createLeaderboardComponentContext(String leaderboardName, UserService userService, String placeToken) { - final LeaderboardPanelLifecycle lifeCycle = new LeaderboardPanelLifecycle(null, StringMessages.INSTANCE); + final LeaderboardPanelLifecycle lifecycle = new LeaderboardPanelLifecycle(null, StringMessages.INSTANCE); final StorageDefinitionId storageDefinitionId = StorageDefinitionIdFactory.createStorageDefinitionIdForSeriesOverallLeaderboard(leaderboardName); - final SettingsStorageManager settingsStorageManager = new PlaceBasedUserSettingsStorageManager<>( - userService, storageDefinitionId, placeToken); - final ComponentContext componentContext = new ComponentContextWithSettingsStorage<>( - lifeCycle, settingsStorageManager); + final ComponentContext componentContext = new PlaceBasedComponentContextWithSettingsStorage<>( + lifecycle, userService, storageDefinitionId, placeToken); return componentContext; } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/fakeseries/leaderboardstab/EventSeriesLeaderboardsTabView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/fakeseries/leaderboardstab/EventSeriesLeaderboardsTabView.java index be3b475a801..e61025a87e4 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/fakeseries/leaderboardstab/EventSeriesLeaderboardsTabView.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/fakeseries/leaderboardstab/EventSeriesLeaderboardsTabView.java @@ -27,12 +27,10 @@ import com.sap.sailing.gwt.ui.client.LeaderboardUpdateListener; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.leaderboard.MultiLeaderboardProxyPanel; import com.sap.sse.gwt.client.shared.settings.ComponentContext; -import com.sap.sse.gwt.client.shared.settings.ComponentContextWithSettingsStorage; import com.sap.sse.gwt.client.shared.settings.DefaultOnSettingsLoadedCallback; -import com.sap.sse.gwt.client.shared.settings.SettingsStorageManager; import com.sap.sse.gwt.shared.GwtHttpRequestUtils; import com.sap.sse.security.ui.client.UserService; -import com.sap.sse.security.ui.settings.PlaceBasedUserSettingsStorageManager; +import com.sap.sse.security.ui.settings.PlaceBasedComponentContextWithSettingsStorage; import com.sap.sse.security.ui.settings.StorageDefinitionId; public class EventSeriesLeaderboardsTabView extends Composite implements SeriesTabView, @@ -130,11 +128,9 @@ public class EventSeriesLeaderboardsTabView extends Composite implements SeriesT String placeToken) { final MultiLeaderboardPanelLifecycle lifecycle = new MultiLeaderboardPanelLifecycle(null, StringMessages.INSTANCE); final StorageDefinitionId storageDefinitionId = StorageDefinitionIdFactory.createStorageDefinitionIdForSeriesRegattaLeaderboards(leaderboardName); - final SettingsStorageManager settingsStorageManager = new PlaceBasedUserSettingsStorageManager<>( - userService, storageDefinitionId, placeToken); - final ComponentContext componentContext = new ComponentContextWithSettingsStorage<>( - lifecycle, settingsStorageManager); + final ComponentContext componentContext = new PlaceBasedComponentContextWithSettingsStorage<>( + lifecycle, userService, storageDefinitionId, placeToken); return componentContext; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/regattaoverview/client/RegattaOverviewPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/regattaoverview/client/RegattaOverviewPanel.java index 09128aa9fc1..2bbd9f61679 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/regattaoverview/client/RegattaOverviewPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/regattaoverview/client/RegattaOverviewPanel.java @@ -40,13 +40,12 @@ import com.sap.sse.gwt.client.player.Timer.PlayModes; import com.sap.sse.gwt.client.player.Timer.PlayStates; import com.sap.sse.gwt.client.shared.components.LinkWithSettingsGenerator; import com.sap.sse.gwt.client.shared.components.SettingsDialog; +import com.sap.sse.gwt.client.shared.perspective.IgnoreLocalSettings; import com.sap.sse.gwt.client.shared.settings.ComponentContext; -import com.sap.sse.gwt.client.shared.settings.ComponentContextWithSettingsStorage; import com.sap.sse.gwt.client.shared.settings.DefaultOnSettingsLoadedCallback; -import com.sap.sse.gwt.client.shared.settings.SettingsStorageManager; import com.sap.sse.security.ui.client.UserService; +import com.sap.sse.security.ui.settings.ComponentContextWithSettingsStorage; import com.sap.sse.security.ui.settings.StorageDefinitionId; -import com.sap.sse.security.ui.settings.UserSettingsStorageManager; public class RegattaOverviewPanel extends SimplePanel { @@ -130,7 +129,7 @@ public class RegattaOverviewPanel extends SimplePanel { // TODO should we always set ignoreLocalSettings=true when creating links? new SettingsDialog(regattaRaceStatesComponent, stringMessages, new LinkWithSettingsGenerator<>(regattaOverviewContextDefinition, - UserSettingsStorageManager.getIgnoreLocalSettings())).show(); + IgnoreLocalSettings.getIgnoreLocalSettingsFromCurrentUrl())).show(); } }); @@ -154,10 +153,8 @@ public class RegattaOverviewPanel extends SimplePanel { final StorageDefinitionId storageDefinitionId = StorageDefinitionIdFactory.createStorageDefinitionIdForRegattaOverview(regattaOverviewContextDefinition); final RegattaRaceStatesComponentLifecycle lifecycle = new RegattaRaceStatesComponentLifecycle(); - final SettingsStorageManager settingsStorageManager = UserSettingsStorageManager - .createSettingsStorageManager(userService, storageDefinitionId); final ComponentContext componentContext = new ComponentContextWithSettingsStorage<>( - lifecycle, settingsStorageManager); + lifecycle, userService, storageDefinitionId); regattaRaceStatesComponent = new RegattaRaceStatesComponent(null, componentContext, sailingService, errorReporter, stringMessages, diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardEntryPoint.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardEntryPoint.java index 2608e26efcd..c19614a3b7c 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardEntryPoint.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardEntryPoint.java @@ -33,11 +33,10 @@ import com.sap.sse.gwt.client.player.Timer.PlayModes; import com.sap.sse.gwt.client.player.Timer.PlayStates; import com.sap.sse.gwt.client.shared.perspective.PerspectiveCompositeSettings; import com.sap.sse.gwt.client.shared.settings.ComponentContext; -import com.sap.sse.gwt.client.shared.settings.ComponentContextWithSettingsStorage; import com.sap.sse.gwt.client.shared.settings.OnSettingsLoadedCallback; import com.sap.sse.gwt.settings.SettingsToUrlSerializer; +import com.sap.sse.security.ui.settings.ComponentContextWithSettingsStorage; import com.sap.sse.security.ui.settings.StorageDefinitionId; -import com.sap.sse.security.ui.settings.UserSettingsStorageManager; public class LeaderboardEntryPoint extends AbstractSailingEntryPoint { public static final long DEFAULT_REFRESH_INTERVAL_MILLIS = 3000l; @@ -117,15 +116,13 @@ public class LeaderboardEntryPoint extends AbstractSailingEntryPoint { // make a single live request as the default but don't continue to play by default final StorageDefinitionId storageDefinitionId = StorageDefinitionIdFactory.createStorageDefinitionIdForLeaderboard(leaderboardContextDefinition); - final UserSettingsStorageManager> settingsManager = new UserSettingsStorageManager<>( - getUserService(), storageDefinitionId); if (leaderboardType.isMetaLeaderboard()) { // overall MetaLeaderboardPerspectiveLifecycle rootComponentLifeCycle = new MetaLeaderboardPerspectiveLifecycle( stringmessages); ComponentContext> context = new ComponentContextWithSettingsStorage<>( - rootComponentLifeCycle, settingsManager); + rootComponentLifeCycle, getUserService(), storageDefinitionId); context.getInitialSettings( new OnSettingsLoadedCallback>() { @Override @@ -153,7 +150,7 @@ public class LeaderboardEntryPoint extends AbstractSailingEntryPoint { LeaderboardPerspectiveLifecycle rootComponentLifeCycle = new LeaderboardPerspectiveLifecycle( StringMessages.INSTANCE); ComponentContext> context = new ComponentContextWithSettingsStorage<>( - rootComponentLifeCycle, settingsManager); + rootComponentLifeCycle, getUserService(), storageDefinitionId); context.getInitialSettings( new OnSettingsLoadedCallback>() { @Override diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardComponentContext.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardComponentContext.java index 17859a4016c..43f25be3ae7 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardComponentContext.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardComponentContext.java @@ -8,12 +8,13 @@ import com.sap.sse.common.settings.util.SettingsMergeUtils; import com.sap.sse.gwt.client.shared.components.Component; import com.sap.sse.gwt.client.shared.components.ComponentLifecycle; import com.sap.sse.gwt.client.shared.perspective.PerspectiveCompositeSettings; -import com.sap.sse.gwt.client.shared.settings.ComponentContextWithSettingsStorage; import com.sap.sse.gwt.client.shared.settings.OnSettingsLoadedCallback; import com.sap.sse.gwt.client.shared.settings.PipelineLevel; +import com.sap.sse.security.ui.client.UserService; +import com.sap.sse.security.ui.settings.ComponentContextWithSettingsStorage; import com.sap.sse.security.ui.settings.ComponentContextWithSettingsStorageAndPatching; import com.sap.sse.security.ui.settings.SettingsPatch; -import com.sap.sse.security.ui.settings.UserSettingsStorageManagerWithPatching; +import com.sap.sse.security.ui.settings.StorageDefinitionId; /** * A specialization of {@link ComponentContextWithSettingsStorageAndPatching} which is specially designed for @@ -32,13 +33,15 @@ public class RaceBoardComponentContext extends ComponentContextWithSettingsStora /** * @param rootLifecycle * The {@link ComponentLifecycle} of the root component/perspective - * @param settingsStorageManager - * The {@link UserSettingsStorageManagerWithPatching} to be used to access stored settings and to store new settings + * @param userService + * The service which is used for server-side settings storage + * @param storageDefinitionId + * The definition for User Settings and Document Settings storage keys */ public RaceBoardComponentContext( RaceBoardPerspectiveLifecycle rootLifecycle, - UserSettingsStorageManagerWithPatching> settingsStorageManager) { - super(rootLifecycle, settingsStorageManager); + UserService userService, StorageDefinitionId storageDefinitionId) { + super(rootLifecycle, userService, storageDefinitionId); } /** diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardEntryPoint.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardEntryPoint.java index d5e4c3f389f..59be7b5cfca 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardEntryPoint.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardEntryPoint.java @@ -30,11 +30,10 @@ import com.sap.sse.gwt.client.player.Timer; import com.sap.sse.gwt.client.player.Timer.PlayModes; import com.sap.sse.gwt.client.shared.components.Component; import com.sap.sse.gwt.client.shared.perspective.PerspectiveCompositeSettings; -import com.sap.sse.gwt.client.shared.settings.ComponentContextWithSettingsStorage; import com.sap.sse.gwt.client.shared.settings.DefaultOnSettingsLoadedCallback; import com.sap.sse.gwt.settings.SettingsToUrlSerializer; +import com.sap.sse.security.ui.settings.ComponentContextWithSettingsStorage; import com.sap.sse.security.ui.settings.StorageDefinitionId; -import com.sap.sse.security.ui.settings.UserSettingsStorageManagerWithPatching; public class RaceBoardEntryPoint extends AbstractSailingEntryPoint { private RaceWithCompetitorsDTO selectedRace; @@ -103,7 +102,7 @@ public class RaceBoardEntryPoint extends AbstractSailingEntryPoint { final boolean showChartMarkEditMediaButtonsAndVideo = !DeviceDetector.isMobile(); final StorageDefinitionId storageDefinitionId = StorageDefinitionIdFactory.createStorageDefinitionIdForRaceBoard(raceboardContextDefinition); final RaceBoardPerspectiveLifecycle lifeCycle = new RaceBoardPerspectiveLifecycle(raceboardData.getRace().getRaceIdentifier(), StringMessages.INSTANCE); - RaceBoardComponentContext componentContext = new RaceBoardComponentContext(lifeCycle, new UserSettingsStorageManagerWithPatching<>(getUserService(), storageDefinitionId)); + RaceBoardComponentContext componentContext = new RaceBoardComponentContext(lifeCycle, getUserService(), storageDefinitionId); componentContext.getInitialSettings(new DefaultOnSettingsLoadedCallback>() { @Override diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/raceboard/SettingsTest.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/raceboard/SettingsTest.java index 8547f8728c0..d3aa1589166 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/raceboard/SettingsTest.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/raceboard/SettingsTest.java @@ -10,7 +10,6 @@ import javax.xml.bind.DatatypeConverter; import org.junit.Assert; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import com.sap.sailing.selenium.pages.adminconsole.AdminConsolePage; @@ -74,127 +73,11 @@ public class SettingsTest extends AbstractSeleniumTest { super.setUp(); } - //FIXME just for debugging the loading of raceboard in hudson - @Test - public void testRaceBoardPageWithoutMode() throws InterruptedException, UnsupportedEncodingException { - AdminConsolePage adminConsole = AdminConsolePage.goToPage(getWebDriver(), getContextRoot()); - EventConfigurationPanelPO events = adminConsole.goToEvents(); - events.createEventWithDefaultLeaderboardGroupRegattaAndDefaultLeaderboard(BMW_CUP_EVENT, BMW_CUP_EVENTS_DESC, - BMW_VENUE, BMW_START_EVENT_TIME, BMW_STOP_EVENT_TIME, true, BMW_CUP_REGATTA, BMW_CUP_BOAT_CLASS, - BMW_START_EVENT_TIME, BMW_STOP_EVENT_TIME, false); - - initTrackingForBmwCupRace(adminConsole); - - RaceBoardPage raceboard = RaceBoardPage.goToRaceboardUrl(getWebDriver(), getContextRoot(), BMW_CUP_REGATTA, - BMW_CUP_REGATTA, String.format(BMW_RACE, 1)); - - MapSettingsPO mapSettings = raceboard.openMapSettings(); - mapSettings.pressCancel(); - - LeaderboardSettingsDialogPO leaderboardSettingsDialog = raceboard.openLeaderboardSettingsDialog(); - LeaderboardSettingsPanelPO leaderboardSettingsPanelPO = leaderboardSettingsDialog.getLeaderboardSettingsPanelPO(); - leaderboardSettingsPanelPO.getSelectedDetails(); - leaderboardSettingsDialog.pressCancel(); - } - - //FIXME just for debugging the loading of raceboard in hudson - @Test - public void testRaceBoardPageStartAnalysis() throws InterruptedException, UnsupportedEncodingException { - AdminConsolePage adminConsole = AdminConsolePage.goToPage(getWebDriver(), getContextRoot()); - EventConfigurationPanelPO events = adminConsole.goToEvents(); - events.createEventWithDefaultLeaderboardGroupRegattaAndDefaultLeaderboard(BMW_CUP_EVENT, BMW_CUP_EVENTS_DESC, - BMW_VENUE, BMW_START_EVENT_TIME, BMW_STOP_EVENT_TIME, true, BMW_CUP_REGATTA, BMW_CUP_BOAT_CLASS, - BMW_START_EVENT_TIME, BMW_STOP_EVENT_TIME, false); - - initTrackingForBmwCupRace(adminConsole); - - RaceBoardPage raceboard = RaceBoardPage.goToRaceboardUrl(getWebDriver(), getContextRoot(), BMW_CUP_REGATTA, - BMW_CUP_REGATTA, String.format(BMW_RACE, 1), "START_ANALYSIS"); - - MapSettingsPO mapSettings = raceboard.openMapSettings(); - mapSettings.pressCancel(); - - LeaderboardSettingsDialogPO leaderboardSettingsDialog = raceboard.openLeaderboardSettingsDialog(); - LeaderboardSettingsPanelPO leaderboardSettingsPanelPO = leaderboardSettingsDialog.getLeaderboardSettingsPanelPO(); - leaderboardSettingsPanelPO.getSelectedDetails(); - leaderboardSettingsDialog.pressCancel(); - } - - //FIXME just for debugging the loading of raceboard in hudson - @Test - public void testRaceBoardPageFullAnalysisMode() throws InterruptedException, UnsupportedEncodingException { - AdminConsolePage adminConsole = AdminConsolePage.goToPage(getWebDriver(), getContextRoot()); - EventConfigurationPanelPO events = adminConsole.goToEvents(); - events.createEventWithDefaultLeaderboardGroupRegattaAndDefaultLeaderboard(BMW_CUP_EVENT, BMW_CUP_EVENTS_DESC, - BMW_VENUE, BMW_START_EVENT_TIME, BMW_STOP_EVENT_TIME, true, BMW_CUP_REGATTA, BMW_CUP_BOAT_CLASS, - BMW_START_EVENT_TIME, BMW_STOP_EVENT_TIME, false); - - initTrackingForBmwCupRace(adminConsole); - - RaceBoardPage raceboard = RaceBoardPage.goToRaceboardUrl(getWebDriver(), getContextRoot(), BMW_CUP_REGATTA, - BMW_CUP_REGATTA, String.format(BMW_RACE, 1), "FULL_ANALYSIS"); - - MapSettingsPO mapSettings = raceboard.openMapSettings(); - mapSettings.pressCancel(); - - LeaderboardSettingsDialogPO leaderboardSettingsDialog = raceboard.openLeaderboardSettingsDialog(); - LeaderboardSettingsPanelPO leaderboardSettingsPanelPO = leaderboardSettingsDialog.getLeaderboardSettingsPanelPO(); - leaderboardSettingsPanelPO.getSelectedDetails(); - leaderboardSettingsDialog.pressCancel(); - } - - //FIXME just for debugging the loading of raceboard in hudson - @Test - public void testRaceBoardPageWinningLanesMode() throws InterruptedException, UnsupportedEncodingException { - AdminConsolePage adminConsole = AdminConsolePage.goToPage(getWebDriver(), getContextRoot()); - EventConfigurationPanelPO events = adminConsole.goToEvents(); - events.createEventWithDefaultLeaderboardGroupRegattaAndDefaultLeaderboard(BMW_CUP_EVENT, BMW_CUP_EVENTS_DESC, - BMW_VENUE, BMW_START_EVENT_TIME, BMW_STOP_EVENT_TIME, true, BMW_CUP_REGATTA, BMW_CUP_BOAT_CLASS, - BMW_START_EVENT_TIME, BMW_STOP_EVENT_TIME, false); - - initTrackingForBmwCupRace(adminConsole); - - RaceBoardPage raceboard = RaceBoardPage.goToRaceboardUrl(getWebDriver(), getContextRoot(), BMW_CUP_REGATTA, - BMW_CUP_REGATTA, String.format(BMW_RACE, 1), "WINNING_LANES"); - - MapSettingsPO mapSettings = raceboard.openMapSettings(); - mapSettings.pressCancel(); - - LeaderboardSettingsDialogPO leaderboardSettingsDialog = raceboard.openLeaderboardSettingsDialog(); - LeaderboardSettingsPanelPO leaderboardSettingsPanelPO = leaderboardSettingsDialog.getLeaderboardSettingsPanelPO(); - leaderboardSettingsPanelPO.getSelectedDetails(); - leaderboardSettingsDialog.pressCancel(); - } - - //FIXME just for debugging the loading of raceboard in hudson - @Test - public void testRaceBoardPagePlayerMode() throws InterruptedException, UnsupportedEncodingException { - AdminConsolePage adminConsole = AdminConsolePage.goToPage(getWebDriver(), getContextRoot()); - EventConfigurationPanelPO events = adminConsole.goToEvents(); - events.createEventWithDefaultLeaderboardGroupRegattaAndDefaultLeaderboard(BMW_CUP_EVENT, BMW_CUP_EVENTS_DESC, - BMW_VENUE, BMW_START_EVENT_TIME, BMW_STOP_EVENT_TIME, true, BMW_CUP_REGATTA, BMW_CUP_BOAT_CLASS, - BMW_START_EVENT_TIME, BMW_STOP_EVENT_TIME, false); - - initTrackingForBmwCupRace(adminConsole); - - RaceBoardPage raceboard = RaceBoardPage.goToRaceboardUrl(getWebDriver(), getContextRoot(), BMW_CUP_REGATTA, - BMW_CUP_REGATTA, String.format(BMW_RACE, 1), "PLAYER"); - - MapSettingsPO mapSettings = raceboard.openMapSettings(); - mapSettings.pressCancel(); - - LeaderboardSettingsDialogPO leaderboardSettingsDialog = raceboard.openLeaderboardSettingsDialog(); - LeaderboardSettingsPanelPO leaderboardSettingsPanelPO = leaderboardSettingsDialog.getLeaderboardSettingsPanelPO(); - leaderboardSettingsPanelPO.getSelectedDetails(); - leaderboardSettingsDialog.pressCancel(); - } - /** * Verifies the settings storage of the raceboard. Checks the precedences of url, context specific settings, mode settings and * global settings. */ @Test - @Ignore public void testRaceBoardPageSettingsStorage() throws InterruptedException, UnsupportedEncodingException { AdminConsolePage adminConsole = AdminConsolePage.goToPage(getWebDriver(), getContextRoot()); EventConfigurationPanelPO events = adminConsole.goToEvents(); diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/components/SettingsDialog.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/components/SettingsDialog.java index 49e634b79fe..52c887aa349 100755 --- a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/components/SettingsDialog.java +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/components/SettingsDialog.java @@ -61,7 +61,7 @@ public class SettingsDialog extends AbstractSetti new SettingsDialogCallback<>(component, callback)); if (component.getComponentContext() != null - && component.getComponentContext().hasMakeCustomDefaultSettingsSupport(component)) { + && component.getComponentContext().isStorageSupported(component)) { initMakeDefaultButtons(component, stringMessages); } } @@ -117,7 +117,7 @@ public class SettingsDialog extends AbstractSetti @Override public void ok(SettingsType editedSettings) { if (component.getComponentContext() != null - && component.getComponentContext().hasMakeCustomDefaultSettingsSupport(component)) { + && component.getComponentContext().isStorageSupported(component)) { component.getComponentContext().storeSettingsForContext(component, editedSettings, new DummyOnSettingsStoredCallback()); } component.updateSettings(editedSettings); diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/perspective/AbstractPerspectiveComposite.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/perspective/AbstractPerspectiveComposite.java index 6a5c785c14b..cda65f8cbd8 100644 --- a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/perspective/AbstractPerspectiveComposite.java +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/perspective/AbstractPerspectiveComposite.java @@ -27,15 +27,14 @@ public abstract class AbstractPerspectiveComposite> childComponents = new HashMap<>(); /** - * Adds the provided component as a child to this perspective and sets the {@link ComponentTreeNodeInfo} - * of the provided component accordingly. + * Adds the provided component as a child to the maintained component tree of this perspective. * * @param childComponent The component to be added as a child to this perspective */ protected void addChildComponent(Component childComponent) { Component old = childComponents.put(childComponent.getId(), childComponent); if (old != null) { - throw new IllegalStateException("Child with same id is allready added"); + throw new IllegalStateException("Child with same id is already added"); } } diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/perspective/IgnoreLocalSettings.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/perspective/IgnoreLocalSettings.java index 5ba45239475..8f6c71d07f9 100644 --- a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/perspective/IgnoreLocalSettings.java +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/perspective/IgnoreLocalSettings.java @@ -1,27 +1,32 @@ -package com.sap.sse.gwt.client.shared.perspective; - -import com.sap.sse.common.settings.generic.AbstractGenericSerializableSettings; -import com.sap.sse.common.settings.generic.BooleanSetting; - -public class IgnoreLocalSettings extends AbstractGenericSerializableSettings { - private static final long serialVersionUID = -282780795782313106L; - - private transient BooleanSetting ignoreLocalSettings; - - public IgnoreLocalSettings() { - } - - public IgnoreLocalSettings(boolean ignoreLocalSettings) { - this.ignoreLocalSettings.setValue(ignoreLocalSettings); - } - - @Override - protected void addChildSettings() { - ignoreLocalSettings = new BooleanSetting("ignoreLocalSettings", this, false); - } - - public boolean isIgnoreLocalSettings() { - return Boolean.TRUE.equals(ignoreLocalSettings.getValue()); - } - -} +package com.sap.sse.gwt.client.shared.perspective; + +import com.sap.sse.common.settings.generic.AbstractGenericSerializableSettings; +import com.sap.sse.common.settings.generic.BooleanSetting; +import com.sap.sse.gwt.settings.SettingsToUrlSerializer; + +public class IgnoreLocalSettings extends AbstractGenericSerializableSettings { + private static final long serialVersionUID = -282780795782313106L; + + private transient BooleanSetting ignoreLocalSettings; + + public IgnoreLocalSettings() { + } + + public IgnoreLocalSettings(boolean ignoreLocalSettings) { + this.ignoreLocalSettings.setValue(ignoreLocalSettings); + } + + @Override + protected void addChildSettings() { + ignoreLocalSettings = new BooleanSetting("ignoreLocalSettings", this, false); + } + + public boolean isIgnoreLocalSettings() { + return Boolean.TRUE.equals(ignoreLocalSettings.getValue()); + } + + public static IgnoreLocalSettings getIgnoreLocalSettingsFromCurrentUrl() { + return new SettingsToUrlSerializer().deserializeFromCurrentLocation(new IgnoreLocalSettings()); + } + +} diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/settings/AbstractSettingsBuildingPipeline.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/settings/AbstractSettingsBuildingPipeline.java deleted file mode 100644 index 11f4802cc18..00000000000 --- a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/settings/AbstractSettingsBuildingPipeline.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.sap.sse.gwt.client.shared.settings; - -import com.sap.sse.common.settings.Settings; - -/** - * Basic implementation for {@link SettingsBuildingPipeline} which provides a implementation of few methods. - * It is highly recommended to inherit all other implementations from this class. - * - * @author Vladislav Chumak - * - * @see SettingsBuildingPipeline - * - */ -public abstract class AbstractSettingsBuildingPipeline implements SettingsBuildingPipeline { - - /** - * Conversion helper which is used by this instance for type conversion/serialization - * between settings objects and JSON Strings. - */ - protected final SettingsStringConverter settingsStringConverter; - - /** - * Constructs an instance with {@link SettingsStringConverter} as conversion helper between - * settings objects and its JSON representation. - */ - public AbstractSettingsBuildingPipeline() { - this(new SettingsStringConverter()); - } - - /** - * Constructs an instance with a custom conversion helper between - * settings objects and its JSON representation. - */ - public AbstractSettingsBuildingPipeline(SettingsStringConverter settingsStringConverter) { - this.settingsStringConverter = settingsStringConverter; - } - - /** - * {@inheritDoc} - */ - @Override - public S getSettingsObject(S defaultSettings, SettingsStrings settingsStrings) { - SettingsJsons settingsJsons = settingsStringConverter.convertToSettingsJson(settingsStrings); - return getSettingsObject(defaultSettings, settingsJsons); - } - - /** - * {@inheritDoc} - */ - @Override - public S getSettingsObject(S defaultSettings) { - return getSettingsObject(defaultSettings, new SettingsJsons(null, null)); - } - - /** - * {@inheritDoc} - */ - @Override - public SettingsStringConverter getSettingsStringConverter() { - return settingsStringConverter; - } - -} diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/settings/ComponentContext.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/settings/ComponentContext.java index 6396136cea8..efcccdd3bd9 100644 --- a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/settings/ComponentContext.java +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/settings/ComponentContext.java @@ -37,7 +37,7 @@ public interface ComponentContext { /** * Stores the provided {@link Settings} of the provided {@link Component} as "User Settings" globally. Make sure to - * call this method only when {@link #hasMakeCustomDefaultSettingsSupport(Component)} method returns {@code true} + * call this method only when {@link #isStorageSupported(Component)} method returns {@code true} * for the provided {@link Component}. * * @param component @@ -50,7 +50,7 @@ public interface ComponentContext { /** * Stores the provided {@link Settings} of the provided {@link Component} as "Document Settings" (old term "Context specific Settings") for the current context. Make sure to - * call this method only when {@link #hasMakeCustomDefaultSettingsSupport(Component)} method returns {@code true} + * call this method only when {@link #isStorageSupported(Component)} method returns {@code true} * for the provided {@link Component}. * * @param component @@ -79,7 +79,7 @@ public interface ComponentContext { * AND the {@link ComponentContext} implementation has settings * storage support */ - boolean hasMakeCustomDefaultSettingsSupport(Component component); + boolean isStorageSupported(Component component); /** * Gets initial settings and passes these settings to the provided callback. diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/settings/ComponentContextWithSettingsStorage.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/settings/ComponentContextWithSettingsStorage.java deleted file mode 100644 index 7cc3908fc45..00000000000 --- a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/settings/ComponentContextWithSettingsStorage.java +++ /dev/null @@ -1,335 +0,0 @@ -package com.sap.sse.gwt.client.shared.settings; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import com.google.gwt.core.client.GWT; -import com.google.gwt.json.client.JSONObject; -import com.google.gwt.json.client.JSONValue; -import com.google.gwt.user.client.rpc.AsyncCallback; -import com.sap.sse.common.settings.Settings; -import com.sap.sse.common.settings.generic.GenericSerializableSettings; -import com.sap.sse.common.settings.generic.SettingsMap; -import com.sap.sse.common.settings.util.SettingsDefaultValuesUtils; -import com.sap.sse.common.settings.util.SettingsMergeUtils; -import com.sap.sse.gwt.client.shared.components.Component; -import com.sap.sse.gwt.client.shared.components.ComponentLifecycle; - -/** - * Manages all the default/initial settings of a component/perspective and its subcomponents if there are any. It supplies - * components with initial settings and determines whether the settings of components are storable or not. This - * implementation provides settings storage support if the storable settings either implement {@link SettingsMap} or - * {@link GenericSerializableSettings}. There are two kinds of settings which are stored separately - User - * Settings (old term "Global Settings") and Document Settings (old term "Context specific Settings"). - *
- *
Document Settings
- *
The settings are stored only for the current context (e.g. a race presented in a RaceBoard). This settings are not considered in any other context. See {@link #storeSettingsForContext(Component, Settings, OnSettingsStoredCallback)}
- * - *
User Settings
- *
The settings are stored for a component/perspective context-independently and may effect a different context presented by the same perspective/component, e.g. a different race in a RaceBoard. See {@link #makeSettingsDefault(Component, Settings, OnSettingsStoredCallback)}
- *
- * That means that Document Settings are stored per context (e.g. race in RaceBoard) whereas User Settings are - * stored globally for all possible contexts (e.g. for the whole RaceBoard independently from selected race). - * - * - * @author Vladislav Chumak - * @see ComponentContext - * - * @param - * The {@link Settings} type of the settings of the root component/perspective containing all the settings - * for itself and its subcomponents - * - */ -public class ComponentContextWithSettingsStorage extends SimpleComponentContext { - - /** - * Settings which have been already constructed, or {@code null} if settings have not been initialized yet. - */ - protected S cachedRootComponentSettings = null; - - /** - * Manages the persistence layer of settings. - */ - protected final SettingsStorageManager settingsStorageManager; - - /** - * @param rootLifecycle - * The {@link ComponentLifecycle} of the root component/perspective - * @param settingsStorageManager - * The {@link SettingsStorageManager} to be used to access stored settings and to store new settings - */ - public ComponentContextWithSettingsStorage(ComponentLifecycle rootLifecycle, - SettingsStorageManager settingsStorageManager) { - super(rootLifecycle); - this.settingsStorageManager = settingsStorageManager; - } - - /** - * Retrieves the initial settings and caches them for further calls of - * {@link #getInitialSettings(OnSettingsLoadedCallback)} and {@link #getInitialSettingsForComponent(Component, OnSettingsLoadedCallback)}. - */ - public void initialize() { - getInitialSettings(new OnSettingsLoadedCallback() { - @Override - public void onError(Throwable caught, S fallbackDefaultSettings) {} - @Override - public void onSuccess(S settings) {} - }); - } - - /** - * Gets initial settings and passes these settings to the provided callback. - * The provided callback gets called when initial/default settings are available. The callback may be called after a delay, e.g. after the settings have been retrieved from a server, - * or immediately, e.g. when the implementation does not query information from server. - * This method produces no side-effects if it gets called multiple times. After this method has been called for the first time, subsequent calls will not produce any server round-trips - * or LocalStorage accesses due to its internal caching. - * - * @param settingsReceiverCallback The callback which supplies the caller with initial settings - */ - @Override - public void getInitialSettings(final OnSettingsLoadedCallback callback) { - if(cachedRootComponentSettings == null) { - S systemDefaultSettings = rootLifecycle.createDefaultSettings(); - settingsStorageManager.retrieveDefaultSettings(systemDefaultSettings, new OnSettingsLoadedCallback() { - - @Override - public void onError(Throwable caught, S fallbackDefaultSettings) { - cachedRootComponentSettings = fallbackDefaultSettings; - callback.onError(caught, fallbackDefaultSettings); - } - - @Override - public void onSuccess(S settings) { - cachedRootComponentSettings = settings; - callback.onSuccess(settings); - } - }); - } else { - callback.onSuccess(cachedRootComponentSettings); - } - } - - /** - * Gets initial settings of the provided component and passes these settings to the provided callback. - * The provided callback gets called when initial/default settings are available. The callback may be called after a delay, e.g. after the settings have been retrieved from a server, - * or immediately, e.g. when the implementation does not query information from server. - * This method produces no side-effects if it gets called multiple times. - * @param settingsReceiverCallback The callback which supplies the caller with initial settings - */ - @Override - public void getInitialSettingsForComponent(final Component component, final OnSettingsLoadedCallback callback) { - OnSettingsLoadedCallback internalCallback = new OnSettingsLoadedCallback() { - - @Override - public void onError(Throwable caught, S fallbackDefaultSettings) { - CS componentFallbackSettings = ComponentUtils.determineComponentSettingsFromPerspectiveSettings(new ArrayList<>(component.getPath()), fallbackDefaultSettings); - callback.onError(caught, componentFallbackSettings); - } - - @Override - public void onSuccess(S settings) { - CS componentSettings = ComponentUtils.determineComponentSettingsFromPerspectiveSettings(new ArrayList<>(component.getPath()), settings); - callback.onSuccess(componentSettings); - } - }; - getInitialSettings(internalCallback); - } - - protected void invalidateCachedSettings() { - cachedRootComponentSettings = null; - } - - /** - * Checks whether the {@link Settings} of the provided {@link Component} are - * storable and whether the underlying implementation supports - * {@link #makeSettingsDefault(Component, Settings)} calls for it. - * - * @param component The component with potentially storable settings - * @return {@code true} if the settings of the component are storable - * AND the {@link ComponentContext} implementation has settings - * storage support - */ - @Override - public boolean hasMakeCustomDefaultSettingsSupport(Component component) { - if (!component.hasSettings()) { - return false; - } - if(!settingsStorageManager.supportsStore()) { - return false; - } - Settings settings = component.getSettings(); - if (settings instanceof SettingsMap || settings instanceof GenericSerializableSettings) { - return true; - } - return false; - } - - /** - * Stores the provided {@link Settings} of the provided {@link Component} as "User Settings" globally. Make sure to - * call this method only when {@link #hasMakeCustomDefaultSettingsSupport(Component)} method returns {@code true} - * for the provided {@link Component}. - * - * @param component - * The component which corresponds to the provided {@link Settings} - * @param newDefaultSettings - * The {@link Settings} to be stored - * @param onSettingsStoredCallback The callback which is called when the settings storage process finishes - */ - @Override - public void makeSettingsDefault(Component component, CS newDefaultSettings, final OnSettingsStoredCallback onSettingsStoredCallback) { - invalidateCachedSettings(); - ComponentLifecycle targetLifecycle = ComponentUtils.determineLifecycle(new ArrayList<>(component.getPath()), rootLifecycle); - CS globalSettings = targetLifecycle.extractGlobalSettings(newDefaultSettings); - updateGlobalSettings(component.getPath(), globalSettings, onSettingsStoredCallback); - } - - /** - * Stores the provided {@link Settings} of the provided {@link Component} as "Document Settings" (old term "Context specific Settings") for the current context. Make sure to - * call this method only when {@link #hasMakeCustomDefaultSettingsSupport(Component)} method returns {@code true} - * for the provided {@link Component}. - * - * @param component - * The component which corresponds to the provided {@link Settings} - * @param newSettings - * The {@link Settings} to be stored - * @param onSettingsStoredCallback The callback which is called when the settings storage process finishes - */ - @Override - public void storeSettingsForContext(Component component, CS newSettings, OnSettingsStoredCallback onSettingsStoredCallback) { - invalidateCachedSettings(); - ComponentLifecycle targetLifecycle = ComponentUtils.determineLifecycle(new ArrayList<>(component.getPath()), rootLifecycle); - CS contextSpecificSettings = targetLifecycle.extractContextSpecificSettings(newSettings); - updateContextSpecificSettings(component.getPath(), contextSpecificSettings, onSettingsStoredCallback); - } - - - /** - * Patches the settings tree with the new settings provided. The settings node with the provided path - * is going to be created/replaced with the new settings. - * - * @param root The root node of the settings tree - * @param path The path of the node to create/update - * @param newSettings The new settings with that the target node in the settings tree is going to be updated - * @param pipelineLevel The scope of settings used for settings storage (e.g. User Settings, or Document Settings) - * @return The patched settings located by provided path as JSON - */ - private JSONObject patchJsonObject(JSONObject root, List path, Settings newSettings, PipelineLevel pipelineLevel) { - newSettings = cloneStorableSettings(newSettings, path); - return patchJsonObject(root, path, Collections.unmodifiableList(new ArrayList<>(path)), newSettings, pipelineLevel); - } - - @SuppressWarnings("unchecked") - private CS cloneStorableSettings(CS settingsToClone, List path) { - CS clonedSettings = ComponentUtils.determineComponentSettingsFromPerspectiveSettings(new ArrayList<>(path), rootLifecycle.createDefaultSettings()); - if(clonedSettings instanceof GenericSerializableSettings) { - GenericSerializableSettings newSettings = (GenericSerializableSettings) clonedSettings; - GenericSerializableSettings originalSettings = (GenericSerializableSettings) settingsToClone; - SettingsDefaultValuesUtils.keepDefaults(originalSettings, newSettings); - SettingsMergeUtils.setValues(originalSettings, newSettings); - clonedSettings = (CS) newSettings; - } - //TODO maybe add support for SettingsMap? Currently, SettingsMap is never provided as parameter to this method - return clonedSettings; - } - - /** - * Internal helper method for {@link #patchJsonObject(JSONObject, List, Settings, PipelineLevel)} - * - * @param root - * @param path - * @param originalPath - * @param newSettings - * @param pipelineLevel - * @return - */ - private JSONObject patchJsonObject(JSONObject root, List path, List originalPath, Settings newSettings, PipelineLevel pipelineLevel) { - if(path.isEmpty()) { - return (JSONObject) settingsStorageManager.settingsToJSON(newSettings, pipelineLevel, originalPath); - } - if (root == null) { - root = new JSONObject(); - } - String current = path.remove(path.size() - 1); - // we need to go further - if (!path.isEmpty()) { - JSONValue child = root.get(current); - boolean haskey = root.containsKey(current); - if (child == null || child.isObject() == null) { - if (haskey) { - GWT.log("Warning: replacing some subtree element that is wrong type!"); - } - child = new JSONObject(); - root.put(current, child); - } - return patchJsonObject(child.isObject(), path, originalPath, newSettings, pipelineLevel); - } else { - JSONValue json = settingsStorageManager.settingsToJSON(newSettings, pipelineLevel, originalPath); - root.put(current, json); - } - return root; - } - - /** - * Updates the User Settings' tree with the new settings provided. The settings node with the provided path - * is going to be created/replaced with the new settings. This method may produce a server round-trip - * if the user is logged in. - * - * @param path The path of the settings' node to create/update - * @param globalSettings User Settings which corresponds to the provided path - * @param onSettingsStoredCallback The callback which is called when the settings storage process finishes - */ - private void updateGlobalSettings(final ArrayList path, final Settings globalSettings, - final OnSettingsStoredCallback onSettingsStoredCallback) { - settingsStorageManager.retrieveSettingsJsons(new AsyncCallback() { - - @Override - public void onSuccess(SettingsJsons result) { - final JSONObject patchedGlobalSettings = patchJsonObject(result.getGlobalSettingsJson(), new ArrayList<>(path), - globalSettings, PipelineLevel.GLOBAL_DEFAULTS); - settingsStorageManager.storeGlobalSettingsJson(patchedGlobalSettings, onSettingsStoredCallback); - } - - @Override - public void onFailure(Throwable caught) { - onSettingsStoredCallback.onError(caught); - } - }); - } - - /** - * Updates the Document Settings' tree with the new settings provided. The settings node with the provided path - * is going to be created/replaced with the new settings. This method may produce a server round-trip - * if the user is logged in. - * - * @param path The path of the settings' node to create/update - * @param contextSpecificSettings Document Settings which corresponds to the provided path - * @param onSettingsStoredCallback The callback which is called when the settings storage process finishes - */ - private void updateContextSpecificSettings(final ArrayList path, final Settings contextSpecificSettings, - final OnSettingsStoredCallback onSettingsStoredCallback) { - settingsStorageManager.retrieveSettingsJsons(new AsyncCallback() { - - @Override - public void onSuccess(SettingsJsons result) { - final JSONObject patchedContextSpecificSettings = patchJsonObject(result.getContextSpecificSettingsJson(), new ArrayList<>(path), - contextSpecificSettings, PipelineLevel.CONTEXT_SPECIFIC_DEFAULTS); - settingsStorageManager.storeContextSpecificSettingsJson(patchedContextSpecificSettings, onSettingsStoredCallback); - } - - @Override - public void onFailure(Throwable caught) { - onSettingsStoredCallback.onError(caught); - } - }); - } - - /** - * {@inheritDoc} - */ - @Override - public void dispose() { - super.dispose(); - settingsStorageManager.dispose(); - } -} diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/settings/OnSettingsLoadedCallback.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/settings/OnSettingsLoadedCallback.java index 943d15fba19..43585a8548f 100644 --- a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/settings/OnSettingsLoadedCallback.java +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/settings/OnSettingsLoadedCallback.java @@ -1,8 +1,6 @@ package com.sap.sse.gwt.client.shared.settings; -import com.sap.sse.common.settings.Settings; - -public interface OnSettingsLoadedCallback { +public interface OnSettingsLoadedCallback { void onError(Throwable caught, S fallbackDefaultSettings); void onSuccess(S settings); } diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/settings/SettingsBuildingPipeline.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/settings/SettingsBuildingPipeline.java index bc6a00d6c24..8a145a090d5 100644 --- a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/settings/SettingsBuildingPipeline.java +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/settings/SettingsBuildingPipeline.java @@ -11,48 +11,25 @@ import com.sap.sse.common.settings.Settings; * implementation of this interface to define the desired way of how the settings are constructed from its persisted * JSON representation, and how the settings are transformed back into its persisted JSON representation. * The pipeline is being used in {@link SettingsStorageManager} when it loads and stores settings. - * It is highly recommended to use at least {@link AbstractSettingsBuildingPipeline} as basic class for - * implementation of this interface. * * @author Vladislav Chumak * + * @param The type of settings representation * @see SettingsStorageManager * @see AbstractSettingsBuildingPipeline * */ -public interface SettingsBuildingPipeline { +public interface SettingsBuildingPipeline { /** - * Constructs a settings object by means of provided defaultSettings and persisted representations of - * User Settings and Document Settings. + * Constructs a settings object by means of provided defaultSettings and persisted representations of Settings. * This method implements the settings construction pipeline for a settings object which is used for settings loading operations. * * @param defaultSettings The basic settings to be used - * @param settingsJsons The persisted representation of User Settings and Document Settings + * @param settingsRepresentation The persisted representation of Settings * @return The constructed settings object */ - S getSettingsObject(S defaultSettings, SettingsJsons settingsJsons); - - /** - * Constructs a settings object by means of provided defaultSettings and persisted representations of - * User Settings and Document Settings. - * This method implements the settings construction pipeline for a settings object which is used for settings loading operations. - * - * @param defaultSettings The basic settings to be used - * @param settingsJsons The persisted representation of User Settings and Document Settings - * @return The constructed settings object - */ - S getSettingsObject(S defaultSettings, SettingsStrings settingsStrings); - - /** - * Constructs a settings object by means of provided defaultSettings without considering - * User Settings and Document Settings. - * This method implements the settings construction pipeline for a settings object which is used for settings loading operations. - * - * @param defaultSettings The basic settings to be used - * @return The constructed settings object - */ - S getSettingsObject(S defaultSettings); + CS getSettingsObject(CS defaultSettings, S settingsRepresentation); /** * Converts the provided settings according the storage scope and path of the provided settings in the settings tree. @@ -65,12 +42,4 @@ public interface SettingsBuildingPipeline { */ JSONValue getJsonObject(Settings settings, PipelineLevel pipelineLevel, List path); - /** - * Gets the {@link SettingsStringConverter} which is used by this instance for type conversion/serialization - * between settings objects and JSON Strings. - * - * @return The conversion helper instance used by this pipeline - */ - SettingsStringConverter getSettingsStringConverter(); - } diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/settings/SettingsStringConverter.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/settings/SettingsSerializationHelper.java similarity index 62% rename from java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/settings/SettingsStringConverter.java rename to java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/settings/SettingsSerializationHelper.java index 7b66ad91d22..bbd449e1a79 100644 --- a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/settings/SettingsStringConverter.java +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/settings/SettingsSerializationHelper.java @@ -9,22 +9,21 @@ import com.sap.sse.gwt.settings.SettingsToJsonSerializerGWT; import com.sap.sse.gwt.settings.SettingsToUrlSerializer; /** - * Conversion helper which is used by this instance for type conversion/serialization - * between settings objects and JSON Strings. The class encapsulates all serializers - * which are required for serialization and deserialization and provides methods - * for an indirect serialization/deserialization functionality required by - * {@link SettingsBuildingPipeline} and {@link SettingsStorageManager} implementations. + * Conversion helper which is used by this instance for type conversion/serialization between settings objects and JSON + * Strings. The class encapsulates all serializers which are required for serialization and deserialization and provides + * methods for an indirect serialization/deserialization functionality required by {@link SettingsBuildingPipeline} and + * {@link ComponentContext} implementations. * * @author Vladislav Chumak * */ -public class SettingsStringConverter { +public class SettingsSerializationHelper { private final SettingsToUrlSerializer urlSerializer = new SettingsToUrlSerializer(); private final SettingsToJsonSerializerGWT jsonSerializer = new SettingsToJsonSerializerGWT(); - + @SuppressWarnings("unchecked") - public S deserializeFromCurrentUrl(S defaultSettings) { + public S deserializeFromCurrentUrl(S defaultSettings) { if (defaultSettings instanceof GenericSerializableSettings) { defaultSettings = (S) urlSerializer .deserializeFromCurrentLocation((GenericSerializableSettings) defaultSettings); @@ -34,9 +33,9 @@ public class SettingsStringConverter { } return defaultSettings; } - + @SuppressWarnings("unchecked") - public S deserializeFromJson(S defaultSettings, JSONObject jsonToDeserialize) { + public S deserializeFromJson(S defaultSettings, JSONObject jsonToDeserialize) { if (defaultSettings instanceof GenericSerializableSettings) { defaultSettings = (S) jsonSerializer.deserialize((GenericSerializableSettings) defaultSettings, jsonToDeserialize); @@ -46,31 +45,19 @@ public class SettingsStringConverter { return defaultSettings; } - public SettingsJsons convertToSettingsJson(SettingsStrings settingsStrings) { - JSONObject globalSettingsJson = convertStringToJson(settingsStrings.getGlobalSettingsString()); - JSONObject contextSpecificSettingsJson = convertStringToJson(settingsStrings.getContextSpecificSettingsString()); - return new SettingsJsons(globalSettingsJson, contextSpecificSettingsJson); - } - public JSONObject convertStringToJson(String str) { return str == null ? null : jsonSerializer.parseStringToJsonObject(str); } - + public String convertJsonToString(JSONObject json) { return json == null ? null : jsonSerializer.jsonObjectToString(json); } - - public SettingsStrings convertToSettingsStrings(SettingsJsons settingsJsons) { - String globalSettingsString = convertJsonToString(settingsJsons.getGlobalSettingsJson()); - String contextSpecificSettingsString = convertJsonToString(settingsJsons.getContextSpecificSettingsJson()); - return new SettingsStrings(globalSettingsString, contextSpecificSettingsString); - } - + public JSONValue serializeFromSettingsObject(Settings newSettings) { if (newSettings instanceof GenericSerializableSettings) { return jsonSerializer.serialize((GenericSerializableSettings) newSettings); } throw new IllegalStateException("Requested save of settings that is not Serializable!"); } - + } diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/settings/SettingsStorageManager.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/settings/SettingsStorageManager.java index 4fcb456fa44..d6d23f0b2cb 100644 --- a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/settings/SettingsStorageManager.java +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/settings/SettingsStorageManager.java @@ -1,11 +1,5 @@ package com.sap.sse.gwt.client.shared.settings; -import java.util.List; - -import com.google.gwt.json.client.JSONObject; -import com.google.gwt.json.client.JSONValue; -import com.google.gwt.user.client.rpc.AsyncCallback; -import com.sap.sse.common.settings.Settings; import com.sap.sse.common.settings.generic.GenericSerializableSettings; /** @@ -16,66 +10,43 @@ import com.sap.sse.common.settings.generic.GenericSerializableSettings; * * @author Vladislav Chumak * - * @param The {@link Settings} type of the settings of the root component/perspective containing all the settings for itself and its subcomponents + * @param The type of settings representation * @see ComponentContextWithSettingsStorage * @see GenericSerializableSettings */ -public interface SettingsStorageManager { +public interface SettingsStorageManager { - /** - * Tells whether the underlying implementation offers persistence for settings, or not. - * - * @return {@code True} if settings storage is supported, otherwise {@code false} - */ - boolean supportsStore(); +// /** +// * Tells whether storage of settings is supported, or not. +// * +// * @return {@code True} if settings storage is supported, otherwise {@code false} +// */ +// boolean supportsStore(); - /** - * Retrieves the {@link Settings} of the root component using the provided callback. - * Depending on the storage media, the callback may be called whether synchronously - * or asynchronously. - * - * @param defaultSettings The system default settings for the root component - * @param asyncCallback The callback to be called when the settings have been retrieved - * from the settings storage - */ - void retrieveDefaultSettings(S defaultSettings, - OnSettingsLoadedCallback asyncCallback); - - /** - * Stores provided settings as User Settings (old term "Global Settings"). Only the delta between default settings and provided settings - * will be stored. - * - * @param globalSettingsJson The settings to store - * @param onSettingsStoredCallback The callback which is called when the settings storage process gets finished - */ - void storeGlobalSettingsJson(JSONObject globalSettingsJson, OnSettingsStoredCallback onSettingsStoredCallback); - - /** - * Stores provided settings as Document Settings (old term "Context specific Settings"). Only the delta between default settings and provided settings - * will be stored. - * - * @param contextSpecificSettingsJson The settings to store - * @param onSettingsStoredCallback The callback which is called when the settings storage process gets finished - */ - void storeContextSpecificSettingsJson(JSONObject contextSpecificSettingsJson, - OnSettingsStoredCallback onSettingsStoredCallback); - - /** - * Converts the provided settings object to JSON. - * - * @param newSettings The settings to convert - * @param pipelineLevel The pipeline level indicating whether the provided settings should be converted for Document Settings storage, or User Settings storage - * @param path The path of the corresponding settings in the settings tree according to the component which the provided settings belong to - * @return The converted settings as JSON - */ - JSONValue settingsToJSON(Settings newSettings, PipelineLevel pipelineLevel, List path); +// /** +// * Converts the provided settings object to JSON. +// * +// * @param newSettings The settings to convert +// * @param pipelineLevel The pipeline level indicating whether the provided settings should be converted for Document Settings storage, or User Settings storage +// * @param path The path of the corresponding settings in the settings tree according to the component which the provided settings belong to +// * @return The converted settings as JSON +// */ +// JSONValue settingsToJSON(Settings newSettings, PipelineLevel pipelineLevel, List path); /** * Retrieves the stored JSON representations of Document Settings and User Settings which get packed together in {@link SettingsJsons}. * - * @param asyncCallback The callback which gets called when the persisted settings representation has been retrieved + * @param callback The callback which gets called when the persisted settings representation has been retrieved */ - void retrieveSettingsJsons(AsyncCallback asyncCallback); + void retrieveSettingsRepresentation(OnSettingsLoadedCallback callback); + + /** + * Stores provided settings representation. + * + * @param settingsRepresentation The settings to store + * @param onSettingsStoredCallback The callback which is called when the settings storage process gets finished + */ + void storeSettingsRepresentation(S settingsRepresentation, OnSettingsStoredCallback onSettingsStoredCallback); /** * Releases all resources and listener registrations acquired by this instance. diff --git a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/settings/ComponentContextWithSettingsStorage.java b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/settings/ComponentContextWithSettingsStorage.java new file mode 100644 index 00000000000..5ef915ae529 --- /dev/null +++ b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/settings/ComponentContextWithSettingsStorage.java @@ -0,0 +1,404 @@ +package com.sap.sse.security.ui.settings; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.json.client.JSONObject; +import com.google.gwt.json.client.JSONValue; +import com.sap.sse.common.settings.Settings; +import com.sap.sse.common.settings.generic.GenericSerializableSettings; +import com.sap.sse.common.settings.generic.SettingsMap; +import com.sap.sse.common.settings.util.SettingsDefaultValuesUtils; +import com.sap.sse.common.settings.util.SettingsMergeUtils; +import com.sap.sse.gwt.client.shared.components.Component; +import com.sap.sse.gwt.client.shared.components.ComponentLifecycle; +import com.sap.sse.gwt.client.shared.perspective.IgnoreLocalSettings; +import com.sap.sse.gwt.client.shared.settings.ComponentContext; +import com.sap.sse.gwt.client.shared.settings.ComponentUtils; +import com.sap.sse.gwt.client.shared.settings.OnSettingsLoadedCallback; +import com.sap.sse.gwt.client.shared.settings.OnSettingsStoredCallback; +import com.sap.sse.gwt.client.shared.settings.PipelineLevel; +import com.sap.sse.gwt.client.shared.settings.SettingsBuildingPipeline; +import com.sap.sse.gwt.client.shared.settings.SettingsJsons; +import com.sap.sse.gwt.client.shared.settings.SettingsSerializationHelper; +import com.sap.sse.gwt.client.shared.settings.SettingsStorageManager; +import com.sap.sse.gwt.client.shared.settings.SettingsStrings; +import com.sap.sse.security.ui.client.UserService; + +/** + * Manages all the default/initial settings of a component/perspective and its subcomponents if there are any. It + * supplies components with initial settings and determines whether the settings of components are storable or not. This + * implementation provides settings storage support if the storable settings either implement {@link SettingsMap} or + * {@link GenericSerializableSettings}. There are two kinds of settings which are stored separately - User + * Settings (old term "Global Settings") and Document Settings (old term "Context specific Settings"). + *
+ *
Document Settings
+ *
The settings are stored only for the current context (e.g. a race presented in a RaceBoard). This settings are + * not considered in any other context. See + * {@link #storeSettingsForContext(Component, Settings, OnSettingsStoredCallback)}
+ * + *
User Settings
+ *
The settings are stored for a component/perspective context-independently and may effect a different context + * presented by the same perspective/component, e.g. a different race in a RaceBoard. See + * {@link #makeSettingsDefault(Component, Settings, OnSettingsStoredCallback)}
+ *
+ * That means that Document Settings are stored per context (e.g. race in RaceBoard) whereas User Settings are stored + * globally for all possible contexts (e.g. for the whole RaceBoard independently from selected race). + *

The underlying access to settings storage gets disabled if the URL contains {@code ignoreLocalSettings=true} flag.

+ * + * + * @author Vladislav Chumak + * @see ComponentContext + * + * @param + * The {@link Settings} type of the settings of the root component/perspective containing all the settings + * for itself and its subcomponents + * + */ +public class ComponentContextWithSettingsStorage extends SimpleComponentContext { + + /** + * {@code SettingsJsons} which have which have been already queried from persistence layer, or {@code null} if + * previous settings retrievement has not been initiated. + */ + protected SettingsJsons cachedSettingsJsons = null; + + /** + * Manages the persistence layer of settings. + */ + protected final SettingsStorageManager settingsStorageManager; + + /** + * @param rootLifecycle + * The {@link ComponentLifecycle} of the root component/perspective + * @param userService + * The service which is used for server-side settings storage + * @param storageDefinitionId + * The definition for User Settings and Document Settings storage keys + */ + public ComponentContextWithSettingsStorage(ComponentLifecycle rootLifecycle, UserService userService, + StorageDefinitionId storageDefinitionId) { + this(rootLifecycle, userService, storageDefinitionId, new SettingsSerializationHelper()); + } + + protected ComponentContextWithSettingsStorage(ComponentLifecycle rootLifecycle, UserService userService, + StorageDefinitionId storageDefinitionId, SettingsSerializationHelper settingsSerializationHelper) { + this(rootLifecycle, userService, storageDefinitionId, settingsSerializationHelper, + new UserSettingsBuildingPipeline(settingsSerializationHelper)); + } + + protected ComponentContextWithSettingsStorage(ComponentLifecycle rootLifecycle, UserService userService, + StorageDefinitionId storageDefinitionId, SettingsSerializationHelper settingsSerializationHelper, + SettingsBuildingPipeline settingsBuildingPipeline) { + super(rootLifecycle, settingsSerializationHelper, settingsBuildingPipeline); + if(IgnoreLocalSettings.getIgnoreLocalSettingsFromCurrentUrl().isIgnoreLocalSettings()) { + this.settingsStorageManager = null; + } else { + this.settingsStorageManager = new UserSettingsStorageManager(userService, storageDefinitionId); + } + } + + /** + * Retrieves the initial settings and caches them for further calls of + * {@link #getInitialSettings(OnSettingsLoadedCallback)} and + * {@link #getInitialSettingsForComponent(Component, OnSettingsLoadedCallback)}. + */ + public void initialize() { + getInitialSettings(new OnSettingsLoadedCallback() { + @Override + public void onError(Throwable caught, S fallbackDefaultSettings) { + } + + @Override + public void onSuccess(S settings) { + } + }); + } + + /** + * Gets initial settings and passes these settings to the provided callback. The provided callback gets called when + * initial/default settings are available. The callback may be called after a delay, e.g. after the settings have + * been retrieved from a server, or immediately, e.g. when the implementation does not query information from + * server. This method produces no side-effects if it gets called multiple times. After this method has been called + * for the first time, subsequent calls will not produce any server round-trips or LocalStorage accesses due to its + * internal caching. + * + * @param settingsReceiverCallback + * The callback which supplies the caller with initial settings + */ + @Override + public void getInitialSettings(final OnSettingsLoadedCallback callback) { + final S systemDefaultSettings = rootLifecycle.createDefaultSettings(); + if (cachedSettingsJsons == null) { + if(settingsStorageManager != null) { + settingsStorageManager.retrieveSettingsRepresentation(new OnSettingsLoadedCallback() { + + @Override + public void onError(Throwable caught, SettingsStrings fallbackSettingsRepresentation) { + callback.onError(caught, getSettingsObject(fallbackSettingsRepresentation, systemDefaultSettings)); + } + + @Override + public void onSuccess(SettingsStrings settingsRepresentation) { + callback.onSuccess(getSettingsObject(settingsRepresentation, systemDefaultSettings)); + } + + }); + } else { + callback.onSuccess(getSettingsObject(new SettingsStrings(null, null), systemDefaultSettings)); + } + + } else { + S newDefaultSettings = settingsBuildingPipeline.getSettingsObject(systemDefaultSettings, + cachedSettingsJsons); + callback.onSuccess(newDefaultSettings); + } + } + + private S getSettingsObject(SettingsStrings settingsRepresentation, S systemDefaultSettings) { + cachedSettingsJsons = convertToSettingsJson(settingsRepresentation); + S settingsObject = settingsBuildingPipeline.getSettingsObject(systemDefaultSettings, + cachedSettingsJsons); + return settingsObject; + } + + /** + * Checks whether the {@link Settings} of the provided {@link Component} are storable and whether the underlying + * implementation enables {@link #makeSettingsDefault(Component, Settings)} calls for it. + * + * @param component + * The component with potentially storable settings + * @return {@code true} if the settings of the component are storable AND the {@link ComponentContext} + * implementation has settings storage support + */ + @Override + public boolean isStorageSupported(Component component) { + if (!component.hasSettings()) { + return false; + } + if(settingsStorageManager == null) { + return false; + } + Settings settings = component.getSettings(); + if (settings instanceof SettingsMap || settings instanceof GenericSerializableSettings) { + return true; + } + return false; + } + + /** + * Stores the provided {@link Settings} of the provided {@link Component} as "User Settings" globally. Make sure to + * call this method only when {@link #isStorageSupported(Component)} method returns {@code true} + * for the provided {@link Component}. + * + * @param component + * The component which corresponds to the provided {@link Settings} + * @param newDefaultSettings + * The {@link Settings} to be stored + * @param onSettingsStoredCallback + * The callback which is called when the settings storage process finishes + */ + @Override + public void makeSettingsDefault(Component component, CS newDefaultSettings, + final OnSettingsStoredCallback onSettingsStoredCallback) { + ComponentLifecycle targetLifecycle = ComponentUtils.determineLifecycle(new ArrayList<>(component.getPath()), + rootLifecycle); + CS globalSettings = targetLifecycle.extractGlobalSettings(newDefaultSettings); + updateGlobalSettings(component.getPath(), globalSettings, onSettingsStoredCallback); + } + + /** + * Stores the provided {@link Settings} of the provided {@link Component} as "Document Settings" (old term "Context + * specific Settings") for the current context. Make sure to call this method only when + * {@link #isStorageSupported(Component)} method returns {@code true} for the provided + * {@link Component}. + * + * @param component + * The component which corresponds to the provided {@link Settings} + * @param newSettings + * The {@link Settings} to be stored + * @param onSettingsStoredCallback + * The callback which is called when the settings storage process finishes + */ + @Override + public void storeSettingsForContext(Component component, CS newSettings, + OnSettingsStoredCallback onSettingsStoredCallback) { + ComponentLifecycle targetLifecycle = ComponentUtils.determineLifecycle(new ArrayList<>(component.getPath()), + rootLifecycle); + CS contextSpecificSettings = targetLifecycle.extractContextSpecificSettings(newSettings); + updateContextSpecificSettings(component.getPath(), contextSpecificSettings, onSettingsStoredCallback); + } + + /** + * Patches the settings tree with the new settings provided. The settings node with the provided path is going to be + * created/replaced with the new settings. + * + * @param root + * The root node of the settings tree + * @param path + * The path of the node to create/update + * @param newSettings + * The new settings with that the target node in the settings tree is going to be updated + * @param pipelineLevel + * The scope of settings used for settings storage (e.g. User Settings, or Document Settings) + * @return The patched settings located by provided path as JSON + */ + private JSONObject patchJsonObject(JSONObject root, List path, Settings newSettings, + PipelineLevel pipelineLevel) { + newSettings = cloneStorableSettings(newSettings, path); + return patchJsonObject(root, path, Collections.unmodifiableList(new ArrayList<>(path)), newSettings, + pipelineLevel); + } + + @SuppressWarnings("unchecked") + private CS cloneStorableSettings(CS settingsToClone, List path) { + CS clonedSettings = ComponentUtils.determineComponentSettingsFromPerspectiveSettings(new ArrayList<>(path), + rootLifecycle.createDefaultSettings()); + if (clonedSettings instanceof GenericSerializableSettings) { + GenericSerializableSettings newSettings = (GenericSerializableSettings) clonedSettings; + GenericSerializableSettings originalSettings = (GenericSerializableSettings) settingsToClone; + SettingsDefaultValuesUtils.keepDefaults(originalSettings, newSettings); + SettingsMergeUtils.setValues(originalSettings, newSettings); + clonedSettings = (CS) newSettings; + } + // TODO maybe add support for SettingsMap? Currently, SettingsMap is never provided as parameter to this method + return clonedSettings; + } + + /** + * Internal helper method for {@link #patchJsonObject(JSONObject, List, Settings, PipelineLevel)} + * + * @param root + * @param path + * @param originalPath + * @param newSettings + * @param pipelineLevel + * @return + */ + private JSONObject patchJsonObject(JSONObject root, List path, List originalPath, + Settings newSettings, PipelineLevel pipelineLevel) { + if (path.isEmpty()) { + return (JSONObject) settingsBuildingPipeline.getJsonObject(newSettings, pipelineLevel, originalPath); + } + if (root == null) { + root = new JSONObject(); + } + String current = path.remove(path.size() - 1); + // we need to go further + if (!path.isEmpty()) { + JSONValue child = root.get(current); + boolean haskey = root.containsKey(current); + if (child == null || child.isObject() == null) { + if (haskey) { + GWT.log("Warning: replacing some subtree element that is wrong type!"); + } + child = new JSONObject(); + root.put(current, child); + } + return patchJsonObject(child.isObject(), path, originalPath, newSettings, pipelineLevel); + } else { + JSONValue json = settingsBuildingPipeline.getJsonObject(newSettings, pipelineLevel, originalPath); + root.put(current, json); + } + return root; + } + + /** + * Updates the User Settings' tree with the new settings provided. The settings node with the provided path is going + * to be created/replaced with the new settings. This method may produce a server round-trip if the user is logged + * in. + * + * @param path + * The path of the settings' node to create/update + * @param globalSettings + * User Settings which corresponds to the provided path + * @param onSettingsStoredCallback + * The callback which is called when the settings storage process finishes + */ + private void updateGlobalSettings(final ArrayList path, final Settings globalSettings, + final OnSettingsStoredCallback onSettingsStoredCallback) { + settingsStorageManager.retrieveSettingsRepresentation(new OnSettingsLoadedCallback() { + + @Override + public void onError(Throwable caught, SettingsStrings fallbackDefaultSettings) { + onSettingsStoredCallback.onError(caught); + } + + @Override + public void onSuccess(SettingsStrings settingsRepresentation) { + SettingsJsons result = convertToSettingsJson(settingsRepresentation); + final JSONObject patchedGlobalSettings = patchJsonObject(result.getGlobalSettingsJson(), + new ArrayList<>(path), globalSettings, PipelineLevel.GLOBAL_DEFAULTS); + settingsRepresentation = convertToSettingsStrings(new SettingsJsons(patchedGlobalSettings, null)); + cachedSettingsJsons = new SettingsJsons(patchedGlobalSettings, cachedSettingsJsons.getContextSpecificSettingsJson()); + settingsStorageManager.storeSettingsRepresentation(settingsRepresentation, onSettingsStoredCallback); + } + + }); + } + + /** + * Updates the Document Settings' tree with the new settings provided. The settings node with the provided path is + * going to be created/replaced with the new settings. This method may produce a server round-trip if the user is + * logged in. + * + * @param path + * The path of the settings' node to create/update + * @param contextSpecificSettings + * Document Settings which corresponds to the provided path + * @param onSettingsStoredCallback + * The callback which is called when the settings storage process finishes + */ + private void updateContextSpecificSettings(final ArrayList path, final Settings contextSpecificSettings, + final OnSettingsStoredCallback onSettingsStoredCallback) { + settingsStorageManager.retrieveSettingsRepresentation(new OnSettingsLoadedCallback() { + + @Override + public void onError(Throwable caught, SettingsStrings fallbackDefaultSettings) { + onSettingsStoredCallback.onError(caught); + } + + @Override + public void onSuccess(SettingsStrings settingsRepresentation) { + SettingsJsons result = convertToSettingsJson(settingsRepresentation); + final JSONObject patchedContextSpecificSettings = patchJsonObject( + result.getContextSpecificSettingsJson(), new ArrayList<>(path), contextSpecificSettings, + PipelineLevel.CONTEXT_SPECIFIC_DEFAULTS); + settingsRepresentation = convertToSettingsStrings( + new SettingsJsons(null, patchedContextSpecificSettings)); + cachedSettingsJsons = new SettingsJsons(cachedSettingsJsons.getGlobalSettingsJson(), patchedContextSpecificSettings); + settingsStorageManager.storeSettingsRepresentation(settingsRepresentation, onSettingsStoredCallback); + } + }); + } + + /** + * {@inheritDoc} + */ + @Override + public void dispose() { + super.dispose(); + if(settingsStorageManager != null) { + settingsStorageManager.dispose(); + } + } + + public SettingsJsons convertToSettingsJson(SettingsStrings settingsStrings) { + JSONObject globalSettingsJson = settingsSerializationHelper + .convertStringToJson(settingsStrings.getGlobalSettingsString()); + JSONObject contextSpecificSettingsJson = settingsSerializationHelper + .convertStringToJson(settingsStrings.getContextSpecificSettingsString()); + return new SettingsJsons(globalSettingsJson, contextSpecificSettingsJson); + } + + public SettingsStrings convertToSettingsStrings(SettingsJsons settingsJsons) { + String globalSettingsString = settingsSerializationHelper + .convertJsonToString(settingsJsons.getGlobalSettingsJson()); + String contextSpecificSettingsString = settingsSerializationHelper + .convertJsonToString(settingsJsons.getContextSpecificSettingsJson()); + return new SettingsStrings(globalSettingsString, contextSpecificSettingsString); + } + +} diff --git a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/settings/ComponentContextWithSettingsStorageAndPatching.java b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/settings/ComponentContextWithSettingsStorageAndPatching.java index 7ae20378be0..3c3c213b81d 100644 --- a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/settings/ComponentContextWithSettingsStorageAndPatching.java +++ b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/settings/ComponentContextWithSettingsStorageAndPatching.java @@ -3,8 +3,9 @@ package com.sap.sse.security.ui.settings; import com.sap.sse.common.settings.Settings; import com.sap.sse.gwt.client.shared.components.Component; import com.sap.sse.gwt.client.shared.components.ComponentLifecycle; -import com.sap.sse.gwt.client.shared.settings.ComponentContextWithSettingsStorage; import com.sap.sse.gwt.client.shared.settings.PipelineLevel; +import com.sap.sse.gwt.client.shared.settings.SettingsSerializationHelper; +import com.sap.sse.security.ui.client.UserService; /** * Adds settings patching functionality to {@link ComponentContextWithSettingsStorage} implementation. @@ -26,20 +27,24 @@ import com.sap.sse.gwt.client.shared.settings.PipelineLevel; */ public class ComponentContextWithSettingsStorageAndPatching extends ComponentContextWithSettingsStorage { - /** - * Manages the persistence layer of settings. - */ - protected final UserSettingsStorageManagerWithPatching settingsStorageManager; - /** * @param rootLifecycle * The {@link ComponentLifecycle} of the root component/perspective - * @param settingsStorageManager - * The {@link UserSettingsStorageManagerWithPatching} to be used to access stored settings and to store new settings + * @param userService + * The service which is used for server-side settings storage + * @param storageDefinitionId + * The definition for User Settings and Document Settings storage keys */ - public ComponentContextWithSettingsStorageAndPatching(ComponentLifecycle rootLifecycle, UserSettingsStorageManagerWithPatching settingsStorageManager) { - super(rootLifecycle, settingsStorageManager); - this.settingsStorageManager = (UserSettingsStorageManagerWithPatching) super.settingsStorageManager; + public ComponentContextWithSettingsStorageAndPatching(ComponentLifecycle rootLifecycle, UserService userService, StorageDefinitionId storageDefinitionId) { + this(rootLifecycle, userService, storageDefinitionId, new SettingsSerializationHelper()); + } + + protected ComponentContextWithSettingsStorageAndPatching(ComponentLifecycle rootLifecycle, UserService userService, StorageDefinitionId storageDefinitionId, SettingsSerializationHelper settingsSerializationHelper) { + this(rootLifecycle, userService, storageDefinitionId, settingsSerializationHelper, new UserSettingsBuildingPipelineWithPatching(settingsSerializationHelper)); + } + + protected ComponentContextWithSettingsStorageAndPatching(ComponentLifecycle rootLifecycle, UserService userService, StorageDefinitionId storageDefinitionId, SettingsSerializationHelper settingsSerializationHelper, UserSettingsBuildingPipelineWithPatching settingsBuildingPipeline) { + super(rootLifecycle, userService, storageDefinitionId, settingsSerializationHelper, settingsBuildingPipeline); } /** @@ -50,7 +55,7 @@ public class ComponentContextWithSettingsStorageAndPatching * @param settingsPatch The settings patch to apply on settings */ public void addPatchForStoringSettings(Component component, PipelineLevel pipelineLevel, SettingsPatch settingsPatch) { - settingsStorageManager.addPatchForStoringSettings(component, pipelineLevel, settingsPatch); + ((UserSettingsBuildingPipelineWithPatching) settingsBuildingPipeline).addPatchForStoringSettings(component, pipelineLevel, settingsPatch); } /** @@ -61,8 +66,7 @@ public class ComponentContextWithSettingsStorageAndPatching * @param settingsPatch The settings patch to apply on settings */ public void addPatchForLoadingSettings(Component component, PipelineLevel pipelineLevel, SettingsPatch settingsPatch) { - invalidateCachedSettings(); - settingsStorageManager.addPatchForLoadingSettings(component, pipelineLevel, settingsPatch); + ((UserSettingsBuildingPipelineWithPatching) settingsBuildingPipeline).addPatchForLoadingSettings(component, pipelineLevel, settingsPatch); } } diff --git a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/settings/PlaceBasedComponentContextWithSettingsStorage.java b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/settings/PlaceBasedComponentContextWithSettingsStorage.java new file mode 100644 index 00000000000..61343ab2d69 --- /dev/null +++ b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/settings/PlaceBasedComponentContextWithSettingsStorage.java @@ -0,0 +1,75 @@ +package com.sap.sse.security.ui.settings; + +import com.sap.sse.common.settings.Settings; +import com.sap.sse.common.settings.generic.GenericSerializableSettings; +import com.sap.sse.common.settings.generic.SettingsMap; +import com.sap.sse.gwt.client.shared.components.ComponentLifecycle; +import com.sap.sse.gwt.client.shared.settings.SettingsBuildingPipeline; +import com.sap.sse.gwt.client.shared.settings.SettingsJsons; +import com.sap.sse.gwt.client.shared.settings.SettingsSerializationHelper; +import com.sap.sse.gwt.settings.SettingsToStringSerializer; +import com.sap.sse.security.ui.client.UserService; + +/** + * Specialization of {@link ComponentContextWithSettingsStorage} which reimplements URL deserialization. This implementation + * handles URL deserialization in such a way, that only the provided {@code serializedSettings} {@code String} is + * considered as URL, and not the URL in the browser. + * + * @author Vladislav Chumak + * + * @see ComponentContextWithSettingsStorage + * + */ +public class PlaceBasedComponentContextWithSettingsStorage extends ComponentContextWithSettingsStorage { + + /** + * Constructs a special case of {@link ComponentContextWithSettingsStorage} which considers the provided {@code serializedSettings} as + * URL parameters for deserialization of URL Settings. + * + * @param rootLifecycle + * The {@link ComponentLifecycle} of the root component/perspective + * @param userService + * The service which is used for server-side settings storage + * @param storageDefinitionId + * The definition for User Settings and Document Settings storage keys + * @param serializedSettings + * Contains URL parameters for serialization of URL Settings + */ + public PlaceBasedComponentContextWithSettingsStorage(ComponentLifecycle rootLifecycle, UserService userService, + StorageDefinitionId storageDefinitionId, final String serializedSettings) { + this(rootLifecycle, userService, storageDefinitionId, new SettingsSerializationHelper() { + + private final SettingsToStringSerializer settingsToStringSerializer = new SettingsToStringSerializer(); + + @SuppressWarnings("unchecked") + @Override + public CS deserializeFromCurrentUrl(CS defaultSettings) { + final CS result; + if (defaultSettings instanceof SettingsMap) { + result = (CS) settingsToStringSerializer.fromString(serializedSettings, + (SettingsMap) defaultSettings); + } else if (defaultSettings instanceof GenericSerializableSettings) { + result = (CS) settingsToStringSerializer.fromString(serializedSettings, + (GenericSerializableSettings) defaultSettings); + } else { + result = defaultSettings; + } + return result; + } + + }); + } + + protected PlaceBasedComponentContextWithSettingsStorage(ComponentLifecycle rootLifecycle, UserService userService, + StorageDefinitionId storageDefinitionId, SettingsSerializationHelper settingsSerializationHelper) { + this(rootLifecycle, userService, storageDefinitionId, settingsSerializationHelper, + new UserSettingsBuildingPipeline(settingsSerializationHelper)); + } + + protected PlaceBasedComponentContextWithSettingsStorage(ComponentLifecycle rootLifecycle, UserService userService, + StorageDefinitionId storageDefinitionId, SettingsSerializationHelper settingsSerializationHelper, + SettingsBuildingPipeline settingsBuildingPipeline) { + super(rootLifecycle, userService, storageDefinitionId, settingsSerializationHelper, settingsBuildingPipeline); + } + +} diff --git a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/settings/PlaceBasedUserSettingsBuildingPipeline.java b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/settings/PlaceBasedUserSettingsBuildingPipeline.java deleted file mode 100644 index 645c52381a1..00000000000 --- a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/settings/PlaceBasedUserSettingsBuildingPipeline.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.sap.sse.security.ui.settings; - -import com.sap.sse.common.settings.Settings; -import com.sap.sse.common.settings.generic.GenericSerializableSettings; -import com.sap.sse.common.settings.generic.SettingsMap; -import com.sap.sse.gwt.client.shared.settings.SettingsStringConverter; -import com.sap.sse.gwt.settings.SettingsToStringSerializer; - -/** - * Specialization of {@link UserSettingsBuildingPipeline} which reimplements URL deserialization. - * This implementation handles URL deserialization in such a way, that only the provided - * {@code serializedSettings} {@code String} is considered as URL, and not the URL in the browser. - * - * @author Vladislav Chumak - * - * @see UserSettingsBuildingPipeline - * - */ -public class PlaceBasedUserSettingsBuildingPipeline extends UserSettingsBuildingPipeline { - - /** - * Constructs an instance with a custom conversion helper which considers the provided {@code serializedSettings} - * as URL parameters for deserialization of URL Settings. - * - * @param serializedSettings - */ - public PlaceBasedUserSettingsBuildingPipeline(final String serializedSettings) { - super(new SettingsStringConverter() { - - private final SettingsToStringSerializer settingsToStringSerializer = new SettingsToStringSerializer(); - - @SuppressWarnings("unchecked") - @Override - public S deserializeFromCurrentUrl(S defaultSettings) { - final S result; - if (defaultSettings instanceof SettingsMap) { - result = (S) settingsToStringSerializer.fromString(serializedSettings, (SettingsMap) defaultSettings); - } else if (defaultSettings instanceof GenericSerializableSettings) { - result = (S) settingsToStringSerializer.fromString(serializedSettings, - (GenericSerializableSettings) defaultSettings); - } else { - result = defaultSettings; - } - return result; - } - - }); - } - -} diff --git a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/settings/PlaceBasedUserSettingsStorageManager.java b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/settings/PlaceBasedUserSettingsStorageManager.java deleted file mode 100644 index d0676fb2364..00000000000 --- a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/settings/PlaceBasedUserSettingsStorageManager.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.sap.sse.security.ui.settings; - -import com.sap.sse.common.settings.Settings; -import com.sap.sse.security.ui.client.UserService; - -/** - * Specialization of {@link UserSettingsStorageManager} which uses {@link PlaceBasedUserSettingsBuildingPipeline} for settings construction. - * - * @author Vladislav Chumak - * - * @param - * The {@link Settings} type of the settings of the root component/perspective containing all the settings - * for itself and its subcomponents - */ -public class PlaceBasedUserSettingsStorageManager extends UserSettingsStorageManager { - - public PlaceBasedUserSettingsStorageManager(UserService userService, StorageDefinitionId storageDefinitionId, String serializedSettings) { - super(userService, storageDefinitionId, new PlaceBasedUserSettingsBuildingPipeline(serializedSettings)); - } - -} diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/settings/SimpleComponentContext.java b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/settings/SimpleComponentContext.java similarity index 57% rename from java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/settings/SimpleComponentContext.java rename to java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/settings/SimpleComponentContext.java index 940a08ce23a..6099273b283 100644 --- a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/settings/SimpleComponentContext.java +++ b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/settings/SimpleComponentContext.java @@ -1,16 +1,22 @@ -package com.sap.sse.gwt.client.shared.settings; +package com.sap.sse.security.ui.settings; import java.util.ArrayList; import com.sap.sse.common.settings.Settings; import com.sap.sse.gwt.client.shared.components.Component; import com.sap.sse.gwt.client.shared.components.ComponentLifecycle; +import com.sap.sse.gwt.client.shared.settings.ComponentContext; +import com.sap.sse.gwt.client.shared.settings.ComponentUtils; +import com.sap.sse.gwt.client.shared.settings.OnSettingsLoadedCallback; +import com.sap.sse.gwt.client.shared.settings.OnSettingsStoredCallback; +import com.sap.sse.gwt.client.shared.settings.SettingsBuildingPipeline; +import com.sap.sse.gwt.client.shared.settings.SettingsJsons; +import com.sap.sse.gwt.client.shared.settings.SettingsSerializationHelper; /** * Manages all default settings of perspectives and components. This simple implementation has no support for settings * storage. It is only capable of creating new default settings by means of {@link ComponentLifecycle#createDefaultSettings()} of the root - * component managed by this {@link ComponentContext}. All in all, it is a dummy implementation for components which does - * not have support for settings storage. If you need settings to be stored, consider + * component managed by this {@link ComponentContext}, considering the URL parameters. If you need settings to be stored, consider * {@link ComponentContextWithSettingsStorage}. * * @author Vladislav Chumak @@ -20,6 +26,13 @@ import com.sap.sse.gwt.client.shared.components.ComponentLifecycle; * for itself and its subcomponents */ public class SimpleComponentContext implements ComponentContext { + + protected final SettingsSerializationHelper settingsSerializationHelper; + + /** + * The pipeline used for the settings construction. + */ + protected final SettingsBuildingPipeline settingsBuildingPipeline; /** * The {@link ComponentLifecycle} of the root component/perspective @@ -32,7 +45,17 @@ public class SimpleComponentContext implements ComponentCont * The {@link ComponentLifecycle} of the root component/perspective */ public SimpleComponentContext(ComponentLifecycle rootLifecycle) { + this(rootLifecycle, new SettingsSerializationHelper()); + } + + protected SimpleComponentContext(ComponentLifecycle rootLifecycle, SettingsSerializationHelper settingsSerializationHelper) { + this(rootLifecycle, settingsSerializationHelper, new UrlSettingsBuildingPipeline(settingsSerializationHelper)); + } + + protected SimpleComponentContext(ComponentLifecycle rootLifecycle, SettingsSerializationHelper settingsSerializationHelper, SettingsBuildingPipeline settingsBuildingPipeline) { this.rootLifecycle = rootLifecycle; + this.settingsSerializationHelper = settingsSerializationHelper; + this.settingsBuildingPipeline = settingsBuildingPipeline; } /** @@ -70,15 +93,16 @@ public class SimpleComponentContext implements ComponentCont * * @return The {@link Settings} of the root component */ - public S getDefaultSettings() { - return rootLifecycle.createDefaultSettings(); + private S getDefaultSettings() { + S defaultSettings = rootLifecycle.createDefaultSettings(); + return settingsBuildingPipeline.getSettingsObject(defaultSettings, new SettingsJsons(null, null)); } /** * This method returns always {@code false}, because it does not offer functionality for settings storage. */ @Override - public boolean hasMakeCustomDefaultSettingsSupport(Component component) { + public boolean isStorageSupported(Component component) { return false; } @@ -101,14 +125,25 @@ public class SimpleComponentContext implements ComponentCont } /** - * Retrieves the "System Default" {@link Settings} of the provided component and passes them to the provided callback. - * - * @see #getDefaultSettings() + * {@inheritDoc} */ @Override public void getInitialSettingsForComponent(final Component component, final OnSettingsLoadedCallback callback) { - ComponentLifecycle componentLifecycle = ComponentUtils.determineLifecycle(new ArrayList<>(component.getPath()), rootLifecycle); - callback.onSuccess(componentLifecycle.createDefaultSettings()); - } + OnSettingsLoadedCallback internalCallback = new OnSettingsLoadedCallback() { + @Override + public void onError(Throwable caught, S fallbackDefaultSettings) { + CS componentFallbackSettings = ComponentUtils.determineComponentSettingsFromPerspectiveSettings(new ArrayList<>(component.getPath()), fallbackDefaultSettings); + callback.onError(caught, componentFallbackSettings); + } + + @Override + public void onSuccess(S settings) { + CS componentSettings = ComponentUtils.determineComponentSettingsFromPerspectiveSettings(new ArrayList<>(component.getPath()), settings); + callback.onSuccess(componentSettings); + } + }; + getInitialSettings(internalCallback); + } + } diff --git a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/settings/SimpleSettingsStorageManager.java b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/settings/SimpleSettingsStorageManager.java deleted file mode 100644 index 3ee1e16208c..00000000000 --- a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/settings/SimpleSettingsStorageManager.java +++ /dev/null @@ -1,92 +0,0 @@ -package com.sap.sse.security.ui.settings; - -import java.util.List; - -import com.google.gwt.json.client.JSONObject; -import com.google.gwt.json.client.JSONValue; -import com.google.gwt.user.client.rpc.AsyncCallback; -import com.sap.sse.common.settings.Settings; -import com.sap.sse.gwt.client.shared.settings.OnSettingsLoadedCallback; -import com.sap.sse.gwt.client.shared.settings.OnSettingsStoredCallback; -import com.sap.sse.gwt.client.shared.settings.PipelineLevel; -import com.sap.sse.gwt.client.shared.settings.SettingsJsons; -import com.sap.sse.gwt.client.shared.settings.SettingsStorageManager; - -/** - * This {@link SettingsStorageManager} implementation only reads settings from the URL and does not support settings storage. - * - * @param - * The {@link Settings} type of the settings of the root component/perspective containing all the settings - * for itself and its subcomponents - * @see SettingsStorageManager - */ -public class SimpleSettingsStorageManager implements SettingsStorageManager { - - /** - * The pipeline used for the settings construction. - */ - protected final UrlSettingsBuildingPipeline settingsBuildingPipeline; - - /** - * Constructs the instance with a {@link UrlSettingsBuildingPipeline}. - */ - public SimpleSettingsStorageManager() { - settingsBuildingPipeline = new UrlSettingsBuildingPipeline(); - } - - /** - * {@inheritDoc} - */ - @Override - public boolean supportsStore() { - return false; - } - - /** - * {@inheritDoc} - */ - @Override - public void retrieveDefaultSettings(S defaultSettings, final OnSettingsLoadedCallback asyncCallback) { - asyncCallback.onSuccess(settingsBuildingPipeline.getSettingsObject(defaultSettings)); - } - - /** - * {@inheritDoc} - */ - @Override - public void storeGlobalSettingsJson(JSONObject globalSettingsJson, OnSettingsStoredCallback onSettingsStoredCallback) { - throw new UnsupportedOperationException("Settings storage is unsupported by SimpleSettingsStorageManager"); - } - - /** - * {@inheritDoc} - */ - @Override - public void storeContextSpecificSettingsJson(JSONObject contextSpecificSettingsJson, - OnSettingsStoredCallback onSettingsStoredCallback) { - throw new UnsupportedOperationException("Settings storage is unsupported by SimpleSettingsStorageManager"); - } - - /** - * {@inheritDoc} - */ - @Override - public JSONValue settingsToJSON(Settings newSettings, PipelineLevel pipelineLevel, List path) { - throw new UnsupportedOperationException("Settings storage is unsupported by SimpleSettingsStorageManager"); - } - - /** - * {@inheritDoc} - */ - @Override - public void retrieveSettingsJsons(AsyncCallback asyncCallback) { - throw new UnsupportedOperationException("Settings storage is unsupported by SimpleSettingsStorageManager"); - } - - /** - * {@inheritDoc} - */ - @Override - public void dispose() { - } -} diff --git a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/settings/UrlSettingsBuildingPipeline.java b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/settings/UrlSettingsBuildingPipeline.java index 29dc8994795..4d50ed9dfde 100644 --- a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/settings/UrlSettingsBuildingPipeline.java +++ b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/settings/UrlSettingsBuildingPipeline.java @@ -4,41 +4,60 @@ import java.util.List; import com.google.gwt.json.client.JSONValue; import com.sap.sse.common.settings.Settings; -import com.sap.sse.gwt.client.shared.settings.AbstractSettingsBuildingPipeline; import com.sap.sse.gwt.client.shared.settings.PipelineLevel; +import com.sap.sse.gwt.client.shared.settings.SettingsBuildingPipeline; import com.sap.sse.gwt.client.shared.settings.SettingsJsons; +import com.sap.sse.gwt.client.shared.settings.SettingsSerializationHelper; import com.sap.sse.gwt.client.shared.settings.SettingsStorageManager; /** - * Settings building pipeline which is only capable of reading settings from URL. - * Conversion to JSON is not supported. This implementation is supposed to be used by {@link SettingsStorageManager} - * which offers read-only functionality for settings, and thus, does not provide persistence support. + * Settings building pipeline which is only capable of reading settings from URL. Conversion to JSON is not supported. + * This implementation is supposed to be used by {@link SettingsStorageManager} which offers read-only functionality for + * settings, and thus, does not provide persistence support. * * * @author Vladislav Chumak * */ -public class UrlSettingsBuildingPipeline extends AbstractSettingsBuildingPipeline { - +public class UrlSettingsBuildingPipeline implements SettingsBuildingPipeline { + /** - * Constructs a settings object by means of provided defaultSettings and current URL. - * - * @param defaultSettings The basic settings to be used - * @param settingsJsons The persisted representation of User Settings and Document Settings, which is ignored by this implementation - * @return The constructed settings object + * Conversion helper which is used by this instance for type conversion/serialization between settings objects and + * JSON Strings. */ - @Override - public S getSettingsObject(S defaultSettings, SettingsJsons settingsJsons) { - return settingsStringConverter.deserializeFromCurrentUrl(defaultSettings); + protected final SettingsSerializationHelper settingsSerializationHelper; + + /** + * Constructs an instance with a custom conversion helper between settings objects and its JSON representation. + * + * @param settingsSerializationHelper + * The custom conversion helper + */ + public UrlSettingsBuildingPipeline(SettingsSerializationHelper settingsSerializationHelper) { + this.settingsSerializationHelper = settingsSerializationHelper; } /** - * This implementation does not provide support for JSON conversion of settings objects, because it is supposed to be used - * by read-only {@link SettingsStorageManager} implementations. + * Constructs a settings object by means of provided defaultSettings and current URL. + * + * @param defaultSettings + * The basic settings to be used + * @param settingsRepresentation + * The persisted representation of Settings, which is ignored by this implementation + * @return The constructed settings object + */ + @Override + public S getSettingsObject(S defaultSettings, SettingsJsons settingsRepresentation) { + return settingsSerializationHelper.deserializeFromCurrentUrl(defaultSettings); + } + + /** + * This implementation does not provide support for JSON conversion of settings objects, because it is supposed to + * be used by read-only {@link SettingsStorageManager} implementations. */ @Override public JSONValue getJsonObject(Settings settings, PipelineLevel pipelineLevel, List path) { throw new UnsupportedOperationException("This pipeline does not support JSON conversion"); } - + } diff --git a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/settings/UserSettingsBuildingPipeline.java b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/settings/UserSettingsBuildingPipeline.java index 0d7b906d8dd..2d820aca1d7 100644 --- a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/settings/UserSettingsBuildingPipeline.java +++ b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/settings/UserSettingsBuildingPipeline.java @@ -4,72 +4,80 @@ import java.util.List; import com.google.gwt.json.client.JSONValue; import com.sap.sse.common.settings.Settings; -import com.sap.sse.gwt.client.shared.settings.AbstractSettingsBuildingPipeline; +import com.sap.sse.gwt.client.shared.perspective.IgnoreLocalSettings; import com.sap.sse.gwt.client.shared.settings.PipelineLevel; import com.sap.sse.gwt.client.shared.settings.SettingsJsons; -import com.sap.sse.gwt.client.shared.settings.SettingsStringConverter; +import com.sap.sse.gwt.client.shared.settings.SettingsSerializationHelper; /** - * Settings building pipeline which is capable of building settings considering - * System Default Settings, persisted representations of - * User Settings and Document Settings, and current URL. - * The precedence of settings is: + * Settings building pipeline which is capable of building settings considering System Default Settings, persisted + * representations of User Settings and Document Settings, and current URL. The precedence of settings is: *
    - *
  • System Default Settings
  • - *
  • User Settings
  • - *
  • Document Settings
  • - *
  • URL Settings
  • + *
  • System Default Settings
  • + *
  • User Settings
  • + *
  • Document Settings
  • + *
  • URL Settings
  • *
* * @author Vladislav Chumak * */ -public class UserSettingsBuildingPipeline extends AbstractSettingsBuildingPipeline { - +public class UserSettingsBuildingPipeline extends UrlSettingsBuildingPipeline { + /** - * Constructs an instance with a custom conversion helper between - * settings objects and its JSON representation. + * Constructs an instance with a custom conversion helper between settings objects and its JSON representation. + * + * @param settingsSerializationHelper + * The custom conversion helper */ - protected UserSettingsBuildingPipeline(SettingsStringConverter settingsStringConverter) { + public UserSettingsBuildingPipeline(SettingsSerializationHelper settingsStringConverter) { super(settingsStringConverter); } - + /** - * Constructs an instance with {@link SettingsStringConverter} as conversion helper between - * settings objects and its JSON representation. - */ - public UserSettingsBuildingPipeline() { - } - - /** - * Constructs a settings object by means of provided defaultSettings, persisted representations of - * User Settings and Document Settings, and current URL. + * Constructs a settings object by means of provided defaultSettings, persisted representations of User Settings and + * Document Settings, and current URL. * - * @param defaultSettings The basic settings to be used - * @param settingsJsons The persisted representation of User Settings and Document Settings + * @param defaultSettings + * The basic settings to be used + * @param settingsJsons + * The persisted representation of User Settings and Document Settings * @return The constructed settings object */ - public S getSettingsObject(S defaultSettings, SettingsJsons settingsJsons) { - if(settingsJsons.getContextSpecificSettingsJson() != null) { - defaultSettings = settingsStringConverter.deserializeFromJson(defaultSettings, settingsJsons.getContextSpecificSettingsJson()); - } else if(settingsJsons.getGlobalSettingsJson() != null) { - defaultSettings = settingsStringConverter.deserializeFromJson(defaultSettings, settingsJsons.getGlobalSettingsJson()); + @Override + public CS getSettingsObject(CS defaultSettings, SettingsJsons settingsJsons) { + if (!isIgnoreLocalSettingsUrlFlagPresent()) { + if (settingsJsons.getContextSpecificSettingsJson() != null) { + defaultSettings = settingsSerializationHelper.deserializeFromJson(defaultSettings, + settingsJsons.getContextSpecificSettingsJson()); + } else if (settingsJsons.getGlobalSettingsJson() != null) { + defaultSettings = settingsSerializationHelper.deserializeFromJson(defaultSettings, + settingsJsons.getGlobalSettingsJson()); + } } - defaultSettings = settingsStringConverter.deserializeFromCurrentUrl(defaultSettings); + defaultSettings = settingsSerializationHelper.deserializeFromCurrentUrl(defaultSettings); return defaultSettings; } /** - * Converts the provided settings object into a JSON representation without considering provided pipeline level and settings tree path. + * Converts the provided settings object into a JSON representation without considering provided pipeline level and + * settings tree path. * - * @param settings The settings to convert to JSON representation - * @param pipelineLevel The pipeline level which indicates the storage scope, e.g. User Settings or Document Settings. - * @param path The path of the settings in the settings tree + * @param settings + * The settings to convert to JSON representation + * @param pipelineLevel + * The pipeline level which indicates the storage scope, e.g. User Settings or Document Settings. + * @param path + * The path of the settings in the settings tree * @return The JSON representation of the provided settings */ @Override public JSONValue getJsonObject(Settings newSettings, PipelineLevel pipelineLevel, List path) { - return settingsStringConverter.serializeFromSettingsObject(newSettings); + return settingsSerializationHelper.serializeFromSettingsObject(newSettings); } - + + public boolean isIgnoreLocalSettingsUrlFlagPresent() { + return settingsSerializationHelper.deserializeFromCurrentUrl(new IgnoreLocalSettings()).isIgnoreLocalSettings(); + } + } diff --git a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/settings/UserSettingsBuildingPipelineWithPatching.java b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/settings/UserSettingsBuildingPipelineWithPatching.java index 967702cf453..d4d34eca191 100644 --- a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/settings/UserSettingsBuildingPipelineWithPatching.java +++ b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/settings/UserSettingsBuildingPipelineWithPatching.java @@ -13,78 +13,100 @@ import com.sap.sse.gwt.client.shared.components.Component; import com.sap.sse.gwt.client.shared.settings.ComponentUtils; import com.sap.sse.gwt.client.shared.settings.PipelineLevel; import com.sap.sse.gwt.client.shared.settings.SettingsJsons; +import com.sap.sse.gwt.client.shared.settings.SettingsSerializationHelper; /** - * Specialization of {@link UserSettingsBuildingPipeline} which offers multiple hooks for settings patching - * throughout the pipeline. These hooks may be used to patch the settings at different pipeline levels during its construction. - * This implementation provides additional methods for attachment of {@link SettingsPatch}s. - * After each {@link PipelineLevel} a custom {@link SettingsPatch} - * may be applied. The patch may partially or completely modify the resulting settings object in order to provide - * the desired behavior of default settings for a dynamic environment, e.g. RaceBoard which determines its default settings regarding - * to RaceModes, PlayModes and etc. + * Specialization of {@link UserSettingsBuildingPipeline} which offers multiple hooks for settings patching throughout + * the pipeline. These hooks may be used to patch the settings at different pipeline levels during its construction. + * This implementation provides additional methods for attachment of {@link SettingsPatch}s. After each + * {@link PipelineLevel} a custom {@link SettingsPatch} may be applied. The patch may partially or completely modify the + * resulting settings object in order to provide the desired behavior of default settings for a dynamic environment, + * e.g. RaceBoard which determines its default settings regarding to RaceModes, PlayModes and etc. * * @author Vladislav Chumak * */ public class UserSettingsBuildingPipelineWithPatching extends UserSettingsBuildingPipeline { - + private SettingsPatches patchesForStoringSettings = new SettingsPatches(); private SettingsPatches patchesForLoadingSettings = new SettingsPatches(); - + /** - * Constructs a settings object by means of provided defaultSettings, persisted representations of - * User Settings and Document Settings, current URL, and loading patches, which have been added to this - * pipeline instance. + * Constructs an instance with a custom conversion helper between settings objects and its JSON representation. * - * @param defaultSettings The basic settings to be used - * @param settingsJsons The persisted representation of User Settings and Document Settings + * @param settingsSerializationHelper + * The custom conversion helper + */ + public UserSettingsBuildingPipelineWithPatching(SettingsSerializationHelper settingsStringConverter) { + super(settingsStringConverter); + } + + /** + * Constructs a settings object by means of provided defaultSettings, persisted representations of User Settings and + * Document Settings, current URL, and loading patches, which have been added to this pipeline instance. + * + * @param defaultSettings + * The basic settings to be used + * @param settingsJsons + * The persisted representation of User Settings and Document Settings * @return The constructed settings object */ @Override public CS getSettingsObject(CS defaultSettings, SettingsJsons settingsJsons) { + boolean ignoreLocalSettings = isIgnoreLocalSettingsUrlFlagPresent(); + defaultSettings = applyPatchesForPipelineLevel(defaultSettings, PipelineLevel.SYSTEM_DEFAULTS); - if(settingsJsons.getContextSpecificSettingsJson() != null) { + if (!ignoreLocalSettings && settingsJsons.getContextSpecificSettingsJson() != null) { defaultSettings = applyPatchesForPipelineLevel(defaultSettings, PipelineLevel.GLOBAL_DEFAULTS); - defaultSettings = settingsStringConverter.deserializeFromJson(defaultSettings, settingsJsons.getContextSpecificSettingsJson()); - } else if(settingsJsons.getGlobalSettingsJson() != null) { - defaultSettings = settingsStringConverter.deserializeFromJson(defaultSettings, settingsJsons.getGlobalSettingsJson()); + defaultSettings = settingsSerializationHelper.deserializeFromJson(defaultSettings, + settingsJsons.getContextSpecificSettingsJson()); + } else if (!ignoreLocalSettings && settingsJsons.getGlobalSettingsJson() != null) { + defaultSettings = settingsSerializationHelper.deserializeFromJson(defaultSettings, + settingsJsons.getGlobalSettingsJson()); defaultSettings = applyPatchesForPipelineLevel(defaultSettings, PipelineLevel.GLOBAL_DEFAULTS); } else { defaultSettings = applyPatchesForPipelineLevel(defaultSettings, PipelineLevel.GLOBAL_DEFAULTS); } defaultSettings = applyPatchesForPipelineLevel(defaultSettings, PipelineLevel.CONTEXT_SPECIFIC_DEFAULTS); - defaultSettings = settingsStringConverter.deserializeFromCurrentUrl(defaultSettings); + defaultSettings = settingsSerializationHelper.deserializeFromCurrentUrl(defaultSettings); return defaultSettings; } private CS applyPatchesForPipelineLevel(CS defaultSettings, PipelineLevel pipelineLevel) { - for (Entry, List>> entry : patchesForLoadingSettings.getSettingsPatches(pipelineLevel).entrySet()) { + for (Entry, List>> entry : patchesForLoadingSettings + .getSettingsPatches(pipelineLevel).entrySet()) { List path = entry.getKey(); List> settingsPatches = entry.getValue(); - if(!settingsPatches.isEmpty()) { - Settings patchedComponentSettings = ComponentUtils.determineComponentSettingsFromPerspectiveSettings(new ArrayList<>(path), defaultSettings); + if (!settingsPatches.isEmpty()) { + Settings patchedComponentSettings = ComponentUtils + .determineComponentSettingsFromPerspectiveSettings(new ArrayList<>(path), defaultSettings); for (SettingsPatch settingsPatch : settingsPatches) { patchedComponentSettings = patchSettings(patchedComponentSettings, settingsPatch); } - defaultSettings = ComponentUtils.patchSettingsTree(new ArrayList<>(path), patchedComponentSettings, defaultSettings); + defaultSettings = ComponentUtils.patchSettingsTree(new ArrayList<>(path), patchedComponentSettings, + defaultSettings); } } return defaultSettings; } - + /** - * Converts the provided settings object into a JSON representation considering storing patches, - * which have been added to this pipeline instance. + * Converts the provided settings object into a JSON representation considering storing patches, which have been + * added to this pipeline instance. * - * @param settings The settings to convert to JSON representation - * @param pipelineLevel The pipeline level which indicates the storage scope, e.g. User Settings or Document Settings. - * @param path The path of the settings in the settings tree + * @param settings + * The settings to convert to JSON representation + * @param pipelineLevel + * The pipeline level which indicates the storage scope, e.g. User Settings or Document Settings. + * @param path + * The path of the settings in the settings tree * @return The JSON representation of the provided settings */ @Override public JSONValue getJsonObject(Settings settings, PipelineLevel pipelineLevel, List path) { for (PipelineLevel level : pipelineLevel.getSortedLevelsUntilCurrent()) { - List> settingsPatches = patchesForStoringSettings.getSettingsPatches(path, level); + List> settingsPatches = patchesForStoringSettings.getSettingsPatches(path, + level); for (SettingsPatch settingsPatch : settingsPatches) { settings = patchSettings(settings, settingsPatch); } @@ -93,76 +115,90 @@ public class UserSettingsBuildingPipelineWithPatching extends UserSettingsBuildi } @SuppressWarnings("unchecked") - private CS patchSettings(Settings settings, SettingsPatch settingsPatch) { + private CS patchSettings(Settings settings, SettingsPatch settingsPatch) { return settingsPatch.patchSettings((CS) settings); } - + /** * Adds a settings patch for transforming settings before storing them. * - * @param component The component which the targeted settings for patching belong to - * @param pipelineLevel The pipeline level AFTER that the patch should be applied on settings - * @param settingsPatch The settings patch to apply on settings + * @param component + * The component which the targeted settings for patching belong to + * @param pipelineLevel + * The pipeline level AFTER that the patch should be applied on settings + * @param settingsPatch + * The settings patch to apply on settings */ - public void addPatchForStoringSettings(Component component, PipelineLevel pipelineLevel, SettingsPatch settingsPatch) { + public void addPatchForStoringSettings(Component component, PipelineLevel pipelineLevel, + SettingsPatch settingsPatch) { patchesForStoringSettings.addSettingsPatch(component.getPath(), settingsPatch, pipelineLevel); } - + /** * Adds a settings patch for settings object construction. * - * @param component The component which the targeted settings for patching belong to - * @param pipelineLevel The pipeline level AFTER that the patch should be applied on settings - * @param settingsPatch The settings patch to apply on settings + * @param component + * The component which the targeted settings for patching belong to + * @param pipelineLevel + * The pipeline level AFTER that the patch should be applied on settings + * @param settingsPatch + * The settings patch to apply on settings */ - public void addPatchForLoadingSettings(Component component, PipelineLevel pipelineLevel, SettingsPatch settingsPatch) { + public void addPatchForLoadingSettings(Component component, PipelineLevel pipelineLevel, + SettingsPatch settingsPatch) { patchesForLoadingSettings.addSettingsPatch(component.getPath(), settingsPatch, pipelineLevel); } - + /** - * Internal helper class for management of provided settings patches in relation to its pipeline levels - * and components that provided patches belong to. + * Internal helper class for management of provided settings patches in relation to its pipeline levels and + * components that provided patches belong to. * * @author Vladislav Chumak * */ private static class SettingsPatches { - + private Map, List>>> patchesForSettings = new HashMap<>(); - - public void addSettingsPatch(List path, SettingsPatch settingsPatch, PipelineLevel pipelineLevel) { - Map, List>> pipelinePatches = patchesForSettings.get(pipelineLevel); - if(pipelinePatches == null) { + + public void addSettingsPatch(List path, SettingsPatch settingsPatch, + PipelineLevel pipelineLevel) { + Map, List>> pipelinePatches = patchesForSettings + .get(pipelineLevel); + if (pipelinePatches == null) { pipelinePatches = new HashMap<>(); patchesForSettings.put(pipelineLevel, pipelinePatches); } List> componentPatches = pipelinePatches.get(path); - if(componentPatches == null) { + if (componentPatches == null) { componentPatches = new ArrayList<>(); pipelinePatches.put(path, componentPatches); } componentPatches.add(settingsPatch); } - - public List> getSettingsPatches(List path, PipelineLevel pipelineLevel) { - Map, List>> pipelinePatches = patchesForSettings.get(pipelineLevel); - if(pipelinePatches == null) { + + public List> getSettingsPatches(List path, + PipelineLevel pipelineLevel) { + Map, List>> pipelinePatches = patchesForSettings + .get(pipelineLevel); + if (pipelinePatches == null) { return Collections.emptyList(); } List> componentPatches = pipelinePatches.get(path); - if(componentPatches == null) { + if (componentPatches == null) { return Collections.emptyList(); } return componentPatches; } - - public Map, List>> getSettingsPatches(PipelineLevel pipelineLevel) { - Map, List>> pipelinePatches = patchesForSettings.get(pipelineLevel); - if(pipelinePatches == null) { + + public Map, List>> getSettingsPatches( + PipelineLevel pipelineLevel) { + Map, List>> pipelinePatches = patchesForSettings + .get(pipelineLevel); + if (pipelinePatches == null) { return Collections.emptyMap(); } return pipelinePatches; } } - + } \ No newline at end of file diff --git a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/settings/UserSettingsStorageManager.java b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/settings/UserSettingsStorageManager.java index 79f8df80213..5b7456fcf33 100644 --- a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/settings/UserSettingsStorageManager.java +++ b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/settings/UserSettingsStorageManager.java @@ -7,20 +7,12 @@ import java.util.List; import java.util.Map; import java.util.Queue; -import com.google.gwt.json.client.JSONObject; -import com.google.gwt.json.client.JSONValue; import com.google.gwt.storage.client.Storage; import com.google.gwt.user.client.rpc.AsyncCallback; -import com.sap.sse.common.settings.Settings; -import com.sap.sse.gwt.client.shared.perspective.IgnoreLocalSettings; import com.sap.sse.gwt.client.shared.settings.OnSettingsLoadedCallback; import com.sap.sse.gwt.client.shared.settings.OnSettingsStoredCallback; -import com.sap.sse.gwt.client.shared.settings.PipelineLevel; -import com.sap.sse.gwt.client.shared.settings.SettingsBuildingPipeline; -import com.sap.sse.gwt.client.shared.settings.SettingsJsons; import com.sap.sse.gwt.client.shared.settings.SettingsStorageManager; import com.sap.sse.gwt.client.shared.settings.SettingsStrings; -import com.sap.sse.gwt.settings.SettingsToUrlSerializer; import com.sap.sse.security.ui.client.UserService; import com.sap.sse.security.ui.client.UserStatusEventHandler; import com.sap.sse.security.ui.shared.UserDTO; @@ -31,23 +23,10 @@ import com.sap.sse.security.ui.shared.UserDTO; * * @author Vladislav Chumak * - * @param - * The {@link Settings} type of the settings of the root component/perspective containing all the settings - * for itself and its subcomponents * @see SettingsStorageManager */ -public class UserSettingsStorageManager implements SettingsStorageManager { +public class UserSettingsStorageManager implements SettingsStorageManager { - /** - * {@code SettingsJsons} which have which have been already queried from persistence layer, or {@code null} if previous settings retrievement has not been initiated. - */ - protected SettingsJsons cachedSettingsJsons = null; - - /** - * The pipeline used for the settings construction. - */ - protected final SettingsBuildingPipeline settingsBuildingPipeline; - /** * The key which is associated with the User Settings. Different keys will cause multiple/different settings * instances to be stored in the storage. @@ -78,109 +57,76 @@ public class UserSettingsStorageManager implements SettingsS /** * Callbacks which are waiting to be called when persistent settings representation has loaded. */ - private Queue> retrieveSettingsCallbacksQueue = new LinkedList<>(); + private Queue> retrieveSettingsCallbacksQueue = new LinkedList<>(); /** - * Constructs the instance with a custom {@link SettingsBuildingPipeline}. - * * @param userService The service which is used for server-side settings storage * @param storageDefinitionId The definition for User Settings and Document Settings storage keys - * @param settingsBuildingPipeline The custom pipeline to be used for settings construction */ - protected UserSettingsStorageManager(UserService userService, StorageDefinitionId storageDefinitionId, SettingsBuildingPipeline settingsBuildingPipeline) { - this.settingsBuildingPipeline = settingsBuildingPipeline; + public UserSettingsStorageManager(UserService userService, StorageDefinitionId storageDefinitionId) { this.userService = userService; this.storageGlobalKey = storageDefinitionId.generateStorageGlobalKey(); this.storageContextSpecificKey = storageDefinitionId.generateStorageContextSpecificKey(); } - /** - * Constructs the instance with {@link UserSettingsBuildingPipeline}. - * - * @param userService The service which is used for server-side settings storage - * @param storageDefinitionId The definition for User Settings and Document Settings storage keys - */ - public UserSettingsStorageManager(UserService userService, StorageDefinitionId storageDefinitionId) { - this(userService, storageDefinitionId, new UserSettingsBuildingPipeline()); + @Override + public void storeSettingsRepresentation(SettingsStrings settingsStrings, OnSettingsStoredCallback onSettingsStoredCallback) { + storeSettingsStringsOnLocalStorage(settingsStrings); + if (userService.getCurrentUser() != null) { + storeSettingsStringsOnServer(settingsStrings, onSettingsStoredCallback); + } else { + onSettingsStoredCallback.onSuccess(); + } } - /** - * {@inheritDoc} - */ - @Override - public boolean supportsStore() { - return true; - } - - private void storeSettingsStringsOnLocalStorage(SettingsStrings settingsStrings, boolean storeGlobalSettings, boolean storeContextSpecificSettings) { + private void storeSettingsStringsOnLocalStorage(SettingsStrings settingsStrings) { Storage localStorage = Storage.getLocalStorageIfSupported(); if (localStorage != null) { - if(storeGlobalSettings) { + if(settingsStrings.getGlobalSettingsString() != null) { localStorage.removeItem(storageGlobalKey); - if(settingsStrings.getGlobalSettingsString() != null) { - localStorage.setItem(storageGlobalKey, settingsStrings.getGlobalSettingsString()); - } + localStorage.setItem(storageGlobalKey, settingsStrings.getGlobalSettingsString()); } - if(storeContextSpecificSettings) { + if(settingsStrings.getContextSpecificSettingsString() != null) { localStorage.removeItem(storageContextSpecificKey); - if(settingsStrings.getContextSpecificSettingsString() != null) { - localStorage.setItem(storageContextSpecificKey, settingsStrings.getContextSpecificSettingsString()); - } + localStorage.setItem(storageContextSpecificKey, settingsStrings.getContextSpecificSettingsString()); } } } - private void storeSettingsStringsOnServer(SettingsStrings settingsStrings, final OnSettingsStoredCallback onSettingsStoredCallback, boolean storeGlobalSettings, boolean storeContextSpecificSettings) { - Map keyValuePairs = new HashMap<>(); - if(storeGlobalSettings) { - keyValuePairs.put(storageGlobalKey, settingsStrings.getGlobalSettingsString()); - } - if(storeContextSpecificSettings) { - keyValuePairs.put(storageContextSpecificKey, settingsStrings.getContextSpecificSettingsString()); - } - userService.setPreferences(keyValuePairs, new AsyncCallback() { - + private void storeSettingsStringsOnServer(SettingsStrings settingsStrings, final OnSettingsStoredCallback onSettingsStoredCallback) { + AsyncCallback asyncCallback = new AsyncCallback() { + @Override public void onFailure(Throwable caught) { onSettingsStoredCallback.onError(caught); } - + @Override public void onSuccess(Void result) { onSettingsStoredCallback.onSuccess(); } - }); + }; + + if(settingsStrings.getContextSpecificSettingsString() == null || settingsStrings.getGlobalSettingsString() == null) { + if(settingsStrings.getContextSpecificSettingsString() != null) { + userService.setPreference(storageContextSpecificKey, settingsStrings.getContextSpecificSettingsString(), asyncCallback); + } + if(settingsStrings.getGlobalSettingsString() != null) { + userService.setPreference(storageGlobalKey, settingsStrings.getGlobalSettingsString(), asyncCallback); + } + } else { + Map keyValuePairs = new HashMap<>(); + if(settingsStrings.getGlobalSettingsString() != null) { + keyValuePairs.put(storageGlobalKey, settingsStrings.getGlobalSettingsString()); + } + if(settingsStrings.getContextSpecificSettingsString() != null) { + keyValuePairs.put(storageContextSpecificKey, settingsStrings.getContextSpecificSettingsString()); + } + userService.setPreferences(keyValuePairs, asyncCallback); + } + } - /** - * {@inheritDoc} - */ - @Override - public void retrieveDefaultSettings(final S defaultSettings, final OnSettingsLoadedCallback callback) { - if(cachedSettingsJsons == null) { - retrieveSettingsJsons(new AsyncCallback() { - - @Override - public void onFailure(Throwable caught) { - SettingsStrings localStorageSettings = retrieveSettingsStringsFromLocalStorage(); - S newDefaultSettings = settingsBuildingPipeline.getSettingsObject(defaultSettings, localStorageSettings); - cachedSettingsJsons = settingsBuildingPipeline.getSettingsStringConverter().convertToSettingsJson(localStorageSettings); - callback.onError(caught, newDefaultSettings); - } - - @Override - public void onSuccess(SettingsJsons settingsJsons) { - S newDefaultSettings = settingsBuildingPipeline.getSettingsObject(defaultSettings, settingsJsons); - cachedSettingsJsons = settingsJsons; - callback.onSuccess(newDefaultSettings); - } - }); - } else { - S newDefaultSettings = settingsBuildingPipeline.getSettingsObject(defaultSettings, cachedSettingsJsons); - callback.onSuccess(newDefaultSettings); - } - } - /** * {@inheritDoc} */ @@ -220,55 +166,13 @@ public class UserSettingsStorageManager implements SettingsS }); } - /** - * {@inheritDoc} - */ - @Override - public JSONValue settingsToJSON(Settings newSettings, PipelineLevel pipelineLevel, List path) { - return settingsBuildingPipeline.getJsonObject(newSettings, pipelineLevel, path); - } - - private void storeSettingsJsons(SettingsJsons settingsJsons, OnSettingsStoredCallback onSettingsStoredCallback, boolean storeGlobalSettings, boolean storeContextSpecificSettings) { - invalidateCache(); - SettingsStrings settingsStrings = settingsBuildingPipeline.getSettingsStringConverter().convertToSettingsStrings(settingsJsons); - storeSettingsStringsOnLocalStorage(settingsStrings, storeGlobalSettings, storeContextSpecificSettings); - if (userService.getCurrentUser() != null) { - storeSettingsStringsOnServer(settingsStrings, onSettingsStoredCallback, storeGlobalSettings, storeContextSpecificSettings); - } else { - onSettingsStoredCallback.onSuccess(); - } - } - - public void invalidateCache() { - cachedSettingsJsons = null; - } - - /** - * {@inheritDoc} - */ - @Override - public void storeGlobalSettingsJson(JSONObject globalSettingsJson, - OnSettingsStoredCallback onSettingsStoredCallback) { - SettingsJsons settingsJsons = new SettingsJsons(globalSettingsJson, null); - storeSettingsJsons(settingsJsons, onSettingsStoredCallback, true, false); - } /** * {@inheritDoc} */ @Override - public void storeContextSpecificSettingsJson(JSONObject contextSpecificSettingsJson, - OnSettingsStoredCallback onSettingsStoredCallback) { - SettingsJsons settingsJsons = new SettingsJsons(null, contextSpecificSettingsJson); - storeSettingsJsons(settingsJsons, onSettingsStoredCallback, false, true); - } - - /** - * {@inheritDoc} - */ - @Override - public void retrieveSettingsJsons(AsyncCallback asyncCallback) { - retrieveSettingsCallbacksQueue.add(asyncCallback); + public void retrieveSettingsRepresentation(OnSettingsLoadedCallback callback) { + retrieveSettingsCallbacksQueue.add(callback); if(userStatusEventHandler == null) { this.userStatusEventHandler = new UserStatusEventHandler() { @@ -277,22 +181,22 @@ public class UserSettingsStorageManager implements SettingsS //call this method always on user status change event in order to cause sync between local storage and server if(!initialUserSetting) { initialUserSetting = true; - requestSettingsJsons(); + retrieveSettingsStringsFromServerOrLocalStorage(); } } }; userService.addUserStatusEventHandler(userStatusEventHandler, true); } else if(initialUserSetting) { - requestSettingsJsons(); + retrieveSettingsStringsFromServerOrLocalStorage(); } } - private void requestSettingsJsons() { + private void retrieveSettingsStringsFromServerOrLocalStorage() { if (userService.getCurrentUser() == null) { SettingsStrings settingsStrings = retrieveSettingsStringsFromLocalStorage(); - AsyncCallback asyncCallback; - while((asyncCallback = retrieveSettingsCallbacksQueue.poll()) != null) { - asyncCallback.onSuccess(settingsBuildingPipeline.getSettingsStringConverter().convertToSettingsJson(settingsStrings)); + OnSettingsLoadedCallback callback; + while((callback = retrieveSettingsCallbacksQueue.poll()) != null) { + callback.onSuccess(settingsStrings); } } else { retrieveSettingsStringsFromServer(new AsyncCallback() { @@ -300,17 +204,18 @@ public class UserSettingsStorageManager implements SettingsS @Override public void onSuccess(SettingsStrings serverSettingsStrings) { serverSettingsStrings = syncLocalStorageAndServer(serverSettingsStrings); - AsyncCallback asyncCallback; - while((asyncCallback = retrieveSettingsCallbacksQueue.poll()) != null) { - asyncCallback.onSuccess(settingsBuildingPipeline.getSettingsStringConverter().convertToSettingsJson(serverSettingsStrings)); + OnSettingsLoadedCallback callback; + while((callback = retrieveSettingsCallbacksQueue.poll()) != null) { + callback.onSuccess(serverSettingsStrings); } } @Override public void onFailure(Throwable caught) { - AsyncCallback asyncCallback; - while((asyncCallback = retrieveSettingsCallbacksQueue.poll()) != null) { - asyncCallback.onFailure(caught); + SettingsStrings fallbackSettingsStrings = retrieveSettingsStringsFromLocalStorage(); + OnSettingsLoadedCallback callback; + while((callback = retrieveSettingsCallbacksQueue.poll()) != null) { + callback.onError(caught, fallbackSettingsStrings); } } }); @@ -332,28 +237,13 @@ public class UserSettingsStorageManager implements SettingsS public void onError(Throwable caught) { //nothing to do } - }, true, true); + }); } serverSettingsStrings = localStorageSettingsStrings; } else { - storeSettingsStringsOnLocalStorage(serverSettingsStrings, true, true); + storeSettingsStringsOnLocalStorage(serverSettingsStrings); } return serverSettingsStrings; } - /** - * Creates a {@link SettingsStorageManager} instance based on the ignoreLocalSettings URL flag. if - * ignoreLocalSettings is set to true, a SimpleSettingsStorageManager is created. A - * UserSettingsStorageManager is created otherwise. - */ - public static SettingsStorageManager createSettingsStorageManager(UserService userService, StorageDefinitionId storageDefinitionId) { - if (getIgnoreLocalSettings().isIgnoreLocalSettings()) { - return new SimpleSettingsStorageManager<>(); - } - return new UserSettingsStorageManager<>(userService, storageDefinitionId); - } - - public static IgnoreLocalSettings getIgnoreLocalSettings() { - return new SettingsToUrlSerializer().deserializeFromCurrentLocation(new IgnoreLocalSettings()); - } } diff --git a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/settings/UserSettingsStorageManagerWithPatching.java b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/settings/UserSettingsStorageManagerWithPatching.java deleted file mode 100644 index 889f8e9f12b..00000000000 --- a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/settings/UserSettingsStorageManagerWithPatching.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.sap.sse.security.ui.settings; - -import com.sap.sse.common.settings.Settings; -import com.sap.sse.gwt.client.shared.components.Component; -import com.sap.sse.gwt.client.shared.settings.PipelineLevel; -import com.sap.sse.security.ui.client.UserService; - -/** - * Specialization of {@link UserSettingsStorageManager} which uses {@link UserSettingsBuildingPipelineWithPatching} for settings construction. - * This implementation provides additional methods for attachment of {@link SettingsPatch}s. There are multiple hooks in - * the underlying {@link UserSettingsBuildingPipelineWithPatching} which can be used to influence the - * settings construction in its construction pipeline. After each {@link PipelineLevel} a custom {@link SettingsPatch} - * may be applied. The patch may partially or completely modify the resulting settings object in order to provide - * the desired behavior of default settings for a dynamic environment, e.g. RaceBoard which determines its default settings regarding - * to RaceModes, PlayModes and etc. - * - * @author Vladislav Chumak - * - * @param - * The {@link Settings} type of the settings of the root component/perspective containing all the settings - * for itself and its subcomponents - */ -public class UserSettingsStorageManagerWithPatching extends UserSettingsStorageManager { - - /** - * The typed pipeline used for the settings construction. - */ - protected final UserSettingsBuildingPipelineWithPatching settingsBuildingPipeline; - - /** - * Constructs the instance with {@link UserSettingsBuildingPipelineWithPatching}. - * - * @param userService The service which is used for server-side settings storage - * @param storageDefinitionId The definition for User Settings and Document Settings storage keys - */ - public UserSettingsStorageManagerWithPatching(UserService userService, StorageDefinitionId storageDefinitionId) { - super(userService, storageDefinitionId, new UserSettingsBuildingPipelineWithPatching()); - settingsBuildingPipeline = (UserSettingsBuildingPipelineWithPatching) super.settingsBuildingPipeline; - } - - /** - * Adds a settings patch for transforming settings before storing them. - * - * @param component The component which the targeted settings for patching belong to - * @param pipelineLevel The pipeline level AFTER that the patch should be applied on settings - * @param settingsPatch The settings patch to apply on settings - */ - public void addPatchForStoringSettings(Component component, PipelineLevel pipelineLevel, SettingsPatch settingsPatch) { - settingsBuildingPipeline.addPatchForStoringSettings(component, pipelineLevel, settingsPatch); - } - - /** - * Adds a settings patch for settings object construction. - * - * @param component The component which the targeted settings for patching belong to - * @param pipelineLevel The pipeline level AFTER that the patch should be applied on settings - * @param settingsPatch The settings patch to apply on settings - */ - public void addPatchForLoadingSettings(Component component, PipelineLevel pipelineLevel, SettingsPatch settingsPatch) { - settingsBuildingPipeline.addPatchForLoadingSettings(component, pipelineLevel, settingsPatch); - } - -}