CMIS-792: Browser Binding: current state of write support
git-svn-id: https://svn.apache.org/repos/asf/chemistry/objectivecmis/branches/browser-binding@1590634 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/ObjectiveCMIS/Bindings/AtomPub/AtomPubParser/CMISAtomEntryWriter.m b/ObjectiveCMIS/Bindings/AtomPub/AtomPubParser/CMISAtomEntryWriter.m
index 4c1cab8..47b5db9 100644
--- a/ObjectiveCMIS/Bindings/AtomPub/AtomPubParser/CMISAtomEntryWriter.m
+++ b/ObjectiveCMIS/Bindings/AtomPub/AtomPubParser/CMISAtomEntryWriter.m
@@ -200,7 +200,7 @@
}
default:
{
- CMISLogDebug(@"Property type did not match: %d", propertyData.type);
+ CMISLogDebug(@"Property type did not match: %d", (int)propertyData.type);
break;
}
}
diff --git a/ObjectiveCMIS/Bindings/Browser/CMISBrowserConstants.h b/ObjectiveCMIS/Bindings/Browser/CMISBrowserConstants.h
index c7c1f57..f45f364 100644
--- a/ObjectiveCMIS/Bindings/Browser/CMISBrowserConstants.h
+++ b/ObjectiveCMIS/Bindings/Browser/CMISBrowserConstants.h
@@ -100,6 +100,7 @@
extern NSString * const kCMISBrowserJSONMaxValue;
extern NSString * const kCMISBrowserJSONPrecision;
extern NSString * const kCMISBrowserJSONResolution;
+extern NSString * const kCMISBrowserJSONFailedToDeleteId;
extern NSString * const kCMISBrowserJSONAcePrincipal;
extern NSString * const kCMISBrowserJSONAcePrincipalId;
extern NSString * const kCMISBrowserJSONAcePermissions;
@@ -161,6 +162,8 @@
// Browser binding control
extern NSString * const kCMISBrowserJSONControlCmisAction;
+extern NSString * const kCMISBrowserJSONControlPropertyId;
+extern NSString * const kCMISBrowserJSONControlPropertyValue;
// Browser binding actions
extern NSString * const kCMISBrowserJSONActionCreateType;
diff --git a/ObjectiveCMIS/Bindings/Browser/CMISBrowserConstants.m b/ObjectiveCMIS/Bindings/Browser/CMISBrowserConstants.m
index 866b90d..e14e5e9 100644
--- a/ObjectiveCMIS/Bindings/Browser/CMISBrowserConstants.m
+++ b/ObjectiveCMIS/Bindings/Browser/CMISBrowserConstants.m
@@ -113,6 +113,7 @@
NSString * const kCMISBrowserJSONMaxValue = @"maxValue";
NSString * const kCMISBrowserJSONPrecision = @"precision";
NSString * const kCMISBrowserJSONResolution = @"resolution";
+NSString * const kCMISBrowserJSONFailedToDeleteId = @"ids";
NSString * const kCMISBrowserJSONAcePrincipal = @"principal";
NSString * const kCMISBrowserJSONAcePrincipalId = @"principalId";
NSString * const kCMISBrowserJSONAcePermissions = @"permissions";
@@ -177,6 +178,8 @@
// Browser binding control
NSString * const kCMISBrowserJSONControlCmisAction = @"cmisaction";
+NSString * const kCMISBrowserJSONControlPropertyId = @"propertyId";
+NSString * const kCMISBrowserJSONControlPropertyValue = @"propertyValue";
// Browser binding actions
diff --git a/ObjectiveCMIS/Bindings/Browser/CMISBrowserNavigationService.m b/ObjectiveCMIS/Bindings/Browser/CMISBrowserNavigationService.m
index 5d66904..94ac2f5 100644
--- a/ObjectiveCMIS/Bindings/Browser/CMISBrowserNavigationService.m
+++ b/ObjectiveCMIS/Bindings/Browser/CMISBrowserNavigationService.m
@@ -81,9 +81,35 @@
includeRelativePathSegment:(BOOL)includeRelativePathSegment
completionBlock:(void (^)(NSArray *parents, NSError *error))completionBlock
{
- NSString * message = [NSString stringWithFormat:@"%s is not implemented yet", __PRETTY_FUNCTION__];
- NSException *exception = [NSException exceptionWithName:NSInvalidArgumentException reason:message userInfo:nil];
- @throw exception;
+ NSString *objectUrl = [self getObjectUrlObjectId:objectId selector:kCMISBrowserJSONSelectorParents];
+ objectUrl = [CMISURLUtil urlStringByAppendingParameter:kCMISParameterFilter value:filter urlString:objectUrl];
+ objectUrl = [CMISURLUtil urlStringByAppendingParameter:kCMISParameterIncludeAllowableActions boolValue:includeAllowableActions urlString:objectUrl];
+ objectUrl = [CMISURLUtil urlStringByAppendingParameter:kCMISParameterIncludeRelationships value:[CMISEnums stringForIncludeRelationShip:relationships] urlString:objectUrl];
+ objectUrl = [CMISURLUtil urlStringByAppendingParameter:kCMISParameterRenditionFilter value:renditionFilter urlString:objectUrl];
+ objectUrl = [CMISURLUtil urlStringByAppendingParameter:kCMISParameterRelativePathSegment boolValue:includeRelativePathSegment urlString:objectUrl];
+ objectUrl = [CMISURLUtil urlStringByAppendingParameter:kCMISBrowserJSONParameterSuccinct value:kCMISParameterValueTrue urlString:objectUrl];
+
+ CMISRequest *cmisRequest = [[CMISRequest alloc] init];
+
+ [self.bindingSession.networkProvider invokeGET:[NSURL URLWithString:objectUrl]
+ session:self.bindingSession
+ cmisRequest:cmisRequest
+ completionBlock:^(CMISHttpResponse *httpResponse, NSError *error) {
+ if (httpResponse.statusCode == 200 && httpResponse.data) {
+ CMISTypeCache *typeCache = [[CMISTypeCache alloc] initWithRepositoryId:self.bindingSession.repositoryId bindingService:self];
+ [CMISBrowserUtil objectParents:httpResponse.data typeCache:typeCache completionBlock:^(NSArray *objectParents, NSError *error) {
+ if (error) {
+ completionBlock(nil, error);
+ } else {
+ completionBlock(objectParents, nil);
+ }
+ }];
+ } else {
+ completionBlock(nil, error);
+ }
+ }];
+
+ return cmisRequest;
}
@end
diff --git a/ObjectiveCMIS/Bindings/Browser/CMISBrowserObjectService.m b/ObjectiveCMIS/Bindings/Browser/CMISBrowserObjectService.m
index 070e593..05907de 100644
--- a/ObjectiveCMIS/Bindings/Browser/CMISBrowserObjectService.m
+++ b/ObjectiveCMIS/Bindings/Browser/CMISBrowserObjectService.m
@@ -28,6 +28,7 @@
#import "CMISErrors.h"
#import "CMISLog.h"
#import "CMISFormDataWriter.h"
+#import "CMISStringInOutParameter.h"
@implementation CMISBrowserObjectService
@@ -211,9 +212,47 @@
changeToken:(CMISStringInOutParameter *)changeTokenParam
completionBlock:(void (^)(NSError *error))completionBlock
{
- NSString * message = [NSString stringWithFormat:@"%s is not implemented yet", __PRETTY_FUNCTION__];
- NSException *exception = [NSException exceptionWithName:NSInvalidArgumentException reason:message userInfo:nil];
- @throw exception;
+ // we need an object id
+ if ((objectIdParam.inParameter == nil) || (objectIdParam.inParameter.length == 0)) {
+ completionBlock([CMISErrors createCMISErrorWithCode:kCMISErrorCodeInvalidArgument
+ detailedDescription:@"Object id must be set!"]);
+ }
+
+ // build URL
+ NSString *objectUrl = [self getObjectUrlObjectId:objectIdParam.inParameter];
+
+ // prepare form data
+ CMISFormDataWriter *formData = [[CMISFormDataWriter alloc] initWithAction:kCMISBrowserJSONActionDeleteContent];
+ [formData addParameter:kCMISParameterChangeToken value:changeTokenParam.inParameter];
+ [formData addSuccinctFlag:true];
+
+
+ CMISRequest *cmisRequest = [[CMISRequest alloc] init];
+
+ // send
+ [self.bindingSession.networkProvider invokePOST:[NSURL URLWithString:objectUrl]
+ session:self.bindingSession
+ body:formData.body
+ headers:formData.headers
+ cmisRequest:cmisRequest
+ completionBlock:^(CMISHttpResponse *httpResponse, NSError *error) {
+ if ((httpResponse.statusCode == 200 || httpResponse.statusCode == 201) && httpResponse.data) {
+ CMISTypeCache *typeCache = [[CMISTypeCache alloc] initWithRepositoryId:self.bindingSession.repositoryId bindingService:self];
+ [CMISBrowserUtil objectDataFromJSONData:httpResponse.data typeCache:typeCache completionBlock:^(CMISObjectData *objectData, NSError *error) {
+ if (error) {
+ completionBlock(error);
+ } else {
+ objectIdParam.outParameter = objectData.identifier;
+ changeTokenParam.outParameter = objectData.properties.propertiesDictionary[kCMISPropertyChangeToken];
+
+ completionBlock(nil);
+ }
+ }];
+ } else {
+ completionBlock(error);
+ }
+ }];
+ return cmisRequest;
}
- (CMISRequest*)changeContentOfObject:(CMISStringInOutParameter *)objectIdParam
@@ -224,9 +263,30 @@
completionBlock:(void (^)(NSError *error))completionBlock
progressBlock:(void (^)(unsigned long long bytesUploaded, unsigned long long bytesTotal))progressBlock
{
- NSString * message = [NSString stringWithFormat:@"%s is not implemented yet", __PRETTY_FUNCTION__];
- NSException *exception = [NSException exceptionWithName:NSInvalidArgumentException reason:message userInfo:nil];
- @throw exception;
+ NSInputStream *inputStream = [NSInputStream inputStreamWithFileAtPath:filePath];
+ if (inputStream == nil) {
+ CMISLogError(@"Could not find file %@", filePath);
+ if (completionBlock) {
+ completionBlock([CMISErrors createCMISErrorWithCode:kCMISErrorCodeInvalidArgument detailedDescription:nil]);
+ }
+ return nil;
+ }
+
+ NSError *fileError = nil;
+ unsigned long long fileSize = [CMISFileUtil fileSizeForFileAtPath:filePath error:&fileError];
+ if (fileError) {
+ CMISLogError(@"Could not determine size of file %@: %@", filePath, [fileError description]);
+ }
+
+ return [self changeContentOfObject:objectIdParam
+ toContentOfInputStream:inputStream
+ bytesExpected:fileSize
+ filename:[filePath lastPathComponent]
+ mimeType:mimeType
+ overwriteExisting:overwrite
+ changeToken:changeTokenParam
+ completionBlock:completionBlock
+ progressBlock:progressBlock];
}
- (CMISRequest*)changeContentOfObject:(CMISStringInOutParameter *)objectId
@@ -322,9 +382,41 @@
properties:(CMISProperties *)properties
completionBlock:(void (^)(NSString *objectId, NSError *error))completionBlock
{
- NSString * message = [NSString stringWithFormat:@"%s is not implemented yet", __PRETTY_FUNCTION__];
- NSException *exception = [NSException exceptionWithName:NSInvalidArgumentException reason:message userInfo:nil];
- @throw exception;
+ // build URL
+ NSString *folderObjectUrl = [self getObjectUrlObjectId:folderObjectId];
+
+ // prepare form data
+ CMISFormDataWriter *formData = [[CMISFormDataWriter alloc] initWithAction:kCMISBrowserJSONActionCreateFolder];
+ [formData addPropertiesParameters:properties];
+ // TODO [formData addPoliciesParameters:policies];
+ // TODO [formData addAddAcesParameters:addAces];
+ // TODO [formData addRemoveAcesParameters:removeAces];
+ [formData addSuccinctFlag:true];
+
+
+ CMISRequest *cmisRequest = [[CMISRequest alloc] init];
+
+ // send
+ [self.bindingSession.networkProvider invokePOST:[NSURL URLWithString:folderObjectUrl]
+ session:self.bindingSession
+ body:formData.body
+ headers:formData.headers
+ cmisRequest:cmisRequest
+ completionBlock:^(CMISHttpResponse *httpResponse, NSError *error) {
+ if ((httpResponse.statusCode == 200 || httpResponse.statusCode == 201) && httpResponse.data) {
+ CMISTypeCache *typeCache = [[CMISTypeCache alloc] initWithRepositoryId:self.bindingSession.repositoryId bindingService:self];
+ [CMISBrowserUtil objectDataFromJSONData:httpResponse.data typeCache:typeCache completionBlock:^(CMISObjectData *objectData, NSError *error) {
+ if (error) {
+ completionBlock(nil, error);
+ } else {
+ completionBlock(objectData.identifier, nil);
+ }
+ }];
+ } else {
+ completionBlock(nil, error);
+ }
+ }];
+ return cmisRequest;
}
- (CMISRequest*)moveObject:(NSString *)objectId
@@ -332,9 +424,45 @@
toFolder:(NSString *)targetFolderId
completionBlock:(void (^)(CMISObjectData *objectData, NSError *error))completionBlock
{
- NSString * message = [NSString stringWithFormat:@"%s is not implemented yet", __PRETTY_FUNCTION__];
- NSException *exception = [NSException exceptionWithName:NSInvalidArgumentException reason:message userInfo:nil];
- @throw exception;
+ // we need an object id
+ if ((objectId == nil) || (objectId.length == 0)) {
+ completionBlock(nil, [CMISErrors createCMISErrorWithCode:kCMISErrorCodeInvalidArgument
+ detailedDescription:@"Object id must be set!"]);
+ }
+
+ // build URL
+ NSString *objectUrl = [self getObjectUrlObjectId:objectId];
+
+ // prepare form data
+ CMISFormDataWriter *formData = [[CMISFormDataWriter alloc] initWithAction:kCMISBrowserJSONActionMove];
+ [formData addParameter:kCMISParameterTargetFolderId value:targetFolderId];
+ [formData addParameter:kCMISParameterSourceFolderId value:sourceFolderId];
+ [formData addSuccinctFlag:true];
+
+
+ CMISRequest *cmisRequest = [[CMISRequest alloc] init];
+
+ // send
+ [self.bindingSession.networkProvider invokePOST:[NSURL URLWithString:objectUrl]
+ session:self.bindingSession
+ body:formData.body
+ headers:formData.headers
+ cmisRequest:cmisRequest
+ completionBlock:^(CMISHttpResponse *httpResponse, NSError *error) {
+ if ((httpResponse.statusCode == 200 || httpResponse.statusCode == 201) && httpResponse.data) {
+ CMISTypeCache *typeCache = [[CMISTypeCache alloc] initWithRepositoryId:self.bindingSession.repositoryId bindingService:self];
+ [CMISBrowserUtil objectDataFromJSONData:httpResponse.data typeCache:typeCache completionBlock:^(CMISObjectData *objectData, NSError *error) {
+ if (error) {
+ completionBlock(nil, error);
+ } else {
+ completionBlock(objectData, nil);
+ }
+ }];
+ } else {
+ completionBlock(nil, error);
+ }
+ }];
+ return cmisRequest;
}
- (CMISRequest*)deleteTree:(NSString *)folderObjectId
@@ -343,9 +471,41 @@
continueOnFailure:(BOOL)continueOnFailure
completionBlock:(void (^)(NSArray *failedObjects, NSError *error))completionBlock
{
- NSString * message = [NSString stringWithFormat:@"%s is not implemented yet", __PRETTY_FUNCTION__];
- NSException *exception = [NSException exceptionWithName:NSInvalidArgumentException reason:message userInfo:nil];
- @throw exception;
+ // build URL
+ NSString *folderObjectUrl = [self getObjectUrlObjectId:folderObjectId];
+
+ CMISFormDataWriter *formData = [[CMISFormDataWriter alloc] initWithAction:kCMISBrowserJSONActionDeleteTree];
+ [formData addParameter:kCMISParameterAllVersions boolValue:allVersions];
+ [formData addParameter:kCMISParameterUnfileObjects value:[CMISEnums stringForUnfileObject:unfileObjects]];
+ [formData addParameter:kCMISParameterContinueOnFailure boolValue:continueOnFailure];
+
+ CMISRequest *cmisRequest = [[CMISRequest alloc] init];
+
+ // send
+ [self.bindingSession.networkProvider invokePOST:[NSURL URLWithString:folderObjectUrl]
+ session:self.bindingSession
+ body:formData.body
+ headers:formData.headers
+ cmisRequest:cmisRequest
+ completionBlock:^(CMISHttpResponse *httpResponse, NSError *error) {
+ if ((httpResponse.statusCode == 200 || httpResponse.statusCode == 201) && httpResponse.data) {
+ NSError *error = nil;
+ if(httpResponse.data.length > 0) {
+ NSArray *failedToDeleteIds = [CMISBrowserUtil failedToDeleteObjectsFromJSONData:httpResponse.data error:&error];
+ if (error) {
+ completionBlock(nil, error);
+ } else {
+ completionBlock(failedToDeleteIds, nil);
+ }
+ } else {
+ completionBlock([NSArray array], nil);
+ }
+ } else {
+ completionBlock(nil, [CMISErrors cmisError:error cmisErrorCode:kCMISErrorCodeConnection]);
+ }
+ }];
+
+ return cmisRequest;
}
- (CMISRequest*)updatePropertiesForObject:(CMISStringInOutParameter *)objectIdParam
@@ -353,9 +513,48 @@
changeToken:(CMISStringInOutParameter *)changeTokenParam
completionBlock:(void (^)(NSError *error))completionBlock
{
- NSString * message = [NSString stringWithFormat:@"%s is not implemented yet", __PRETTY_FUNCTION__];
- NSException *exception = [NSException exceptionWithName:NSInvalidArgumentException reason:message userInfo:nil];
- @throw exception;
+ // we need an object id
+ if ((objectIdParam.inParameter == nil) || (objectIdParam.inParameter.length == 0)) {
+ completionBlock([CMISErrors createCMISErrorWithCode:kCMISErrorCodeInvalidArgument
+ detailedDescription:@"Object id must be set!"]);
+ }
+
+ // build URL
+ NSString *objectUrl = [self getObjectUrlObjectId:objectIdParam.inParameter];
+
+ // prepare form data
+ CMISFormDataWriter *formData = [[CMISFormDataWriter alloc] initWithAction:kCMISBrowserJSONActionUpdateProperties];
+ [formData addPropertiesParameters:properties];
+ [formData addParameter:kCMISParameterChangeToken value:changeTokenParam.inParameter];
+ [formData addSuccinctFlag:true];
+
+
+ CMISRequest *cmisRequest = [[CMISRequest alloc] init];
+
+ // send
+ [self.bindingSession.networkProvider invokePOST:[NSURL URLWithString:objectUrl]
+ session:self.bindingSession
+ body:formData.body
+ headers:formData.headers
+ cmisRequest:cmisRequest
+ completionBlock:^(CMISHttpResponse *httpResponse, NSError *error) {
+ if ((httpResponse.statusCode == 200 || httpResponse.statusCode == 201) && httpResponse.data) {
+ CMISTypeCache *typeCache = [[CMISTypeCache alloc] initWithRepositoryId:self.bindingSession.repositoryId bindingService:self];
+ [CMISBrowserUtil objectDataFromJSONData:httpResponse.data typeCache:typeCache completionBlock:^(CMISObjectData *objectData, NSError *error) {
+ if (error) {
+ completionBlock(error);
+ } else {
+ objectIdParam.outParameter = objectData.identifier;
+ changeTokenParam.outParameter = objectData.properties.propertiesDictionary[kCMISPropertyChangeToken];
+
+ completionBlock(nil);
+ }
+ }];
+ } else {
+ completionBlock(error);
+ }
+ }];
+ return cmisRequest;
}
- (CMISRequest*)retrieveRenditions:(NSString *)objectId
diff --git a/ObjectiveCMIS/Bindings/Browser/CMISBrowserUtil.h b/ObjectiveCMIS/Bindings/Browser/CMISBrowserUtil.h
index e9aa63c..d2da4ed 100644
--- a/ObjectiveCMIS/Bindings/Browser/CMISBrowserUtil.h
+++ b/ObjectiveCMIS/Bindings/Browser/CMISBrowserUtil.h
@@ -51,4 +51,14 @@
*/
+ (NSArray *)renditionsFromJSONData:(NSData *)jsonData error:(NSError **)outError;
+/**
+ Returns an array of NSString objects that failed to be deleted, parsed from the given JSON data.
+ */
++ (NSArray *)failedToDeleteObjectsFromJSONData:(NSData *)jsonData error:(NSError **)outError;
+
+/**
+ Returns all object parents as an array of CMISObjectData objects, parsed from the given JSON data.
+ */
++ (void)objectParents:(NSData *)jsonData typeCache:(CMISTypeCache *)typeCache completionBlock:(void(^)(NSArray *objectParents, NSError *error))completionBlock;
+
@end
diff --git a/ObjectiveCMIS/Bindings/Browser/CMISBrowserUtil.m b/ObjectiveCMIS/Bindings/Browser/CMISBrowserUtil.m
index 7228a0b..5ec21b1 100644
--- a/ObjectiveCMIS/Bindings/Browser/CMISBrowserUtil.m
+++ b/ObjectiveCMIS/Bindings/Browser/CMISBrowserUtil.m
@@ -89,6 +89,9 @@
[repositories setObject:repoInfo forKey:repoInfo.identifier];
}
+ } else {
+ if (outError != NULL) *outError = [CMISErrors cmisError:serialisationError cmisErrorCode:kCMISErrorCodeRuntime];
+ return nil;
}
return repositories;
@@ -271,11 +274,55 @@
if (!serialisationError) {
// parse the json into a CMISObjectData object
renditions = [CMISBrowserUtil renditionsFromArray:jsonDictionary];
+ } else {
+ if (outError != NULL) *outError = [CMISErrors cmisError:serialisationError cmisErrorCode:kCMISErrorCodeRuntime];
+ return nil;
}
return renditions;
}
++ (NSArray *)failedToDeleteObjectsFromJSONData:(NSData *)jsonData error:(NSError **)outError
+{
+ // TODO: error handling i.e. if jsonData is nil, also handle outError being nil
+
+ // parse the JSON response
+ NSError *serialisationError = nil;
+ id jsonDictionary = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&serialisationError];
+
+ if (!serialisationError) {
+ NSMutableArray *ids = [[NSMutableArray alloc] init];
+ NSArray *jsonIds = [jsonDictionary cmis_objectForKeyNotNull:kCMISBrowserJSONFailedToDeleteId];
+
+ if (jsonIds) {
+ for (NSObject *obj in jsonIds) {
+ [ids addObject:obj.description]; //obj can't be nil as it came out of an array
+ }
+ }
+
+ return ids;
+ } else {
+ if (outError != NULL) *outError = [CMISErrors cmisError:serialisationError cmisErrorCode:kCMISErrorCodeRuntime];
+ return nil;
+ }
+}
+
++ (void)objectParents:(NSData *)jsonData typeCache:(CMISTypeCache *)typeCache completionBlock:(void(^)(NSArray *objectParents, NSError *error))completionBlock
+{
+ // TODO: error handling i.e. if jsonData is nil, also handle outError being nil
+
+ // parse the JSON response
+ NSError *serialisationError = nil;
+ id jsonDictionary = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&serialisationError];
+
+ if (!serialisationError) {
+ [self convertObjects:jsonDictionary typeCache:typeCache completionBlock:completionBlock];
+ } else {
+ completionBlock(nil, [CMISErrors cmisError:serialisationError cmisErrorCode:kCMISErrorCodeRuntime]);
+ return;
+ }
+}
+
#pragma mark -
#pragma mark Private helper methods
diff --git a/ObjectiveCMIS/Bindings/Browser/CMISBrowserVersioningService.m b/ObjectiveCMIS/Bindings/Browser/CMISBrowserVersioningService.m
index 7909155..df6dea2 100644
--- a/ObjectiveCMIS/Bindings/Browser/CMISBrowserVersioningService.m
+++ b/ObjectiveCMIS/Bindings/Browser/CMISBrowserVersioningService.m
@@ -24,6 +24,10 @@
#import "CMISBrowserUtil.h"
#import "CMISURLUtil.h"
#import "CMISConstants.h"
+#import "CMISErrors.h"
+#import "CMISFormDataWriter.h"
+#import "CMISFileUtil.h"
+#import "CMISLog.h"
@implementation CMISBrowserVersioningService
@@ -114,9 +118,43 @@
- (CMISRequest*)checkOut:(NSString *)objectId
completionBlock:(void (^)(CMISObjectData *objectData, NSError *error))completionBlock
{
- NSString * message = [NSString stringWithFormat:@"%s is not implemented yet", __PRETTY_FUNCTION__];
- NSException *exception = [NSException exceptionWithName:NSInvalidArgumentException reason:message userInfo:nil];
- @throw exception;
+ // we need an object id
+ if ((objectId == nil) || (objectId.length == 0)) {
+ completionBlock(nil, [CMISErrors createCMISErrorWithCode:kCMISErrorCodeInvalidArgument
+ detailedDescription:@"Object id must be set!"]);
+ }
+
+ // build URL
+ NSString *objectUrl = [self getObjectUrlObjectId:objectId];
+
+ // prepare form data
+ CMISFormDataWriter *formData = [[CMISFormDataWriter alloc] initWithAction:kCMISBrowserJSONActionCheckOut];
+ [formData addSuccinctFlag:true];
+
+
+ CMISRequest *cmisRequest = [[CMISRequest alloc] init];
+
+ // send
+ [self.bindingSession.networkProvider invokePOST:[NSURL URLWithString:objectUrl]
+ session:self.bindingSession
+ body:formData.body
+ headers:formData.headers
+ cmisRequest:cmisRequest
+ completionBlock:^(CMISHttpResponse *httpResponse, NSError *error) {
+ if ((httpResponse.statusCode == 200 || httpResponse.statusCode == 201) && httpResponse.data) {
+ CMISTypeCache *typeCache = [[CMISTypeCache alloc] initWithRepositoryId:self.bindingSession.repositoryId bindingService:self];
+ [CMISBrowserUtil objectDataFromJSONData:httpResponse.data typeCache:typeCache completionBlock:^(CMISObjectData *objectData, NSError *error) {
+ if (error) {
+ completionBlock(nil, error);
+ } else {
+ completionBlock(objectData, nil);
+ }
+ }];
+ } else {
+ completionBlock(nil, error);
+ }
+ }];
+ return cmisRequest;
}
/**
@@ -128,9 +166,35 @@
- (CMISRequest*)cancelCheckOut:(NSString *)objectId
completionBlock:(void (^)(BOOL checkOutCancelled, NSError *error))completionBlock
{
- NSString * message = [NSString stringWithFormat:@"%s is not implemented yet", __PRETTY_FUNCTION__];
- NSException *exception = [NSException exceptionWithName:NSInvalidArgumentException reason:message userInfo:nil];
- @throw exception;
+ // we need an object id
+ if ((objectId == nil) || (objectId.length == 0)) {
+ completionBlock(NO, [CMISErrors createCMISErrorWithCode:kCMISErrorCodeInvalidArgument
+ detailedDescription:@"Object id must be set!"]);
+ }
+
+ // build URL
+ NSString *objectUrl = [self getObjectUrlObjectId:objectId];
+
+ // prepare form data
+ CMISFormDataWriter *formData = [[CMISFormDataWriter alloc] initWithAction:kCMISBrowserJSONActionCancelCheckOut];
+
+
+ CMISRequest *cmisRequest = [[CMISRequest alloc] init];
+
+ // send
+ [self.bindingSession.networkProvider invokePOST:[NSURL URLWithString:objectUrl]
+ session:self.bindingSession
+ body:formData.body
+ headers:formData.headers
+ cmisRequest:cmisRequest
+ completionBlock:^(CMISHttpResponse *httpResponse, NSError *error) {
+ if ((httpResponse.statusCode == 200 || httpResponse.statusCode == 201) && httpResponse.data) {
+ completionBlock(YES, nil);
+ } else {
+ completionBlock(NO, error);
+ }
+ }];
+ return cmisRequest;
}
/**
@@ -154,9 +218,30 @@
completionBlock:(void (^)(CMISObjectData *objectData, NSError *error))completionBlock
progressBlock:(void (^)(unsigned long long bytesUploaded, unsigned long long bytesTotal))progressBlock
{
- NSString * message = [NSString stringWithFormat:@"%s is not implemented yet", __PRETTY_FUNCTION__];
- NSException *exception = [NSException exceptionWithName:NSInvalidArgumentException reason:message userInfo:nil];
- @throw exception;
+ NSInputStream *inputStream = [NSInputStream inputStreamWithFileAtPath:filePath];
+ if (inputStream == nil) {
+ CMISLogError(@"Could not find file %@", filePath);
+ if (completionBlock) {
+ completionBlock(nil, [CMISErrors createCMISErrorWithCode:kCMISErrorCodeInvalidArgument detailedDescription:nil]);
+ }
+ return nil;
+ }
+
+ NSError *fileError = nil;
+ unsigned long long fileSize = [CMISFileUtil fileSizeForFileAtPath:filePath error:&fileError];
+ if (fileError) {
+ CMISLogError(@"Could not determine size of file %@: %@", filePath, [fileError description]);
+ }
+
+ return [self checkIn:objectId
+ asMajorVersion:asMajorVersion
+ inputStream:inputStream
+ bytesExpected:fileSize
+ mimeType:mimeType
+ properties:properties
+ checkinComment:checkinComment
+ completionBlock:completionBlock
+ progressBlock:progressBlock];
}
/**
diff --git a/ObjectiveCMIS/Bindings/Browser/CMISFormDataWriter.h b/ObjectiveCMIS/Bindings/Browser/CMISFormDataWriter.h
index 8dc5f8e..a20d0ab 100644
--- a/ObjectiveCMIS/Bindings/Browser/CMISFormDataWriter.h
+++ b/ObjectiveCMIS/Bindings/Browser/CMISFormDataWriter.h
@@ -18,6 +18,7 @@
*/
#import <Foundation/Foundation.h>
+#import "CMISProperties.h"
@interface CMISFormDataWriter : NSObject
@@ -27,6 +28,10 @@
- (void)addParameter:(NSString *)name boolValue:(BOOL)value;
+- (void)addPropertiesParameters:(CMISProperties *)properties;
+
+- (void)addSuccinctFlag:(BOOL)succinct;
+
- (NSDictionary *)headers;
- (NSData *)body;
diff --git a/ObjectiveCMIS/Bindings/Browser/CMISFormDataWriter.m b/ObjectiveCMIS/Bindings/Browser/CMISFormDataWriter.m
index faf883a..80e12bb 100644
--- a/ObjectiveCMIS/Bindings/Browser/CMISFormDataWriter.m
+++ b/ObjectiveCMIS/Bindings/Browser/CMISFormDataWriter.m
@@ -20,6 +20,8 @@
#import "CMISFormDataWriter.h"
#import "CMISConstants.h"
#import "CMISBrowserConstants.h"
+#import "CMISEnums.h"
+#import "CMISLog.h"
NSString * const kCMISFormDataContentTypeUrlEncoded = @"application/x-www-form-urlencoded;charset=utf-8";
@@ -62,6 +64,66 @@
[self addParameter:name value:(value? kCMISParameterValueTrue : kCMISParameterValueFalse)];
}
+- (void)addSuccinctFlag:(BOOL)succinct
+{
+ if (succinct) {
+ [self addParameter:kCMISBrowserJSONParameterSuccinct value:kCMISParameterValueTrue];
+ }
+}
+
+- (void)addPropertiesParameters:(CMISProperties *)properties
+{
+ if (!properties) {
+ return;
+ }
+
+ int idx = 0;
+
+ for (CMISPropertyData *prop in properties.propertyList) {
+
+ NSString *idxStr = [NSString stringWithFormat:@"[%d]", idx];
+
+
+ [self addParameter:[NSString stringWithFormat:@"%@%@", kCMISBrowserJSONControlPropertyId, idxStr] value:prop.identifier];
+
+ if (prop.values && prop.values.count > 0) {
+ if (prop.values.count == 1) {
+ NSString *value = [self convertPropertyValue:prop.firstValue forPropertyType:prop.type];
+ [self addParameter:[NSString stringWithFormat:@"%@%@", kCMISBrowserJSONControlPropertyValue, idxStr] value:value];
+ } else {
+ int vidx = 0;
+ for (id obj in prop.values) {
+ NSString *vidxStr = [NSString stringWithFormat:@"[%d]", vidx];
+ NSString *value = [self convertPropertyValue:obj forPropertyType:prop.type];
+ [self addParameter:[NSString stringWithFormat:@"%@%@%@", kCMISBrowserJSONControlPropertyValue, idxStr, vidxStr] value:value];
+ vidx++;
+ }
+ }
+ }
+
+ idx++;
+ }
+}
+
+// TODO should this method be part of CMISPropertyData class (as class method?)
+- (NSString *)convertPropertyValue:(id)value forPropertyType:(CMISPropertyType)type
+{
+ if (!value) {
+ return nil;
+ }
+
+ if (type == CMISPropertyTypeBoolean) {
+ return [value boolValue] ? kCMISParameterValueTrue : kCMISParameterValueFalse;
+ } else if (type == CMISPropertyTypeDateTime) {
+ if ([value isKindOfClass:NSDate.class]) {
+ return [NSNumber numberWithDouble:[(NSDate *)value timeIntervalSinceReferenceDate]].description;
+ } else {
+ CMISLogWarning(@"value is not a date!");
+ }
+ }
+ return value;
+}
+
- (NSDictionary *)headers
{
return @{@"Content-Type" : kCMISFormDataContentTypeUrlEncoded};
diff --git a/ObjectiveCMIS/Bindings/CMISObjectService.h b/ObjectiveCMIS/Bindings/CMISObjectService.h
index bc7bfe2..7aa8746 100644
--- a/ObjectiveCMIS/Bindings/CMISObjectService.h
+++ b/ObjectiveCMIS/Bindings/CMISObjectService.h
@@ -215,7 +215,7 @@
/**
* Deletes the given folder and all of its subfolder and files
*
- * Returns a list of objects which failed to be deleted.
+ * Returns a list of object ids which failed to be deleted.
* completionBlock returns array of failed objects if any. NSError will be nil if successful
*/
- (CMISRequest*)deleteTree:(NSString *)folderObjectId
diff --git a/ObjectiveCMIS/Common/CMISConstants.h b/ObjectiveCMIS/Common/CMISConstants.h
index c27f0d4..3598125 100644
--- a/ObjectiveCMIS/Common/CMISConstants.h
+++ b/ObjectiveCMIS/Common/CMISConstants.h
@@ -116,6 +116,7 @@
extern NSString * const kCMISParameterCheckin;
extern NSString * const kCMISParameterCheckinComment;
extern NSString * const kCMISParameterSourceFolderId;
+extern NSString * const kCMISParameterTargetFolderId;
extern NSString * const kCMISParameterReturnVersion;
extern NSString * const kCMISParameterTypeId;
extern NSString * const kCMISParameterStatement;
diff --git a/ObjectiveCMIS/Common/CMISConstants.m b/ObjectiveCMIS/Common/CMISConstants.m
index 263ef19..1f5ffcd 100644
--- a/ObjectiveCMIS/Common/CMISConstants.m
+++ b/ObjectiveCMIS/Common/CMISConstants.m
@@ -124,6 +124,7 @@
NSString * const kCMISParameterCheckin = @"checkin";
NSString * const kCMISParameterCheckinComment = @"checkinComment";
NSString * const kCMISParameterSourceFolderId = @"sourceFolderId";
+NSString * const kCMISParameterTargetFolderId = @"targetFolderId";
NSString * const kCMISParameterReturnVersion = @"returnVersion";
NSString * const kCMISParameterTypeId = @"typeId";
NSString * const kCMISParameterStatement = @"statement";
diff --git a/ObjectiveCMIS/Common/CMISEnums.m b/ObjectiveCMIS/Common/CMISEnums.m
index 69c9671..b651ecf 100644
--- a/ObjectiveCMIS/Common/CMISEnums.m
+++ b/ObjectiveCMIS/Common/CMISEnums.m
@@ -41,7 +41,7 @@
includeRelationShipString = @"both";
break;
default:
- CMISLogError(@"Invalid enum type %d", includeRelationship);
+ CMISLogError(@"Invalid enum type %d", (int)includeRelationship);
break;
}
return includeRelationShipString;
@@ -61,7 +61,7 @@
unfileObjectString = @"delete";
break;
default:
- CMISLogError(@"Inavlid enum type %d", unfileObject);
+ CMISLogError(@"Inavlid enum type %d", (int)unfileObject);
break;
}
return unfileObjectString;
diff --git a/ObjectiveCMIS/Utils/CMISDefaultNetworkProvider.m b/ObjectiveCMIS/Utils/CMISDefaultNetworkProvider.m
index 0834fec..aa52c02 100644
--- a/ObjectiveCMIS/Utils/CMISDefaultNetworkProvider.m
+++ b/ObjectiveCMIS/Utils/CMISDefaultNetworkProvider.m
@@ -302,7 +302,7 @@
httpMethod = @"PUT";
break;
default:
- CMISLogError(@"Invalid http request method: %d", httpRequestMethod);
+ CMISLogError(@"Invalid http request method: %d", (int)httpRequestMethod);
return nil;
}
diff --git a/ObjectiveCMIS/Utils/CMISHttpRequest.m b/ObjectiveCMIS/Utils/CMISHttpRequest.m
index 35b246f..10c84bc 100644
--- a/ObjectiveCMIS/Utils/CMISHttpRequest.m
+++ b/ObjectiveCMIS/Utils/CMISHttpRequest.m
@@ -194,7 +194,7 @@
- (BOOL)checkStatusCodeForResponse:(CMISHttpResponse *)response httpRequestMethod:(CMISHttpRequestMethod)httpRequestMethod error:(NSError **)error
{
if ([CMISLog sharedInstance].logLevel == CMISLogLevelTrace) {
- CMISLogTrace(@"Response status code: %d", response.statusCode);
+ CMISLogTrace(@"Response status code: %ld", (long)response.statusCode);
CMISLogTrace(@"Response body: %@", [[NSString alloc] initWithData:response.data encoding:NSUTF8StringEncoding]);
}
diff --git a/ObjectiveCMISTests/ObjectiveCMISTests.m b/ObjectiveCMISTests/ObjectiveCMISTests.m
index 0ab7ce8..6fbb9ce 100644
--- a/ObjectiveCMISTests/ObjectiveCMISTests.m
+++ b/ObjectiveCMISTests/ObjectiveCMISTests.m
@@ -743,6 +743,7 @@
continueOnFailure:YES
completionBlock:^(NSArray *failedObjects, NSError *error) {
XCTAssertNil(error, @"Error while move test folders and document: %@", [error description]);
+ XCTAssertTrue(failedObjects.count == 0, @"some objects could not be deleted");
self.testCompleted = YES;
}];