package br.gov.servicos.editor.frontend; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectReader; import com.github.slugify.Slugify; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.SneakyThrows; import lombok.experimental.FieldDefaults; import lombok.experimental.NonFinal; import lombok.experimental.Wither; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.cache.annotation.Cacheable; import org.springframework.core.io.ClassPathResource; import org.springframework.stereotype.Component; import org.springframework.web.client.RestTemplate; import java.util.List; import java.util.function.Predicate; import java.util.zip.GZIPInputStream; import static br.gov.servicos.editor.frontend.Siorg.Unidade; import static java.util.Comparator.comparing; import static java.util.stream.Collectors.toList; import static lombok.AccessLevel.PRIVATE; import static net.logstash.logback.marker.Markers.append; @Slf4j @Component @FieldDefaults(level = PRIVATE, makeFinal = true) public class Orgaos implements InitializingBean { public static final ClassPathResource RESOURCE = new ClassPathResource("estrutura-organizacional.json.gz"); RestTemplate rest; ObjectReader reader; Slugify slugify; @NonFinal EstruturaOrganizacional estruturaOrganizacional; @Autowired public Orgaos(@Qualifier("restTemplate") RestTemplate rest, ObjectMapper mapper, Slugify slugify) { this.rest = rest; this.slugify = slugify; reader = mapper.reader(EstruturaOrganizacional.class); } @Override @SneakyThrows public void afterPropertiesSet() throws Exception { log.debug("Lendo estrutura organizacional de {}...", RESOURCE); estruturaOrganizacional = reader.readValue(new GZIPInputStream(RESOURCE.getInputStream())); log.debug("Estrutura organizacional lida com sucesso", RESOURCE); } @Cacheable("orgaos") public List<OrgaoDTO> get(String termo) { List<OrgaoDTO> busca = estruturaOrganizacional.getUnidades() .stream() .filter(new FiltroDeOrgaos(termo)) .map(u -> new OrgaoDTO().withNome(String.format("%s (%s)", u.getNome().trim(), u.getSigla().trim())) .withId(u.getCodigoUnidade())) .sorted(comparing(OrgaoDTO::getNome)) .collect(toList()); log.info(append("orgaos.termo", termo).and(append("orgaos.resultados", busca.size())), "Buscando órgãos com termo '{}': {} resultados", termo, busca.size()); return busca; } @Data @Wither @NoArgsConstructor @AllArgsConstructor public static class EstruturaOrganizacional { List<Unidade> unidades; } @FieldDefaults(level = PRIVATE, makeFinal = true) private class FiltroDeOrgaos implements Predicate<Unidade> { String termo; public FiltroDeOrgaos(String termo) { this.termo = termo; } @Override public boolean test(Unidade u) { return limpa(u.getNome()).contains(limpa(termo)) || limpa(u.getSigla()).contains(limpa(termo)); } private String limpa(String s) { return slugify.slugify(s).replace('-', ' '); } } }