package org.gbif.checklistbank.service.mybatis; import org.gbif.api.model.Constants; import org.gbif.api.model.common.paging.Pageable; import org.gbif.api.model.common.paging.PagingRequest; import org.gbif.api.model.common.paging.PagingResponse; import org.gbif.api.service.checklistbank.NameUsageExtensionService; import org.gbif.checklistbank.model.UsageRelated; import org.gbif.checklistbank.service.mybatis.mapper.NameUsageComponentMapper; import java.util.List; import java.util.Map; import javax.annotation.Nullable; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.inject.Inject; /** * Implements the NameUsageComponentService using MyBatis. * All PagingResponses will not have the count set as it can be too costly sometimes. * * @param <T> the interpreted model class. */ public class NameUsageComponentServiceMyBatis<T> implements NameUsageExtensionService<T> { private final NameUsageComponentMapper<T> mapper; @Inject NameUsageComponentServiceMyBatis(NameUsageComponentMapper<T> mapper) { this.mapper = mapper; } @Override public PagingResponse<T> listByUsage(int usageKey, @Nullable Pageable page) { if (page == null) { page = new PagingRequest(); } // is this a non nub usage? List<T> result; if (isNub(usageKey)) { result = mapper.listByNubUsage(usageKey, page); } else { result = mapper.listByChecklistUsage(usageKey, page); } return new PagingResponse<T>(page, null, result); } protected boolean isNub(int usageKey) { return usageKey <= Constants.NUB_MAXIMUM_KEY; } /** * Lists all name usages with a key between start / end. * * @throws IllegalArgumentException if start <= end */ public Map<Integer, List<T>> listRange(int usageKeyStart, int usageKeyEnd) { if (usageKeyStart > usageKeyEnd) { throw new IllegalArgumentException("start " + usageKeyStart + " > end " + usageKeyEnd + " range"); } List<UsageRelated<T>> related; if (isNub(usageKeyEnd)) { // only nub usages related = mapper.listByNubUsageRange(usageKeyStart, usageKeyEnd); } else if (!isNub(usageKeyStart)) { // only checklist usages related = mapper.listByChecklistUsageRange(usageKeyStart, usageKeyEnd); } else { // mixed !!! // get nubs first related = mapper.listByNubUsageRange(usageKeyStart, Constants.NUB_MAXIMUM_KEY); related.addAll(mapper.listByChecklistUsageRange(Constants.NUB_MAXIMUM_KEY + 1, usageKeyEnd)); } Map<Integer, List<T>> result = Maps.newHashMap(); for (UsageRelated<T> r : related) { if (r.getValue() == null || r.getValue() instanceof Integer ) { // value can be null when all properties of the bean (e.g. SpeciesProfile) are null // in that case mybatis DOES NOT CREATE AN OBJECT !!! // for some association queries it actually returns an INTEGER instead of the UsageRelated class :( continue; } if (!result.containsKey(r.getUsageKey())) { result.put(r.getUsageKey(), Lists.<T>newArrayList()); } result.get(r.getUsageKey()).add(r.getValue()); } return result; } }