/***************************************************************************
* Copyright 2010 Global Biodiversity Information Facility Secretariat
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
***************************************************************************/
package org.gbif.ipt.task;
import org.gbif.ipt.action.BaseAction;
import org.gbif.ipt.config.AppConfig;
import org.gbif.ipt.config.DataDir;
import org.gbif.ipt.config.IPTModule;
import org.gbif.ipt.config.JdbcSupport;
import org.gbif.ipt.mock.MockAppConfig;
import org.gbif.ipt.mock.MockDataDir;
import org.gbif.ipt.mock.MockRegistryManager;
import org.gbif.ipt.model.Extension;
import org.gbif.ipt.model.Ipt;
import org.gbif.ipt.model.Resource;
import org.gbif.ipt.model.User;
import org.gbif.ipt.model.converter.ConceptTermConverter;
import org.gbif.ipt.model.converter.ExtensionRowTypeConverter;
import org.gbif.ipt.model.converter.JdbcInfoConverter;
import org.gbif.ipt.model.converter.OrganisationKeyConverter;
import org.gbif.ipt.model.converter.PasswordConverter;
import org.gbif.ipt.model.converter.UserEmailConverter;
import org.gbif.ipt.model.factory.ExtensionFactory;
import org.gbif.ipt.model.factory.ThesaurusHandlingRule;
import org.gbif.ipt.service.AlreadyExistingException;
import org.gbif.ipt.service.ImportException;
import org.gbif.ipt.service.InvalidFilenameException;
import org.gbif.ipt.service.admin.ExtensionManager;
import org.gbif.ipt.service.admin.RegistrationManager;
import org.gbif.ipt.service.admin.UserAccountManager;
import org.gbif.ipt.service.admin.VocabulariesManager;
import org.gbif.ipt.service.admin.impl.VocabulariesManagerImpl;
import org.gbif.ipt.service.manage.ResourceManager;
import org.gbif.ipt.service.manage.SourceManager;
import org.gbif.ipt.service.manage.impl.ResourceManagerImpl;
import org.gbif.ipt.service.manage.impl.SourceManagerImpl;
import org.gbif.ipt.service.registry.RegistryManager;
import org.gbif.ipt.struts2.SimpleTextProvider;
import org.gbif.metadata.eml.Agent;
import org.gbif.metadata.eml.KeywordSet;
import org.gbif.utils.file.FileUtils;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;
import javax.validation.constraints.NotNull;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.servlet.ServletModule;
import com.google.inject.struts2.Struts2GuicePluginModule;
import org.apache.http.impl.client.DefaultHttpClient;
import org.junit.BeforeClass;
import org.junit.Test;
import org.xml.sax.SAXException;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
/**
* Test class for the DCAT generation.
*/
public class GenerateDCATTest {
private static final String RESOURCE_SHORTNAME = "res1";
private static AppConfig mockAppConfig = MockAppConfig.buildMock();
private static GenerateDCAT mockGenerateDCAT;
private DataDir mockDataDir = MockDataDir.buildMock();
private static RegistrationManager mockRegistrationManager = mock(RegistrationManager.class);
@BeforeClass
public static void init() {
when(mockAppConfig.getResourceArchiveUrl(RESOURCE_SHORTNAME)).thenReturn("distributionURL");
when(mockAppConfig.getResourceUrl(RESOURCE_SHORTNAME)).thenReturn("resourceURL");
when(mockAppConfig.getBaseUrl()).thenReturn("baseURL");
//create IPT
Ipt ipt = new Ipt();
ipt.setDescription("Test IPT for testing");
ipt.setName("Test IPT");
ipt.setKey(UUID.randomUUID().toString());
ipt.setOrganisationKey(UUID.randomUUID().toString());
when(mockRegistrationManager.getIpt()).thenReturn(ipt);
mockGenerateDCAT = new GenerateDCAT(mockAppConfig, mockRegistrationManager, mock(ResourceManager.class));
}
@Test
public void testCreateCatalog() throws ParserConfigurationException, SAXException {
String dcat = mockGenerateDCAT.createDCATCatalogInformation();
assertTrue(dcat.contains("a dcat:Catalog"));
assertTrue(dcat.contains("dct:title \"Test IPT\""));
assertTrue(dcat.contains("dct:description \"Test IPT for testing\""));
assertTrue(dcat.contains("dcat:themeTaxonomy <http://eurovoc.europa.eu/218403>"));
assertTrue(dcat.contains("dct:license <https://creativecommons.org/publicdomain/zero/1.0/>"));
assertTrue(dcat.contains(
"dct:spatial [ a dct:Location ; locn:geometry \"{ \\\"type\\\": \\\"Point\\\", \\\"coordinates\\\": [ 0.0,0.0 ] }\" ]"));
assertTrue(dcat.contains("a skos:ConceptScheme"));
}
@Test
public void testCreatePrefixes() {
String prefixes = mockGenerateDCAT.createPrefixesInformation();
assertTrue(prefixes.contains("@prefix schema: <http://schema.org/>"));
assertTrue(prefixes.contains("@prefix dct: <http://purl.org/dc/terms/>"));
assertTrue(prefixes.contains("@prefix adms: <http://www.w3.org/ns/adms#>"));
assertTrue(prefixes.contains("@prefix xsd: <http://www.w3.org/2001/XMLSchema#>"));
assertTrue(prefixes.contains("@prefix skos: <http://www.w3.org/2004/02/skos/core#>"));
assertTrue(prefixes.contains("@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>"));
assertTrue(prefixes.contains("@prefix vcard: <http://www.w3.org/2006/vcard/ns#>"));
assertTrue(prefixes.contains("@prefix dcat: <http://www.w3.org/ns/dcat#>"));
assertTrue(prefixes.contains("@prefix locn: <http://www.w3.org/ns/locn#>"));
assertTrue(prefixes.contains("@prefix foaf: <http://xmlns.com/foaf/0.1/>"));
}
@Test
public void testCreateDCATDataset()
throws ImportException, ParserConfigurationException, InvalidFilenameException, IOException,
AlreadyExistingException, SAXException {
// create resource from single source file
File resourceXML = FileUtils.getClasspathFile("resources/res1/resource.xml");
Resource res = getResource(resourceXML);
assertNotNull(res.getTitle());
assertEquals("TEST \"RESOURCE\"", res.getTitle());
String dcat = mockGenerateDCAT.createDCATDatasetInformation(res);
assertTrue(dcat.contains("a dcat:Dataset"));
// ensure literals (e.g. title, description) are properly escaped
assertTrue(dcat.contains("dct:title \"" + "TEST \\\"RESOURCE\\\"" + "\""));
assertTrue(dcat.contains("dct:description \"" + "Test \\\"description\\\"" + "\""));
// ensure duplicate keywords have been removed
assertTrue(dcat.contains("dcat:keyword \"" + "Phytosociology" + "\"" + " , " + "\"" + "Occurrence" + "\"" + " , " + "\"" + "Observation" + "\"" + " ;"));
assertTrue(dcat.contains("dcat:theme <http://eurovoc.europa.eu/5463>"));
assertTrue(dcat.contains(
"dcat:contactPoint [ a vcard:Individual ; vcard:fn \"Eric Stienen\"; vcard:hasEmail <mailto:eric.stienen@inbo.be> ]"));
assertTrue(dcat.contains("dcat:distribution <distributionURL>"));
}
/**
* Test that turtle format requiring line breaks to be escaped is honored.
*/
@Test
public void testCreateDCATDatasetNewline()
throws ImportException, ParserConfigurationException, InvalidFilenameException, IOException,
AlreadyExistingException, SAXException {
// create resource from single source file
File resourceXML = FileUtils.getClasspathFile("resources/res1/resource.xml");
Resource res = getResource(resourceXML);
// add another paragraph to description
res.getEml().getDescription().add("Second paragraph");
assertEquals(2, res.getEml().getDescription().size());
String dcat = mockGenerateDCAT.createDCATDatasetInformation(res);
assertTrue(dcat.contains("a dcat:Dataset"));
// ensure line break is properly escaped
assertTrue(dcat.contains("dct:description \"" + "Test \\\"description\\\"" + "\\n" + "Second paragraph" + "\""));
assertTrue(dcat.contains("dcat:distribution <distributionURL>"));
}
@Test
public void testCreateDCATDistribution()
throws ImportException, ParserConfigurationException, InvalidFilenameException, IOException,
AlreadyExistingException, SAXException {
// create resource from single source file
File resourceXML = FileUtils.getClasspathFile("resources/res1/resource.xml");
Resource res = getResource(resourceXML);
assertNotNull(res.getEml().parseLicenseUrl());
String dcat = mockGenerateDCAT.createDCATDistributionInformation(res);
assertTrue(dcat.contains("a dcat:Distribution"));
assertTrue(dcat.contains("dct:description \"Darwin Core Archive\""));
assertTrue(dcat.contains("dct:format \"dwc-a\""));
assertTrue(dcat.contains("dcat:mediaType \"application/zip\""));
assertTrue(dcat.contains("dcat:downloadURL <distributionURL>"));
}
/**
* Generates a test Resource from zipped resource folder, and populates resource with license, contacts, etc.
*
* @param resourceXML resource (XML) configuration file defining column mapping of sourceFile
*
* @return test Resource
*/
private Resource getResource(@NotNull File resourceXML)
throws IOException, SAXException, ParserConfigurationException, AlreadyExistingException, ImportException,
InvalidFilenameException {
UserAccountManager mockUserAccountManager = mock(UserAccountManager.class);
UserEmailConverter mockEmailConverter = new UserEmailConverter(mockUserAccountManager);
OrganisationKeyConverter mockOrganisationKeyConverter = new OrganisationKeyConverter(mockRegistrationManager);
RegistryManager mockRegistryManager = MockRegistryManager.buildMock();
GenerateDwcaFactory mockDwcaFactory = mock(GenerateDwcaFactory.class);
Eml2Rtf mockEml2Rtf = mock(Eml2Rtf.class);
VocabulariesManager mockVocabulariesManager = mock(VocabulariesManager.class);
SimpleTextProvider mockSimpleTextProvider = mock(SimpleTextProvider.class);
BaseAction baseAction = new BaseAction(mockSimpleTextProvider, mockAppConfig, mockRegistrationManager);
// construct ExtensionFactory using injected parameters
Injector injector = Guice.createInjector(new ServletModule(), new Struts2GuicePluginModule(), new IPTModule());
DefaultHttpClient httpClient = injector.getInstance(DefaultHttpClient.class);
ThesaurusHandlingRule thesaurusRule = new ThesaurusHandlingRule(mock(VocabulariesManagerImpl.class));
SAXParserFactory saxf = injector.getInstance(SAXParserFactory.class);
ExtensionFactory extensionFactory = new ExtensionFactory(thesaurusRule, saxf, httpClient);
JdbcSupport support = injector.getInstance(JdbcSupport.class);
PasswordConverter passwordConverter = injector.getInstance(PasswordConverter.class);
JdbcInfoConverter jdbcConverter = new JdbcInfoConverter(support);
// construct occurrence core Extension
InputStream occurrenceCoreIs =
GenerateDwcaTest.class.getResourceAsStream("/extensions/dwc_occurrence_2015-04-24.xml");
Extension occurrenceCore = extensionFactory.build(occurrenceCoreIs);
ExtensionManager extensionManager = mock(ExtensionManager.class);
// mock ExtensionManager returning occurrence core Extension
when(extensionManager.get("http://rs.tdwg.org/dwc/terms/Occurrence")).thenReturn(occurrenceCore);
ExtensionRowTypeConverter extensionRowTypeConverter = new ExtensionRowTypeConverter(extensionManager);
ConceptTermConverter conceptTermConverter = new ConceptTermConverter(extensionRowTypeConverter);
// mock finding resource.xml file
when(mockDataDir.resourceFile(anyString(), anyString())).thenReturn(resourceXML);
// retrieve sample zipped resource folder
File zippedResourceFolder = FileUtils.getClasspathFile("resources/res1.zip");
// retrieve sample eml.xml file
File emlXML = FileUtils.getClasspathFile("resources/res1/eml.xml");
// mock finding eml.xml file
when(mockDataDir.resourceEmlFile(anyString())).thenReturn(emlXML);
// mock finding dwca.zip file that does not exist
when(mockDataDir.resourceDwcaFile(anyString())).thenReturn(new File("dwca.zip"));
// create SourceManagerImpl
SourceManager mockSourceManager = new SourceManagerImpl(mock(AppConfig.class), mockDataDir);
// create temp directory
File tmpDataDir = FileUtils.createTempDir();
when(mockDataDir.tmpDir()).thenReturn(tmpDataDir);
// create ResourceManagerImpl
ResourceManagerImpl resourceManager =
new ResourceManagerImpl(mockAppConfig, mockDataDir, mockEmailConverter, mockOrganisationKeyConverter,
extensionRowTypeConverter, jdbcConverter, mockSourceManager, extensionManager, mockRegistryManager,
conceptTermConverter, mockDwcaFactory, passwordConverter, mockEml2Rtf, mockVocabulariesManager,
mockSimpleTextProvider, mockRegistrationManager);
// creator
User creator = new User();
creator.setEmail("jcuadra@gbif.org");
creator.setLastname("Cuadra");
// create a new resource.
Resource resource = resourceManager.create(RESOURCE_SHORTNAME, null, zippedResourceFolder, creator, baseAction);
// update resource title and description, to have double quotation marks which need to be escaped
resource.setTitle("TEST \"RESOURCE\"");
resource.getEml().getDescription().set(0, "Test \"description\"");
// update keyword sets: should be three, with "Occurrence" and "Observation" repeating more than once which breaks the feed
resource.getEml().getKeywords().clear();
KeywordSet keywordSet1 = new KeywordSet();
keywordSet1.add("Phytosociology");
keywordSet1.add("Occurrence");
keywordSet1.add("Observation");
keywordSet1.setKeywordThesaurus("n/a");
KeywordSet keywordSet2 = new KeywordSet();
keywordSet2.add("Occurrence");
keywordSet2.setKeywordThesaurus("http://rs.gbif.org/vocabulary/gbif/dataset_type.xml");
KeywordSet keywordSet3 = new KeywordSet();
keywordSet3.add("Observation");
keywordSet3.setKeywordThesaurus("http://rs.gbif.org/vocabulary/gbif/dataset_subtype.xml");
resource.getEml().addKeywordSet(keywordSet1);
resource.getEml().addKeywordSet(keywordSet2);
resource.getEml().addKeywordSet(keywordSet3);
// CCO
resource.getEml().setIntellectualRights(
"This work is licensed under <a href=\"http://creativecommons.org/publicdomain/zero/1.0/legalcode\">Creative Commons CCZero (CC0) 1.0 License</a>.");
assertEquals("http://creativecommons.org/publicdomain/zero/1.0/legalcode", resource.getEml().parseLicenseUrl());
// set creator, contact, and metadata provider
Agent agent = new Agent();
agent.setFirstName("Eric");
agent.setLastName("Stienen");
agent.setEmail("eric.stienen@inbo.be");
resource.getEml().addCreator(agent);
resource.getEml().addContact(agent);
resource.getEml().addMetadataProvider(agent);
return resource;
}
}