Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
uk.co.it.modular.beans.InstanceInspector Maven / Gradle / Ivy
Go to download
Utilities for manipulating and inspecting Java classes implementing the Java Beans standard
package uk.co.it.modular.beans;
import static java.lang.System.identityHashCode;
import static org.apache.commons.lang.StringUtils.uncapitalize;
import static uk.co.it.modular.beans.Type.type;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Helper class which inspects the bean and exposes the properties of the bean to support the visitor pattern
*
* @author Stewart Bissett
*/
class InstanceInspector {
static InstanceInspector beanInspector() {
return new InstanceInspector(new BeanInspectorConfiguration() {
{
setInspectChildren(false);
setOverflowLimit(0);
setStopOverflow(true);
}
});
}
static InstanceInspector graphInspector() {
return new InstanceInspector(new BeanInspectorConfiguration() {
{
setInspectChildren(true);
setOverflowLimit(0);
setStopOverflow(true);
}
});
};
static class BeanInspectorConfiguration {
private boolean inspectChildren = false;
private boolean stopOverflow = true;
private Integer overflowLimit = 0;
boolean isInspectChildren() {
return inspectChildren;
}
void setInspectChildren(final boolean inspectChildren) {
this.inspectChildren = inspectChildren;
}
boolean isStopOverflow() {
return stopOverflow;
}
void setStopOverflow(final boolean stopOverflow) {
this.stopOverflow = stopOverflow;
}
Integer getOverflowLimit() {
return overflowLimit;
}
void setOverflowLimit(final Integer overflowLimit) {
this.overflowLimit = overflowLimit;
}
}
private static final Logger LOG = LoggerFactory.getLogger(InstanceInspector.class);
private final BeanInspectorConfiguration config;
private final ThreadLocal> inspected = new ThreadLocal>() {
@Override
protected Map initialValue() {
return new HashMap();
}
};
InstanceInspector(final BeanInspectorConfiguration config) {
this.config = config;
}
/**
* Inspect the supplied object and fire callbacks on the supplied {@link BeanVisitor} for every property exposed on the object
*
* @param instance
* an object instance to inspect for Java Bean properties
* @param visitor
* the visitor to raise events when Java Bean properties are found
*/
void inspect(final Object instance, final BeanVisitor visitor) {
inspect(instance, null, visitor);
}
/**
* Inspect the supplied object and fire callbacks on the supplied {@link BeanVisitor} for every property exposed on the object.
*
* The root object will be referred to be the supplied rootPath parameter.
*
*
* @param instance
* an object instance to inspect for Java Bean properties
* @param rootPath
* a name to be used as the root object name for the path included when the visitor is notified
* @param visitor
* the visitor to raise events when Java Bean properties are found
*/
void inspect(final Object instance, final String rootPath, final BeanVisitor visitor) {
try {
inspectObject(new ArrayList(), rootPath, instance, visitor);
} finally {
inspected.get().clear();
}
}
@SuppressWarnings("rawtypes")
private void inspectObject(final List currentStack, final String path, final Object instance, final BeanVisitor visitor) {
if (instance == null) {
return;
}
final List stack = new ArrayList(currentStack);
logInspection(path, "Object", instance);
if (config.isStopOverflow()) {
int instanceKey = identityHashCode(instance);
Integer hits = inspected.get().get(instanceKey);
if (hits != null) {
if (hits > config.getOverflowLimit()) {
return;
} else {
inspected.get().put(instanceKey, ++hits);
}
} else {
inspected.get().put(instanceKey, 1);
}
}
if (!config.isInspectChildren() && currentStack.size() > 0) {
return;
}
Class extends Object> type = instance.getClass();
if (type.isArray()) {
inspectArray(new ArrayList(), path, instance, visitor);
} else if (Iterable.class.isAssignableFrom(type)) {
inspectIterable(new ArrayList(), path, (Iterable) instance, visitor);
} else if (Map.class.isAssignableFrom(type)) {
inspectMap(new ArrayList(), path, (Map) instance, visitor);
} else {
String rootPath = path == null ? uncapitalize(type(instance.getClass()).simpleName()) : path;
stack.add(instance);
for (BeanProperty property : type(instance.getClass()).propertyList()) {
String nextPath = nextPath(rootPath, property);
visitor.visit(new BeanPropertyInstance(property, instance), instance, nextPath, stack.toArray());
if (property.isArray()) {
Object value = property.getValue(instance);
if (value != null) {
inspectArray(stack, nextPath, value, visitor);
}
} else if (property.isIterable()) {
Iterable value = property.getValue(instance, Iterable.class);
if (value != null) {
inspectIterable(stack, nextPath, value, visitor);
}
} else if (property.isMap()) {
Map value = property.getValue(instance, Map.class);
if (value != null) {
inspectMap(stack, nextPath, value, visitor);
}
} else {
Object propertyValue = property.getValue(instance);
if (propertyValue != null) {
inspectObject(stack, nextPath, propertyValue, visitor);
}
}
}
}
}
private String nextPath(final String path, final BeanProperty property) {
return StringUtils.isEmpty(path) ? property.getName() : path + "." + property.getName();
}
private void inspectMap(final List stack, final String path, final Map, ?> instance, final BeanVisitor visitor) {
logInspection(path, "Map", instance);
for (Map.Entry, ?> entry : instance.entrySet()) {
String nextPath = path == null ? "map" : path;
inspectObject(stack, nextPath + "[" + entry.getKey() + "]", entry.getValue(), visitor);
}
}
private void inspectArray(final List stack, final String path, final Object instance, final BeanVisitor visitor) {
logInspection(path, "Array", instance);
for (int i = 0; i < Array.getLength(instance); ++i) {
String nextPath = path == null ? "array" : path;
inspectObject(stack, nextPath + "[" + i + "]", Array.get(instance, i), visitor);
}
}
private void inspectIterable(final List stack, final String path, final Iterable> instance, final BeanVisitor visitor) {
logInspection(path, "Iterable", instance);
int seq = 0;
for (Object object : instance) {
String nextPath = path == null ? "collection" : path;
inspectObject(stack, nextPath + "[" + (seq++) + "]", object, visitor);
}
}
private void logInspection(final String path, final String loggedType, final Object instance) {
LOG.trace("Inspect Path [{}]. {} [{}:{}]", new Object[] {
path, loggedType, instance.getClass().getSimpleName(), identityHashCode(instance)
});
}
}