package org.activityinfo.server.command; /* * #%L * ActivityInfo Server * %% * Copyright (C) 2009 - 2013 UNICEF * %% * 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 3 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, see * <http://www.gnu.org/licenses/gpl-3.0.html>. * #L% */ import com.google.common.base.Joiner; import com.google.common.collect.Lists; import org.activityinfo.fixtures.InjectionSupport; import org.activityinfo.legacy.shared.command.*; import org.activityinfo.model.legacy.CuidAdapter; import org.activityinfo.legacy.shared.adapter.ResourceLocatorAdaptor; import org.activityinfo.legacy.shared.command.result.CreateResult; import org.activityinfo.legacy.shared.exception.CommandException; import org.activityinfo.legacy.shared.model.*; import org.activityinfo.model.form.FormClass; import org.activityinfo.model.form.FormElement; import org.activityinfo.model.form.FormField; import org.activityinfo.model.resource.ResourceId; import org.activityinfo.model.type.Cardinality; import org.activityinfo.model.type.enumerated.EnumItem; import org.activityinfo.model.type.enumerated.EnumType; import org.activityinfo.model.type.number.QuantityType; import org.activityinfo.model.type.primitive.TextType; import org.activityinfo.server.database.OnDataSet; import org.hamcrest.Matcher; import org.hamcrest.Matchers; import org.junit.Before; 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.activityFormClass; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.hasItem; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.hasProperty; import static org.hamcrest.Matchers.hasSize; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; @RunWith(InjectionSupport.class) @OnDataSet("/dbunit/schema1.db.xml") public class ActivityTest extends CommandTestCase2 { @Before public void setUser() { setUser(1); } @Test public void testActivity() throws CommandException { /* * Initial data load */ SchemaDTO schema = execute(new GetSchema()); UserDatabaseDTO db = schema.getDatabaseById(1); /* * Create a new activity */ LocationTypeDTO locType = schema.getCountryById(1).getLocationTypes().get(0); ActivityFormDTO act = new ActivityFormDTO(); act.setName("Warshing the dishes"); act.setLocationType(locType); act.setReportingFrequency(ActivityFormDTO.REPORT_MONTHLY); act.setClassicView(false); CreateResult cresult = execute(CreateEntity.Activity(db, act)); int newId = cresult.getNewId(); /* * Reload schema to verify the changes have stuck */ act = execute(new GetActivityForm(newId)); assertEquals("name", "Warshing the dishes", act.getName()); assertEquals("locationType", locType.getName(), act.getLocationType().getName()); assertEquals("reportingFrequency", ActivityFormDTO.REPORT_MONTHLY, act.getReportingFrequency()); assertEquals("public", Published.NOT_PUBLISHED.getIndex(), act.getPublished()); assertEquals("classicView", false, act.getClassicView()); } @Test @OnDataSet("/dbunit/schema2.db.xml") public void testActivityFormWithAdminLocationType() throws CommandException { ActivityFormDTO form = execute(new GetActivityForm(1)); assertEquals("name", "NFI", form.getName()); assertThat("locationType", form.getLocationType().isAdminLevel(), equalTo(true)); } @Test public void updateSortOrderTest() throws Throwable { /* Update Sort Order */ Map<String, Object> changes1 = new HashMap<String, Object>(); changes1.put("sortOrder", 2); Map<String, Object> changes2 = new HashMap<String, Object>(); changes2.put("sortOrder", 1); execute(new BatchCommand( new UpdateEntity("Activity", 1, changes1), new UpdateEntity("Activity", 2, changes2))); /* Confirm the order is changed */ SchemaDTO schema = execute(new GetSchema()); assertEquals(2, schema.getDatabaseById(1).getActivities().get(0).getId()); assertEquals(1, schema.getDatabaseById(1).getActivities().get(1).getId()); } @Test public void updatePublished() throws Throwable { /* Update Sort Order */ Map<String, Object> changes = new HashMap<String, Object>(); changes.put("published", Published.ALL_ARE_PUBLISHED.getIndex()); execute(new UpdateEntity("Activity", 1, changes)); /* Confirm the order is changed */ SchemaDTO schema = execute(new GetSchema()); assertEquals(Published.ALL_ARE_PUBLISHED.getIndex(), schema.getActivityById(1).getPublished()); } @Test public void orderIndicatorsActivities() { SchemaDTO schema = execute(new GetSchema()); UserDatabaseDTO db = schema.getDatabaseById(1); LocationTypeDTO locType = schema.getCountryById(1).getLocationTypes().get(0); ActivityFormDTO act = new ActivityFormDTO(); act.setName("Household Survey"); act.setLocationType(locType); act.setReportingFrequency(ActivityFormDTO.REPORT_ONCE); CreateResult createResult = execute(CreateEntity.Activity(db, act)); ResourceId classId = activityFormClass(createResult.getNewId()); ResourceLocatorAdaptor resourceLocator = new ResourceLocatorAdaptor(getDispatcher()); FormClass formClass = assertResolves(resourceLocator.getFormClass(classId)); // create three new fields with an order that mixes "attributes" and "indicators" FormField newField = new FormField(ResourceId.generateFieldId(QuantityType.TYPE_CLASS)); newField.setLabel("How old are you?"); newField.setType(new QuantityType().setUnits("years")); formClass.addElement(newField); FormField newGenderField = new FormField(ResourceId.generateFieldId(EnumType.TYPE_CLASS)); newGenderField.setLabel("Gender"); EnumItem male = new EnumItem(EnumItem.generateId(), "Male"); EnumItem female = new EnumItem(EnumItem.generateId(), "Female"); newGenderField.setType(new EnumType(Cardinality.SINGLE, Arrays.asList(male, female))); formClass.addElement(newGenderField); FormField newTextField = new FormField(ResourceId.generateFieldId(TextType.TYPE_CLASS)); newTextField.setLabel("What is your name?"); newTextField.setType(TextType.INSTANCE); formClass.addElement(newTextField); assertResolves(resourceLocator.persist(formClass)); FormClass reform = assertResolves(resourceLocator.getFormClass(formClass.getId())); System.out.println(Joiner.on("\n").join(reform.getFields())); int a = indexOf(reform.getFields(), hasProperty("label", equalTo("How old are you?"))); int b = indexOf(reform.getFields(), hasProperty("label", equalTo("Gender"))); int c = indexOf(reform.getFields(), hasProperty("label", equalTo("What is your name?"))); assertTrue(a < b && b < c); } @Test public void createActivity() { SchemaDTO schema = execute(new GetSchema()); UserDatabaseDTO db = schema.getDatabaseById(1); LocationTypeDTO locType = schema.getCountryById(1).getLocationTypes().get(0); ActivityFormDTO act = new ActivityFormDTO(); act.setName("Household Survey"); act.setLocationType(locType); act.setReportingFrequency(ActivityFormDTO.REPORT_ONCE); CreateResult createResult = execute(CreateEntity.Activity(db, act)); ResourceId classId = activityFormClass(createResult.getNewId()); ResourceLocatorAdaptor resourceLocator = new ResourceLocatorAdaptor(getDispatcher()); FormClass formClass = assertResolves(resourceLocator.getFormClass(classId)); FormField newField = new FormField(ResourceId.generateFieldId(QuantityType.TYPE_CLASS)); newField.setLabel("How old are you?"); newField.setType(new QuantityType().setUnits("years")); formClass.addElement(newField); FormField newTextField = new FormField(ResourceId.generateFieldId(TextType.TYPE_CLASS)); newTextField.setLabel("What is your name?"); newTextField.setType(TextType.INSTANCE); formClass.addElement(newTextField); assertResolves(resourceLocator.persist(formClass)); FormClass reform = assertResolves(resourceLocator.getFormClass(formClass.getId())); assertHasFieldWithLabel(reform, "How old are you?"); newField.setLabel("How old are you today?"); // save again assertResolves(resourceLocator.persist(formClass)); reform = assertResolves(resourceLocator.getFormClass(formClass.getId())); assertHasFieldWithLabel(reform, "How old are you today?"); System.out.println(reform.getFields().toString()); assertThat(reform.getFields(), hasSize(8)); List<EnumItem> values = Lists.newArrayList(); values.add(new EnumItem(EnumItem.generateId(), "Option 1")); values.add(new EnumItem(EnumItem.generateId(), "Option 2")); } @Test public void createAttributeGroup() { ResourceLocatorAdaptor resourceLocator = new ResourceLocatorAdaptor(getDispatcher()); FormClass formClass = assertResolves(resourceLocator.getFormClass(CuidAdapter.activityFormClass(1))); FormField newField = new FormField(ResourceId.generateFieldId(EnumType.TYPE_CLASS)); newField.setLabel("New Group"); EnumItem yes = new EnumItem(EnumItem.generateId(), "Yes"); EnumItem no = new EnumItem(EnumItem.generateId(), "No"); newField.setType(new EnumType(Cardinality.SINGLE, Arrays.asList(yes, no))); formClass.getElements().add(newField); resourceLocator.persist(formClass); // verify that it appears as attribute group ActivityFormDTO activity = getActivity(1); AttributeGroupDTO group = findGroup(activity, "New Group"); assertThat(group.isMultipleAllowed(), equalTo(false)); assertThat(group.getAttributes(), hasSize(2)); assertThat(group.getAttributes().get(0), hasProperty("name", Matchers.equalTo("Yes"))); assertThat(group.getAttributes().get(1), hasProperty("name", Matchers.equalTo("No"))); // Now update the same attribute group and a value newField.setLabel("Do you like ice cream?"); yes.setLabel("Oui"); no.setLabel("Non"); resourceLocator.persist(formClass); group = findGroup(getActivity(1), "Do you like ice cream?"); assertThat(group.isMultipleAllowed(), equalTo(false)); assertThat(group.getAttributes(), contains( hasProperty("name", Matchers.equalTo("Oui")), hasProperty("name", Matchers.equalTo("Non")))); // Remove one of our new enum values newField.setType(new EnumType(Cardinality.SINGLE, Arrays.asList(yes))); resourceLocator.persist(formClass); group = findGroup(getActivity(1), "Do you like ice cream?"); assertThat(group.isMultipleAllowed(), equalTo(false)); assertThat(group.getAttributes(), contains(hasProperty("name", Matchers.equalTo("Oui")))); } @Test public void updateIndicator() { ResourceLocatorAdaptor resourceLocator = new ResourceLocatorAdaptor(getDispatcher()); FormClass formClass = assertResolves(resourceLocator.getFormClass(CuidAdapter.activityFormClass(1))); FormField beneficiaries = find(formClass.getFields(), hasProperty("label", equalTo("beneficiaries"))); beneficiaries.setLabel("Number of benes"); resourceLocator.persist(formClass); ActivityFormDTO activity = getActivity(1); assertThat(activity.getIndicatorById(1), hasProperty("name", Matchers.equalTo("Number of benes"))); } @Test public void updateIndicatorWithLongUnits() { ResourceLocatorAdaptor resourceLocator = new ResourceLocatorAdaptor(getDispatcher()); FormClass formClass = assertResolves(resourceLocator.getFormClass(CuidAdapter.activityFormClass(1))); FormField beneficiaries = find(formClass.getFields(), hasProperty("label", equalTo("beneficiaries"))); QuantityType updatedType = new QuantityType().setUnits("imperial tonne with very long qualifying text"); beneficiaries.setType(updatedType); assertResolves(resourceLocator.persist(formClass)); ActivityFormDTO activity = getActivity(1); assertThat(activity.getIndicatorById(1), hasProperty("units", Matchers.equalTo(updatedType.getUnits()))); } private <T> T find(List<T> list, Matcher<? super T> matcher) { assertThat(list, hasItem(matcher)); for(T t : list) { if(matcher.matches(t)) { return t; } } throw new AssertionError(); } private <T> int indexOf(List<T> list, Matcher<? super T> matcher) { assertThat(list, hasItem(matcher)); for(int i=0;i!=list.size();++i) { if(matcher.matches(list.get(i))) { return i; } } throw new AssertionError(); } private ActivityFormDTO getActivity(int activityId) { return execute(new GetActivityForm(activityId)); } private AttributeGroupDTO findGroup(ActivityFormDTO activityDTO, String label) { for(AttributeGroupDTO group : activityDTO.getAttributeGroups()) { if(group.getName().equals(label)) { return group; } } throw new AssertionError("No such attribute group: " + label); } @Test public void deleteAttributeGroup() { ResourceLocatorAdaptor resourceLocator = new ResourceLocatorAdaptor(getDispatcher()); FormClass formClass = assertResolves(resourceLocator.getFormClass(CuidAdapter.activityFormClass(1))); // Remove attribute ListIterator<FormElement> it = formClass.getElements().listIterator(); while(it.hasNext()) { FormElement element = it.next(); if(element.getLabel().equals("Cause")) { it.remove(); } } resourceLocator.persist(formClass); // Ensure deleted ActivityFormDTO form = execute(new GetActivityForm(1)); assertTrue("Cause attribute is gone", form.getAttributeGroupById(1) == null); } private static void assertHasFieldWithLabel(FormClass formClass, String label) { for (FormField field : formClass.getFields()) { if (label.equals(field.getLabel())) { return; } } throw new RuntimeException("No field with label: " + label); } }