package org.gbif.ipt.action.portal;
import org.gbif.api.model.common.DOI;
import org.gbif.ipt.action.BaseAction;
import org.gbif.ipt.config.AppConfig;
import org.gbif.ipt.config.Constants;
import org.gbif.ipt.config.DataDir;
import org.gbif.ipt.model.Resource;
import org.gbif.ipt.model.User;
import org.gbif.ipt.model.VersionHistory;
import org.gbif.ipt.model.voc.IdentifierStatus;
import org.gbif.ipt.model.voc.PublicationStatus;
import org.gbif.ipt.service.admin.ExtensionManager;
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.struts2.SimpleTextProvider;
import org.gbif.metadata.eml.EmlWriter;
import org.gbif.metadata.eml.TaxonKeyword;
import org.gbif.metadata.eml.TaxonomicCoverage;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.Maps;
import freemarker.template.TemplateException;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class ResourceActionTest {
private ResourceAction action;
private Resource resource;
private static final String RESOURCE_SHORT_NAME = "test_resource";
private static final BigDecimal LATEST_RESOURCE_VERSION = new BigDecimal("3.0");
private static final BigDecimal RESOURCE_VERSION_TWO = new BigDecimal("2.0");
private static final BigDecimal RESOURCE_VERSION_ONE = new BigDecimal("1.0");
private static User MANAGER;
@Before
public void setup() throws IOException, TemplateException {
SimpleTextProvider textProvider = new SimpleTextProvider();
AppConfig mockCfg = mock(AppConfig.class);
RegistrationManager mockRegistrationManager = mock(RegistrationManager.class);
ResourceManager mockResourceManager = mock(ResourceManager.class);
VocabulariesManager mockVocabManager = mock(VocabulariesManager.class);
DataDir mockDataDir = mock(DataDir.class);
// mock: vocabManager.getI18nVocab(Constants.VOCAB_URI_RANKS, Locale.getDefault().getLanguage(), false);
Map<String, String> ranks = new LinkedHashMap<String, String>();
ranks.put("kingdom", "http://rs.gbif.org/vocabulary/gbif/rank/kingdom");
ranks.put("Class", "http://rs.gbif.org/vocabulary/gbif/rank/class");
when(mockVocabManager.getI18nVocab(anyString(), anyString(), anyBoolean())).thenReturn(ranks);
// setup Resource with TaxonomicCoverage with 3 TaxonKeyword
resource = new Resource();
resource.setShortname(RESOURCE_SHORT_NAME);
resource.setEmlVersion(LATEST_RESOURCE_VERSION);
// setup manager as resource creator
MANAGER = new User();
MANAGER.setEmail("jc@gbif.org");
MANAGER.setLastname("Costa");
MANAGER.setFirstname("Jose");
MANAGER.setRole(User.Role.Manager);
resource.setCreator(MANAGER);
// add three published versions to version history, all published by manager, some private, other public
VersionHistory v1 = new VersionHistory(RESOURCE_VERSION_ONE, new Date(), PublicationStatus.PRIVATE);
resource.addVersionHistory(v1);
VersionHistory v2 = new VersionHistory(RESOURCE_VERSION_TWO, new Date(), PublicationStatus.PUBLIC);
resource.addVersionHistory(v2);
VersionHistory v3 = new VersionHistory(LATEST_RESOURCE_VERSION, new Date(), PublicationStatus.PRIVATE);
resource.addVersionHistory(v3);
assertEquals(3, resource.getVersionHistory().size());
TaxonomicCoverage coverage1 = new TaxonomicCoverage();
coverage1.setDescription("Description1");
TaxonKeyword keyword1 = new TaxonKeyword();
keyword1.setRank("Kingdom");
keyword1.setCommonName("Plants");
keyword1.setScientificName("Plantae");
TaxonKeyword keyword2 = new TaxonKeyword();
keyword2.setRank("Class");
keyword2.setScientificName("Equisetopsida");
TaxonKeyword keyword3 = new TaxonKeyword();
keyword3.setCommonName("Sedges");
List<TaxonKeyword> keywordList = new ArrayList<TaxonKeyword>();
keywordList.add(keyword1);
keywordList.add(keyword2);
keywordList.add(keyword3);
coverage1.setTaxonKeywords(keywordList);
List<TaxonomicCoverage> coverages = new ArrayList<TaxonomicCoverage>();
coverages.add(coverage1);
resource.getEml().setTaxonomicCoverages(coverages);
// mock returning EML file, with actual resource metadata
File emlFile = File.createTempFile("eml-3.0.xml", ".xml");
EmlWriter.writeEmlFile(emlFile, resource.getEml());
when(mockDataDir.resourceEmlFile(anyString(), any(BigDecimal.class))).thenReturn(emlFile);
// mock returning RTF file, with empty content
File rtfFile = File.createTempFile(RESOURCE_SHORT_NAME + "-3.0", ".rtf");
when(mockDataDir.resourceRtfFile(anyString(), any(BigDecimal.class))).thenReturn(rtfFile);
// mock returning DwC-A file, with file that doesn't exist. This means the resource is metadata-only
File nonExistingDwca = new File("dwca", ".zip");
assertFalse(nonExistingDwca.exists());
when(mockDataDir.resourceDwcaFile(anyString(), any(BigDecimal.class))).thenReturn(nonExistingDwca);
action = new ResourceAction(textProvider, mockCfg, mockRegistrationManager, mockResourceManager, mockVocabManager,
mockDataDir, mock(ExtensionManager.class));
action.setResource(resource);
}
@Test
public void testSetOrganizedTaxonomicCoverages() {
List<OrganizedTaxonomicCoverage> coverages =
action.constructOrganizedTaxonomicCoverages(resource.getEml().getTaxonomicCoverages());
assertEquals(1, coverages.size());
assertEquals(3, coverages.get(0).getKeywords().size());
assertEquals("Plantae (Plants)", coverages.get(0).getKeywords().get(0).getDisplayNames().get(0));
assertEquals("Equisetopsida", coverages.get(0).getKeywords().get(1).getDisplayNames().get(0));
assertEquals("Sedges", coverages.get(0).getKeywords().get(2).getDisplayNames().get(0));
}
@Test
public void testFindDoiAssignedToPublishedVersion() {
action.setVersion(new BigDecimal("1.34"));
// DOI must be PUBLIC to be assigned
VersionHistory history = new VersionHistory(new BigDecimal("1.34"), new Date(), PublicationStatus.PUBLIC);
history.setModifiedBy(MANAGER);
history.setStatus(IdentifierStatus.PUBLIC_PENDING_PUBLICATION);
history.setDoi(new DOI("10.1126", "IO65467"));
resource.addVersionHistory(history);
action.setResource(resource);
assertNull(action.findDoiAssignedToPublishedVersion());
// Change DOI to PUBLIC now, and ensure it is returned
resource.removeVersionHistory(new BigDecimal("1.34"));
history.setStatus(IdentifierStatus.PUBLIC);
resource.addVersionHistory(history);
assertEquals("10.1126/io65467", action.findDoiAssignedToPublishedVersion().getDoiName());
}
/**
* When manager is not logged in, ensure published REGISTERED versions shown publicly.
*/
@Test
public void testDetailForPublishedRegisteredVersion() {
// simulate pre v2.2 resource that is registered and has no VersionHistory
action.getResource().setKey(UUID.randomUUID());
action.getResource().setStatus(PublicationStatus.REGISTERED);
action.getResource().getVersionHistory().clear();
assertTrue(action.getResource().isRegistered());
assertTrue(action.getResource().getVersionHistory().isEmpty());
assertEquals(LATEST_RESOURCE_VERSION, action.getResource().getEmlVersion());
// the last published version was registered and therefore can be shown publicly
assertEquals(BaseAction.SUCCESS, action.detail());
}
/**
* When manager is not logged in, ensure published PRIVATE versions not shown publicly.
*/
@Test
public void testDetailForPublishedPrivateVersion() {
// the last published version (3.0) was private at the time of publication
assertEquals(BaseAction.NOT_ALLOWED, action.detail());
}
/**
* When manager is not logged in, ensure specific published PUBLIC versions are shown publicly.
*/
@Test
public void testDetailForSpecificPublishedPublicVersion() {
// the published version 2.0 was public at time of publication
action.setVersion(RESOURCE_VERSION_TWO);
assertEquals(BaseAction.SUCCESS, action.detail());
}
/**
* When manager is not logged in, ensure specific published PRIVATE versions are shown publicly.
*/
@Test
public void testDetailForSpecificPrivatePublicVersion() {
// the published version 1.0 was private at time of publication
action.setVersion(RESOURCE_VERSION_ONE);
assertEquals(BaseAction.NOT_ALLOWED, action.detail());
}
/**
* When manager IS logged in, ensure ALL published versions are shown.
*/
@Test
public void testDetailForLoggedInManager() {
// simulate manager being logged in
Map<String, Object> session = new HashMap<String, Object>();
session.put(Constants.SESSION_USER, MANAGER);
action.setSession(session);
assertNotNull(action.getCurrentUser());
// ensure all versions available to manager
action.setVersion(RESOURCE_VERSION_ONE);
assertNotEquals(resource.getEmlVersion(), action.getVersion());
assertEquals(BaseAction.SUCCESS, action.detail());
// ensure warnings were generated:
// 1. warning about this resource being private and not available to everyone
// 2. warning about requesting version that is not the latest
assertEquals(2, action.getActionWarnings().size());
// reset warnings
action.getActionWarnings().clear();
action.setVersion(RESOURCE_VERSION_TWO);
assertEquals(BaseAction.SUCCESS, action.detail());
// ensure warning was generated:
// 1. warning about requesting version that is not the latest
assertEquals(1, action.getActionWarnings().size());
// reset warnings
action.getActionWarnings().clear();
action.setVersion(LATEST_RESOURCE_VERSION);
assertEquals(BaseAction.SUCCESS, action.detail());
// ensure warning was generated:
// 1. warning about this resource being private and not available to everyone
assertEquals(1, action.getActionWarnings().size());
}
@Test
public void testGetRecordsByExtensionOrdered() {
Map<String, Integer> counts = Maps.newLinkedHashMap();
counts.put(Constants.DWC_ROWTYPE_TAXON, 55);
counts.put(Constants.DWC_ROWTYPE_EVENT, 100);
counts.put(Constants.DWC_ROWTYPE_OCCURRENCE, 10);
action.setRecordsByExtensionForVersion(counts);
// do ordering
ImmutableSortedMap<String, Integer> orderedCounts = action.getRecordsByExtensionOrdered();
orderedCounts.firstEntry().getValue();
assertEquals(100, orderedCounts.firstEntry().getValue().intValue());
assertEquals(10, orderedCounts.lastEntry().getValue().intValue());
}
@Test
public void testGetMaxRecordsInExtension() {
Map<String, Integer> counts = Maps.newLinkedHashMap();
counts.put(Constants.DWC_ROWTYPE_TAXON, 55);
counts.put(Constants.DWC_ROWTYPE_EVENT, 100);
counts.put(Constants.DWC_ROWTYPE_OCCURRENCE, 10);
action.setRecordsByExtensionForVersion(counts);
// do ordering
assertEquals(100, action.getMaxRecordsInExtension());
}
}