You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
160 lines
6.7 KiB
160 lines
6.7 KiB
package com.mydreamjob.skill;
|
|
|
|
import com.mydreamjob.common.exception.BusinessException;
|
|
import com.mydreamjob.common.exception.ErrorCode;
|
|
import com.mydreamjob.skill.domain.SkillCategory;
|
|
import com.mydreamjob.skill.domain.SkillIndustry;
|
|
import com.mydreamjob.skill.domain.SkillOccupation;
|
|
import com.mydreamjob.skill.dto.SkillCloudItem;
|
|
import com.mydreamjob.skill.dto.SkillCloudNode;
|
|
import com.mydreamjob.skill.dto.SkillCloudResponse;
|
|
import com.mydreamjob.skill.dto.SkillCloudSkillProjection;
|
|
import com.mydreamjob.skill.repository.OccupationSkillRepository;
|
|
import com.mydreamjob.skill.repository.SkillCategoryRepository;
|
|
import com.mydreamjob.skill.repository.SkillIndustryRepository;
|
|
import com.mydreamjob.skill.repository.SkillOccupationRepository;
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
|
import java.math.BigDecimal;
|
|
import java.util.Comparator;
|
|
import java.util.List;
|
|
import java.util.stream.IntStream;
|
|
|
|
@Service
|
|
@Transactional(readOnly = true)
|
|
public class SkillCloudQueryService {
|
|
|
|
private static final Comparator<SkillCloudSkillProjection> SKILL_ORDER = (left, right) -> {
|
|
int heatComparison = compareHeat(left.importance(), right.importance());
|
|
if (heatComparison != 0) {
|
|
return heatComparison;
|
|
}
|
|
|
|
int nameComparison = compareNullable(left.nameZh(), right.nameZh());
|
|
if (nameComparison != 0) {
|
|
return nameComparison;
|
|
}
|
|
|
|
return compareNullable(left.skillId(), right.skillId());
|
|
};
|
|
|
|
private final SkillIndustryRepository industryRepository;
|
|
private final SkillOccupationRepository occupationRepository;
|
|
private final SkillCategoryRepository categoryRepository;
|
|
private final OccupationSkillRepository occupationSkillRepository;
|
|
|
|
public SkillCloudQueryService(SkillIndustryRepository industryRepository,
|
|
SkillOccupationRepository occupationRepository,
|
|
SkillCategoryRepository categoryRepository,
|
|
OccupationSkillRepository occupationSkillRepository) {
|
|
this.industryRepository = industryRepository;
|
|
this.occupationRepository = occupationRepository;
|
|
this.categoryRepository = categoryRepository;
|
|
this.occupationSkillRepository = occupationSkillRepository;
|
|
}
|
|
|
|
public SkillCloudResponse query(Long industryId, Long occupationId, Long categoryId) {
|
|
long validatedIndustryId = requirePositive(industryId, "industryId");
|
|
long validatedOccupationId = requirePositive(occupationId, "occupationId");
|
|
Long validatedCategoryId = categoryId == null ? null : requirePositive(categoryId, "categoryId");
|
|
|
|
SkillIndustry industry = industryRepository.findById(validatedIndustryId)
|
|
.orElseThrow(() -> badRequest("industry not found: industryId=" + validatedIndustryId));
|
|
SkillOccupation occupation = occupationRepository.findById(validatedOccupationId)
|
|
.orElseThrow(() -> badRequest("occupation not found: occupationId=" + validatedOccupationId));
|
|
if (!occupation.getIndustryId().equals(validatedIndustryId)) {
|
|
throw badRequest("occupation does not belong to industry: occupationId="
|
|
+ validatedOccupationId + ", industryId=" + validatedIndustryId);
|
|
}
|
|
|
|
SkillCategory category = null;
|
|
if (validatedCategoryId != null) {
|
|
category = categoryRepository.findById(validatedCategoryId)
|
|
.orElseThrow(() -> badRequest("category not found: categoryId=" + validatedCategoryId));
|
|
if (!category.getOccupationId().equals(validatedOccupationId)) {
|
|
throw badRequest("category does not belong to occupation: categoryId="
|
|
+ validatedCategoryId + ", occupationId=" + validatedOccupationId);
|
|
}
|
|
}
|
|
|
|
List<SkillCloudSkillProjection> projections = validatedCategoryId == null
|
|
? occupationSkillRepository.findSkillProjectionsByOccupationId(validatedOccupationId)
|
|
: occupationSkillRepository.findSkillProjectionsByOccupationIdAndCategoryId(
|
|
validatedOccupationId, validatedCategoryId);
|
|
|
|
List<SkillCloudSkillProjection> sortedProjections = projections.stream()
|
|
.sorted(SKILL_ORDER)
|
|
.toList();
|
|
List<SkillCloudItem> items = IntStream.range(0, sortedProjections.size())
|
|
.mapToObj(index -> toItem(sortedProjections.get(index), index + 1))
|
|
.toList();
|
|
|
|
return new SkillCloudResponse(
|
|
toNode(industry.getId(), industry.getCode(), industry.getNameZh()),
|
|
toNode(occupation.getId(), occupation.getCode(), occupation.getNameZh()),
|
|
category == null ? null : toNode(category.getId(), category.getCode(), category.getNameZh()),
|
|
items.size(),
|
|
items
|
|
);
|
|
}
|
|
|
|
private SkillCloudItem toItem(SkillCloudSkillProjection projection, int rank) {
|
|
return new SkillCloudItem(
|
|
rank,
|
|
projection.skillId(),
|
|
projection.skillCode(),
|
|
projection.nameZh(),
|
|
projection.nameEn(),
|
|
projection.sourceType(),
|
|
projection.sourceCode(),
|
|
projection.categoryId(),
|
|
projection.categoryName(),
|
|
projection.importance(),
|
|
projection.importanceSourceCode(),
|
|
projection.importanceElementId(),
|
|
projection.importanceIsProxy()
|
|
);
|
|
}
|
|
|
|
private static int compareHeat(BigDecimal left, BigDecimal right) {
|
|
if (left == null && right == null) {
|
|
return 0;
|
|
}
|
|
if (left == null) {
|
|
return 1;
|
|
}
|
|
if (right == null) {
|
|
return -1;
|
|
}
|
|
return right.compareTo(left);
|
|
}
|
|
|
|
private static <T extends Comparable<? super T>> int compareNullable(T left, T right) {
|
|
if (left == null && right == null) {
|
|
return 0;
|
|
}
|
|
if (left == null) {
|
|
return 1;
|
|
}
|
|
if (right == null) {
|
|
return -1;
|
|
}
|
|
return left.compareTo(right);
|
|
}
|
|
|
|
private static SkillCloudNode toNode(Long id, String code, String name) {
|
|
return new SkillCloudNode(id, code, name);
|
|
}
|
|
|
|
private static long requirePositive(Long value, String parameterName) {
|
|
if (value == null || value <= 0) {
|
|
throw badRequest(parameterName + " must be a positive integer");
|
|
}
|
|
return value;
|
|
}
|
|
|
|
private static BusinessException badRequest(String detail) {
|
|
return new BusinessException(ErrorCode.BAD_REQUEST, detail);
|
|
}
|
|
}
|
|
|