package org.activityinfo.ui.client.component.form.field.hierarchy;
import com.google.common.base.Strings;
import com.google.common.base.Supplier;
import com.google.gwt.cell.client.ValueUpdater;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.logical.shared.SelectionHandler;
import com.google.gwt.event.shared.GwtEvent;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.event.shared.SimpleEventBus;
import org.activityinfo.core.shared.Projection;
import org.activityinfo.core.shared.application.ApplicationProperties;
import org.activityinfo.fixtures.InjectionSupport;
import org.activityinfo.legacy.shared.adapter.LocationClassAdapter;
import org.activityinfo.legacy.shared.adapter.ResourceLocatorAdaptor;
import org.activityinfo.model.form.FormClass;
import org.activityinfo.model.form.FormField;
import org.activityinfo.model.legacy.CuidAdapter;
import org.activityinfo.model.resource.ResourceId;
import org.activityinfo.model.type.ReferenceType;
import org.activityinfo.promise.Promise;
import org.activityinfo.server.command.CommandTestCase2;
import org.activityinfo.server.database.OnDataSet;
import org.hamcrest.Matchers;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.*;
import static org.activityinfo.core.client.PromiseMatchers.assertResolves;
import static org.activityinfo.model.legacy.CuidAdapter.entity;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.isEmptyOrNullString;
import static org.junit.Assert.assertThat;
@RunWith(InjectionSupport.class)
@OnDataSet("/dbunit/jordan-admin.db.xml")
public class HierarchyTest extends CommandTestCase2 {
public static final ResourceId CAMP_CLASS = CuidAdapter.locationFormClass(50505);
public static final ResourceId CAMP_DISTRICT_CLASS = CuidAdapter.adminLevelFormClass(1528);
public static final ResourceId REGION = CuidAdapter.adminLevelFormClass(1520);
public static final ResourceId GOVERNORATE_ID = CuidAdapter.adminLevelFormClass(1360);
private Map<ResourceId, MockLevelWidget> widgets;
@Test
public void buildViewModelTest() {
ResourceLocatorAdaptor resourceLocator = new ResourceLocatorAdaptor(getDispatcher());
FormClass campForm = assertResolves(resourceLocator.getFormClass(CAMP_CLASS));
FormField adminField = campForm.getField(LocationClassAdapter.getAdminFieldId(CAMP_CLASS));
Set<ResourceId> fieldValue = Collections.singleton(entity(325703));
Hierarchy tree = assertResolves(Hierarchy.get(resourceLocator, (ReferenceType) adminField.getType()));
prettyPrintTree(tree);
assertThat(tree.getRoots(), hasSize(1));
createWidgets(tree);
Presenter presenter = new Presenter(resourceLocator, tree, widgets, new ValueUpdater() {
@Override
public void update(Object value) {
System.out.println("VALUE = " + value);
}
});
assertResolves(presenter.setInitialSelection(fieldValue));
assertThat(presenter.getSelectionLabel(CAMP_DISTRICT_CLASS), equalTo("District 5"));
// now try to get options for the root level
List<Projection> choices = assertResolves(widgets.get(REGION).choices.get());
System.out.println(choices);
assertThat(choices, hasSize(3));
// if we change the root item, then all descendants should be cleared
widgets.get(REGION).setSelection("South");
prettyPrintWidgets(tree);
assertThat(widgets.get(CAMP_DISTRICT_CLASS).selection, isEmptyOrNullString());
assertThat(widgets.get(GOVERNORATE_ID).choices, Matchers.notNullValue());
List<Projection> governorateChoices = assertResolves(widgets.get(GOVERNORATE_ID).choices.get());
System.out.println(governorateChoices);
assertThat(governorateChoices, hasSize(4));
}
private void prettyPrintWidgets(Hierarchy tree) {
for(Level level : tree.getLevels()) {
System.out.println(widgets.get(level.getClassId()));
}
}
private void createWidgets(Hierarchy tree) {
Map<ResourceId, MockLevelWidget> levels = new HashMap<>();
for(Level level : tree.getLevels()) {
levels.put(level.getClassId(), new MockLevelWidget(level.getLabel()));
}
this.widgets = levels;
}
private void prettyPrintTree(Hierarchy tree) {
for(Level level : tree.getRoots()) {
printTree(0, level);
}
}
private void printTree(int indent, Level parent) {
System.out.println(Strings.repeat(" ", indent) + parent.getLabel());
for(Level child : parent.getChildren()) {
printTree(indent+1, child);
}
}
private static class MockLevelWidget implements LevelView {
private SimpleEventBus eventBus = new SimpleEventBus();
private String selection;
private String label;
private MockLevelWidget(String label) {
this.label = label;
}
private Supplier<Promise<List<Projection>>> choices;
@Override
public void clearSelection() {
this.selection = null;
}
@Override
public void setReadOnly(boolean readOnly) {
}
@Override
public void setEnabled(boolean enabled) {
}
@Override
public void setSelection(Projection selection) {
this.selection = selection.getStringValue(ApplicationProperties.LABEL_PROPERTY);
}
@Override
public void setChoices(Supplier<Promise<List<Projection>>> choices) {
this.choices = choices;
}
public void setSelection(String label) {
List<Projection> choices = assertResolves(this.choices.get());
for(Projection projection : choices) {
if(Objects.equals(projection.getStringValue(ApplicationProperties.LABEL_PROPERTY), label)) {
this.selection = label;
SelectionEvent.fire(this, projection);
return;
}
}
throw new AssertionError("No item with label '" + label + "', we have: " + choices);
}
@Override
public HandlerRegistration addSelectionHandler(SelectionHandler<Projection> handler) {
return eventBus.addHandler(SelectionEvent.getType(), handler);
}
@Override
public void fireEvent(GwtEvent<?> event) {
eventBus.fireEvent(event);
}
@Override
public String toString() {
return Strings.padEnd(label, 20, ' ') + " [" +
Strings.padEnd(Strings.nullToEmpty(selection), 30, ' ') + "]";
}
}
}