From bc598c274c2f61f0a66d541e1fa6cdc4ba4538fb Mon Sep 17 00:00:00 2001 From: Kevin Lam Date: Wed, 30 Mar 2016 11:06:03 -0700 Subject: [PATCH] Collection specialization tweaks & fixes for ObjC --- Templates/ObjC/Base/SharedObjC.template.tt | 48 ++++++++++++++++- Templates/ObjC/Models/CollectionType.h.tt | 19 +++++-- Templates/ObjC/Models/CollectionType.m.tt | 39 +++++++++++--- .../Requests/EntityCollectionRequest.h.tt | 5 -- .../Requests/EntityCollectionRequest.m.tt | 8 +-- Templates/ObjC/Requests/MethodRequest.h.tt | 26 +++------ Templates/ObjC/Requests/MethodRequest.m.tt | 54 ++++++++----------- .../.config/ObjCSettings.json | 5 +- .../CodeHelpers/ObjC/TypeHelperObjC.cs | 16 ++++++ .../TemplateProcessor/TemplateProcessor.cs | 3 +- 10 files changed, 148 insertions(+), 75 deletions(-) diff --git a/Templates/ObjC/Base/SharedObjC.template.tt b/Templates/ObjC/Base/SharedObjC.template.tt index 84f98e11d..63cb395d7 100644 --- a/Templates/ObjC/Base/SharedObjC.template.tt +++ b/Templates/ObjC/Base/SharedObjC.template.tt @@ -35,12 +35,29 @@ private string GetObjCTypeIdentifier(OdcmObject o, bool getUnderlyingType=false) } else { - return GetObjCTypeIdentifier(prop.Type) + "Collection"; + return prop.Type.GetCollectionTypeString(); } } return GetObjCTypeIdentifier(prop.Type,getUnderlyingType); } + else if(o is OdcmMethod) + { + OdcmMethod method = (OdcmMethod)o; + if (method.IsCollection && !getUnderlyingType) + { + if (IsNSJSONSerializable(method.ReturnType)) + { + return GetStaticCollectionObject(); + } + else + { + return method.ReturnType.GetCollectionTypeString(); + } + } + + return GetObjCTypeIdentifier(method.ReturnType, getUnderlyingType); + } else if(o is OdcmType) { return ((OdcmType)o).GetTypeString(); @@ -126,6 +143,35 @@ private string GetHydratedPropertyFromNSJSONSerializableExpression(string expr,O prop.Type.GetNSNumberValueMethod()); } +private string GetHydratedPropertyFromNSJSONSerializableExpression(string expr,OdcmMethod method) +{ + if(GetObjCTypeIdentifier(method,true)=="NSDate") + { + return String.Format(@"[NSDate ms_dateFromString: {0}]",expr); + } + + if(method.IsEnum()) + { + return String.Format( + @"[{0} to{1}]", + expr, + GetObjCTypeIdentifier(method,true)); + } + //Complex catch-all + if(method.IsComplex()) + { + return String.Format( + @"[[{0} alloc] initWithDictionary: {1} ]", + GetObjCTypeIdentifier(method,true), + expr); + } + + return String.Format( + @"[{0} {1}]", + expr, + method.ReturnType.GetNSNumberValueMethod()); +} + private string GetHydratedPropertyFromDictionary(OdcmProperty prop) { return GetHydratedPropertyFromNSJSONSerializableExpression(String.Format(@"self.dictionary[@""{0}""]",prop.Name),prop); diff --git a/Templates/ObjC/Models/CollectionType.h.tt b/Templates/ObjC/Models/CollectionType.h.tt index 83b58d554..785095d19 100644 --- a/Templates/ObjC/Models/CollectionType.h.tt +++ b/Templates/ObjC/Models/CollectionType.h.tt @@ -3,7 +3,16 @@ <#@ include file="SharedObjC.template.tt"#> <# var prop = host.CurrentType.AsOdcmProperty(); -var innerEntity = prop.Type; +var method = host.CurrentType.AsOdcmMethod(); +OdcmType innerEntity = null; +if (prop != null) +{ + innerEntity = prop.Type; +} +else if (method != null) +{ + innerEntity = method.ReturnType; +} #> #import "<#=GetStaticCollectionObject()#>.h" @@ -25,10 +34,10 @@ if(!innerEntity.IsSystem()) } #> -@interface <#=GetObjCTypeIdentifier(innerEntity)#>Collection : <#=GetStaticCollectionObject()#> +@interface <#=innerEntity.GetCollectionTypeString()#> : <#=GetStaticCollectionObject()#> -+ (<#=GetObjCTypeIdentifier(innerEntity)#>Collection *) fromMSCollection:(<#=GetStaticCollectionObject()#> *)collection; -- (<#=GetObjCTypeForVarDeclaration(innerEntity)#>) objectAtIndexInCurrentPage:(NSUInteger)index; -@property(readonly) NSUInteger countInCurrentPage; ++ (<#=innerEntity.GetCollectionTypeString()#> *) fromMSCollection:(<#=GetStaticCollectionObject()#> *)collection; +- (<#=GetObjCTypeForVarDeclaration(innerEntity)#>) objectAtIndex:(NSUInteger)index; +@property(readonly) NSUInteger count; @end diff --git a/Templates/ObjC/Models/CollectionType.m.tt b/Templates/ObjC/Models/CollectionType.m.tt index 62055db6f..b69ae5a7c 100644 --- a/Templates/ObjC/Models/CollectionType.m.tt +++ b/Templates/ObjC/Models/CollectionType.m.tt @@ -3,23 +3,39 @@ <#@ include file="SharedObjC.template.tt"#> <# var prop = host.CurrentType.AsOdcmProperty(); -var innerEntity = prop.Type; +var method = host.CurrentType.AsOdcmMethod(); +OdcmType innerEntity = null; +if (prop != null) +{ + innerEntity = prop.Type; +} +else if (method != null) +{ + innerEntity = method.ReturnType; +} #> -#import "<#=GetObjCTypeIdentifier(innerEntity)#>Collection.h" +#import "<#=innerEntity.GetCollectionTypeString()#>.h" +<# +if (!innerEntity.IsSystem() && innerEntity.IsComplex()) +{ +#> #import "<#=GetObjCTypeIdentifier(innerEntity)#>.h" +<# +} +#> -@implementation <#=GetObjCTypeIdentifier(innerEntity)#>Collection +@implementation <#=innerEntity.GetCollectionTypeString()#> -+ (<#=GetObjCTypeIdentifier(innerEntity)#>Collection *) fromMSCollection:(<#=GetStaticCollectionObject()#> *)collection { - <#=GetObjCTypeIdentifier(innerEntity)#>Collection *col = [[<#=GetObjCTypeIdentifier(innerEntity)#>Collection alloc] init]; ++ (<#=innerEntity.GetCollectionTypeString()#> *) fromMSCollection:(<#=GetStaticCollectionObject()#> *)collection { + <#=innerEntity.GetCollectionTypeString()#> *col = [[<#=innerEntity.GetCollectionTypeString()#> alloc] init]; col.value = collection.value; col.nextLink = collection.nextLink; col.additionalData = collection.additionalData; return col; } -- (<#=GetObjCTypeForVarDeclaration(innerEntity)#>) objectAtIndexInCurrentPage:(NSUInteger)index { +- (<#=GetObjCTypeForVarDeclaration(innerEntity)#>) objectAtIndex:(NSUInteger)index { <# if(IsNSJSONSerializable(innerEntity)) { @@ -29,15 +45,24 @@ var innerEntity = prop.Type; } else { + if (prop != null) + { #> return <#=GetHydratedPropertyFromNSJSONSerializableExpression("[super.value objectAtIndex:index]",prop)#>; <# + } + else + { + #> + return <#=GetHydratedPropertyFromNSJSONSerializableExpression("[super.value objectAtIndex:index]",method)#>; + <# + } } #> } -- (NSUInteger) countInCurrentPage { +- (NSUInteger) count { return [super.value count]; } diff --git a/Templates/ObjC/Requests/EntityCollectionRequest.h.tt b/Templates/ObjC/Requests/EntityCollectionRequest.h.tt index 2575f2ddc..138ba042e 100644 --- a/Templates/ObjC/Requests/EntityCollectionRequest.h.tt +++ b/Templates/ObjC/Requests/EntityCollectionRequest.h.tt @@ -29,11 +29,6 @@ if (innerEntityType.Equals(propName)) #import "<#=writer.GetPrefix()#>Models.h" #import "<#=writer.GetStaticCodePrefix()#>CollectionRequest.h" -<# -if(prop.IsReference()) { -#> -#import "<#=writer.GetStaticCodePrefix()#>CollectionReferences.h" -<# } #> typedef void (^<#=innerEntityType#>CompletionHandler)(<#=innerEntityType#> *response, NSError *error); diff --git a/Templates/ObjC/Requests/EntityCollectionRequest.m.tt b/Templates/ObjC/Requests/EntityCollectionRequest.m.tt index 5f9997436..f74869f44 100644 --- a/Templates/ObjC/Requests/EntityCollectionRequest.m.tt +++ b/Templates/ObjC/Requests/EntityCollectionRequest.m.tt @@ -33,6 +33,10 @@ if (innerEntityType.Equals(propName)) @implementation <#=propNameRequest#> +<# + if(!collectionReference) + { +#> - (MSURLSessionDataTask *)<#=GetObjCTypeIdentifier(prop)#>TaskWithRequest:(NSMutableURLRequest *)request odObjectWithDictionary:(MSObject* (^)(NSDictionary *response))castBlock completion:(void (^)(<#=GetObjCTypeForVarDeclaration(prop)#> response, NSError *error))completionHandler @@ -43,10 +47,6 @@ if (innerEntityType.Equals(propName)) }]; } -<# - if(!collectionReference) - { -#> - (NSMutableURLRequest *)get { return [self requestWithMethod:@"GET" diff --git a/Templates/ObjC/Requests/MethodRequest.h.tt b/Templates/ObjC/Requests/MethodRequest.h.tt index 209c51cb9..f20f7dac2 100644 --- a/Templates/ObjC/Requests/MethodRequest.h.tt +++ b/Templates/ObjC/Requests/MethodRequest.h.tt @@ -17,27 +17,23 @@ else returnType = "NSDictionary"; } -var superClass = writer.GetStaticCodePrefix() + ((func.IsCollection || func.LongDescriptionContains("specialCollection")) ? "CollectionRequest" : "Request"); +var superClass = writer.GetStaticCodePrefix() + (func.IsCollection ? "CollectionRequest" : "Request"); var method = ((func.Verbs & OdcmAllowedVerbs.Get) != OdcmAllowedVerbs.Get) ? "POST" : "GET"; var isAsync = func.LongDescriptionContains("async"); -var specialCollectionType = writer.GetPrefix() + func.Class.Name.ToUpperFirstChar() + func.Name.Substring(func.Name.IndexOf('.') + 1).ToUpperFirstChar() + "Collection"; -if (func.LongDescriptionContains("specialCollection")) -{ #> -@class <#=writer.GetStaticCodePrefix()#>URLSessionDataTask, <#=specialCollectionType#>; +@class <#=writer.GetStaticCodePrefix()#>URLSessionDataTask; + +#import "<#=superClass#>.h" <# -} -else +if (func.ReturnType != null && func.IsCollection) { #> -@class <#=writer.GetStaticCodePrefix()#>URLSessionDataTask; +#import "<#=func.ReturnType.GetCollectionTypeString()#>.h" <# } #> -#import "<#=superClass#>.h" - @interface <#=requestType#> : <#=superClass#> @property (readonly) NSMutableURLRequest *mutableRequest; @@ -51,15 +47,10 @@ if (func.Parameters.Count > 0) } string completionHandler; string taskType = writer.GetStaticCodePrefix() + "URLSessionDataTask *"; -if (func.IsCollection || func.LongDescriptionContains("specialCollection")) +if (func.IsCollection) { - string collectionType = writer.GetStaticCodePrefix() + "Collection"; - if (func.LongDescriptionContains("specialCollection")) - { - collectionType = specialCollectionType; - } + string collectionType = func.ReturnType.GetCollectionTypeString(); completionHandler = "(void (^)(" + collectionType + " *response, " + requestType + " *nextRequest, NSError *error))"; - } else if(isAsync) { @@ -68,7 +59,6 @@ else if(isAsync) } else { - completionHandler = writer.GetNetworkCompletionBlock(returnType, "response"); } if (!returnType.Contains("Stream")) diff --git a/Templates/ObjC/Requests/MethodRequest.m.tt b/Templates/ObjC/Requests/MethodRequest.m.tt index 8c27abb0d..181639692 100644 --- a/Templates/ObjC/Requests/MethodRequest.m.tt +++ b/Templates/ObjC/Requests/MethodRequest.m.tt @@ -27,21 +27,12 @@ else var superClass = writer.GetStaticCodePrefix() + ((func.IsCollection) ? "CollectionRequest" : "Request"); var method = ((func.Verbs & OdcmAllowedVerbs.Get) != OdcmAllowedVerbs.Get) ? "POST" : "GET"; var isAsync = func.LongDescriptionContains("async"); -var specialCollecitonName = writer.GetPrefix() + func.Class.Name.ToUpperFirstChar() + func.Name.Substring(func.Name.IndexOf('.') + 1).ToUpperFirstChar() + "Collection"; #> #import "<#=writer.GetPrefix()#>ODataEntities.h" #import "<#=writer.GetPrefix()#>Models.h" #import "<#=writer.GetStaticCodePrefix()#>URLSessionDataTask.h" -<# -if (func.LongDescriptionContains("specialCollection")) -{ -#> -#import "<#=specialCollecitonName#>.h" -<# -} -#> <# @@ -131,6 +122,22 @@ if (func.Parameters.Count > 0) } <# } + +if (func.IsCollection) +{ +#> + +- (MSURLSessionDataTask *)<#=func.ReturnType.GetCollectionTypeString()#>TaskWithRequest:(NSMutableURLRequest *)request + odObjectWithDictionary:(MSObject* (^)(NSDictionary *response))castBlock + completion:(void (^)(<#=func.ReturnType.GetCollectionTypeString()#> *response, NSError *error))completionHandler +{ + return [self collectionTaskWithRequest: request odObjectWithDictionary:castBlock + completion:^(MSCollection* collectionResponse, NSError *error){ + completionHandler([<#=func.ReturnType.GetCollectionTypeString()#> fromMSCollection:collectionResponse],error); + }]; +} +<# +} #> - (NSMutableURLRequest *)mutableRequest @@ -176,30 +183,16 @@ string completionBlock; string completionHandler; string taskMethod; string taskType = writer.GetStaticCodePrefix() + "URLSessionDataTask *"; -if (func.IsCollection || func.LongDescriptionContains("specialCollection")) +if (func.IsCollection) { - - if (func.LongDescriptionContains("specialCollection")) - { - completionHandler = "(void (^)(" + specialCollecitonName + " *response, " + requestType + " *nextRequest, NSError *error))"; - } - else - { - completionHandler = "(void (^)(" + writer.GetStaticCodePrefix() +"Collection *response, " + requestType + " *nextRequest, NSError *error))"; - } + completionHandler = "(void (^)(" + func.ReturnType.GetCollectionTypeString() + " *response, " + requestType + " *nextRequest, NSError *error))"; + var stringBuilder = new StringBuilder(); var baseIndents = (" " + writer.GetStaticCodePrefix() + "URLSessionDataTask *task = [").ToSpaces(); - stringBuilder.AppendLine("^(" + writer.GetStaticCodePrefix() + "Collection *collectionResponse, NSError *error){"); + stringBuilder.AppendLine("^(" + func.ReturnType.GetCollectionTypeString() + " *collectionResponse, NSError *error){"); string returnCollectionName = "collectionResponse"; - if (func.LongDescriptionContains("specialCollection")) - { - returnCollectionName = "collection"; - stringBuilder.AppendLine(baseIndents + " " + specialCollecitonName + " *" + returnCollectionName +"= nil;"); - stringBuilder.AppendLine(baseIndents + " if(collectionResponse){"); - stringBuilder.AppendLine(baseIndents + " " + returnCollectionName + " = [[" + specialCollecitonName + " alloc] initWithCollection:collectionResponse];"); - stringBuilder.AppendLine(baseIndents + " }"); - } + stringBuilder.AppendLine(baseIndents + " if(!error && "+ returnCollectionName + ".nextLink && completionHandler){"); stringBuilder.AppendLine(baseIndents + " " + requestType + " *nextRequest = [[" + requestType + " alloc] initWithURL:" + returnCollectionName + ".nextLink"); stringBuilder.AppendLine(baseIndents + " options:nil"); @@ -212,8 +205,7 @@ if (func.IsCollection || func.LongDescriptionContains("specialCollection")) stringBuilder.Append(baseIndents + "}"); completionBlock = stringBuilder.ToString(); - taskMethod = "[self collectionTaskWithRequest:"; - + taskMethod = "[self " + func.ReturnType.GetCollectionTypeString() + "TaskWithRequest:"; } else if(isAsync) { @@ -239,7 +231,7 @@ if (!returnType.Contains("Stream")) <#=taskType#>task = <#=taskMethod#>self.mutableRequest <#=indentSpace.Substring("odObjectWithDictionary".Length + 1)#>odObjectWithDictionary:^(id responseObject){ <# -if (returnType == writer.GetPrefix() + "String" || returnType == writer.GetStaticCodePrefix() + "Guid") +if (func.IsCollection || IsNSJSONSerializable(func.ReturnType)) { #> <#=indentSpace#> return [responseObject copy]; diff --git a/src/GraphODataTemplateWriter/.config/ObjCSettings.json b/src/GraphODataTemplateWriter/.config/ObjCSettings.json index 4b6b48da5..e03bc82a6 100644 --- a/src/GraphODataTemplateWriter/.config/ObjCSettings.json +++ b/src/GraphODataTemplateWriter/.config/ObjCSettings.json @@ -24,9 +24,8 @@ { "Template": "StreamRequest", "SubProcessor": "MediaEntityType", "Type": "Request", "Name": "StreamRequest" }, - { "Template": "CollectionType", "SubProcessor": "CollectionProperty", "Type": "Model", "Name": "Collection" }, - - + { "Template": "CollectionType", "SubProcessor": "CollectionProperty", "Type": "Model", "Name": "Collection" }, + { "Template": "CollectionType", "SubProcessor": "CollectionMethod", "Type": "Model", "Name": "Collection" }, { "Template": "EntityWithReferenceRequest", "SubProcessor": "EntityReferenceType", "Type": "Request", "Name": "WithReferenceRequest" }, { "Template": "EntityWithReferenceRequestBuilder", "SubProcessor": "EntityReferenceType", "Type": "Request", "Name": "WithReferenceRequestBuilder" }, diff --git a/src/GraphODataTemplateWriter/CodeHelpers/ObjC/TypeHelperObjC.cs b/src/GraphODataTemplateWriter/CodeHelpers/ObjC/TypeHelperObjC.cs index 5fb0a77e6..23820bb05 100644 --- a/src/GraphODataTemplateWriter/CodeHelpers/ObjC/TypeHelperObjC.cs +++ b/src/GraphODataTemplateWriter/CodeHelpers/ObjC/TypeHelperObjC.cs @@ -118,6 +118,11 @@ public static string GetTypeString(this OdcmType type) } } + public static string GetCollectionTypeString(this OdcmType type) + { + return Prefix + type.Name.ToUpperFirstChar() + "Collection"; + } + public static string GetTypeString(this OdcmProperty property) { return property.Type.GetTypeString(); @@ -136,6 +141,11 @@ public static bool IsComplex(this OdcmProperty property) return property.Type.IsComplex(); } + public static bool IsComplex(this OdcmMethod method) + { + return method.ReturnType.IsComplex(); + } + public static string ToSetterTypeString(this OdcmProperty property) { return string.Format("{0} {1}", property.GetFullType(), (property.IsComplex() ? "*" : string.Empty)); @@ -209,6 +219,12 @@ public static bool IsEnum(this OdcmProperty property) { return property.Type is OdcmEnum; } + + public static bool IsEnum(this OdcmMethod method) + { + return method.ReturnType is OdcmEnum; + } + public static string GetNSNumberValueMethod(this OdcmType type) { string objectiveCType = type.GetTypeString(); diff --git a/src/GraphODataTemplateWriter/TemplateProcessor/TemplateProcessor.cs b/src/GraphODataTemplateWriter/TemplateProcessor/TemplateProcessor.cs index c0bef21b9..02cfea138 100644 --- a/src/GraphODataTemplateWriter/TemplateProcessor/TemplateProcessor.cs +++ b/src/GraphODataTemplateWriter/TemplateProcessor/TemplateProcessor.cs @@ -197,7 +197,8 @@ protected virtual IEnumerable ProcessMethods(ITemplateInfo templateInf .Select(method => method as OdcmMethod) .Select(odcmMethod => this.ProcessTemplate(templateInfo, odcmMethod, className: odcmMethod.Class.Name, - methodName: odcmMethod.Name)); + methodName: odcmMethod.Name, + propertyType: odcmMethod.ReturnType!=null?odcmMethod.ReturnType.Name:"")); } protected virtual IEnumerable NonCollectionMethods()