com.eg.google.gson.internal.ConstructorConstructor Maven / Gradle / Ivy
package com.eg.google.gson.internal;
/*
* Copyright (C) 2011 Google Inc.
*
* Licensed 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 com.eg.google.gson.InstanceCreator;
import com.eg.google.gson.JsonIOException;
import com.eg.google.gson.reflect.TypeToken;
import org.gradle.internal.impldep.com.google.gson.internal.LinkedTreeMap;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.EnumSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ConcurrentNavigableMap;
import java.util.concurrent.ConcurrentSkipListMap;
/**
* Returns a function that can construct an instance of a requested type.
*/
public final class ConstructorConstructor {
private final Map> instanceCreators;
public ConstructorConstructor(Map> instanceCreators) {
this.instanceCreators = instanceCreators;
}
public ObjectConstructor get(TypeToken typeToken) {
final Type type = typeToken.getType();
final Class> rawType = typeToken.getRawType();
// first try an instance creator
@SuppressWarnings("unchecked") // types must agree
final InstanceCreator typeCreator = (InstanceCreator) instanceCreators.get(type);
if (typeCreator != null) {
return new ObjectConstructor() {
@Override public T construct() {
return typeCreator.createInstance(type);
}
};
}
// Next try raw type match for instance creators
@SuppressWarnings("unchecked") // types must agree
final InstanceCreator rawTypeCreator =
(InstanceCreator) instanceCreators.get(rawType);
if (rawTypeCreator != null) {
return new ObjectConstructor() {
@Override public T construct() {
return rawTypeCreator.createInstance(type);
}
};
}
ObjectConstructor defaultConstructor = newDefaultConstructor((Class super T>) rawType);
if (defaultConstructor != null) {
return defaultConstructor;
}
ObjectConstructor defaultImplementation = newDefaultImplementationConstructor(type, (Class super T>) rawType);
if (defaultImplementation != null) {
return defaultImplementation;
}
// finally try unsafe
return newUnsafeAllocator(type, (Class super T>) rawType);
}
private ObjectConstructor newDefaultConstructor(Class super T> rawType) {
try {
final Constructor super T> constructor = rawType.getDeclaredConstructor();
if (!constructor.isAccessible()) {
constructor.setAccessible(true);
}
return new ObjectConstructor() {
@SuppressWarnings("unchecked") // T is the same raw type as is requested
@Override public T construct() {
try {
Object[] args = null;
return (T) constructor.newInstance(args);
} catch (InstantiationException e) {
// TODO: JsonParseException ?
throw new RuntimeException("Failed to invoke " + constructor + " with no args", e);
} catch (InvocationTargetException e) {
// TODO: don't wrap if cause is unchecked!
// TODO: JsonParseException ?
throw new RuntimeException("Failed to invoke " + constructor + " with no args",
e.getTargetException());
} catch (IllegalAccessException e) {
throw new AssertionError(e);
}
}
};
} catch (NoSuchMethodException e) {
return null;
}
}
/**
* Constructors for common interface types like Map and List and their
* subtypes.
*/
@SuppressWarnings("unchecked") // use runtime checks to guarantee that 'T' is what it is
private ObjectConstructor newDefaultImplementationConstructor(
final Type type, Class super T> rawType) {
if (Collection.class.isAssignableFrom(rawType)) {
if (SortedSet.class.isAssignableFrom(rawType)) {
return new ObjectConstructor() {
@Override public T construct() {
return (T) new TreeSet
© 2015 - 2024 Weber Informatics LLC | Privacy Policy