VocabularyApiServiceImpl.java
/*
* Copyright 2025 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.server.api.v2.facade.impl;
import lombok.extern.slf4j.Slf4j;
import org.genesys.server.api.Pagination;
import org.genesys.server.api.v2.facade.VocabularyApiService;
import org.genesys.server.api.v2.mapper.MapstructMapper;
import org.genesys.server.api.v2.model.impl.VocabularyTermDTO;
import org.genesys.server.api.v2.model.vocab.ControlledVocabularyDTO;
import org.genesys.server.exception.InvalidApiUsageException;
import org.genesys.server.model.filters.ControlledVocabularyFilter;
import org.genesys.server.model.vocab.ControlledVocabulary;
import org.genesys.server.model.vocab.VocabularyTerm;
import org.genesys.server.service.CountryService;
import org.genesys.server.service.InstituteService;
import org.genesys.server.service.VocabularyService;
import org.genesys.server.service.worker.ISO639VocabularyUpdater;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.IOException;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
@Transactional(readOnly = true)
@Service
@Slf4j
public class VocabularyApiServiceImpl implements VocabularyApiService {
@Value("${api.page.max:1000}")
protected int MAX_PAGE_SIZE;
@Value("${api.page.default:100}")
protected int DEFAULT_PAGE_SIZE;
@Autowired
private VocabularyService service;
@Autowired
private InstituteService instituteService;
@Autowired
private CountryService geoService;
@Autowired
private ISO639VocabularyUpdater iso639VocabularyUpdater;
@Autowired
private MapstructMapper mapper;
@Override
public ControlledVocabularyDTO getVocabulary(UUID uuid) {
return mapper.map(service.getVocabulary(uuid));
}
@Override
public VocabularyTermDTO getTerm(UUID uuid, String code) {
VocabularyTerm resultTerm;
switch (uuid.toString()) {
case FAO_WIEWS_UUID:
resultTerm = instituteService.getInstituteTerm(code);
break;
case ISO3166_2ALPHA_UUID:
resultTerm = geoService.get3166Alpha2Term(code);
break;
case ISO3166_3ALPHA_UUID:
resultTerm = geoService.get3166Alpha3Term(code);
break;
case ISO3166_NUMERIC_UUID:
resultTerm = geoService.get3166NumericTerm(code);
break;
default:
resultTerm = service.getVocabularyTerm(uuid, code);
}
return mapper.map(resultTerm);
}
@Override
public List<VocabularyTermDTO> autocompleteTerms(UUID uuid, String like) {
return mapper.map(service.autocompleteTerms(uuid, like), mapper::map);
}
@Override
public Map<String, String> decodeTerms(UUID uuid, String locale, Set<String> codes) {
switch (uuid.toString()) {
case FAO_WIEWS_UUID:
return instituteService.decodeCodes(codes);
case ISO3166_3ALPHA_UUID:
return geoService.decode3166Alpha3Terms(codes, Locale.forLanguageTag(locale));
default:
throw new InvalidApiUsageException("No decoding for such vocabulary");
}
}
@Override
public Page<VocabularyTermDTO> listTerms(UUID uuid, Pagination page) {
final ControlledVocabulary vocabulary = service.getVocabulary(uuid);
switch (uuid.toString()) {
case FAO_WIEWS_UUID:
return mapper.map(instituteService.listTerms(page.toPageRequest(MAX_PAGE_SIZE, DEFAULT_PAGE_SIZE, Sort.Direction.ASC, "code")), mapper::map);
case ISO3166_2ALPHA_UUID:
return mapper.map(geoService.list3166Alpha2Terms(page.toPageRequest(MAX_PAGE_SIZE, DEFAULT_PAGE_SIZE, Sort.Direction.ASC, "code2")), mapper::map);
case ISO3166_3ALPHA_UUID:
return mapper.map(geoService.list3166Alpha3Terms(page.toPageRequest(MAX_PAGE_SIZE, DEFAULT_PAGE_SIZE, Sort.Direction.ASC, "code3")), mapper::map);
case ISO3166_NUMERIC_UUID:
return mapper.map(geoService.list3166NumericTerms(page.toPageRequest(MAX_PAGE_SIZE, DEFAULT_PAGE_SIZE, Sort.Direction.ASC, "codeNum")), mapper::map);
default:
return mapper.map(service.listTerms(vocabulary, page.toPageRequest(MAX_PAGE_SIZE, DEFAULT_PAGE_SIZE, Sort.Direction.ASC, "code")), mapper::map);
}
}
@Override
@Transactional
public ControlledVocabularyDTO delete(UUID uuid, int version) {
return mapper.map(service.deleteVocabulary(service.getVocabulary(uuid, version)));
}
@Override
@Transactional
public ControlledVocabularyDTO createVocabulary(ControlledVocabularyDTO source) {
return mapper.map(service.createVocabulary(mapper.map(source)));
}
@Override
@Transactional
public ControlledVocabularyDTO updateVocabulary(ControlledVocabularyDTO source) {
return mapper.map(service.updateVocabulary(mapper.map(source)));
}
@Override
public Page<ControlledVocabularyDTO> listVocabularies(ControlledVocabularyFilter filter, Pageable page) {
return mapper.map(service.listVocabularies(filter, page), mapper::map);
}
@Override
@Transactional
public String updateLanguageVocabulary() throws IOException {
log.info("Updating ISO language codes");
service.autoUpdateOrCreateVocabulary(ISO639VocabularyUpdater.ISO639_3, iso639VocabularyUpdater.getISO639Vocabulary());
return "OK";
}
@Override
public VocabularyTermDTO getVocabularyTerm(UUID iso6393, String code) {
return mapper.map(service.getVocabularyTerm(iso6393, code));
}
}