Skip to content

Commit

Permalink
Expose class information for TypeReference<T> (Azure#24568)
Browse files Browse the repository at this point in the history
  • Loading branch information
samvaity authored Oct 20, 2021
1 parent 92d47eb commit a980583
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 0 deletions.
1 change: 1 addition & 0 deletions sdk/core/azure-core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## 1.22.0-beta.2 (Unreleased)

### Features Added
- Added `getJavaClass` method to retrieve the representing instance of the `TypeReference` created.

### Breaking Changes

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

package com.azure.core.util.serializer;

import com.azure.core.implementation.TypeUtil;
import com.azure.core.util.logging.ClientLogger;

import java.lang.reflect.ParameterizedType;
Expand Down Expand Up @@ -41,23 +42,27 @@ public abstract class TypeReference<T> {
private static final Map<Class<?>, TypeReference<?>> CACHE = new ConcurrentHashMap<>();

private final Type javaType;
private final Class<T> clazz;

/**
* Constructs a new {@link TypeReference} which maintains generic information.
*
* @throws IllegalArgumentException If the reference is constructed without type information.
*/
@SuppressWarnings("unchecked")
public TypeReference() {
Type superClass = this.getClass().getGenericSuperclass();
if (superClass instanceof Class) {
throw LOGGER.logExceptionAsError(new IllegalArgumentException(MISSING_TYPE));
} else {
this.javaType = ((ParameterizedType) superClass).getActualTypeArguments()[0];
}
this.clazz = (Class<T>) TypeUtil.getRawClass(javaType);
}

private TypeReference(Class<T> clazz) {
this.javaType = clazz;
this.clazz = clazz;
}

/**
Expand Down Expand Up @@ -88,4 +93,14 @@ public static <T> TypeReference<T> createInstance(Class<T> clazz) {
*/
return (TypeReference<T>) CACHE.computeIfAbsent(clazz, c -> new TypeReference<T>(clazz) { });
}

/**
* Returns the {@link Class} representing instance of the {@link TypeReference} created.
*
* @return The {@link Class} representing instance of the {@link TypeReference} created
* using the {@link TypeReference#createInstance(Class)}, otherwise returns {@code null}.
*/
public Class<T> getJavaClass() {
return this.clazz;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.azure.core.util.serializer;

import org.junit.jupiter.api.Test;

import java.util.HashMap;
import java.util.Map;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

public class TypeReferenceTests {

@Test
public void createGenericTypeReference() {
final TypeReference<HashMap<String, Object>> typeReference = new TypeReference<HashMap<String, Object>>() { };
final Map<String, Object> expectedJavaType = new HashMap<String, Object>() { };
assertEquals(expectedJavaType.getClass().getGenericSuperclass(), typeReference.getJavaType());
assertEquals(HashMap.class, typeReference.getJavaClass());
}

@Test
public void createFactoryInstance() {
TypeReference<Integer> typeReference = TypeReference.createInstance(int.class);
assertEquals(int.class, typeReference.getJavaType());
assertEquals(int.class, typeReference.getJavaClass());
}

@SuppressWarnings("rawtypes")
@Test
public void createTypeReferenceWithoutType() {
IllegalArgumentException thrown
= assertThrows(IllegalArgumentException.class, () -> new TypeReference() { });
assertEquals("Type constructed without type information.", thrown.getMessage());
}
}

0 comments on commit a980583

Please sign in to comment.