001/* 002 * Licensed under the Apache License, Version 2.0 (the "License"); 003 * you may not use this file except in compliance with the License. 004 * You may obtain a copy of the License at 005 * 006 * http://www.apache.org/licenses/LICENSE-2.0 007 * 008 * Unless required by applicable law or agreed to in writing, software 009 * distributed under the License is distributed on an "AS IS" BASIS, 010 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 011 * See the License for the specific language governing permissions and 012 * limitations under the License. 013 */ 014package org.gbif.api.util.iterables; 015 016import java.util.Collections; 017import java.util.Date; 018import java.util.Map; 019import java.util.Optional; 020import java.util.UUID; 021import java.util.function.Function; 022import javax.annotation.Nullable; 023import org.gbif.api.model.collections.Institution; 024import org.gbif.api.model.collections.descriptors.Descriptor; 025import org.gbif.api.model.collections.request.CollectionSearchRequest; 026import org.gbif.api.model.collections.request.DescriptorSearchRequest; 027import org.gbif.api.model.collections.request.InstitutionSearchRequest; 028import org.gbif.api.model.collections.view.CollectionView; 029import org.gbif.api.model.common.paging.Pageable; 030import org.gbif.api.model.common.paging.PagingConstants; 031import org.gbif.api.model.common.paging.PagingRequest; 032import org.gbif.api.model.common.paging.PagingResponse; 033import org.gbif.api.model.occurrence.DownloadStatistics; 034import org.gbif.api.model.registry.Dataset; 035import org.gbif.api.model.registry.DatasetOccurrenceDownloadUsage; 036import org.gbif.api.model.registry.Node; 037import org.gbif.api.model.registry.Organization; 038import org.gbif.api.model.registry.search.DatasetSearchRequest; 039import org.gbif.api.model.registry.search.DatasetSearchResult; 040import org.gbif.api.service.collections.CollectionService; 041import org.gbif.api.service.collections.DescriptorsService; 042import org.gbif.api.service.collections.InstitutionService; 043import org.gbif.api.service.registry.DatasetSearchService; 044import org.gbif.api.service.registry.DatasetService; 045import org.gbif.api.service.registry.InstallationService; 046import org.gbif.api.service.registry.NetworkService; 047import org.gbif.api.service.registry.NodeService; 048import org.gbif.api.service.registry.OccurrenceDownloadService; 049import org.gbif.api.service.registry.OrganizationService; 050import org.gbif.api.vocabulary.Country; 051import org.gbif.api.vocabulary.DatasetType; 052import org.slf4j.Logger; 053import org.slf4j.LoggerFactory; 054 055/** Factory constructing registry entity iterables using specific pagers under the hood. */ 056@SuppressWarnings("unused") 057public class Iterables { 058 private static final Logger LOG = LoggerFactory.getLogger(Iterables.class); 059 060 /** Private default constructor. */ 061 private Iterables() { 062 // empty private constructor 063 } 064 065 /** 066 * @param key a valid dataset, organization or installation key. If null all datasets will be 067 * iterated over 068 * @throws IllegalArgumentException if given key is not existing 069 */ 070 public static Iterable<Dataset> datasets( 071 @Nullable UUID key, 072 @Nullable DatasetType type, 073 DatasetService ds, 074 OrganizationService os, 075 InstallationService is, 076 NetworkService ns, 077 NodeService nos) { 078 return datasets(key, type, ds, os, is, ns, nos, PagingConstants.DEFAULT_PARAM_LIMIT); 079 } 080 081 /** 082 * Returns a dataset iterable by testing the given registry key first to see whether it is a 083 * dataset, organization or installation. In case of an organization key the published datasets 084 * will be returned. 085 * 086 * @param key a valid dataset, organization or installation key. If null all datasets will be 087 * iterated over 088 * @param pageSize to use when talking to the registry 089 * @throws IllegalArgumentException if given key is not existing 090 */ 091 public static Iterable<Dataset> datasets( 092 @Nullable UUID key, 093 @Nullable DatasetType type, 094 DatasetService ds, 095 OrganizationService os, 096 InstallationService is, 097 NetworkService ns, 098 NodeService nos, 099 int pageSize) { 100 if (key == null) { 101 LOG.info("Iterate over all {} datasets", type == null ? "" : type); 102 return new DatasetPager(ds, type, pageSize); 103 104 } else if (isDataset(key, ds)) { 105 LOG.info("Iterate over dataset {}", key); 106 return Collections.singletonList(ds.get(key)); 107 108 } else if (isOrganization(key, os)) { 109 LOG.info("Iterate over all {} datasets published by {}", type == null ? "" : type, key); 110 return new OrgPublishingPager(os, key, type, pageSize); 111 112 } else if (isInstallation(key, is)) { 113 LOG.info( 114 "Iterate over all {} datasets hosted by installation {}", type == null ? "" : type, key); 115 return new InstallationPager(is, key, type, pageSize); 116 117 } else if (isNode(key, nos)) { 118 LOG.info("Iterate over all {} datasets endorsed by node {}", type == null ? "" : type, key); 119 return new NetworkPager(ns, key, type, pageSize); 120 121 } else if (isNetwork(key, ns)) { 122 LOG.info( 123 "Iterate over all {} datasets belonging to network {}", type == null ? "" : type, key); 124 return new NodeDatasetPager(nos, key, type, pageSize); 125 } 126 throw new IllegalArgumentException("Given key is no valid GBIF registry key: " + key); 127 } 128 129 /** 130 * @param type an optional filter to just include the given dataset type 131 */ 132 public static Iterable<Dataset> datasets(@Nullable DatasetType type, DatasetService service) { 133 LOG.info("Iterate over all {} datasets", type == null ? "" : type); 134 return new DatasetPager(service, type, PagingConstants.DEFAULT_PARAM_LIMIT); 135 } 136 137 /** Iterates over dataset search results. */ 138 public static Iterable<DatasetSearchResult> datasetSearchResults( 139 @Nullable DatasetSearchRequest datasetSearchRequest, 140 DatasetSearchService datasetSearchService, 141 @Nullable Integer limit) { 142 return new DatasetSearchResultsPager( 143 datasetSearchService, 144 datasetSearchRequest, 145 Optional.ofNullable(limit).orElse(PagingConstants.DEFAULT_PARAM_LIMIT)); 146 } 147 148 /** 149 * @param key a valid organization key 150 * @param type an optional filter to just include the given dataset type 151 */ 152 public static Iterable<Dataset> publishedDatasets( 153 UUID key, @Nullable DatasetType type, OrganizationService service) { 154 LOG.info("Iterate over all {} datasets published by {}", type == null ? "" : type, key); 155 return new OrgPublishingPager(service, key, type, PagingConstants.DEFAULT_PARAM_LIMIT); 156 } 157 158 /** 159 * @param key a valid organization key 160 * @param type an optional filter to just include the given dataset type 161 */ 162 public static Iterable<Dataset> hostedDatasets( 163 UUID key, @Nullable DatasetType type, OrganizationService service) { 164 LOG.info( 165 "Iterate over all {} datasets hosted by organization {}", type == null ? "" : type, key); 166 return new OrgHostingPager(service, key, type, PagingConstants.DEFAULT_PARAM_LIMIT); 167 } 168 169 /** 170 * @param key a valid installation key 171 * @param type an optional filter to just include the given dataset type 172 */ 173 public static Iterable<Dataset> hostedDatasets( 174 UUID key, @Nullable DatasetType type, InstallationService service) { 175 LOG.info( 176 "Iterate over all {} datasets hosted by installation {}", type == null ? "" : type, key); 177 return new InstallationPager(service, key, type, PagingConstants.DEFAULT_PARAM_LIMIT); 178 } 179 180 /** 181 * @param key a valid dataset key 182 */ 183 public static Iterable<Dataset> constituentDatasets(UUID key, DatasetService service) { 184 LOG.info("Iterate over all constituent datasets of {}", key); 185 return new DatasetConstituentPager(service, key, PagingConstants.DEFAULT_PARAM_LIMIT); 186 } 187 188 /** 189 * Iterates over all constituents of a given network. 190 * 191 * @param key a valid network key 192 * @param type an optional filter to just include the given dataset type 193 */ 194 public static Iterable<Dataset> networkDatasets( 195 UUID key, @Nullable DatasetType type, NetworkService service) { 196 LOG.info("Iterate over all {} datasets belonging to network {}", type == null ? "" : type, key); 197 return new NetworkPager(service, key, type, PagingConstants.DEFAULT_PARAM_LIMIT); 198 } 199 200 /** 201 * @param nodeKey a valid endorsing node key 202 * @param type an optional filter to just include the given dataset type 203 */ 204 public static Iterable<Dataset> endorsedDatasets( 205 UUID nodeKey, @Nullable DatasetType type, NodeService service) { 206 LOG.info("Iterate over all {} datasets endorsed by node {}", type == null ? "" : type, nodeKey); 207 return new NodeDatasetPager(service, nodeKey, type, PagingConstants.DEFAULT_PARAM_LIMIT); 208 } 209 210 /** 211 * @param pager producer function of next page response 212 * @return a dataset iterable based on producer function 213 */ 214 public static Iterable<Dataset> datasetsIterable( 215 Function<PagingRequest, PagingResponse<Dataset>> pager) { 216 return new DatasetBasePager(null, PagingConstants.DEFAULT_PARAM_LIMIT) { 217 @Override 218 public PagingResponse<Dataset> nextPage(PagingRequest page) { 219 return pager.apply(page); 220 } 221 }; 222 } 223 224 /** 225 * @param country an optional country filter 226 */ 227 public static Iterable<Organization> organizations( 228 @Nullable Country country, OrganizationService service) { 229 LOG.info("Iterate over all organizations {}", country == null ? "" : "from country " + country); 230 return new OrganizationPager(service, country, PagingConstants.DEFAULT_PARAM_LIMIT); 231 } 232 233 /** 234 * @param nodeKey a valid endorsing node key 235 */ 236 public static Iterable<Organization> endorsedOrganizations(UUID nodeKey, NodeService service) { 237 LOG.info("Iterate over all organizations endorsed by node {}", nodeKey); 238 return new NodeOrganizationPager(service, nodeKey, PagingConstants.DEFAULT_PARAM_LIMIT); 239 } 240 241 /** Iterate over all endorsing nodes */ 242 public static Iterable<Node> nodes(NodeService service) { 243 LOG.info("Iterate over all nodes"); 244 return new NodePager(service, PagingConstants.DEFAULT_PARAM_LIMIT); 245 } 246 247 /** 248 * Iterable for {@link OccurrenceDownloadService#getDownloadStatistics(Date, Date, Country, UUID, 249 * UUID, Pageable)}. 250 */ 251 public static Iterable<DownloadStatistics> downloadStatistics( 252 OccurrenceDownloadService service, 253 @Nullable Date fromDate, 254 @Nullable Date toDate, 255 @Nullable Country publishingCountry, 256 @Nullable UUID datasetKey, 257 @Nullable UUID publishingOrgKey, 258 @Nullable Integer limit) { 259 LOG.info("Iterate over download statistics"); 260 return new DownloadStatisticPager( 261 service, 262 fromDate, 263 toDate, 264 publishingCountry, 265 datasetKey, 266 publishingOrgKey, 267 Optional.ofNullable(limit).orElse(PagingConstants.DEFAULT_PARAM_LIMIT)); 268 } 269 270 /** Iterable for {@link OccurrenceDownloadService#listDatasetUsages(String, Pageable)}. */ 271 public static Iterable<DatasetOccurrenceDownloadUsage> datasetOccurrenceDownloadUsages( 272 OccurrenceDownloadService service, String downloadKey, @Nullable Integer limit) { 273 LOG.info("Iterate over download dataset usages of download {}", downloadKey); 274 return new DatasetOccurrenceDownloadUsagesPager( 275 service, 276 downloadKey, 277 Optional.ofNullable(limit).orElse(PagingConstants.DEFAULT_PARAM_LIMIT)); 278 } 279 280 /** Iterable for {@link CollectionService#list(CollectionSearchRequest)}. */ 281 public static Iterable<CollectionView> collections( 282 CollectionSearchRequest searchRequest, CollectionService service, @Nullable Integer limit) { 283 LOG.info("Iterating over a collection's search results"); 284 return new CollectionsPager( 285 service, 286 searchRequest, 287 Optional.ofNullable(limit).orElse(PagingConstants.DEFAULT_PARAM_LIMIT)); 288 } 289 290 /** Iterable for {@link InstitutionService#list(InstitutionSearchRequest)}. */ 291 public static Iterable<Institution> institutions( 292 InstitutionSearchRequest searchRequest, InstitutionService service, @Nullable Integer limit) { 293 LOG.info("Iterating over a institution's search results"); 294 return new InstitutionsPager( 295 service, 296 searchRequest, 297 Optional.ofNullable(limit).orElse(PagingConstants.DEFAULT_PARAM_LIMIT)); 298 } 299 300 /** Iterable for {@link DescriptorsService#listDescriptors(DescriptorSearchRequest)}. */ 301 public static Iterable<Descriptor> descriptors( 302 DescriptorsService service, DescriptorSearchRequest searchRequest, @Nullable Integer limit) { 303 LOG.info("Iterating over a collection descriptor's search results"); 304 return new CollectionDescriptorPager( 305 service, 306 searchRequest, 307 Optional.ofNullable(limit).orElse(PagingConstants.DEFAULT_PARAM_LIMIT)); 308 } 309 310 /** 311 * Iterable for the verbatim fields of {@link 312 * DescriptorsService#listDescriptors(DescriptorSearchRequest)}. 313 */ 314 public static Iterable<Map<String, String>> descriptorVerbatims( 315 DescriptorsService service, DescriptorSearchRequest searchRequest, @Nullable Integer limit) { 316 LOG.info("Iterating over a collection descriptor's search results"); 317 return new CollectionDescriptorVerbatimPager( 318 service, 319 searchRequest, 320 Optional.ofNullable(limit).orElse(PagingConstants.DEFAULT_PARAM_LIMIT)); 321 } 322 323 private static boolean isDataset(UUID key, DatasetService ds) { 324 return ds.get(key) != null; 325 } 326 327 private static boolean isOrganization(UUID key, OrganizationService os) { 328 return os.get(key) != null; 329 } 330 331 private static boolean isInstallation(UUID key, InstallationService is) { 332 return is.get(key) != null; 333 } 334 335 private static boolean isNetwork(UUID key, NetworkService ns) { 336 return ns.get(key) != null; 337 } 338 339 private static boolean isNode(UUID key, NodeService ns) { 340 return ns.get(key) != null; 341 } 342}