package com.izouma.nineth.service; import com.alibaba.fastjson.JSON; import com.github.kevinsawicki.http.HttpRequest; import com.izouma.nineth.domain.District; import com.izouma.nineth.enums.DistrictLevel; import com.izouma.nineth.repo.DistrictRepo; import com.izouma.nineth.utils.amap.DistrictsItem; import com.izouma.nineth.utils.amap.QueryDistrictResponse; import lombok.AllArgsConstructor; import org.apache.commons.lang3.StringUtils; import org.springframework.data.jpa.domain.Specification; import org.springframework.stereotype.Service; import javax.persistence.criteria.Predicate; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; @Service @AllArgsConstructor public class DistrictService { private final DistrictRepo districtRepo; public List get(DistrictLevel level, DistrictLevel maxLevel, Long parent) { return districtRepo.findAll((Specification) (root, criteriaQuery, criteriaBuilder) -> { List predicates = new ArrayList<>(); if (level != null) { predicates.add(criteriaBuilder.equal(root.get("level"), level)); } if (parent != null) { predicates.add(criteriaBuilder.equal(root.get("parent"), parent)); } if (maxLevel != null) { List list = Arrays.stream(DistrictLevel.values()) .filter(l -> l.getValue() <= maxLevel.getValue()) .collect(Collectors.toList()); if (list.isEmpty()) { predicates.add(criteriaBuilder.equal(root.get("level"), DistrictLevel.NONE)); } else { predicates.add(root.get("level").in(list)); } } return criteriaBuilder.and(predicates.toArray(new Predicate[0])); }).stream().peek(district -> { if (maxLevel != null) { int childCount = 0; switch (maxLevel) { case PROVINCE: break; case CITY: childCount = district.getCityCount(); break; case DISTRICT: childCount = district.getCityCount() + district.getDistrictCount(); break; case STREET: childCount = district.getCityCount() + district.getDistrictCount() + district.getStreetCount(); break; } district.setLeaf(childCount == 0); } else { district.setLeaf(district.getChildCount() == 0); } }).collect(Collectors.toList()); } public void sync() { QueryDistrictResponse response = JSON.parseObject(HttpRequest.get("https://restapi.amap.com/v3/config/district?key=3d59fb422c5c13af59bf82a8b6f3ad54&subdistrict=4") .body(), QueryDistrictResponse.class); response.getDistricts().get(0).getDistricts().stream().parallel().forEach(item -> saveDistrict(item, null)); } private void saveDistrict(DistrictsItem item, Long parentId) { District district = District.builder() .id(Long.parseLong(item.getAdcode())) .name(item.getName()) .parent(parentId) .level(DistrictLevel.valueOf(item.getLevel().toUpperCase())) .build(); if (district.getLevel() == DistrictLevel.STREET) { district.setId(Long.parseLong(district.getId() + String.format("%02d", item.getIdx()))); } if (StringUtils.isNotBlank(item.getCenter())) { String[] arr = item.getCenter().split(","); district.setLng(Double.parseDouble(arr[0])); district.setLat(Double.parseDouble(arr[1])); } if (item.getCitycode() != null && item.getCitycode() instanceof String) { district.setCityCode((String) item.getCitycode()); } if (item.getDistricts() != null) { district.setChildCount(item.getDistricts().size()); district.setCityCount((int) item.getDistricts() .stream() .filter(d -> DistrictLevel.valueOf(d.getLevel().toUpperCase()) == DistrictLevel.CITY) .count()); district.setDistrictCount((int) item.getDistricts() .stream() .filter(d -> DistrictLevel.valueOf(d.getLevel().toUpperCase()) == DistrictLevel.DISTRICT) .count()); district.setStreetCount((int) item.getDistricts() .stream() .filter(d -> DistrictLevel.valueOf(d.getLevel().toUpperCase()) == DistrictLevel.STREET) .count()); } else { district.setChildCount(0); } districtRepo.save(district); if (item.getDistricts() != null) { int[] idx = {1}; item.getDistricts().stream().parallel().forEach(child -> { child.setIdx(idx[0]++); saveDistrict(child, district.getId()); }); } } }