ProtocolLib/ProtocolLib/src/main/java/com/comphenix/protocol/reflect/instances/ExistingGenerator.java

129 lines
4.2 KiB
Java

/*
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
* Copyright (C) 2012 Kristian S. Stangeland
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program;
* if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
*/
package com.comphenix.protocol.reflect.instances;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Nullable;
import com.comphenix.protocol.reflect.FieldUtils;
import com.comphenix.protocol.reflect.FuzzyReflection;
/**
* Provides instance constructors using a list of existing values.
* <p>
* Only one instance per individual class.
* @author Kristian
*/
public class ExistingGenerator implements InstanceProvider {
private Map<String, Object> existingValues = new HashMap<String, Object>();
private ExistingGenerator() {
// Only accessible to the constructors
}
/**
* Automatically create an instance provider from a objects public and private fields.
* <p>
* If two or more fields share the same type, the last declared non-null field will take
* precedent.
* @param object - object to create an instance generator from.
* @return The instance generator.
*/
public static ExistingGenerator fromObjectFields(Object object) {
if (object == null)
throw new IllegalArgumentException("Object cannot be NULL.");
return fromObjectFields(object, object.getClass());
}
/**
* Automatically create an instance provider from a objects public and private fields.
* <p>
* If two or more fields share the same type, the last declared non-null field will take
* precedent.
* @param object - object to create an instance generator from.
* @param type - the type to cast the object.
* @return The instance generator.
*/
public static ExistingGenerator fromObjectFields(Object object, Class<?> type) {
ExistingGenerator generator = new ExistingGenerator();
// Possible errors
if (object == null)
throw new IllegalArgumentException("Object cannot be NULL.");
if (type == null)
throw new IllegalArgumentException("Type cannot be NULL.");
if (!type.isAssignableFrom(object.getClass()))
throw new IllegalArgumentException("Type must be a superclass or be the same type.");
// Read instances from every field.
for (Field field : FuzzyReflection.fromClass(type, true).getFields()) {
try {
Object value = FieldUtils.readField(field, object, true);
// Use the type of the field, not the object itself
if (value != null)
generator.addObject(field.getType(), value);
} catch (Exception e) {
// Yes, swallow it. No, really.
}
}
return generator;
}
/**
* Create an instance generator from a pre-defined array of values.
* @param values - values to provide.
* @return An instance provider that uses these values.
*/
public static ExistingGenerator fromObjectArray(Object[] values) {
ExistingGenerator generator = new ExistingGenerator();
for (Object value : values)
generator.addObject(value);
return generator;
}
private void addObject(Object value) {
if (value == null)
throw new IllegalArgumentException("Value cannot be NULL.");
existingValues.put(value.getClass().getName(), value);
}
private void addObject(Class<?> type, Object value) {
existingValues.put(type.getName(), value);
}
@Override
public Object create(@Nullable Class<?> type) {
Object value = existingValues.get(type.getName());
// NULL values indicate that the generator failed
return value;
}
}