package org.gbif.ipt.action.manage; import org.gbif.dwc.terms.DwcTerm; import org.gbif.ipt.config.AppConfig; import org.gbif.ipt.config.Constants; import org.gbif.ipt.model.Extension; import org.gbif.ipt.model.ExtensionMapping; import org.gbif.ipt.model.ExtensionProperty; import org.gbif.ipt.model.PropertyMapping; import org.gbif.ipt.model.Resource; import org.gbif.ipt.model.SourceBase; import org.gbif.ipt.model.TextFileSource; import org.gbif.ipt.model.Vocabulary; import org.gbif.ipt.model.VocabularyConcept; import org.gbif.ipt.model.VocabularyTerm; import org.gbif.ipt.model.factory.ExtensionFactory; import org.gbif.ipt.model.factory.ExtensionFactoryTest; import org.gbif.ipt.service.admin.RegistrationManager; import org.gbif.ipt.service.admin.VocabulariesManager; import org.gbif.ipt.service.manage.ResourceManager; import org.gbif.ipt.service.manage.SourceManager; import org.gbif.ipt.struts2.SimpleTextProvider; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; import javax.servlet.http.HttpServletRequest; import javax.xml.parsers.ParserConfigurationException; import org.junit.Before; import org.junit.Test; import org.xml.sax.SAXException; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyBoolean; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; public class TranslationActionTest { TranslationAction action; @Before public void setup() throws IOException, ParserConfigurationException, SAXException { // mock needed managers SimpleTextProvider mockTextProvider = mock(SimpleTextProvider.class); AppConfig mockCfg = mock(AppConfig.class); ResourceManager mockResourceManager = mock(ResourceManager.class); SourceManager mockSourceManager = mock(SourceManager.class); VocabulariesManager mockVocabManager = mock(VocabulariesManager.class); TranslationAction.Translation translation = new TranslationAction.Translation(); RegistrationManager mockRegistrationManager = mock(RegistrationManager.class); // mock getting list of values back for BasisOfRecord field/column in source Set<String> values = new LinkedHashSet<String>(); values.add("spe"); values.add("obs"); values.add("fos"); when(mockSourceManager.inspectColumn(any(SourceBase.class), anyInt(), anyInt(), anyInt())).thenReturn(values); // mock getI18nVocab - only called in prepare() Map<String, String> mockVocab = new HashMap<String, String>(); mockVocab.put("NomenclaturalChecklist", "Nomenclatural Checklist"); mockVocab.put("MachineObservation", "Machine Observation"); when(mockVocabManager.getI18nVocab(anyString(), anyString(), anyBoolean())).thenReturn(mockVocab); // initialize new Resource Resource resource = new Resource(); String resourceShortName = "TestResource"; resource.setShortname(resourceShortName); // initialize new ExtensionMapping ExtensionMapping mapping = new ExtensionMapping(); // add source to mapping mapping.setSource(new TextFileSource()); ExtensionFactory factory = ExtensionFactoryTest.getFactory(); Extension e = factory.build(ExtensionFactoryTest.class.getResourceAsStream("/extensions/dwc_occurrence.xml")); // ensure rowType for Extension is set if (e.getRowType() == null) { e.setRowType(Constants.DWC_ROWTYPE_TAXON); } // add extension to ExtensionMapping mapping.setExtension(e); // create map of source value TreeMap<String, String> sourceValues = new TreeMap<String, String>(); sourceValues.put("k1", "spe"); sourceValues.put("k2", "obs"); // create map of translation values TreeMap<String, String> translatedValues = new TreeMap<String, String>(); translatedValues.put("k1", "Preserved Specimen"); translatedValues.put("k2", "observation"); // create map of translations that get persisted Map<String, String> persistedTranslations = new HashMap<String, String>(); persistedTranslations.put("spe", "Preserved Specimen"); persistedTranslations.put("obs", "observation"); // initialize PropertyMapping for BasisOfRecord term PropertyMapping field = new PropertyMapping(); // set ConceptTerm field.setTerm(DwcTerm.basisOfRecord); // set index field.setIndex(1); // add translations to field field.setTranslation(persistedTranslations); // add set of PropertyMapping, including field, to ExtensionMapping Set<PropertyMapping> fields = new TreeSet<PropertyMapping>(); fields.add(field); mapping.setFields(fields); // add ExtensionMapping to resource, with mapping ID 0 List<ExtensionMapping> mappings = new LinkedList<ExtensionMapping>(); mappings.add(mapping); resource.setMappings(mappings); // mock resourceManager.get - called only in ManagerBaseAction.prepare() when(mockResourceManager.get(anyString())).thenReturn(resource); // create mock Action action = new TranslationAction(mockTextProvider, mockCfg, mockRegistrationManager, mockResourceManager, mockSourceManager, mockVocabManager, translation); // initialize ExtensionProperty representing BasisOfRecord field on Occurrence core Extension ExtensionProperty property = mapping.getExtension().getProperty(field.getTerm()); // set a vocabulary for the BasisOfRecord field // mock creation of BasisOfRecord vocabulary VocabularyConcept concept = new VocabularyConcept(); concept.setIdentifier("PreservedSpecimen"); concept.setUri("http://rs.tdwg.org/dwc/dwctype/PreservedSpecimen"); // preferred titles Set<VocabularyTerm> preferredTerms = new HashSet<VocabularyTerm>(); VocabularyTerm term = new VocabularyTerm(); term.setLang("en"); term.setTitle("Preserved Specimen"); preferredTerms.add(term); concept.setPreferredTerms(preferredTerms); // alternative titles Set<VocabularyTerm> alternateTerms = new HashSet<VocabularyTerm>(); term = new VocabularyTerm(); term.setLang("en"); term.setTitle("Conserved Specimen"); alternateTerms.add(term); concept.setAlternativeTerms(alternateTerms); Vocabulary vocab = new Vocabulary(); List<VocabularyConcept> concepts = new ArrayList<VocabularyConcept>(); concepts.add(concept); vocab.setConcepts(concepts); vocab.setUriString("http://rs.gbif.org/vocabulary/dwc/basis_of_record"); property.setVocabulary(vocab); // create sessionScoped Translation // populate sessionScoped Translation with translations action.getTrans().setTmap(mapping.getExtension().getRowType(), property, sourceValues, translatedValues); // set various properties on Action action.setField(field); action.setExtensionMapping(mapping); action.setProperty(property); // mock servlet request HttpServletRequest mockRequest = mock(HttpServletRequest.class); // the mapping id is 0 - relates to resource's List<ExtensionMapping> mappings when(mockRequest.getParameter(TranslationAction.REQ_PARAM_MAPPINGID)).thenReturn("0"); when(mockRequest.getParameter(TranslationAction.REQ_PARAM_ROWTYPE)).thenReturn(Constants.DWC_ROWTYPE_OCCURRENCE); when(mockRequest.getParameter(TranslationAction.REQ_PARAM_TERM)).thenReturn(DwcTerm.basisOfRecord.qualifiedName()); when(mockRequest.getParameter(Constants.REQ_PARAM_RESOURCE)).thenReturn(resourceShortName); action.setServletRequest(mockRequest); // ensure the resource is set action.setResource(resource); } @Test public void testDelete() { // check there are 2 sessionScoped source values, 2 sessionScoped translated values, and the // 2 PropertyMapping (field) translations assertEquals(2, action.getTrans().getSourceValues().size()); assertEquals(2, action.getTrans().getTranslatedValues().size()); assertEquals(2, action.getField().getTranslation().size()); // perform deletion action.delete(); // check 1. there are 0 sessionScoped source values or translations - both get cleared assertEquals(0, action.getTrans().getTranslatedValues().size()); // check 2. the PropertyMapping (field) translations are empty assertTrue(action.getField().getTranslation().isEmpty()); // check 3. the 3 source values got reloaded assertEquals(3, action.getTrans().getSourceValues().size()); } @Test public void testReload() { // check there are 2 sessionScoped and PropertyMapping (field) translations assertEquals(2, action.getTrans().getSourceValues().size()); assertEquals(2, action.getField().getTranslation().size()); // perform reload action.reload(); // check an additional sessionScoped translation was read from source (added to source values) assertEquals(3, action.getTrans().getSourceValues().size()); // reloading source doesn't change the number of translated values, or persisted translations on the field itself assertEquals(2, action.getTrans().getTranslatedValues().size()); assertEquals(2, action.getField().getTranslation().size()); } @Test public void testSaveTranslations() { // create new set of 5 translations TreeMap<String, String> sourceValues = new TreeMap<String, String>(); sourceValues.put("k1", "spe"); sourceValues.put("k2", "obs"); sourceValues.put("k3", "liv"); sourceValues.put("k4", "mac"); sourceValues.put("k5", "zoo"); TreeMap<String, String> translatedValues = new TreeMap<String, String>(); translatedValues.put("k1", "specimen"); translatedValues.put("k2", "observation"); translatedValues.put("k3", "livingSpecimen"); translatedValues.put("k4", "machineObservation"); translatedValues.put("k5", ""); // pretend this is the list of translations coming in from the UI action.getTrans().setTmap(Constants.DWC_ROWTYPE_TAXON, DwcTerm.basisOfRecord, sourceValues, translatedValues); // perform the save action.save(); // ensure it has been saved to the PropertyMapping (field) // only 4 should be present, since those translations with empty string values get removed assertEquals(4, action.getField().getTranslation().entrySet().size()); } @Test public void testAutoMap() { // create new map of source values that haven't been mapped yet TreeMap<String, String> sourceValues = new TreeMap<String, String>(); // will match vocab on concept sourceValues.put("k1", "PreservedSpecimen"); // will match vocab on preferred title sourceValues.put("k2", "Preserved Specimen"); // will match vocab on alternative title sourceValues.put("k3", "Conserved Specimen"); // will not match vocab on anything sourceValues.put("k4", "Unknown"); // create an empty map of translted values TreeMap<String, String> translatedValues = new TreeMap<String, String>(); action.getTrans().setTmap(Constants.DWC_ROWTYPE_TAXON, DwcTerm.basisOfRecord, sourceValues, translatedValues); // perform auto mapping action.automap(); // assert there are 4 source values still in total assertEquals(4, action.getTrans().getSourceValues().size()); // assert there are 3 auto-mapped translated values now in total, and they all auto-mapped to PreservedSpecimen assertEquals(3, action.getTrans().getTranslatedValues().size()); for (String val : action.getTmap().values()) { assertEquals("PreservedSpecimen", val); } } @Test public void testPrepare() { action.prepare(); assertEquals("0", String.valueOf(action.getMid())); assertEquals(DwcTerm.basisOfRecord.qualifiedName(), action.getProperty().getQualname()); assertEquals(2, action.getVocabTerms().size()); assertEquals(3, action.getTrans().getSourceValues().size()); assertEquals(2, action.getTrans().getTranslatedValues().size()); } }