package org.activityinfo.ui.client.importer;
/*
* #%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.Charsets;
import com.google.common.collect.Lists;
import com.google.common.io.Resources;
import org.activityinfo.core.client.InstanceQuery;
import org.activityinfo.core.server.type.converter.JvmConverterFactory;
import org.activityinfo.model.resource.ResourceId;
import org.activityinfo.core.shared.Projection;
import org.activityinfo.core.shared.criteria.ClassCriteria;
import org.activityinfo.model.formTree.FieldPath;
import org.activityinfo.model.formTree.FormTree;
import org.activityinfo.core.shared.form.tree.FormTreePrettyPrinter;
import org.activityinfo.core.shared.importing.model.ImportModel;
import org.activityinfo.core.shared.importing.source.SourceRow;
import org.activityinfo.core.shared.importing.strategy.*;
import org.activityinfo.fixtures.InjectionSupport;
import org.activityinfo.promise.Promise;
import org.activityinfo.model.legacy.CuidAdapter;
import org.activityinfo.server.database.OnDataSet;
import org.activityinfo.ui.client.component.importDialog.Importer;
import org.activityinfo.ui.client.component.importDialog.data.PastedTable;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import static com.google.common.io.Resources.getResource;
import static org.activityinfo.core.client.PromiseMatchers.assertResolves;
import static org.activityinfo.model.legacy.CuidAdapter.field;
import static org.activityinfo.model.legacy.CuidAdapter.locationFormClass;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;
/**
* @author yuriyz on 5/20/14.
*/
@RunWith(InjectionSupport.class)
@OnDataSet("/dbunit/nfi-import.db.xml")
public class InstanceScoreTest extends AbstractImporterTest {
private static final ResourceId ADMINISTRATIVE_UNIT_FIELD = field(locationFormClass(2), CuidAdapter.ADMIN_FIELD);
@Test
public void adminEntityScoring() throws IOException {
setUser(3);
FormTree formTree = assertResolves(formTreeBuilder.apply(ImportWithMultiClassRangeTest.SCHOOL_FORM_CLASS));
FormTreePrettyPrinter.print(formTree);
importModel = new ImportModel(formTree);
importer = new Importer(resourceLocator, formTree, FieldImportStrategies.get(JvmConverterFactory.get()));
// Step 1: User pastes in data to import
PastedTable source = new PastedTable(
Resources.toString(getResource("org/activityinfo/core/shared/importing/school-import.csv"), Charsets.UTF_8));
importModel.setSource(source);
dumpList("COLUMNS", source.getColumns());
importModel.setColumnAction(columnIndex("School"), target("Name"));
// Province is at the root of both hierarchies
importModel.setColumnAction(columnIndex("Province"), target("Province Name"));
// Admin hierarchy
importModel.setColumnAction(columnIndex("District"), target("District Name"));
importModel.setColumnAction(columnIndex("Territoire"), target("Territoire Name"));
importModel.setColumnAction(columnIndex("Secteur"), target("Secteur Name"));
importModel.setColumnAction(columnIndex("Groupement"), target("Secteur Name"));
// health ministry hierarchy
importModel.setColumnAction(columnIndex("Zone de Santé"), target("Zone de Santé Name"));
FormTree.Node rootField = formTree.getRootField(ADMINISTRATIVE_UNIT_FIELD);
TargetCollector targetCollector = new TargetCollector(rootField);
Map<TargetSiteId, ColumnAccessor> mappedColumns = importModel.getMappedColumns(rootField.getFieldId());
List<ColumnAccessor> sourceColumns = Lists.newArrayList();
Map<FieldPath, Integer> referenceFields = targetCollector.getPathMap(mappedColumns, sourceColumns);
// Province level
List<Projection> projections = assertResolves(query(referenceFields, ImportWithMultiClassRangeTest.PROVINCE_LEVEL));
InstanceScoreSource scoreSource = new InstanceScoreSourceBuilder(referenceFields, sourceColumns).build(projections);
InstanceScorer.Score score = score(source.getRows().get(0), scoreSource);
assertScore(score, "Katanga");
// District level
projections = assertResolves(query(referenceFields, ImportWithMultiClassRangeTest.DISTRICT_LEVEL));
scoreSource = new InstanceScoreSourceBuilder(referenceFields, sourceColumns).build(projections);
score = score(source.getRows().get(1), scoreSource);
assertScore(score, "Katanga");
assertScore(score, "Tanganika");
// Territoire level
projections = assertResolves(query(referenceFields, ImportWithMultiClassRangeTest.TERRITOIRE_LEVEL));
scoreSource = new InstanceScoreSourceBuilder(referenceFields, sourceColumns).build(projections);
score = score(source.getRows().get(2), scoreSource);
assertScore(score, "Katanga");
assertScore(score, "Tanganika");
assertScore(score, "Kalemie");
assertThat(scoreSource.getReferenceInstanceIds().get(score.getBestMatchIndex()), equalTo(ImportWithMultiClassRangeTest.TERRITOIRE_KALEMIE));
}
private Promise<List<Projection>> query(Map<FieldPath, Integer> referenceFields, int adminLevel) {
ResourceId range = CuidAdapter.adminLevelFormClass(adminLevel);
return resourceLocator.query(new InstanceQuery(Lists.newArrayList(referenceFields.keySet()), new ClassCriteria(range)));
}
private InstanceScorer.Score score(SourceRow row, InstanceScoreSource scoreSource) {
return new InstanceScorer(scoreSource).score(row);
}
private static void assertScore(InstanceScorer.Score score, String name) {
for (int i = 0; i < score.getImported().length; i++) {
String imported = score.getImported()[i];
if (name.equals(imported) && score.getBestScores()[i] >= 1.0) {
return;
}
}
throw new RuntimeException("Failed to score : " + name);
}
}