# TabletConfiguration is cached on client side

# TabletConfiguration is applied
This commit is contained in:
Lukas Niemeier committed 2013-10-08 17:59:52 +02:00
1 parent ccd6fa0159
commit be5cdbf511
10 files changed
+151 -56

No files matched your search

@@ -2,6 +2,7 @@ package com.sap.sailing.racecommittee.app;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import android.content.Context;
import android.content.SharedPreferences;
@@ -110,6 +111,16 @@ public class AppPreferences {
return Arrays.asList(managedCourseAreas);
}
public static void setManagedCourseAreaNames(Context context, Set<String> courseAreaNames) {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
StringBuilder builder = new StringBuilder();
for (String name : courseAreaNames) {
builder.append(name);
builder.append(",");
}
sp.edit().putString(PREFERENCE_MANAGED_COURSE_AREAS, builder.substring(0, builder.length() - 1)).commit();
}
public static double getWindBearingFromDirection(Context context) {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
long windBearingAsLong = sp.getLong(PREFERENCE_WIND_BEARING, 0);
@@ -7,7 +7,9 @@ import com.sap.sailing.domain.base.CourseArea;
import com.sap.sailing.domain.base.CourseBase;
import com.sap.sailing.domain.base.EventBase;
import com.sap.sailing.domain.base.Mark;
import com.sap.sailing.domain.base.TabletConfiguration;
import com.sap.sailing.racecommittee.app.domain.ManagedRace;
import com.sap.sailing.server.gateway.deserialization.impl.TabletConfigurationJsonDeserializer;
public interface DataStore {
@@ -35,4 +37,7 @@ public interface DataStore {
public CourseBase getLastPublishedCourseDesign();
public void setLastPublishedCourseDesign(CourseBase courseData);
public TabletConfiguration getTabletConfiguration();
public void setTabletConfiguration(TabletConfiguration configuration);
}
@@ -8,6 +8,7 @@ import com.sap.sailing.domain.base.CourseArea;
import com.sap.sailing.domain.base.CourseBase;
import com.sap.sailing.domain.base.EventBase;
import com.sap.sailing.domain.base.Mark;
import com.sap.sailing.domain.base.TabletConfiguration;
import com.sap.sailing.racecommittee.app.domain.ManagedRace;
import com.sap.sailing.racecommittee.app.utils.CollectionUtils;
@@ -18,6 +19,7 @@ public enum InMemoryDataStore implements DataStore {
private HashMap<Serializable, ManagedRace> managedRaceById;
private HashMap<Serializable, Mark> marksById;
private CourseBase courseData;
private TabletConfiguration configuration;
private InMemoryDataStore() {
reset();
@@ -28,7 +30,6 @@ public enum InMemoryDataStore implements DataStore {
this.eventsById = new HashMap<Serializable, EventBase>();
this.managedRaceById = new HashMap<Serializable, ManagedRace>();
this.marksById = new HashMap<Serializable, Mark>();
this.courseData = null;
}
/*
@@ -162,4 +163,14 @@ public enum InMemoryDataStore implements DataStore {
public void setLastPublishedCourseDesign(CourseBase courseData) {
this.courseData = courseData;
}
@Override
public TabletConfiguration getTabletConfiguration() {
return configuration;
}
@Override
public void setTabletConfiguration(TabletConfiguration configuration) {
this.configuration = configuration;
}
}
@@ -17,6 +17,8 @@ import com.sap.sailing.domain.base.CourseArea;
import com.sap.sailing.domain.base.CourseBase;
import com.sap.sailing.domain.base.EventBase;
import com.sap.sailing.domain.base.Mark;
import com.sap.sailing.domain.base.TabletConfiguration;
import com.sap.sailing.domain.base.TabletConfigurationIdentifier;
import com.sap.sailing.domain.base.impl.BoatClassImpl;
import com.sap.sailing.domain.base.impl.CompetitorImpl;
import com.sap.sailing.domain.base.impl.CourseAreaImpl;
@@ -192,12 +194,12 @@ public class OfflineDataManager extends DataManager {
}
@Override
public LoaderCallbacks<DataLoaderResult<String>> createConfigurationLoader(String clientId,
LoadClient<String> callback) {
return new ImmediateDataLoaderCallbacks<String>(context, callback, new Callable<String>() {
public LoaderCallbacks<DataLoaderResult<TabletConfiguration>> createConfigurationLoader(TabletConfigurationIdentifier identifier,
LoadClient<TabletConfiguration> callback) {
return new ImmediateDataLoaderCallbacks<TabletConfiguration>(context, callback, new Callable<TabletConfiguration>() {
@Override
public String call() throws Exception {
return "";
public TabletConfiguration call() throws Exception {
throw new IllegalStateException("No remote configuration in offline mode.");
}
});
}
@@ -1,7 +1,5 @@
package com.sap.sailing.racecommittee.app.data;
import java.io.BufferedReader;
import java.io.Reader;
import java.io.Serializable;
import java.net.URL;
import java.net.URLEncoder;
@@ -20,6 +18,8 @@ import com.sap.sailing.domain.base.CourseBase;
import com.sap.sailing.domain.base.EventBase;
import com.sap.sailing.domain.base.Mark;
import com.sap.sailing.domain.base.SharedDomainFactory;
import com.sap.sailing.domain.base.TabletConfiguration;
import com.sap.sailing.domain.base.TabletConfigurationIdentifier;
import com.sap.sailing.racecommittee.app.AppPreferences;
import com.sap.sailing.racecommittee.app.data.clients.LoadClient;
import com.sap.sailing.racecommittee.app.data.handlers.CompetitorsDataHandler;
@@ -28,7 +28,7 @@ import com.sap.sailing.racecommittee.app.data.handlers.DataHandler;
import com.sap.sailing.racecommittee.app.data.handlers.EventsDataHandler;
import com.sap.sailing.racecommittee.app.data.handlers.ManagedRacesDataHandler;
import com.sap.sailing.racecommittee.app.data.handlers.MarksDataHandler;
import com.sap.sailing.racecommittee.app.data.handlers.NullDataHandler;
import com.sap.sailing.racecommittee.app.data.handlers.TabletConfigurationDataHandler;
import com.sap.sailing.racecommittee.app.data.loaders.DataLoaderCallbacks;
import com.sap.sailing.racecommittee.app.data.loaders.DataLoaderCallbacks.LoaderCreator;
import com.sap.sailing.racecommittee.app.data.loaders.DataLoaderResult;
@@ -40,6 +40,7 @@ import com.sap.sailing.racecommittee.app.data.parsers.DataParser;
import com.sap.sailing.racecommittee.app.data.parsers.EventsDataParser;
import com.sap.sailing.racecommittee.app.data.parsers.ManagedRacesDataParser;
import com.sap.sailing.racecommittee.app.data.parsers.MarksDataParser;
import com.sap.sailing.racecommittee.app.data.parsers.TabletConfigurationParser;
import com.sap.sailing.racecommittee.app.domain.ManagedRace;
import com.sap.sailing.racecommittee.app.domain.ManagedRaceIdentifier;
import com.sap.sailing.racecommittee.app.domain.impl.DomainFactoryImpl;
@@ -56,6 +57,7 @@ import com.sap.sailing.server.gateway.deserialization.impl.CompetitorDeserialize
import com.sap.sailing.server.gateway.deserialization.impl.CourseAreaJsonDeserializer;
import com.sap.sailing.server.gateway.deserialization.impl.EventBaseJsonDeserializer;
import com.sap.sailing.server.gateway.deserialization.impl.FleetDeserializer;
import com.sap.sailing.server.gateway.deserialization.impl.TabletConfigurationJsonDeserializer;
import com.sap.sailing.server.gateway.deserialization.impl.VenueJsonDeserializer;
import com.sap.sailing.server.gateway.deserialization.racegroup.impl.RaceCellDeserializer;
import com.sap.sailing.server.gateway.deserialization.racegroup.impl.RaceGroupDeserializer;
@@ -233,32 +235,19 @@ public class OnlineDataManager extends DataManager {
}
@Override
public LoaderCallbacks<DataLoaderResult<String>> createConfigurationLoader(final String clientId,
LoadClient<String> callback) {
return new DataLoaderCallbacks<String>(callback, new LoaderCreator<String>() {
public LoaderCallbacks<DataLoaderResult<TabletConfiguration>> createConfigurationLoader(final TabletConfigurationIdentifier identifier,
LoadClient<TabletConfiguration> callback) {
return new DataLoaderCallbacks<TabletConfiguration>(callback, new LoaderCreator<TabletConfiguration>() {
@Override
public Loader<DataLoaderResult<String>> create(int id, Bundle args) throws Exception {
public Loader<DataLoaderResult<TabletConfiguration>> create(int id, Bundle args) throws Exception {
ExLog.i(TAG, String.format("Creating Configuration-OnlineDataLoader %d", id));
DataHandler<String> handler = new NullDataHandler<String>();
DataParser<String> parser = new DataParser<String>() {
@Override
public String parse(Reader reader) throws Exception {
BufferedReader in = null;
try {
in = new BufferedReader(reader);
return in.readLine();
} finally {
if (in != null) {
in.close();
}
}
}
};
DataHandler<TabletConfiguration> handler = new TabletConfigurationDataHandler(OnlineDataManager.this);
DataParser<TabletConfiguration> parser = new TabletConfigurationParser(new TabletConfigurationJsonDeserializer());
return new OnlineDataLoader<String>(
return new OnlineDataLoader<TabletConfiguration>(
context,
new URL(AppPreferences.getServerBaseURL(context) + "/sailingserver/rc/configuration?client="+ clientId),
new URL(AppPreferences.getServerBaseURL(context) + "/sailingserver/rc/configuration?client="+ identifier.getClientIdentifier()),
parser, handler);
}
});
@@ -11,6 +11,8 @@ import com.sap.sailing.domain.base.CourseArea;
import com.sap.sailing.domain.base.CourseBase;
import com.sap.sailing.domain.base.EventBase;
import com.sap.sailing.domain.base.Mark;
import com.sap.sailing.domain.base.TabletConfiguration;
import com.sap.sailing.domain.base.TabletConfigurationIdentifier;
import com.sap.sailing.racecommittee.app.data.clients.LoadClient;
import com.sap.sailing.racecommittee.app.data.loaders.DataLoaderResult;
import com.sap.sailing.racecommittee.app.domain.ManagedRace;
@@ -127,6 +129,6 @@ public interface ReadonlyDataManager {
* {@link LoaderManager#initLoader(int, android.os.Bundle, LoaderCallbacks)} or
* {@link LoaderManager#restartLoader(int, android.os.Bundle, LoaderCallbacks)}.
*/
public LoaderCallbacks<DataLoaderResult<String>> createConfigurationLoader(String clientId,
LoadClient<String> callback);
public LoaderCallbacks<DataLoaderResult<TabletConfiguration>> createConfigurationLoader(TabletConfigurationIdentifier identifier,
LoadClient<TabletConfiguration> callback);
}
@@ -0,0 +1,27 @@
package com.sap.sailing.racecommittee.app.data.handlers;
import com.sap.sailing.domain.base.TabletConfiguration;
import com.sap.sailing.racecommittee.app.data.OnlineDataManager;
public class TabletConfigurationDataHandler extends DataHandler<TabletConfiguration> {
public TabletConfigurationDataHandler(OnlineDataManager manager) {
super(manager);
}
@Override
public boolean hasCachedResults() {
return manager.getDataStore().getTabletConfiguration() != null;
}
@Override
public TabletConfiguration getCachedResults() {
return manager.getDataStore().getTabletConfiguration();
}
@Override
public void onResult(TabletConfiguration data) {
manager.getDataStore().setTabletConfiguration(data);
}
}
@@ -0,0 +1,27 @@
package com.sap.sailing.racecommittee.app.data.parsers;
import java.io.Reader;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import com.sap.sailing.domain.base.TabletConfiguration;
import com.sap.sailing.server.gateway.deserialization.JsonDeserializer;
import com.sap.sailing.server.gateway.deserialization.impl.Helpers;
public class TabletConfigurationParser implements DataParser<TabletConfiguration> {
private JsonDeserializer<TabletConfiguration> deserializer;
public TabletConfigurationParser(JsonDeserializer<TabletConfiguration> deserializer) {
this.deserializer = deserializer;
}
@Override
public TabletConfiguration parse(Reader reader) throws Exception {
Object parsedResult = JSONValue.parseWithException(reader);
JSONObject jsonObject = Helpers.toJSONObjectSafe(parsedResult);
return deserializer.deserialize(jsonObject);
}
}
@@ -12,6 +12,9 @@ import android.widget.Toast;
import com.sap.sailing.domain.base.CourseArea;
import com.sap.sailing.domain.base.EventBase;
import com.sap.sailing.domain.base.TabletConfiguration;
import com.sap.sailing.domain.base.TabletConfigurationIdentifier;
import com.sap.sailing.domain.base.impl.TabletConfigurationIdentifierImpl;
import com.sap.sailing.racecommittee.app.AppConstants;
import com.sap.sailing.racecommittee.app.AppPreferences;
import com.sap.sailing.racecommittee.app.R;
@@ -27,11 +30,12 @@ import com.sap.sailing.racecommittee.app.ui.fragments.lists.EventListFragment;
import com.sap.sailing.racecommittee.app.ui.fragments.lists.selection.CourseAreaSelectedListenerHost;
import com.sap.sailing.racecommittee.app.ui.fragments.lists.selection.EventSelectedListenerHost;
import com.sap.sailing.racecommittee.app.ui.fragments.lists.selection.ItemSelectedListener;
import com.sap.sailing.racecommittee.app.utils.TabletConfigurationHelper;
public class LoginActivity extends BaseActivity implements EventSelectedListenerHost,
CourseAreaSelectedListenerHost, DialogListenerHost {
public class LoginActivity extends BaseActivity implements EventSelectedListenerHost, CourseAreaSelectedListenerHost,
DialogListenerHost {
private final static String TAG = LoginActivity.class.getName();
private final static String CourseAreaListFragmentTag = "CourseAreaListFragmentTag";
private LoginDialog loginDialog;
@@ -41,7 +45,7 @@ public class LoginActivity extends BaseActivity implements EventSelectedListener
this.loginDialog = new LoginDialog();
this.selectedCourseArea = null;
}
@Override
protected boolean onReset() {
Fragment courseAreaFragment = getFragmentManager().findFragmentByTag(CourseAreaListFragmentTag);
@@ -57,9 +61,9 @@ public class LoginActivity extends BaseActivity implements EventSelectedListener
public void onCreate(Bundle savedInstanceState) {
// features must be requested before anything else
getWindow().requestFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
super.onCreate(savedInstanceState);
setContentView(R.layout.login_view);
setProgressBarIndeterminateVisibility(false);
@@ -95,38 +99,40 @@ public class LoginActivity extends BaseActivity implements EventSelectedListener
public void itemSelected(Fragment sender, EventBase event) {
final Serializable eventId = event.getId();
ExLog.i(ExLog.EVENT_SELECTED, eventId.toString(), getBaseContext());
setProgressBarIndeterminateVisibility(true);
final ProgressDialog progressDialog = new ProgressDialog(LoginActivity.this);
progressDialog.setMessage(getString(R.string.loading_configuration));
progressDialog.setCancelable(false);
progressDialog.setIndeterminate(true);
progressDialog.show();
String identifier = AppPreferences.getAndroidIdentifier(getApplicationContext());
ReadonlyDataManager dataManager = OnlineDataManager.create(LoginActivity.this);
getLoaderManager().restartLoader(
0,
null,
dataManager.createConfigurationLoader(identifier, new LoadClient<String>() {
TabletConfigurationIdentifier identifier = new TabletConfigurationIdentifierImpl(
AppPreferences.getAndroidIdentifier(getApplicationContext()));
getLoaderManager().restartLoader(0, null,
dataManager.createConfigurationLoader(identifier, new LoadClient<TabletConfiguration>() {
@Override
public void onLoadSucceded(String data, boolean isCached) {
public void onLoadSucceded(TabletConfiguration configuration, boolean isCached) {
setProgressBarIndeterminateVisibility(false);
progressDialog.dismiss();
Toast.makeText(getApplicationContext(), data, Toast.LENGTH_SHORT).show();
TabletConfigurationHelper.apply(getApplicationContext(), configuration);
Toast.makeText(getApplicationContext(), getString(R.string.loading_configuration_succeded),
Toast.LENGTH_LONG).show();
showCourseAreaListFragment(eventId);
}
@Override
public void onLoadFailed(Exception reason) {
setProgressBarIndeterminateVisibility(false);
progressDialog.dismiss();
Toast.makeText(getApplicationContext(), getString(R.string.loading_configuration_failed), Toast.LENGTH_LONG).show();
Toast.makeText(getApplicationContext(), getString(R.string.loading_configuration_failed),
Toast.LENGTH_LONG).show();
ExLog.ex(TAG, reason);
showCourseAreaListFragment(eventId);
}
})).forceLoad();
@@ -162,7 +168,7 @@ public class LoginActivity extends BaseActivity implements EventSelectedListener
@Override
public DialogResultListener getListener() {
return new DialogResultListener() {
@Override
public void onDialogPositiveButton(AttachedDialogFragment dialog) {
switch (loginDialog.getSelectedLoginType()) {
@@ -176,7 +182,8 @@ public class LoginActivity extends BaseActivity implements EventSelectedListener
break;
default:
ExLog.i(TAG, "An invalid log type, e.g. NONE, was selected");
Toast.makeText(LoginActivity.this, getString(R.string.please_select_a_login_type), Toast.LENGTH_LONG).show();
Toast.makeText(LoginActivity.this, getString(R.string.please_select_a_login_type),
Toast.LENGTH_LONG).show();
return;
}
@@ -190,7 +197,7 @@ public class LoginActivity extends BaseActivity implements EventSelectedListener
message.putExtra(AppConstants.COURSE_AREA_UUID_KEY, selectedCourseArea.getId());
fadeActivity(message);
}
@Override
public void onDialogNegativeButton(AttachedDialogFragment dialog) {
/* nothing here... */
@@ -0,0 +1,14 @@
package com.sap.sailing.racecommittee.app.utils;
import android.content.Context;
import com.sap.sailing.domain.base.TabletConfiguration;
import com.sap.sailing.racecommittee.app.AppPreferences;
public class TabletConfigurationHelper {
public static void apply(Context context, TabletConfiguration configuration) {
AppPreferences.setManagedCourseAreaNames(context, configuration.getAllowedCourseAreaNames());
}
}