package org.robobinding.widget;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.lang.reflect.ParameterizedType;
import java.util.Map;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.robobinding.attribute.EnumAttribute;
import org.robobinding.attribute.PendingGroupAttributes;
import org.robobinding.attribute.ResolvedGroupAttributes;
import org.robobinding.attribute.StaticResourceAttribute;
import org.robobinding.attribute.ValueModelAttribute;
import org.robobinding.viewattribute.grouped.ChildViewAttribute;
import org.robobinding.viewattribute.grouped.ChildViewAttributeFactory;
import org.robobinding.viewattribute.grouped.ChildViewAttributesBuilder;
import org.robobinding.viewattribute.grouped.GroupAttributesResolver;
import org.robobinding.viewattribute.grouped.GroupedViewAttribute;
import org.robobinding.viewattribute.property.OneWayMultiTypePropertyViewAttribute;
import org.robobinding.viewattribute.property.OneWayMultiTypePropertyViewAttributeFactory;
import org.robobinding.viewattribute.property.OneWayPropertyViewAttribute;
import org.robobinding.viewattribute.property.OneWayPropertyViewAttributeFactory;
import org.robobinding.viewattribute.property.TwoWayMultiTypePropertyViewAttribute;
import org.robobinding.viewattribute.property.TwoWayMultiTypePropertyViewAttributeFactory;
import org.robobinding.viewattribute.property.TwoWayPropertyViewAttribute;
import org.robobinding.viewattribute.property.TwoWayPropertyViewAttributeFactory;
import org.robolectric.RobolectricTestRunner;
import android.view.View;
import com.google.common.collect.Maps;
/**
*
* @since 1.0
* @version $Revision: 1.0 $
* @author Robert Taylor
*/
@RunWith(RobolectricTestRunner.class)
public abstract class AbstractGroupedViewAttributeTest<ViewType extends View, ViewAttributeType extends GroupedViewAttribute<? super ViewType>> {
private ViewAttributeType attribute;
private ViewType view;
private Map<String, String> presentAttributeMappings;
private Map<String, Object> childViewAttributeMap;
@Before
public void initialize() {
ParameterizedType superclass = (ParameterizedType) getClass().getGenericSuperclass();
view = ParameterizedTypeUtils.createTypeArgument(superclass, 0);
attribute = createAttributeUnderTest();
presentAttributeMappings = Maps.newHashMap();
childViewAttributeMap = Maps.newHashMap();
}
protected ViewAttributeType createAttributeUnderTest() {
try {
ParameterizedType superclass = (ParameterizedType) getClass().getGenericSuperclass();
return ParameterizedTypeUtils.createTypeArgument(superclass, 1);
} catch (Exception e) {
throw new RuntimeException("Error instantiating grouped attribute class: " + e.getMessage());
}
}
@SuppressWarnings({ "unchecked" })
protected void performInitialization() {
PendingGroupAttributes pendingGroupAttributes = new PendingGroupAttributes(presentAttributeMappings);
GroupAttributesResolver resolvedGroupAttributesFactory = new GroupAttributesResolver();
ResolvedGroupAttributes resolvedGroupAttributes = resolvedGroupAttributesFactory.resolve(pendingGroupAttributes, attribute);
ChildViewAttributesBuilder<View> childViewAttributesBuilder = new ChildViewAttributesBuilderForTest(childViewAttributeMap, resolvedGroupAttributes);
((GroupedViewAttribute<View>) attribute).setupChildViewAttributes(view, childViewAttributesBuilder);
}
protected Attribute attribute(String attribute) {
if (attribute.indexOf('=') == -1)
throw new IllegalArgumentException("Expected attribute in the form '[attributeName]=[attributeValue]'");
String[] components = attribute.split("=");
return new Attribute(components[0], components[1]);
}
protected void givenAttributes(Attribute... attributes) {
for (Attribute attribute : attributes) {
givenAttribute(attribute);
}
}
protected void givenAttribute(Attribute attribute) {
presentAttributeMappings.put(attribute.name, attribute.value);
}
protected void assertThatAttributesWereCreated(Class<?>... attributeClasses) {
for (Class<?> attributeClass : attributeClasses) {
assertThatAttributeWasCreated(attributeClass);
}
}
protected void assertThatAttributeWasCreated(Class<?> attributeClass) {
Object childAttribute = findChildAttributeOfType(attributeClass);
assertNotNull("Child attribute of type '" + attributeClass.getName() + "' not found", childAttribute);
}
private Object findChildAttributeOfType(Class<?> childViewAttributeClass) {
for (Object childViewAttribute : childViewAttributeMap.values()) {
if (childViewAttributeClass.isInstance(childViewAttribute)) {
return childViewAttribute;
}
}
return null;
}
protected void assertThatAttributesWereCreated(String... attributeNames) {
for (String attributeName : attributeNames) {
assertThatAttributeWasCreated(attributeName);
}
}
protected void assertThatAttributeWasCreated(String attributeName) {
assertTrue("Child attribute of '" + attributeName + "' not found", hasAttribute(attributeName));
}
private boolean hasAttribute(String attributeName) {
return childViewAttributeMap.containsKey(attributeName);
}
protected Object childViewAttribute(String attributeName) {
return childViewAttributeMap.get(attributeName);
}
public static class Attribute {
private final String name;
private final String value;
private Attribute(String name, String value) {
this.name = name;
this.value = value;
}
@Override
public String toString() {
return name;
}
}
private static class ChildViewAttributesBuilderForTest implements ChildViewAttributesBuilder<View> {
private final Map<String, Object> childViewAttributeMap;
private final ResolvedGroupAttributes resolvedGroupAttributes;
public ChildViewAttributesBuilderForTest(Map<String, Object> childViewAttributeMap, ResolvedGroupAttributes resolvedGroupAttributes) {
this.childViewAttributeMap = childViewAttributeMap;
this.resolvedGroupAttributes = resolvedGroupAttributes;
}
@Override
public void add(String attributeName, ChildViewAttribute childAttribute) {
childViewAttributeMap.put(attributeName, childAttribute);
}
@Override
public void add(String attributeName, ChildViewAttributeFactory factory) {
childViewAttributeMap.put(attributeName, factory.create());
}
@Override
public void addDependent(String attributeName, ChildViewAttributeFactory factory) {
add(attributeName, factory);
}
@Override
public void add(String attributeName, OneWayMultiTypePropertyViewAttribute<View> viewAttribute) {
childViewAttributeMap.put(attributeName, viewAttribute);
}
@Override
public void add(String attributeName, OneWayMultiTypePropertyViewAttributeFactory<View> factory) {
childViewAttributeMap.put(attributeName, factory.create());
}
@Override
public void add(String attributeName, OneWayPropertyViewAttribute<View, ?> viewAttribute) {
childViewAttributeMap.put(attributeName, viewAttribute);
}
@Override
public void add(String attributeName, OneWayPropertyViewAttributeFactory<View> factory) {
childViewAttributeMap.put(attributeName, factory.create());
}
@Override
public void add(String attributeName, TwoWayPropertyViewAttribute<View, ?, ?> viewAttribute) {
childViewAttributeMap.put(attributeName, viewAttribute);
}
@Override
public void add(String attributeName, TwoWayPropertyViewAttributeFactory<View> factory) {
childViewAttributeMap.put(attributeName, factory.create());
}
@Override
public void add(String attributeName, TwoWayMultiTypePropertyViewAttribute<View> viewAttribute) {
childViewAttributeMap.put(attributeName, viewAttribute);
}
@Override
public void add(String attributeName, TwoWayMultiTypePropertyViewAttributeFactory<View> factory) {
childViewAttributeMap.put(attributeName, factory.create());
}
@Override
public void failOnFirstBindingError() {
}
@Override
public boolean hasAttribute(String attributeName) {
return resolvedGroupAttributes.hasAttribute(attributeName);
}
@Override
public ValueModelAttribute valueModelAttributeFor(String attributeName) {
return resolvedGroupAttributes.valueModelAttributeFor(attributeName);
}
@Override
public StaticResourceAttribute staticResourceAttributeFor(String attributeName) {
return resolvedGroupAttributes.staticResourceAttributeFor(attributeName);
}
@Override
public <E extends Enum<E>> EnumAttribute<E> enumAttributeFor(String attributeName) {
return resolvedGroupAttributes.enumAttributeFor(attributeName);
}
}
}