Skip to content

Commit 17442ce

Browse files
author
Caitlin Bales (MSFT)
authored
Merge pull request #96 from microsoftgraph/android-custom-file-updates
Android custom file updates
2 parents 458bf8f + f7e6cc3 commit 17442ce

15 files changed

+475
-7
lines changed

Templates/Android/BaseModel.template.tt

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
<#@ template debug="true" hostspecific="true" language="C#" #>
33
<#@ output extension="\\" #>
44
<#
5+
56
CustomT4Host host = (CustomT4Host) Host;
67
var model = host.CurrentModel;
78
CodeWriterAndroid writer = (CodeWriterAndroid) host.CodeWriter;
@@ -799,4 +800,59 @@ public {1} {2}{3}{4} {{";
799800
return
800801
@"// **NOTE** This file was generated by a tool and any changes will be overwritten.";
801802
}
803+
804+
/*
805+
* Add additional methods to a generated class
806+
* @param className The class that you will be adding methods to
807+
* @return The additional text to add to the generated file
808+
*/
809+
public string AddCustomCode(string className) {
810+
CustomMethods customMethods = new CustomMethods();
811+
var type = customMethods.GetType();
812+
var property = type.GetFields().Where(x => x.Name == className).FirstOrDefault();
813+
814+
return property != null ? property.GetValue(customMethods).ToString() : string.Empty;
815+
}
816+
817+
/*
818+
* Add additional import statements to a generated class
819+
* @param className The class that you will be adding methods to
820+
* @return The additional text to add to the generated file
821+
*/
822+
public string AddCustomImport(string className) {
823+
CustomImports customImports = new CustomImports();
824+
var type = customImports.GetType();
825+
var property = type.GetFields().Where(x => x.Name == className).FirstOrDefault();
826+
827+
return property != null ? property.GetValue(customImports).ToString() : string.Empty;
828+
}
829+
830+
/*
831+
* Find and replace overwrite values for the given class
832+
* @param className The class that you will be applying overwrites to
833+
* @return An empty string (does not write anything new to the file)
834+
*/
835+
public string PostProcess(string className)
836+
{
837+
//Load the StringBuilder with the file contents
838+
var strb = this.GenerationEnvironment;
839+
840+
//Get the list of available classes to overwrite
841+
CustomOverwrites customOverwrites = new CustomOverwrites();
842+
var type = customOverwrites.GetType();
843+
844+
//Load the dictionary that corresponds to the current class
845+
var results = type.GetFields().Where(x => x.Name == className).FirstOrDefault();
846+
847+
if (results != null) {
848+
var dictionary = (Dictionary<string, string>)results.GetValue(this);
849+
//Find and replace for each item in the dictionary
850+
foreach (var item in dictionary) {
851+
strb.Replace(item.Key, item.Value);
852+
}
853+
}
854+
//This seems to be a requirement of the template builder
855+
//Specifying a return type of "void" throws an error
856+
return string.Empty;
857+
}
802858
#>
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
<# // Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License in the project root for license information. #>
2+
<#@ template debug="true" hostspecific="true" language="C#" #>
3+
<#@ include file="BaseModel.template.tt"#>
4+
<#@ output extension="\\" #>
5+
<#=writer.WriteHeader()#>
6+
package com.microsoft.graph.extensions;
7+
8+
import com.microsoft.graph.concurrency.ChunkedUploadResponseHandler;
9+
import com.microsoft.graph.core.ClientException;
10+
import com.microsoft.graph.core.GraphErrorCodes;
11+
import com.microsoft.graph.http.BaseRequest;
12+
import com.microsoft.graph.http.HttpMethod;
13+
import com.microsoft.graph.options.Option;
14+
15+
import java.util.List;
16+
17+
/**
18+
* The chunk upload request.
19+
*/
20+
public class ChunkedUploadRequest {
21+
22+
/**
23+
* Content Range header name.
24+
*/
25+
private static final String CONTENT_RANGE_HEADER_NAME = "Content-Range";
26+
27+
/**
28+
* Content Range value format.
29+
*/
30+
private static final String CONTENT_RANGE_FORMAT = "bytes %1$d-%2$d/%3$d";
31+
32+
/**
33+
* The seconds for retry delay.
34+
*/
35+
private static final int RETRY_DELAY = 2 * 1000;
36+
37+
/**
38+
* The chunk data sent to the server.
39+
*/
40+
private final byte[] mData;
41+
42+
/**
43+
* The base request.
44+
*/
45+
private final BaseRequest mBaseRequest;
46+
47+
/**
48+
* The max retry for single request.
49+
*/
50+
private final int mMaxRetry;
51+
52+
/**
53+
* The retry counter.
54+
*/
55+
private int mRetryCount;
56+
57+
/**
58+
* Construct the ChunkedUploadRequest
59+
*
60+
* @param requestUrl The upload url.
61+
* @param client The OneDrive client.
62+
* @param options The query options.
63+
* @param chunk The chunk byte array.
64+
* @param chunkSize The chunk array size.
65+
* @param maxRetry The limit on retry.
66+
* @param beginIndex The begin index of this chunk in the input stream.
67+
* @param totalLength The total length of the input stream.
68+
*/
69+
public ChunkedUploadRequest(final String requestUrl,
70+
final IGraphServiceClient client,
71+
final List<Option> options,
72+
final byte[] chunk,
73+
final int chunkSize,
74+
final int maxRetry,
75+
final int beginIndex,
76+
final int totalLength) {
77+
this.mData = new byte[chunkSize];
78+
System.arraycopy(chunk, 0, this.mData, 0, chunkSize);
79+
this.mRetryCount = 0;
80+
this.mMaxRetry = maxRetry;
81+
this.mBaseRequest = new BaseRequest(requestUrl, client, options, ChunkedUploadResult.class) {
82+
};
83+
this.mBaseRequest.setHttpMethod(HttpMethod.PUT);
84+
this.mBaseRequest.addHeader(CONTENT_RANGE_HEADER_NAME,
85+
String.format(
86+
CONTENT_RANGE_FORMAT,
87+
beginIndex,
88+
beginIndex + chunkSize - 1,
89+
totalLength));
90+
}
91+
92+
/**
93+
* Upload a chunk with tries.
94+
*
95+
* @param responseHandler The handler handle http response.
96+
* @param <UploadType> The upload item type.
97+
* @return The upload result.
98+
*/
99+
public <UploadType> ChunkedUploadResult upload(
100+
final ChunkedUploadResponseHandler<UploadType> responseHandler) {
101+
while (this.mRetryCount < this.mMaxRetry) {
102+
try {
103+
Thread.sleep(RETRY_DELAY * this.mRetryCount * this.mRetryCount);
104+
} catch (final InterruptedException e) {
105+
this.mBaseRequest.getClient().getLogger().logError("Exception while waiting upload file retry", e);
106+
}
107+
108+
ChunkedUploadResult result = null;
109+
110+
try {
111+
result = this.mBaseRequest
112+
.getClient()
113+
.getHttpProvider()
114+
.send(mBaseRequest, ChunkedUploadResult.class, this.mData, responseHandler);
115+
} catch (final ClientException e) {
116+
this.mBaseRequest.getClient().getLogger().logDebug("Request failed with, retry if necessary.");
117+
}
118+
119+
if (result != null && result.chunkCompleted()) {
120+
return result;
121+
}
122+
123+
this.mRetryCount++;
124+
}
125+
126+
return new ChunkedUploadResult(
127+
new ClientException("Upload session failed to many times.", null,
128+
GraphErrorCodes.UploadSessionIncomplete));
129+
}
130+
}
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
<# // Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License in the project root for license information. #>
2+
<#@ template debug="true" hostspecific="true" language="C#" #>
3+
<#@ include file="BaseModel.template.tt"#>
4+
<#@ output extension="\\" #>
5+
<#=writer.WriteHeader()#>
6+
package com.microsoft.graph.extensions;
7+
8+
import com.microsoft.graph.core.ClientException;
9+
import com.microsoft.graph.core.GraphErrorCodes;
10+
import com.microsoft.graph.http.GraphServiceException;
11+
12+
/**
13+
* Wrapper class for different upload response from server.
14+
*/
15+
public class ChunkedUploadResult<UploadType> {
16+
/**
17+
* The uploaded item response.
18+
*/
19+
private final UploadType mUploadedItem;
20+
21+
/**
22+
* The next session response.
23+
*/
24+
private final UploadSession mSession;
25+
26+
/**
27+
* The error happened during upload.
28+
*/
29+
private final ClientException mError;
30+
31+
/**
32+
* Construct result with item created.
33+
*
34+
* @param uploaded The created item.
35+
*/
36+
public ChunkedUploadResult(UploadType uploaded) {
37+
this.mUploadedItem = uploaded;
38+
this.mSession = null;
39+
this.mError = null;
40+
}
41+
42+
/**
43+
* Construct result with next session.
44+
*
45+
* @param session The next session.
46+
*/
47+
public ChunkedUploadResult(UploadSession session) {
48+
this.mSession = session;
49+
this.mUploadedItem = null;
50+
this.mError = null;
51+
}
52+
53+
/**
54+
* Construct result with error.
55+
*
56+
* @param error The error occurred during uploading.
57+
*/
58+
public ChunkedUploadResult(ClientException error) {
59+
this.mError = error;
60+
this.mUploadedItem = null;
61+
this.mSession = null;
62+
}
63+
64+
/**
65+
* Construct result with server exception.
66+
*
67+
* @param exception The exception received from server.
68+
*/
69+
public ChunkedUploadResult(GraphServiceException exception) {
70+
this(new ClientException(exception.getMessage(/* verbose */ true), exception, GraphErrorCodes.UploadSessionFailed));
71+
}
72+
73+
/**
74+
* Checks the chunk upload is completed.
75+
*
76+
* @return true if current chunk upload is completed.
77+
*/
78+
public boolean chunkCompleted() {
79+
return this.mUploadedItem != null || this.mSession != null;
80+
}
81+
82+
/**
83+
* Checks the whole upload is completed.
84+
*
85+
* @return true if the response is a an item.
86+
*/
87+
public boolean uploadCompleted() {
88+
return this.mUploadedItem != null;
89+
}
90+
91+
/**
92+
* Checks if error happened.
93+
*
94+
* @return true if current request has error.
95+
*/
96+
public boolean hasError() {
97+
return this.mError != null;
98+
}
99+
100+
/**
101+
* Get the uploaded item.
102+
*
103+
* @return The item.
104+
*/
105+
public UploadType getItem() {
106+
return this.mUploadedItem;
107+
}
108+
109+
/**
110+
* Get the next session.
111+
*
112+
* @return The next session for uploading.
113+
*/
114+
public UploadSession getSession() {
115+
return this.mSession;
116+
}
117+
118+
/**
119+
* Get the error.
120+
*
121+
* @return The error.
122+
*/
123+
public ClientException getError() {
124+
return this.mError;
125+
}
126+
}

Templates/Android/extensions/EntityRequestBuilder.java.tt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,6 @@
1818
public <#=TypeRequestBuilder(c)#>(final String requestUrl, final <#=IBaseClientType()#> client, final java.util.List<Option> requestOptions) {
1919
super(requestUrl, client, requestOptions);
2020
}
21+
22+
<#=AddCustomCode(TypeRequestBuilder(c))#>
2123
}

Templates/Android/extensions/ExtensableEntity.java.tt renamed to Templates/Android/extensions/ExtensibleEntity.tt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<#@ output extension="\\" #>
55
<#=writer.WriteHeader()#>
66
<#=CreatePackageDef(host)#>
7-
7+
<#=AddCustomImport(TypeName(c))#>
88
<#=CreateClassDef(TypeName(c), BaseTypeName(c))#>
99

1010
}

Templates/Android/extensions/IEntityRequestBuilder.java.tt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@
88

99
<#=CreateInterfaceDef(ITypeRequestBuilder(c), IBaseTypeRequestBuilder(c))#>
1010

11+
<#=AddCustomCode(ITypeRequestBuilder(c))#>
1112
}

Templates/Android/generated/BaseEntityCollectionRequest.java.tt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,4 @@
104104
return page;
105105
}
106106
}
107+
<#=PostProcess(BaseTypeCollectionRequest(c))#>

Templates/Android/generated/BaseEntityRequest.java.tt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@
9393
}
9494
<# } #>
9595
}
96+
<#=PostProcess(BaseTypeRequest(c))#>
9697
<#+
9798
public String deleteMethods(OdcmObject c)
9899
{
@@ -192,4 +193,4 @@
192193
";
193194
return string.Format(formatString, TypeName(odcmObject));
194195
}
195-
#>
196+
#>

Templates/Android/generated/IBaseEntityCollectionRequest.java.tt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,4 @@
4747

4848
<# } #>
4949
}
50+
<#=PostProcess(IBaseTypeCollectionRequest(c))#>

Templates/Android/generated/IBaseEntityRequest.java.tt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
<#=IBaseTypeRequest(c)#> top(final int value);
7070
<# } #>
7171
}
72+
<#=PostProcess(IBaseTypeRequest(c))#>
7273
<#+
7374
public String deleteMethods(OdcmObject c)
7475
{

0 commit comments

Comments
 (0)