| /* |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, |
| software distributed under the License is distributed on an |
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| KIND, either express or implied. See the License for the |
| specific language governing permissions and limitations |
| under the License. |
| */ |
| |
| #import "CMISObjectConverter.h" |
| #import "CMISDocument.h" |
| #import "CMISFolder.h" |
| #import "CMISTypeDefinition.h" |
| #import "CMISErrors.h" |
| #import "CMISPropertyDefinition.h" |
| #import "CMISSession.h" |
| #import "CMISDateUtil.h" |
| |
| @interface CMISObjectConverter () |
| @property (nonatomic, weak) CMISSession *session; |
| @end |
| |
| @implementation CMISObjectConverter |
| |
| |
| - (id)initWithSession:(CMISSession *)session |
| { |
| self = [super init]; |
| if (self) { |
| self.session = session; |
| } |
| |
| return self; |
| } |
| |
| - (void)convertObject:(CMISObjectData *)objectData completionBlock:(void (^)(CMISObject *object, NSError *error))completionBlock |
| { |
| CMISObject *object = nil; |
| |
| if (objectData.baseType == CMISBaseTypeDocument) { |
| object = [[CMISDocument alloc] initWithObjectData:objectData session:self.session]; |
| } else if (objectData.baseType == CMISBaseTypeFolder) { |
| object = [[CMISFolder alloc] initWithObjectData:objectData session:self.session]; |
| } |
| |
| [object fetchTypeDefinitionWithCompletionBlock:^(NSError *error) { |
| completionBlock(object, error); |
| }]; |
| } |
| |
| |
| - (void)internalConvertObject:(NSArray *)objectDatas position:(NSInteger)position completionBlock:(void (^)(NSMutableArray *objects, NSError *error))completionBlock |
| { |
| [self convertObject:[objectDatas objectAtIndex:position] |
| completionBlock:^(CMISObject *object, NSError *error) { |
| if (position == 0) { |
| NSMutableArray *objects = [[NSMutableArray alloc] initWithCapacity:objectDatas.count]; |
| [objects addObject:object]; |
| completionBlock(objects, error); |
| } else { |
| [self internalConvertObject:objectDatas position:(position - 1) completionBlock:^(NSMutableArray *objects, NSError *error) { |
| [objects addObject:object]; |
| completionBlock(objects, error); |
| }]; |
| } |
| }]; |
| } |
| |
| |
| - (void)convertObjects:(NSArray *)objectDatas completionBlock:(void (^)(NSArray *objects, NSError *error))completionBlock |
| { |
| if (objectDatas.count > 0) { |
| [self internalConvertObject:objectDatas |
| position:(objectDatas.count - 1) // start recursion with last item |
| completionBlock:^(NSMutableArray *objects, NSError *error) { |
| completionBlock(objects, error); |
| }]; |
| } else { |
| completionBlock([[NSArray alloc] init], nil); |
| } |
| } |
| |
| |
| - (void)convertProperties:(NSDictionary *)properties |
| forObjectTypeId:(NSString *)objectTypeId |
| completionBlock:(void (^)(CMISProperties *convertedProperties, NSError *error))completionBlock |
| { |
| [self internalNormalConvertProperties:properties objectTypeId:objectTypeId completionBlock:completionBlock]; |
| } |
| |
| |
| - (void)internalNormalConvertProperties:(NSDictionary *)properties |
| typeDefinition:(CMISTypeDefinition *)typeDefinition |
| completionBlock:(void (^)(CMISProperties *convertedProperties, NSError *error))completionBlock |
| { |
| CMISProperties *convertedProperties = [[CMISProperties alloc] init]; |
| for (NSString *propertyId in properties) { |
| id propertyValue = [properties objectForKey:propertyId]; |
| // If the value is already a CMISPropertyData, we don't need to do anything |
| if ([propertyValue isKindOfClass:[CMISPropertyData class]]) { |
| [convertedProperties addProperty:(CMISPropertyData *)propertyValue]; |
| } else { |
| // Convert to CMISPropertyData based on the string |
| CMISPropertyDefinition *propertyDefinition = [typeDefinition propertyDefinitionForId:propertyId]; |
| |
| if (propertyDefinition == nil) { |
| NSError *error = [CMISErrors createCMISErrorWithCode:kCMISErrorCodeInvalidArgument |
| detailedDescription:[NSString stringWithFormat:@"Invalid property '%@' for this object type", propertyId]]; |
| completionBlock(nil, error); |
| return; |
| } |
| |
| Class expectedType = nil; |
| BOOL validType = YES; |
| |
| switch (propertyDefinition.propertyType) { |
| case(CMISPropertyTypeString): { |
| expectedType = [NSString class]; |
| if ([propertyValue isKindOfClass:expectedType]) { |
| [convertedProperties addProperty:[CMISPropertyData createPropertyForId:propertyId stringValue:propertyValue]]; |
| } else if ([propertyValue isKindOfClass:[NSArray class]]) { |
| for (id propertyValueItemValue in propertyValue) { |
| if (![propertyValueItemValue isKindOfClass:expectedType]) { |
| validType = NO; |
| break; |
| } |
| } |
| if (validType) { |
| [convertedProperties addProperty:[CMISPropertyData createPropertyForId:propertyId arrayValue:propertyValue type:propertyDefinition.propertyType]]; |
| } |
| } else { |
| validType = NO; |
| } |
| break; |
| } |
| case(CMISPropertyTypeBoolean): { |
| expectedType = [NSNumber class]; |
| if ([propertyValue isKindOfClass:expectedType]) { |
| BOOL boolValue = ((NSNumber *) propertyValue).boolValue; |
| [convertedProperties addProperty:[CMISPropertyData createPropertyForId:propertyId boolValue:boolValue]]; |
| } else if ([propertyValue isKindOfClass:[NSArray class]]) { |
| for (id propertyValueItemValue in propertyValue) { |
| if (![propertyValueItemValue isKindOfClass:expectedType]) { |
| validType = NO; |
| break; |
| } |
| } |
| if (validType) { |
| [convertedProperties addProperty:[CMISPropertyData createPropertyForId:propertyId arrayValue:propertyValue type:propertyDefinition.propertyType]]; |
| } |
| } else { |
| validType = NO; |
| } |
| break; |
| } |
| case(CMISPropertyTypeInteger): { |
| expectedType = [NSNumber class]; |
| if ([propertyValue isKindOfClass:expectedType]) { |
| NSInteger intValue = ((NSNumber *) propertyValue).integerValue; |
| [convertedProperties addProperty:[CMISPropertyData createPropertyForId:propertyId integerValue:intValue]]; |
| } else if ([propertyValue isKindOfClass:[NSArray class]]) { |
| for (id propertyValueItemValue in propertyValue) { |
| if (![propertyValueItemValue isKindOfClass:expectedType]) { |
| validType = NO; |
| break; |
| } |
| } |
| if (validType) { |
| [convertedProperties addProperty:[CMISPropertyData createPropertyForId:propertyId arrayValue:propertyValue type:propertyDefinition.propertyType]]; |
| } |
| } else { |
| validType = NO; |
| } |
| break; |
| } |
| case(CMISPropertyTypeDecimal): { |
| expectedType = [NSNumber class]; |
| if ([propertyValue isKindOfClass:expectedType]) { |
| [convertedProperties addProperty:[CMISPropertyData createPropertyForId:propertyId decimalValue:propertyValue]]; |
| } else if ([propertyValue isKindOfClass:[NSArray class]]) { |
| for (id propertyValueItemValue in propertyValue) { |
| if (![propertyValueItemValue isKindOfClass:expectedType]) { |
| validType = NO; |
| break; |
| } |
| } |
| if (validType) { |
| [convertedProperties addProperty:[CMISPropertyData createPropertyForId:propertyId arrayValue:propertyValue type:propertyDefinition.propertyType]]; |
| } |
| } else { |
| validType = NO; |
| } |
| break; |
| } |
| case(CMISPropertyTypeId): { |
| expectedType = [NSString class]; |
| if ([propertyValue isKindOfClass:expectedType]) { |
| [convertedProperties addProperty:[CMISPropertyData createPropertyForId:propertyId idValue:propertyValue]]; |
| } else if ([propertyValue isKindOfClass:[NSArray class]]) { |
| for (id propertyValueItemValue in propertyValue) { |
| if (![propertyValueItemValue isKindOfClass:expectedType]) { |
| validType = NO; |
| break; |
| } |
| } |
| if (validType) { |
| [convertedProperties addProperty:[CMISPropertyData createPropertyForId:propertyId arrayValue:propertyValue type:propertyDefinition.propertyType]]; |
| } |
| } else { |
| validType = NO; |
| } |
| break; |
| } |
| case(CMISPropertyTypeDateTime): { |
| if ([propertyValue isKindOfClass:[NSString class]]) { |
| propertyValue = [CMISDateUtil dateFromString:propertyValue]; |
| } |
| expectedType = [NSDate class]; |
| if ([propertyValue isKindOfClass:expectedType]) { |
| [convertedProperties addProperty:[CMISPropertyData createPropertyForId:propertyId dateTimeValue:propertyValue]]; |
| } else if ([propertyValue isKindOfClass:[NSArray class]]) { |
| for (__strong id propertyValueItemValue in propertyValue) { |
| if ([propertyValueItemValue isKindOfClass:[NSString class]]) { |
| propertyValueItemValue = [CMISDateUtil dateFromString:propertyValueItemValue]; |
| } |
| if (![propertyValueItemValue isKindOfClass:expectedType]) { |
| validType = NO; |
| break; |
| } |
| } |
| if (validType) { |
| [convertedProperties addProperty:[CMISPropertyData createPropertyForId:propertyId arrayValue:propertyValue type:propertyDefinition.propertyType]]; |
| } |
| } else { |
| validType = NO; |
| } |
| break; |
| } |
| case(CMISPropertyTypeUri): { |
| if ([propertyValue isKindOfClass:[NSString class]]) { |
| propertyValue = [NSURL URLWithString:propertyValue]; |
| } |
| expectedType = [NSURL class]; |
| if ([propertyValue isKindOfClass:expectedType]) { |
| [convertedProperties addProperty:[CMISPropertyData createPropertyForId:propertyId uriValue:propertyValue]]; |
| } else if ([propertyValue isKindOfClass:[NSArray class]]) { |
| for (__strong id propertyValueItemValue in propertyValue) { |
| if ([propertyValueItemValue isKindOfClass:[NSString class]]) { |
| propertyValueItemValue = [NSURL URLWithString:propertyValueItemValue]; |
| } |
| if (![propertyValueItemValue isKindOfClass:expectedType]) { |
| validType = NO; |
| break; |
| } |
| } |
| if (validType) { |
| [convertedProperties addProperty:[CMISPropertyData createPropertyForId:propertyId arrayValue:propertyValue type:propertyDefinition.propertyType]]; |
| } |
| } else { |
| validType = NO; |
| } |
| break; |
| } |
| case(CMISPropertyTypeHtml): { |
| expectedType = [NSString class]; |
| if ([propertyValue isKindOfClass:expectedType]) { |
| [convertedProperties addProperty:[CMISPropertyData createPropertyForId:propertyId htmlValue:propertyValue]]; |
| } else if ([propertyValue isKindOfClass:[NSArray class]]) { |
| for (id propertyValueItemValue in propertyValue) { |
| if (![propertyValueItemValue isKindOfClass:expectedType]) { |
| validType = NO; |
| break; |
| } |
| } |
| if (validType) { |
| [convertedProperties addProperty:[CMISPropertyData createPropertyForId:propertyId arrayValue:propertyValue type:propertyDefinition.propertyType]]; |
| } |
| } else { |
| validType = NO; |
| } |
| break; |
| } |
| default: { |
| NSError *error = [CMISErrors createCMISErrorWithCode:kCMISErrorCodeInvalidArgument |
| detailedDescription:[NSString stringWithFormat:@"Unsupported: cannot convert property type %li", (long)propertyDefinition.propertyType]]; |
| completionBlock(nil, error); |
| return; |
| } |
| } |
| |
| if (!validType) { |
| NSError *error = [CMISErrors createCMISErrorWithCode:kCMISErrorCodeInvalidArgument |
| detailedDescription:[NSString stringWithFormat:@"Property value for %@ should be of type '%@'", propertyId, expectedType]]; |
| completionBlock(nil, error); |
| return; |
| } |
| } |
| } |
| |
| completionBlock(convertedProperties, nil); |
| } |
| |
| |
| - (void)internalNormalConvertProperties:(NSDictionary *)properties |
| objectTypeId:(NSString *)objectTypeId |
| completionBlock:(void (^)(CMISProperties *convertedProperties, NSError *error))completionBlock |
| |
| { |
| // Validate params |
| if (!properties) { |
| completionBlock(nil, nil); |
| return; |
| } |
| |
| BOOL onlyPropertyData = YES; |
| for (id propertyValue in properties.objectEnumerator) { |
| if (![propertyValue isKindOfClass:[CMISPropertyData class]]) { |
| if ([propertyValue isKindOfClass:[NSArray class]]) { |
| for (id propertyValueItemValue in propertyValue) { |
| if (![propertyValueItemValue isKindOfClass:[CMISPropertyData class]]) { |
| onlyPropertyData = NO; |
| break; |
| } |
| } |
| } else { |
| onlyPropertyData = NO; |
| } |
| break; |
| } |
| } |
| |
| // Convert properties |
| if (onlyPropertyData) { |
| [self internalNormalConvertProperties:properties |
| typeDefinition:nil // not needed because all properties are of type CMISPropertyData |
| completionBlock:completionBlock]; |
| |
| } else { |
| [self.session retrieveTypeDefinition:objectTypeId |
| completionBlock:^(CMISTypeDefinition *typeDefinition, NSError *error) { |
| if (error) { |
| completionBlock(nil, [CMISErrors cmisError:error cmisErrorCode:kCMISErrorCodeRuntime]); |
| } else { |
| [self internalNormalConvertProperties:properties |
| typeDefinition:typeDefinition |
| completionBlock:completionBlock]; |
| } |
| }]; |
| } |
| } |
| |
| @end |