#import <SyncServices/ISyncCommon.h>
#include <AppKit/NSResponder.h>
@class ISyncChange, ISyncClient, ISyncRecordSnapshot;

/*Constants

This constant is a key used by a record pushed to the sync engine.
Constant	
Description
ISyncRecordEntityNameKey	
Each record pushed to the sync engine must have a value for this key that specifies the record’s entity name.

Available in Mac OS X v10.4 and later.


These are the exceptions that might be thrown by ISyncSession methods during a sync.
Constant	
Description
ISyncSessionCancelledException	
Thrown by any method if invoked after the session was canceled.

Available in Mac OS X v10.4 and later.
ISyncSessionUnavailableException	
Thrown if a session cannot be created, for example, if a client is already syncing.

Available in Mac OS X v10.4 and later.
ISyncInvalidEntityException	
Thrown if a client tries creating a session with an entity that does not exist.

Available in Mac OS X v10.4 and later.
ISyncUnsupportedEntityException	
Thrown if a client tries creating a session with an entity that exists but the client does not support.

Available in Mac OS X v10.4 and later.
ISyncInvalidRecordException	
Thrown if a client pushes a malformed record.

Available in Mac OS X v10.4 and later.


These keys are used in the userInfo dictionary when a ISyncInvalidRecordException exception is raised.
Constant	
Description
ISyncInvalidRecordIdentifiersKey	
An array of the record identifiers that raised the exception.

Available in Mac OS X v10.4 and later.
ISyncInvalidRecordReasonsKey	
A dictionary where keys are the invalid record identifies and the values are the reasons for the exception.

Available in Mac OS X v10.4 and later.
ISyncInvalidRecordsKey	
A dictionary where the keys are the invalid record identifiers and the values are the property keys that raised the exception.

Available in Mac OS X v10.4 and later.*/
extern NSString * const ISyncRecordEntityNameKey;
extern NSString * const ISyncSessionCancelledException;
extern NSString * const ISyncSessionUnavailableException;
extern NSString * const ISyncInvalidEntityException;
extern NSString * const ISyncUnsupportedEntityException	;
extern NSString * const ISyncInvalidRecordException;
extern NSString * const ISyncInvalidRecordIdentifiersKey;
extern NSString * const ISyncInvalidRecordReasonsKey;
extern NSString * const ISyncInvalidRecordsKey;



@interface ISyncSession : NSObject

/*beginSessionInBackgroundWithClient:entityNames:target:selector:

Creates a new sync session for the specified client. 

+ (void)beginSessionInBackgroundWithClient:(ISyncClient *)client entityNames:(NSArray *)entityNames target:(id)target selector:(SEL)selector
Discussion

Returns immediately and sends selector to target when a session was successfully or unsuccessfully created. The selector is passed two arguments: the first argument is the ISyncClient object and the second argument is the new ISyncSession object. If the sync engine is disabled and this method failed to create a session, selector is sent to target with nil as the ISyncSession object.

The entityNames argument specifies which entities the client wants to sync during this session. They can be a subset of the client's supported entities and may include entities which have been disabled. However, the sync engine does not allow the client to push changes to disabled entities nor does it provide changes to disabled entities while pulling changes. Typically, you use the array returned by sending enabledEntityNames to your ISyncClient object as the entityNames argument to this method.

Creating a session for client may trigger notifications to other clients observing syncs of this client type. This method differs from beginSessionWithClient:entityNames:beforeDate: by not blocking and sending selector to target when all dependent clients have joined the sync session. (Send setShouldSynchronize:withClientsOfType: to an ISyncClient object to setup these dependencies.) This method requires the client have a run loop running in the default mode.

Note: ISyncSession is not thread-safe. You can pass an ISyncSession object between threads but you should not use it concurrently. Asynchronous callbacks from ISyncSession are delivered to any client thread that used any of the SyncServices API. The client is responsible for directing the callback to an appropriate thread.

Availability
Available in Mac OS X v10.4 and later.
See Also
cancelPreviousBeginSessionWithClient: 
isEnabled (ISyncManager)*/

+ (void)beginSessionInBackgroundWithClient:(ISyncClient *)client entityNames:(NSArray *)entityNames target:(id)target selector:(SEL)selector;

/*shouldReplaceAllRecordsOnClientForEntityName:

Returns YES if the client should delete all the records for the entity, specified by entityName, and replace them with records pulled from the sync engine, NO otherwise.

- (BOOL)shouldReplaceAllRecordsOnClientForEntityName:(NSString *)entityName
Discussion

Send setShouldReplaceClientRecords:forEntityNames: to the client for this session to request a different behavior.

You can invoke this method at any time. However, you should not delete the local client data until the session enters the pulling state (after prepareToPullChangesForEntityNames:beforeDate: returns). Otherwise, if the session is canceled prematurely, the client may be left in an non synchronized state with no data.
Availability
Available in Mac OS X v10.4 and later.
See Also
shouldPullChangesForEntityName: 
clientDidResetEntityNames:*/

- (BOOL)shouldReplaceAllRecordsOnClientForEntityName:(NSString *)entityName;

/*prepareToPullChangesForEntityNames:beforeDate:

Returns NO if date expires before the sync engine is ready for the client to begin pulling changes, YES otherwise.

- (BOOL)prepareToPullChangesForEntityNames:(NSArray *)entityNames beforeDate:(NSDate *)date
Discussion

Moves the receiver to the mingling state and returns when the sync engine is ready for the client to begin pulling changes to the specified entities. Invoke this method after you have finished pushing changes to the sync engine and want to begin pulling changes. The entityNames array can contain a subset of the supported entity names. If this method returns NO, you can invoke it multiple times until it returns YES or the sync session is canceled or finished. 

Use this method during the pushing state to transition to the mingling state, otherwise an exception is raised. The mingling state ends when this method returns YES.
Availability
Available in Mac OS X v10.4 and later.
See Also
prepareToPullChangesInBackgroundForEntityNames:target:selector:*/
- (BOOL)prepareToPullChangesForEntityNames:(NSArray *)entityNames beforeDate:(NSDate *)date;

/*changeEnumeratorForEntityNames:

Returns the object enumerator for the ISyncChange objects which contain all the changes the client should apply to its local data.

- (NSEnumerator *)changeEnumeratorForEntityNames:(NSArray *)entityNames
Discussion

Use the returned object to iterate through the record changes during the pulling state. The entityNames argument can contain a subset of the supported entities. 

The sync engine applies client filters to the returned changes so that the client does not receive changes that were rejected. See Sync Services Programming Guide for more information on setting filters.

When the client applies a change described by an ISyncChange object, it must either accept or reject the change. You accept a change by sending clientAcceptedChangesForRecordWithIdentifier:formattedRecord:newRecordIdentifier: to the sync session, and reject a change by sending clientRefusedChangesForRecordWithIdentifier: to the sync session. After processing all changes (saving them on the device or locally) you send clientCommittedAcceptedChanges to the sync session to commit those changes. Any uncommitted accepted changes or rejected changes are sent again to the client during the next sync.

Use this method during the pulling state only, otherwise an exception is raised.
Availability
Available in Mac OS X v10.4 and later.
See Also
prepareToPullChangesForEntityNames:beforeDate:*/
- (NSEnumerator *)changeEnumeratorForEntityNames:(NSArray *)entityNames;

/*clientAcceptedChangesForRecordWithIdentifier:formattedRecord:newRecordIdentifier:

Informs the sync engine that the client has accepted the changes to the record identified by recordIdentifier during the pulling state.

- (void)clientAcceptedChangesForRecordWithIdentifier:(NSString *)recordIdentifier formattedRecord:(NSDictionary *)formattedRecord newRecordIdentifier:(NSString *)newRecordIdentifier
Discussion

If your client or device can not store properties using the defined schema, then you can use the formattedRecord to specify an alternate format. By specifying an alternate format, you assist the sync engine in figuring out which records and properties are equal during the mingling state, so that the sync engine doesn’t generate false changes for records that were simply reformatted. The formattedRecord dictionary should contain the entire record—key-value pairs for the formatted and unformatted properties including the ISyncRecordEntityNameKey key identifying the record’s entity name. Otherwise, the formattedRecord argument should be nil.

For example, if you are syncing a device and the device truncates first and last names to 20 characters long, then you should specify a formattedRecord record for truncated values when invoking this method. The formattedRecord dictionary should contain key-value pairs for only the properties that have different formats (were truncated by the device). See Sync Services Programming Guide for more details on formatting records.

The sync engine creates a new identifier for added records using CFUUIDRef. However, if your client generates its own unique record identifiers, then you can use the newRecordIdentifier argument to request that your identifier be used in future communications with the sync engine. 

You can use this method to batch up changes by invoking it repeatedly. You can also use the clientRefusedChangesForRecordWithIdentifier: method to reject changes. However, after a sequence of accepting and rejecting changes, you need to invoke clientCommittedAcceptedChanges to end the transaction and actually commit them. 

Use this method during the pulling state only, otherwise an exception is raised.
Availability
Available in Mac OS X v10.4 and later.
See Also
clientChangedRecordIdentifiers: 
clientLostRecordWithIdentifier:shouldReplaceOnNextSync:*/

- (void)clientAcceptedChangesForRecordWithIdentifier:(NSString *)recordIdentifier formattedRecord:(NSDictionary *)formattedRecord newRecordIdentifier:(NSString *)newRecordIdentifier;

/*clientCommittedAcceptedChanges

Informs the sync engine that all accepted and rejected changes in the current transaction during the pulling state should be committed.

- (void)clientCommittedAcceptedChanges
Discussion

Invoke this method after you save the accepted changes locally or on the device you are syncing.

You accept a change by sending clientAcceptedChangesForRecordWithIdentifier:formattedRecord:newRecordIdentifier: to the sync session, and reject a change by sending clientRefusedChangesForRecordWithIdentifier: to the sync session. 

Invoking this method ends an open pull transaction that began by sending either prepareToPullChangesForEntityNames:beforeDate: or prepareToPullChangesInBackgroundForEntityNames:target:selector: to the receiver. Once a transaction ends the sync engine commits the changes to the truth database, and opens a new pull transaction.

Use this method during the pulling state only, otherwise an exception is raised.
Availability
Available in Mac OS X v10.4 and later.
See Also
cancelSyncing
finishSyncing*/
- (void)clientCommittedAcceptedChanges;

/*finishSyncing

Tells the sync engine that the client is done syncing. Invoking this method closes any open transactions in the pushing or pulling states.

- (void)finishSyncing
Discussion

You must invoke this method to cleanly terminate the session.

Use this method at any time but the receiver should be released soon afterwards since you can not continue using a finished session. 
Availability
Available in Mac OS X v10.4 and later.
See Also
cancelSyncing
isCancelled*/
- (void)finishSyncing;

/*deleteRecordWithIdentifier:

Creates a delete change for the record specified by recordIdentifier and pushes the change to the sync engine.

- (BOOL)deleteRecordWithIdentifier:(NSString *)recordIdentifier
Discussion

Use this method during the negotiation state or pushing state only, otherwise an exception is raised. Invoking this method in the negotiation state transitions the receiver to the pushing state.
Availability
Available in Mac OS X v10.4 and later.
See Also
pushChange: 
pushChangesFromRecord:withIdentifier: 
clientLostRecordWithIdentifier:shouldReplaceOnNextSync: 
shouldPushAllRecordsForEntityName:*/
- (BOOL)deleteRecordWithIdentifier:(NSString *)recordIdentifier;

/*clientWantsToPushAllRecordsForEntityNames:

Forces a slow sync of all the records for the specified entities.

- (void)clientWantsToPushAllRecordsForEntityNames:(NSArray *)entityNames
Discussion

The entityNames array can contain a subset of the supported entity names. A slow sync is when the client pushes all of its records to the sync engine, and the sync engine determines, by comparing records, what changes need to be applied and pushed to the client. By default, the sync engine assumes the client is fast syncing and expects the client to push only the changes to records since the last sync (added, modified, and deleted records). Use this method if you want to change this default behavior by forcing a slow sync. For example, if the client can’t determine what records changed.

Use this method during the negotiation state only, otherwise an exception is raised.
Availability
Available in Mac OS X v10.4 and later.
See Also
shouldPushAllRecordsForEntityName: 
shouldPushChangesForEntityName:*/
- (void)clientWantsToPushAllRecordsForEntityNames:(NSArray *)entityNames;

/*clientDidResetEntityNames:

Tells the sync engine to perform a refresh sync of all the records for the specified entities.

- (void)clientDidResetEntityNames:(NSArray *)entityNames
Discussion

The entityNames array can contain a subset of the supported entity names. Use this method if a user hard-resets a device by removing all its records, or if the local client data file is accidently deleted.

After invoking this method, the client is expected to push all the records for the specified entities similar to a slow sync. However, during a refresh sync, the sync engine resets the client’s sync state (as if it never synced before) and consequently, does not generate any delete changes when the client pulls records. Although the client may pull delete changes if the sync engine detects duplicate records. 

Use this method during the negotiation state only, otherwise an exception is raised.
Availability
Available in Mac OS X v10.4 and later.
See Also
shouldPullChangesForEntityName: 
shouldReplaceAllRecordsOnClientForEntityName:*/
- (void)clientDidResetEntityNames:(NSArray *)entityNames;

/*shouldPushAllRecordsForEntityName:

Returns YES if the client should push all the records for entityName to the sync engine, NO otherwise.

- (BOOL)shouldPushAllRecordsForEntityName:(NSString *)entityName
Discussion

For example, returns YES if you previously sent clientWantsToPushAllRecordsForEntityNames: or clientDidResetEntityNames: to the session to force a slow sync. This method also returns YES if the sync engine decides to slow sync entityName. If this method returns NO, the client should only push changes made since the last sync. You can invoke this method at any time.

Warning: If this method returns YES and the client does not push a record that the client was known to have on the last sync, the sync engine assumes the record was deleted and deletes it from the truth.

Availability
Available in Mac OS X v10.4 and later.
See Also
shouldPushChangesForEntityName: 
pushChange: 
pushChangesFromRecord:withIdentifier: 
deleteRecordWithIdentifier:*/
- (BOOL)shouldPushAllRecordsForEntityName:(NSString *)entityName;

/*pushChangesFromRecord:withIdentifier:

Compares record to the client’s previous known state of the record, identified by recordIdentifier, and pushes the changes to the sync engine.

- (void)pushChangesFromRecord:(NSDictionary *)record withIdentifier:(NSString *)recordIdentifier
Discussion

Use this method if you know a record changed but don’t know what properties changed. Otherwise, use the pushChange: method to specify the exact property changes made to this record.

Use this method during the negotiation or pushing state only, otherwise an exception is raised. Invoking this method during the negotiation state transitions to the pushing state.
Availability
Available in Mac OS X v10.4 and later.
See Also
shouldPushAllRecordsForEntityName: 
shouldPushChangesForEntityName:*/
- (void)pushChangesFromRecord:(NSDictionary *)record withIdentifier:(NSString *)recordIdentifier;

/*shouldPushChangesForEntityName:

Returns YES if the client should push changes to records for entityName since the last sync, NO otherwise.

- (BOOL)shouldPushChangesForEntityName:(NSString *)entityName
Discussion

For example, this method returns NO if you previously sent setShouldReplaceClientRecords:forEntityNames: to the client for this session passing YES as the flag argument. If this method returns NO. the sync engine does not accept any changes from the client for this entity. You can invoke this method at any time.
Availability
Available in Mac OS X v10.4 and later.
See Also
shouldPushAllRecordsForEntityName: 
clientWantsToPushAllRecordsForEntityNames:*/
- (BOOL)shouldPushChangesForEntityName:(NSString *)entityName;

/*shouldPullChangesForEntityName:

Returns YES if the client should pull changes to records for entityName, NO otherwise.

- (BOOL)shouldPullChangesForEntityName:(NSString *)entityName
Discussion

However, a return value of YES, doesn’t imply the sync engine has changes for the entity. The sync engine doesn’t know if there are any changes until after the mingling state. Use this method to determine if the client should try to pull changes for entityName. You can invoke this method at any time.
Availability
Available in Mac OS X v10.4 and later.
See Also
shouldReplaceAllRecordsOnClientForEntityName: 
clientDidResetEntityNames:*/
- (BOOL)shouldPullChangesForEntityName:(NSString *)entityName;

/*cancelSyncing

Cancels the current session.

- (void)cancelSyncing
Discussion

May close an open pull or push transaction, and rolls back the state of the client to the previous transaction.

In the case of a pull transaction, the sync engine assumes the client is able to reapply the same changes on the next sync. In the case of a push transaction, the changes are reapplied to the client on the next sync. If the client cannot push or pull the same changes, it must force a slow sync by sending clientWantsToPushAllRecordsForEntityNames: to the session before the next sync.

Use this method at any time but the receiver should be released soon afterward because you cannot continue using a canceled session.
Availability
Available in Mac OS X v10.4 and later.
See Also
isCancelled
finishSyncing*/
- (void)cancelSyncing;

@end

/*Notifications
ISyncAvailabilityChangedNotification

Posted by the distributed notification center when syncing is enabled or disabled. The notification object is an NSString equal to “YES” if enabled and “NO” if disabled. The receiver should still invoke isEnabled before beginning a sync session. This notification does not contain a userInfo dictionary.
Availability
Available in Mac OS X v10.4 and later.*/
APPKIT_EXPORT NSString *ISyncAvailabilityChangedNotification;

