//
// Copyright 2014-2015 Amazon.com,
// Inc. or its affiliates. All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//
using System;
using System.Collections.Generic;
using Amazon.Runtime;
using Amazon.CognitoSync.SyncManager.Internal;
using Amazon.CognitoIdentity;
using Logger = Amazon.Runtime.Internal.Util.Logger;
using Amazon.Util.Internal;
#if BCL45
using System.Threading.Tasks;
#endif
using System.Threading;
namespace Amazon.CognitoSync.SyncManager
{
/// ;
/// The Cognito Sync Manager allows your application to store data
/// in the cloud for your users and synchronize across other devices. The library
/// uses the sqlite for local storage API and defaults to inmemory where sqlite
/// is not available to create a local cache for the data, similar to our SDK.
/// This allows your application to access stored data even when there is no connectivity.
///
/// CognitoAWSCredentials credentials = new CognitoAWSCredentials("identityPoolId","RegionEndpoint")
/// //using default region from your app.config or awsconfig.xml
/// CognitoSyncManager cognitoSyncManager = new CognitoSyncManager(credentials);
/// // creating a dataset
/// Dataset playerInfo = cognitoSyncManager.OpenOrCreateDataset("playerInfo");
/// // add some values into your dataset
/// playerInfo.Put("high_score", "90");
/// playerInfo.Put("name", "John");
/// // push changes to remote if needed
/// playerInfo.Synchronize();
///
/// Note: Some platforms may only expose async methods such as SynchronizeAsync().
///
/// Amazon Cognito Sync Dev. Guide - Synchronizing Data
public partial class CognitoSyncManager : IDisposable
{
private Logger _logger;
private bool _disposed;
private readonly ILocalStorage Local;
private readonly CognitoSyncStorage Remote;
private readonly CognitoAWSCredentials CognitoCredentials;
#region Constructor
///
/// Creates an instance of CognitoSyncManager using Cognito Credentials, the region is picked up from the config if it available
///
/// CognitoSyncManager cognitoSyncManager = new CognitoSyncManager(credentials)
///
///
///
/// Amazon Cognito Sync Dev. Guide - Initializing Client
public CognitoSyncManager(CognitoAWSCredentials cognitoCredentials) : this(cognitoCredentials, new AmazonCognitoSyncConfig()) { }
///
/// Creates an instance of CognitoSyncManager using cognito credentials and a specific region
///
/// CognitoSyncManager cognitoSyncManager = new CognitoSyncManager(credentials, RegionEndpoint.USEAST1)
///
///
///
///
/// Amazon Cognito Sync Dev. Guide - Initializing Client
public CognitoSyncManager(CognitoAWSCredentials cognitoCredentials, RegionEndpoint endpoint)
: this(cognitoCredentials, new AmazonCognitoSyncConfig
{
RegionEndpoint = endpoint
})
{ }
///
/// Creates an instance of CognitoSyncManager using cognito credentials and a configuration object
///
/// CognitoSyncManager cognitoSyncManager = new CognitoSyncManager(credentials,new AmazonCognitoSyncConfig { RegionEndpoint = RegionEndpoint.USEAST1})
///
///
///
///
/// Amazon Cognito Sync Dev. Guide - Initializing Client
public CognitoSyncManager(CognitoAWSCredentials cognitoCredentials, AmazonCognitoSyncConfig config)
{
if (cognitoCredentials == null)
{
throw new ArgumentNullException("cognitoCredentials");
}
#if BCL
ValidateParameters();
#endif
this.CognitoCredentials = cognitoCredentials;
Local = new SQLiteLocalStorage();
Remote = new CognitoSyncStorage(CognitoCredentials, config);
cognitoCredentials.IdentityChangedEvent += this.IdentityChanged;
_logger = Logger.GetLogger(this.GetType());
}
#endregion
#region Dispose Methods
///
/// Releases the resources consumed by this object
///
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
///
/// Releases the resources consumed by this object if disposing is true.
///
protected virtual void Dispose(bool disposing)
{
if (_disposed)
return;
if (disposing)
{
Remote.Dispose();
Local.Dispose();
CognitoCredentials.IdentityChangedEvent -= this.IdentityChanged;
_disposed = true;
}
}
#endregion
#region Public Methods
///
/// Opens or creates a dataset. If the dataset doesn't exist, an empty one
/// with the given name will be created. Otherwise, the dataset is loaded from
/// local storage. If a dataset is marked as deleted but hasn't been deleted
/// on remote via the RefreshDatasetMetadata operation, it will throw
/// .
///
/// Dataset dataset = cognitoSyncManager.OpenOrCreateDataset("myDatasetName");
///
///
/// Dataset loaded from local storage
/// DatasetName, must be [a-zA-Z0=9_.:-]+
/// Amazon Cognito Sync Dev. Guide - Understanding Datasets
public Dataset OpenOrCreateDataset(string datasetName)
{
DatasetUtils.ValidateDatasetName(datasetName);
Local.CreateDataset(IdentityId, datasetName);
return new Dataset(datasetName, CognitoCredentials, Local, Remote);
}
///
/// Retrieves a list of datasets from local storage. It may not reflect the
/// latest dataset on the remote storage until the RefreshDatasetMetadata
/// operation is performed.
///
/// List of datasets
public List ListDatasets()
{
return Local.GetDatasetMetadata(IdentityId);
}
///
/// Wipes all user data cached locally, including dataset metadata, and all records,
/// and optionally identity id and session credentials. Any data that hasn't been
/// synced will be lost. This method is usually used when customer logs out.
/// Wipe Credentials and IdentityId.
///
public void WipeData(bool wipeCredentialsAndID)
{
Local.WipeData();
_logger.InfoFormat("All data has been wiped");
if (wipeCredentialsAndID)
{
CognitoCredentials.Clear();
_logger.InfoFormat("All datasets and records have been wiped");
}
else
{
_logger.InfoFormat("All data has been wiped");
}
}
///
/// Wipes all user data cached locally, including identity id, session
/// credentials, dataset metadata, and all records. Any data that hasn't been
/// synced will be lost. This method is usually used when customer logs out.
///
public void WipeData()
{
WipeData(true);
}
#endregion
#region Protected Methods
///
/// This is triggered when an Identity Change event occurs.
/// The dataset are then remapped to the new identity id.
/// This may happend for example when a user is working with
/// unauthenticated id and later decides to authenticate
/// himself with a public login provider
///
/// The object which triggered this methos
/// Event Arguments
protected void IdentityChanged(object sender, EventArgs e)
{
Amazon.CognitoIdentity.CognitoAWSCredentials.IdentityChangedArgs identityChangedEvent = e as Amazon.CognitoIdentity.CognitoAWSCredentials.IdentityChangedArgs;
if (identityChangedEvent.NewIdentityId != null)
{
String oldIdentity = string.IsNullOrEmpty(identityChangedEvent.OldIdentityId) ? DatasetUtils.UNKNOWN_IDENTITY_ID : identityChangedEvent.OldIdentityId;
String newIdentity = identityChangedEvent.NewIdentityId;
_logger.InfoFormat("Identity changed from {0} to {1}", oldIdentity, newIdentity);
Local.ChangeIdentityId(oldIdentity, newIdentity);
}
}
///
/// Returns the IdentityId, if the application is not online then an
/// Unknown Identity Will be returned
///
/// Identity ID
protected string IdentityId
{
get
{
return DatasetUtils.GetIdentityId(CognitoCredentials);
}
}
#endregion
#region private methods
#if BCL
static void ValidateParameters()
{
if (string.IsNullOrEmpty(AWSConfigs.ApplicationName))
{
throw new ArgumentException("A valid application name needs to configured to use this API." +
"The application name can be configured through app.config or by setting the Amazon.AWSConfigs.ApplicationName property.");
}
}
#endif
#endregion
}
}