Commit 5bbb5449 authored by Matija Obreza's avatar Matija Obreza
Browse files

Merge branch '127-iso-codes' into 'master'

Resolve "ISO codes"

Closes #127

See merge request !118
parents 1036413c 404b82a7
......@@ -154,6 +154,10 @@ public class Dataset extends UuidModel implements Publishable, PublishValidation
/** The source. */
private String source;
/** Information about time of creation of the dataset. */
@Column(nullable = true, length = 200)
private String created;
/** The published. */
private boolean published = false;
......@@ -370,6 +374,24 @@ public class Dataset extends UuidModel implements Publishable, PublishValidation
this.subject = subject;
}
/**
* Gets the created.
*
* @return the created
*/
public String getCreated() {
return created;
}
/**
* Sets the created.
*
* @param created the new created
*/
public void setCreated(String created) {
this.created = created;
}
/*
* (non-Javadoc)
* @see org.genesys.blocks.model.Publishable#isPublished()
......
......@@ -62,6 +62,16 @@ public interface VocabularyService {
@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#input, 'write')")
ControlledVocabulary updateVocabulary(ControlledVocabulary input);
/**
* Update persisted vocabulary or register a new controlled vocabulary
*
* @param updated updated vocabulary definition
* @param uuid the uuid
* @return persisted vocabulary
*/
@PreAuthorize("hasRole('ADMINISTRATOR')")
ControlledVocabulary updateOrCreateVocabulary(UUID uuid, ControlledVocabulary updated);
/**
* Delete vocabulary.
*
......
......@@ -21,6 +21,7 @@ import java.util.UUID;
import org.genesys.catalog.exceptions.InvalidApiUsageException;
import org.genesys.catalog.model.vocab.ControlledVocabulary;
import org.genesys.catalog.persistence.vocab.ControlledVocabularyRepository;
import org.genesys.catalog.service.PartnerService;
import org.genesys.catalog.service.VocabularyService;
import org.genesys.catalog.service.filters.ControlledVocabularyFilter;
import org.slf4j.Logger;
......@@ -46,8 +47,8 @@ public class VocabularyServiceImpl implements VocabularyService {
@Autowired
private ControlledVocabularyRepository vocabRepository;
// @Autowired
// private VocabularyTermRepository termRepository;
@Autowired
private PartnerService partnerService;
@Override
@Transactional
......@@ -118,6 +119,23 @@ public class VocabularyServiceImpl implements VocabularyService {
return vocabRepository.save(vocabulary);
}
@Override
@Transactional
public ControlledVocabulary updateOrCreateVocabulary(final UUID uuid, final ControlledVocabulary updated) {
final ControlledVocabulary oldVocabulary = getVocabulary(uuid);
if (oldVocabulary != null) {
updated.setUuid(oldVocabulary.getUuid());
updated.setVersion(oldVocabulary.getVersion());
LOG.info("Updating {} vocabulary with {} terms", oldVocabulary.getTitle(), updated.getTerms().size());
return updateVocabulary(updated);
} else {
updated.setUuid(uuid);
updated.setOwner(partnerService.getPrimaryPartner());
LOG.info("Creating {} vocabulary with {} terms", updated.getTitle(), updated.getTerms().size());
return createVocabulary(updated);
}
}
@Override
public Page<ControlledVocabulary> listVocabularies(ControlledVocabularyFilter filters, Pageable page) {
return vocabRepository.findAll(filters.buildQuery(), page);
......
......@@ -41,7 +41,7 @@ import org.springframework.stereotype.Component;
*/
@Component
public class DavrosCountrySource {
private static final String DAVROS_ISO3166_URL = "http://www.davros.org/misc/iso3166.txt";
public static final String DAVROS_ISO3166_URL = "http://www.davros.org/misc/iso3166.txt";
/** The Constant LOG. */
public static final Logger LOG = LoggerFactory.getLogger(DavrosCountrySource.class);
......
......@@ -21,6 +21,7 @@ import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.function.Function;
import org.apache.commons.logging.Log;
......@@ -40,6 +41,24 @@ import org.springframework.stereotype.Component;
@Component
public class ISO3166VocabularyUpdater {
/**
* ISO 3166-1 alpha-2 representation of names of countries and their subdivisions, contains two-letter country codes
* https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2
*/
public static UUID ISO3166_2ALPHA = UUID.fromString("3e39a73e-d1ed-40b0-9944-ac5795128686");
/**
* ISO 3166-1 alpha-2 representation of names of countries and their subdivisions, contains three-letter country codes
* https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3
*/
public static UUID ISO3166_3ALPHA = UUID.fromString("39a3d6a2-20e6-4fab-8bfe-acb1f9fe774c");
/**
* ISO 3166-1 numeric representation of names of countries and their subdivisions, contains three-letter country codes
* https://en.wikipedia.org/wiki/ISO_3166-1_numeric
*/
public static UUID ISO3166_NUMERIC = UUID.fromString("bd45f660-853f-4034-a434-ed50679579cc");
/** The Constant LOG. */
public static final Log LOG = LogFactory.getLog(ISO3166VocabularyUpdater.class);
......@@ -90,6 +109,7 @@ public class ISO3166VocabularyUpdater {
protected ControlledVocabulary createVocabulary(final String title, final Function<CountryInfo, String> toTerm) throws IOException {
final ControlledVocabulary vocabulary = new ControlledVocabulary();
vocabulary.setTitle(title);
vocabulary.setUrl(DavrosCountrySource.DAVROS_ISO3166_URL);
final DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy.MM.dd");
final LocalDate localDate = LocalDate.now();
......
......@@ -34,7 +34,7 @@ import org.springframework.core.io.Resource;
@Configuration
@Import({ FileRepositoryConfig.class })
@ComponentScan({ "org.genesys.catalog.service.impl", "org.genesys.catalog.util", "org.genesys.blocks.security.service.*",
@ComponentScan({ "org.genesys.catalog.service.impl", "org.genesys.catalog.service.worker", "org.genesys.catalog.util", "org.genesys.blocks.security.service.*",
"org.genesys.blocks.auditlog.service.impl", "org.genesys.blocks.security.component" })
@EnableAspectJAutoProxy
public class ApplicationConfig {
......
......@@ -21,8 +21,6 @@ import java.util.concurrent.TimeUnit;
import org.genesys.catalog.server.components.AddStuffInterceptor;
import org.genesys.catalog.server.components.StartupInitializer;
import org.genesys.catalog.service.worker.GeonamesISOLanguageSource;
import org.genesys.catalog.service.worker.ISO639VocabularyUpdater;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
......@@ -117,16 +115,6 @@ public class WebConfiguration extends WebMvcConfigurerAdapter {
return cookieLocaleResolver;
}
@Bean
public ISO639VocabularyUpdater iSO639VocabularyUpdater() {
return new ISO639VocabularyUpdater();
}
@Bean
public GeonamesISOLanguageSource geonamesISOLanguageSource() {
return new GeonamesISOLanguageSource();
}
@Bean
public AddStuffInterceptor addStuffInterceptor() {
return new AddStuffInterceptor();
......
/*
* Copyright 2018 Global Crop Diversity Trust
*
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.genesys.catalog.server.controller.api.v0;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import org.genesys.catalog.exceptions.NotFoundElement;
import org.genesys.catalog.model.vocab.ControlledVocabulary;
import org.genesys.catalog.model.vocab.VocabularyTerm;
import org.genesys.catalog.service.VocabularyService;
import org.genesys.catalog.service.worker.ISO3166VocabularyUpdater;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* The Class GeoController.
*
* @author Maxym Borodenko
*/
@RestController
@RequestMapping(GeoController.API_BASE)
@PreAuthorize("isAuthenticated()")
public class GeoController {
protected static final String API_BASE = "/api/v0/geo";
public static final UUID ISO3166_2ALPHA = ISO3166VocabularyUpdater.ISO3166_2ALPHA;
public static final UUID ISO3166_3ALPHA = ISO3166VocabularyUpdater.ISO3166_3ALPHA;
public static final UUID ISO3166_NUMERIC = ISO3166VocabularyUpdater.ISO3166_NUMERIC;
private static final Logger LOG = LoggerFactory.getLogger(GeoController.class);
@Autowired
private ISO3166VocabularyUpdater iso3166VocabularyUpdater;
@Autowired
private VocabularyService vocabularyService;
@PreAuthorize("hasRole('ADMINISTRATOR')")
@PostMapping(value = "/update")
public List<ControlledVocabulary> updateCountriesCodes() throws IOException {
List<ControlledVocabulary> resultList = new ArrayList<>();
resultList.add(vocabularyService.updateOrCreateVocabulary(ISO3166_2ALPHA, iso3166VocabularyUpdater.getISO3166Alpha2Vocabulary()));
resultList.add(vocabularyService.updateOrCreateVocabulary(ISO3166_3ALPHA, iso3166VocabularyUpdater.getISO3166Alpha3Vocabulary()));
resultList.add(vocabularyService.updateOrCreateVocabulary(ISO3166_NUMERIC, iso3166VocabularyUpdater.getISO3166NumericVocabulary()));
return resultList;
}
@GetMapping(value = "/iso3166/{code}", produces = MediaType.APPLICATION_JSON_VALUE)
public VocabularyTerm get(@PathVariable("code") final String code) {
ControlledVocabulary iso3166 = null;
boolean isNumeric = code.chars().allMatch(Character::isDigit);
if (isNumeric) {
iso3166 = vocabularyService.getVocabulary(ISO3166_NUMERIC);
} else if (code.length() == 2) {
iso3166 = vocabularyService.getVocabulary(ISO3166_2ALPHA);
} else if (code.length() == 3) {
iso3166 = vocabularyService.getVocabulary(ISO3166_3ALPHA);
}
if (iso3166 != null) {
return iso3166.getTerms().stream().filter(term -> term.getCode().toLowerCase().equals(code.toLowerCase())).findFirst().orElseThrow(() -> new NotFoundElement(
"Country with such code not found"));
}
throw new NotFoundElement("Country with such code not found");
}
}
......@@ -24,7 +24,6 @@ import java.util.stream.Collectors;
import org.genesys.catalog.exceptions.NotFoundElement;
import org.genesys.catalog.model.vocab.ControlledVocabulary;
import org.genesys.catalog.model.vocab.VocabularyTerm;
import org.genesys.catalog.service.PartnerService;
import org.genesys.catalog.service.VocabularyService;
import org.genesys.catalog.service.worker.ISO639VocabularyUpdater;
import org.slf4j.Logger;
......@@ -60,26 +59,10 @@ public class LanguagesController {
@Autowired
private VocabularyService vocabularyService;
@Autowired
private PartnerService partnerService;
@PreAuthorize("hasRole('ADMINISTRATOR')")
@PostMapping(value = "/update")
public ControlledVocabulary updateLanguages() throws IOException {
final ControlledVocabulary iso639 = vocabularyService.getVocabulary(ISO639_3);
ControlledVocabulary updated = iso639VocabularyUpdater.getISO639Vocabulary();
if (iso639 != null) {
updated.setUuid(iso639.getUuid());
updated.setVersion(iso639.getVersion());
LOG.info("Updating ISO639-3 vocabulary with {} terms", updated.getTerms().size());
return vocabularyService.updateVocabulary(updated);
} else {
updated.setUuid(ISO639_3);
updated.setOwner(partnerService.getPrimaryPartner());
LOG.info("Creating ISO639-3 vocabulary with {} terms", updated.getTerms().size());
return vocabularyService.createVocabulary(updated);
}
return vocabularyService.updateOrCreateVocabulary(ISO639_3, iso639VocabularyUpdater.getISO639Vocabulary());
}
@GetMapping(value = "/{code}", produces = MediaType.APPLICATION_JSON_VALUE)
......
......@@ -3178,3 +3178,15 @@ databaseChangeLog:
name: publisher
indexName: FK_1d4veryraxx6fll3y8cnte24p
tableName: descriptor
- changeSet:
id: 1516883189000-1
author: mobreza
changes:
- addColumn:
columns:
- column:
name: created
type: VARCHAR(200)
tableName: dataset
/*
* Copyright 2018 Global Crop Diversity Trust
*
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.genesys.catalog.server.controller.api.v0;
import static org.hamcrest.Matchers.is;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import com.google.common.collect.Lists;
import org.genesys.catalog.model.vocab.ControlledVocabulary;
import org.genesys.catalog.model.vocab.VocabularyTerm;
import org.genesys.catalog.server.controller.rest.AbstractRestTest;
import org.genesys.catalog.service.PartnerService;
import org.genesys.catalog.service.VocabularyService;
import org.genesys.catalog.service.worker.ISO3166VocabularyUpdater;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.WebApplicationContext;
/**
* The Class GeoControllerTest.
*
* @author Maxym Borodenko
*/
public class GeoControllerTest extends AbstractRestTest {
@Autowired
private WebApplicationContext webApplicationContext;
private MockMvc mockMvc;
@Autowired
private PartnerService partnerService;
@Autowired
private VocabularyService vocabularyService;
@After
@Override
public void cleanup() {
super.cleanup();
}
@Before
@Transactional
public void setUp() throws Exception {
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).apply(documentationConfiguration(restDocumentation).uris().withScheme("https").withHost(
"api.catalog.genesys-pgr.org").withPort(443)).build();
if (vocabularyService.getVocabulary(ISO3166VocabularyUpdater.ISO3166_3ALPHA) == null) {
// create the vocabulary
ControlledVocabulary vocabulary=new ControlledVocabulary();
vocabulary.setUuid(ISO3166VocabularyUpdater.ISO3166_3ALPHA);
vocabulary.setOwner(partnerService.getPrimaryPartner());
vocabulary.setTitle("ISO-3166-3alpha");
vocabulary.setTerms(Lists.newArrayList(VocabularyTerm.fromData("eng", "English"), VocabularyTerm.fromData("ukr", "Ukraine")));
vocabularyService.createVocabulary(vocabulary);
}
}
@Test
@WithMockUser(username = "user", password = "user", roles = "ADMINISTRATOR")
public void getTermByCodeTest() throws Exception {
VocabularyTerm term = VocabularyTerm.fromData("ukr", "Ukraine");
/*@formatter:off*/
mockMvc
.perform(RestDocumentationRequestBuilders.get(GeoController.API_BASE.concat("/iso3166/{code}"), "ukr"))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
.andExpect(jsonPath("$.code", is(term.getCode())))
.andExpect(jsonPath("$.title", is(term.getTitle())));
/*@formatter:on*/
}
}
......@@ -29,12 +29,11 @@ import org.genesys.blocks.oauth.service.OAuthServiceImpl;
import org.genesys.catalog.server.config.SwaggerConfig;
import org.genesys.catalog.server.controller.api.v0.DatasetCreatorController;
import org.genesys.catalog.server.controller.api.v0.DescriptorController;
import org.genesys.catalog.server.controller.api.v0.GeoController;
import org.genesys.catalog.server.controller.api.v0.LocationController;
import org.genesys.catalog.server.controller.api.v0.PartnerController;
import org.genesys.catalog.server.controller.api.v0.PermissionController;
import org.genesys.catalog.server.tests.ServiceTest;
import org.genesys.catalog.service.worker.GeonamesISOLanguageSource;
import org.genesys.catalog.service.worker.ISO639VocabularyUpdater;
import org.junit.Rule;
import org.junit.runner.RunWith;
import org.springframework.context.annotation.Bean;
......@@ -82,7 +81,7 @@ public abstract class AbstractRestTest extends ServiceTest {
@EnableWebMvc
@Import(SwaggerConfig.class)
@ComponentScan(basePackageClasses = { DescriptorController.class, PartnerController.class, DatasetCreatorController.class,
LocationController.class, PermissionController.class})
LocationController.class, PermissionController.class, GeoController.class})
@DirtiesContext(hierarchyMode = HierarchyMode.CURRENT_LEVEL, classMode = DirtiesContext.ClassMode.AFTER_CLASS)
public static class Config extends WebMvcConfigurerAdapter {
......@@ -91,16 +90,6 @@ public abstract class AbstractRestTest extends ServiceTest {
return new OAuthServiceImpl();
}
@Bean
public ISO639VocabularyUpdater iSO639VocabularyUpdater() {
return new ISO639VocabularyUpdater();
}
@Bean
public GeonamesISOLanguageSource geonamesISOLanguageSource() {
return new GeonamesISOLanguageSource();
}
public MappingJackson2HttpMessageConverter jacksonMessageConverter() {
final MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment