Skip to content

Commit afa91d9

Browse files
committed
- fixes a bug where collections would not be deserialized properly
1 parent cd97702 commit afa91d9

File tree

4 files changed

+164
-107
lines changed

4 files changed

+164
-107
lines changed

src/main/java/com/microsoft/graph/serializer/AttachmentCollectionPageSerializer.java

Lines changed: 0 additions & 95 deletions
This file was deleted.
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
// ------------------------------------------------------------------------------
2+
// Copyright (c) 2017 Microsoft Corporation
3+
//
4+
// Permission is hereby granted, free of charge, to any person obtaining a copy
5+
// of this software and associated documentation files (the "Software"), to deal
6+
// in the Software without restriction, including without limitation the rights
7+
// to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
8+
// copies of the Software, and to permit persons to whom the Software is
9+
// furnished to do so, subject to the following conditions:
10+
//
11+
// The above copyright notice and this permission notice shall be included in
12+
// all copies or substantial portions of the Software.
13+
//
14+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20+
// THE SOFTWARE.
21+
// ------------------------------------------------------------------------------
22+
23+
package com.microsoft.graph.serializer;
24+
25+
import java.lang.reflect.InvocationTargetException;
26+
import java.lang.reflect.Type;
27+
import java.util.ArrayList;
28+
import java.util.Arrays;
29+
import java.util.List;
30+
31+
import com.google.gson.JsonArray;
32+
import com.google.gson.JsonElement;
33+
import com.google.gson.JsonObject;
34+
import com.google.gson.JsonParseException;
35+
import com.google.gson.JsonParser;
36+
import com.google.common.reflect.TypeToken;
37+
import com.microsoft.graph.http.BaseCollectionPage;
38+
import com.microsoft.graph.http.IRequestBuilder;
39+
import com.microsoft.graph.logger.ILogger;
40+
41+
// those imports are useless but build will fail if code-gen conventions change, keep it
42+
import com.microsoft.graph.models.extensions.Attachment;
43+
import com.microsoft.graph.requests.extensions.AttachmentCollectionPage;
44+
import com.microsoft.graph.requests.extensions.AttachmentCollectionResponse;
45+
import com.microsoft.graph.requests.extensions.IAttachmentCollectionRequestBuilder;
46+
47+
public class CollectionPageSerializer {
48+
49+
private static DefaultSerializer serializer;
50+
/** length of the word "page" */
51+
private final static Integer pageLength = 4;
52+
/** length of the word "collection" */
53+
private final static Integer collectionLength = 10;
54+
/** length of the work "response" */
55+
private final static Integer responseLength = 8;
56+
/** the extensions segment in the package name of target classes */
57+
private final static String extensionsPath = "extensions.";
58+
59+
/**
60+
* Not available for instantiation
61+
*/
62+
private CollectionPageSerializer() {
63+
}
64+
65+
/**
66+
* Serializes an CollectionPage
67+
*
68+
* @param src the CollectionPage variable for serialization
69+
* @param logger the logger
70+
* @return JsonElement of CollectionPage
71+
*/
72+
public static <T1, T2 extends IRequestBuilder> JsonElement serialize(final BaseCollectionPage<T1, T2> src, final ILogger logger) {
73+
if(src == null) {
74+
return null;
75+
}
76+
JsonArray jsonArray = new JsonArray();
77+
List<T1> items = src.getCurrentPage();
78+
serializer = new DefaultSerializer(logger);
79+
for(T1 item : items) {
80+
final String json = serializer.serializeObject(item);
81+
final JsonElement element = JsonParser.parseString(json);
82+
if(element != null && element.isJsonObject()) {
83+
final JsonObject jsonObject = element.getAsJsonObject();
84+
jsonArray.add(jsonObject);
85+
}
86+
}
87+
return jsonArray;
88+
}
89+
90+
/**
91+
* Deserializes the JsonElement
92+
*
93+
* @param json the source CollectionPage's Json
94+
* @param typeOfT The type of the CollectionPage to deserialize to
95+
* @param logger the logger
96+
* @throws JsonParseException the parse exception
97+
* @return the deserialized CollectionPage
98+
*/
99+
@SuppressWarnings("unchecked")
100+
public static <T1, T2 extends IRequestBuilder> BaseCollectionPage<T1, T2> deserialize(final JsonElement json, Type typeOfT, final ILogger logger) throws JsonParseException {
101+
if (json == null) {
102+
return null;
103+
}
104+
serializer = new DefaultSerializer(logger);
105+
final JsonObject[] sourceArray = serializer.deserializeObject(json.toString(), JsonObject[].class);
106+
final ArrayList<T1> list = new ArrayList<T1>(sourceArray.length);
107+
final String collectionPageClassCanonicalName = typeOfT.getTypeName();
108+
final String entityClassCanonicalName = collectionPageClassCanonicalName
109+
.substring(0, collectionPageClassCanonicalName.length() - pageLength - collectionLength)
110+
.replace("requests", "models");
111+
try {
112+
final Class<?> entityClass = Class.forName(entityClassCanonicalName);
113+
for (JsonObject sourceObject : sourceArray) {
114+
final T1 targetObject = (T1)serializer.deserializeObject(sourceObject.toString(), entityClass);
115+
((IJsonBackedObject)targetObject).setRawObject(serializer, sourceObject);
116+
list.add(targetObject);
117+
}
118+
final String responseClassCanonicalName = collectionPageClassCanonicalName
119+
.substring(0, collectionPageClassCanonicalName.length() - pageLength) + "Response";
120+
final Class<?> responseClass = Class.forName(responseClassCanonicalName);
121+
final Object response = responseClass.getConstructor().newInstance();
122+
responseClass.getField("value").set(response, list);
123+
final Class<?> collectionPageClass = Class.forName(collectionPageClassCanonicalName);
124+
final String responseBuilderInterfaceCanonicalName = responseClassCanonicalName
125+
.substring(0, responseClassCanonicalName.length() - responseLength)
126+
.replace(extensionsPath, extensionsPath + "I") + "RequestBuilder";
127+
final Class<?> responseBuilderInterfaceClass = Class.forName(responseBuilderInterfaceCanonicalName);
128+
return (BaseCollectionPage<T1, T2>)collectionPageClass.getConstructor(responseClass, responseBuilderInterfaceClass).newInstance(response, null);
129+
} catch(ClassNotFoundException ex) {
130+
logger.logError("Could not find class during deserialization", ex);
131+
} catch(NoSuchMethodException | InstantiationException | InvocationTargetException ex) {
132+
logger.logError("Could not instanciate type during deserialization", ex);
133+
} catch(NoSuchFieldException | IllegalAccessException ex) {
134+
logger.logError("Unable to set field value during deserialization", ex);
135+
}
136+
return null;
137+
}
138+
}

src/main/java/com/microsoft/graph/serializer/GsonFactory.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@
3131
import com.google.gson.JsonPrimitive;
3232
import com.google.gson.JsonSerializationContext;
3333
import com.google.gson.JsonSerializer;
34+
import com.microsoft.graph.http.BaseCollectionPage;
3435
import com.microsoft.graph.logger.ILogger;
3536
import com.microsoft.graph.models.extensions.DateOnly;
36-
import com.microsoft.graph.requests.extensions.AttachmentCollectionPage;
3737

3838
import com.microsoft.graph.models.extensions.TimeOfDay;
3939
import java.lang.reflect.Type;
@@ -212,21 +212,21 @@ public Duration deserialize(final JsonElement json,
212212
}
213213
};
214214

215-
final JsonSerializer<AttachmentCollectionPage> attachmentCollectionPageSerializer = new JsonSerializer<AttachmentCollectionPage>() {
215+
final JsonSerializer<BaseCollectionPage<?,?>> collectionPageSerializer = new JsonSerializer<BaseCollectionPage<?,?>>() {
216216
@Override
217-
public JsonElement serialize(final AttachmentCollectionPage src,
217+
public JsonElement serialize(final BaseCollectionPage<?,?> src,
218218
final Type typeOfSrc,
219219
final JsonSerializationContext context) {
220-
return AttachmentCollectionPageSerializer.serialize(src, logger);
220+
return CollectionPageSerializer.serialize(src, logger);
221221
}
222222
};
223223

224-
final JsonDeserializer<AttachmentCollectionPage> attachmentCollectionPageDeserializer = new JsonDeserializer<AttachmentCollectionPage>() {
224+
final JsonDeserializer<BaseCollectionPage<?,?>> collectionPageDeserializer = new JsonDeserializer<BaseCollectionPage<?,?>>() {
225225
@Override
226-
public AttachmentCollectionPage deserialize(final JsonElement json,
226+
public BaseCollectionPage<?,?> deserialize(final JsonElement json,
227227
final Type typeOfT,
228228
final JsonDeserializationContext context) throws JsonParseException {
229-
return AttachmentCollectionPageSerializer.deserialize(json, logger);
229+
return CollectionPageSerializer.deserialize(json, typeOfT, logger);
230230
}
231231
};
232232

@@ -257,8 +257,8 @@ public TimeOfDay deserialize(final JsonElement json,
257257
.registerTypeAdapter(EnumSet.class, enumSetJsonDeserializer)
258258
.registerTypeAdapter(Duration.class, durationJsonSerializer)
259259
.registerTypeAdapter(Duration.class, durationJsonDeserializer)
260-
.registerTypeAdapter(AttachmentCollectionPage.class, attachmentCollectionPageSerializer)
261-
.registerTypeAdapter(AttachmentCollectionPage.class, attachmentCollectionPageDeserializer)
260+
.registerTypeHierarchyAdapter(BaseCollectionPage.class, collectionPageSerializer)
261+
.registerTypeHierarchyAdapter(BaseCollectionPage.class, collectionPageDeserializer)
262262
.registerTypeAdapter(TimeOfDay.class, timeOfDayJsonDeserializer)
263263
.registerTypeAdapterFactory(new FallbackTypeAdapterFactory(logger))
264264
.create();

src/test/java/com/microsoft/graph/serializer/AttachmentCollectionPageSerializerTests.java renamed to src/test/java/com/microsoft/graph/serializer/CollectionPageSerializerTests.java

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package com.microsoft.graph.serializer;
22

33
import static org.junit.Assert.assertEquals;
4+
import static org.junit.Assert.assertNotNull;
5+
import static org.junit.Assert.assertTrue;
46

57
import java.nio.charset.StandardCharsets;
68
import java.util.ArrayList;
@@ -11,19 +13,21 @@
1113

1214
import com.google.gson.JsonElement;
1315
import com.google.gson.JsonParser;
16+
import com.microsoft.graph.http.BaseCollectionPage;
1417
import com.microsoft.graph.logger.MockLogger;
1518
import com.microsoft.graph.models.extensions.Attachment;
1619
import com.microsoft.graph.models.extensions.Attendee;
1720
import com.microsoft.graph.models.extensions.Contact;
1821
import com.microsoft.graph.models.extensions.DateTimeTimeZone;
22+
import com.microsoft.graph.models.extensions.DriveItem;
1923
import com.microsoft.graph.models.extensions.EmailAddress;
2024
import com.microsoft.graph.models.extensions.Event;
2125
import com.microsoft.graph.models.extensions.FileAttachment;
2226
import com.microsoft.graph.models.extensions.ItemAttachment;
2327
import com.microsoft.graph.requests.extensions.AttachmentCollectionPage;
2428
import com.microsoft.graph.requests.extensions.AttachmentCollectionResponse;
2529

26-
public class AttachmentCollectionPageSerializerTests {
30+
public class CollectionPageSerializerTests {
2731
private MockLogger logger;
2832
@Before
2933
public void setUp() {
@@ -36,7 +40,7 @@ public void testAttachmentCollectionPageSerialization() throws Exception {
3640
AttachmentCollectionResponse response = new AttachmentCollectionResponse();
3741
response.value = Arrays.asList(getFileAttachment(),getItemAttachmentWithEvent(),getItemAttachmentWithContact());
3842
AttachmentCollectionPage attachmentCollectionPage = new AttachmentCollectionPage(response, null);
39-
JsonElement serializedJson = AttachmentCollectionPageSerializer.serialize(attachmentCollectionPage, logger);
43+
JsonElement serializedJson = CollectionPageSerializer.serialize(attachmentCollectionPage, logger);
4044
logger.logDebug(serializedJson.toString());
4145
assertEquals(expectedString,serializedJson.toString());
4246
}
@@ -45,7 +49,7 @@ public void testAttachmentCollectionPageSerialization() throws Exception {
4549
public void testAttachmentCollectionPageDeserialization() throws Exception {
4650
String jsonString = "[{\"contentBytes\":\"ZGF0YQ==\",\"name\":\"document.pdf\",\"@odata.type\":\"#microsoft.graph.fileAttachment\",\"id\":\"54321\"},{\"@odata.type\":\"#microsoft.graph.itemAttachment\",\"name\":\"Holiday event\",\"id\":null,\"isInline\":null,\"size\":null,\"item\":{\"subject\":\"Test Event Subject\",\"start\":{\"dateTime\":\"2018-10-16T06:15:26.544Z\",\"timeZone\":\"UTC\"},\"end\":{\"dateTime\":\"2018-11-18T07:30:26.544Z\",\"timeZone\":\"UTC\"},\"@odata.type\":\"microsoft.graph.event\",\"id\":\"1234\"}},{\"@odata.type\":\"#microsoft.graph.itemAttachment\",\"name\":\"Attachment name\",\"id\":null,\"isInline\":null,\"size\":null,\"item\":{\"displayName\":\"displayname\",\"mobilePhone\":\"123456890\",\"@odata.type\":\"microsoft.graph.contact\"}}]";
4751
JsonElement jsonElement = JsonParser.parseString(jsonString);
48-
AttachmentCollectionPage attachmentCollectionPage = AttachmentCollectionPageSerializer.deserialize(jsonElement, logger);
52+
BaseCollectionPage<Attachment,?> attachmentCollectionPage = CollectionPageSerializer.deserialize(jsonElement, AttachmentCollectionPage.class, logger);
4953
for(Attachment attachment: attachmentCollectionPage.getCurrentPage()) {
5054
if(attachment instanceof FileAttachment) {
5155
FileAttachment fileAttachment = (FileAttachment)attachment;
@@ -69,6 +73,16 @@ else if(itemAttachment.item instanceof Contact) {
6973
}
7074
}
7175

76+
@Test
77+
public void testEntityWithCollectionOnDefaultDeserializer() throws Exception {
78+
final String jsonString = "{\"createdBy\":{\"application\":{\"displayName\":\"UmtPlus\",\"id\":\"4458250c\"},\"user\":{\"id\":\"c1fba35378bf924c\"}},\"createdDateTime\":\"2020-09-16T14:53:53.61Z\",\"cTag\":\"aYzpDMUZCQTM1Mzc4QkY5MjRDITIzNDkyNS4yNTc\",\"eTag\":\"aQzFGQkEzNTM3OEJGOTI0QyEyMzQ5MjUuMTE\",\"id\":\"C1FBA35378BF924C!234925\",\"lastModifiedBy\":{\"application\":{\"displayName\":\"UmtPlus\",\"id\":\"4458250c\"},\"user\":{\"id\":\"c1fba35378bf924c\"}},\"lastModifiedDateTime\":\"2020-09-16T17:42:17.847Z\",\"name\":\"Change Flat Tire.sco\",\"parentReference\":{\"driveId\":\"c1fba35378bf924c\",\"driveType\":\"personal\",\"id\":\"C1FBA35378BF924C!234867\",\"name\":\"UmtPlus\",\"path\":\"/drive/root:/UmtPlus\"},\"size\":59228,\"webUrl\":\"https://1drv.ms/u/s!AEySv3hTo_vBjqst\",\"items\":[],\"file\":{\"hashes\":{\"quickXorHash\":\"RjqF6zG7yzMKxLlRmXkKr0tK7oQ=\",\"sha1Hash\":\"A7A1DB7C7355A372E6097C5BD7DF6CF702AFA897\",\"sha256Hash\":\"97EF73D523368EE939D084F87DE22E28BD9236CC55D6A67EE69183FFC456CA08\"},\"mimeType\":\"application/octet-stream\"},\"fileSystemInfo\":{\"createdDateTime\":\"2020-09-16T14:53:53.61Z\",\"lastModifiedDateTime\":\"2020-09-16T17:42:17.846Z\"},\"reactions\":{\"commentCount\":0},\"tags\":[],\"lenses\":[],\"thumbnails\":[{\"id\":\"0\",\"large\":{\"height\":800,\"url\":\"https://oxo45g.bl.files.1drv.com/y4pi3j1XhJr0-LmucbMAY7erAc5yeeX8yXaxUqk7p5O1mYVUMnRmzIeFC8LgpZLXCNFkFfVzt_PlChpIBL2VwTp9bdXVToVWsHRKC5MmEiO4Zv3eR9_JCc2ih4jstMbx6AusvkIpCW7FEpWWSeyFQEJR0jbaNNZSs_n6Ryrio2xYl9LhINf19-xYBxVCR4kV188?width=800&height=800&cropmode=none\",\"width\":800},\"medium\":{\"height\":176,\"url\":\"https://oxo45g.bl.files.1drv.com/y4pi3j1XhJr0-LmucbMAY7erAc5yeeX8yXaxUqk7p5O1mYVUMnRmzIeFC8LgpZLXCNFkFfVzt_PlChpIBL2VwTp9bdXVToVWsHRKC5MmEiO4Zv3eR9_JCc2ih4jstMbx6AusvkIpCW7FEpWWSeyFQEJR0jbaNNZSs_n6Ryrio2xYl9LhINf19-xYBxVCR4kV188?width=176&height=176&cropmode=none\",\"width\":176},\"small\":{\"height\":96,\"url\":\"https://oxo45g.bl.files.1drv.com/y4pi3j1XhJr0-LmucbMAY7erAc5yeeX8yXaxUqk7p5O1mYVUMnRmzIeFC8LgpZLXCNFkFfVzt_PlChpIBL2VwTp9bdXVToVWsHRKC5MmEiO4Zv3eR9_JCc2ih4jstMbx6AusvkIpCW7FEpWWSeyFQEJR0jbaNNZSs_n6Ryrio2xYl9LhINf19-xYBxVCR4kV188?width=96&height=96&cropmode=none\",\"width\":96}}]}";
79+
final DefaultSerializer defaultSerializer = new DefaultSerializer(logger);
80+
final DriveItem driveItem = defaultSerializer.deserializeObject(jsonString, DriveItem.class);
81+
assertNotNull(driveItem);
82+
assertNotNull(driveItem.thumbnails);
83+
assertTrue(driveItem.thumbnails.getCurrentPage().size() > 0);
84+
}
85+
7286
private FileAttachment getFileAttachment() throws Exception{
7387
FileAttachment fileAttachment = new FileAttachment();
7488
fileAttachment.name = "document.pdf";

0 commit comments

Comments
 (0)