001/*
002 * Copyright 2020 Global Biodiversity Information Facility (GBIF)
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.gbif.api.util;
017
018import java.util.Objects;
019import java.util.UUID;
020
021import org.apache.commons.lang3.StringUtils;
022
023/**
024 * A typed dataset key for both registered and external datasets.
025 * External dataset keys are compound keys based on the originating network UUID key and a free String based
026 * local identifier. The compound external datasetKey is structured as follows in its serialized form:
027 * <pre>{NETWORK_KEY}:{DATASET_ID}</pre>
028 *
029 * This class is intended as a utility class, lacks mutability and therefore is not suitable serialization via Jackson!
030 */
031public class DatasetKey {
032
033  private static final int UUID_LENGTH = 36;
034  private static final int EXTERNAL_KEY_DATASET_ID_START_INDEX = UUID_LENGTH + 1;
035  private static final char DELIMITER = ':';
036
037  private final UUID registryKey;
038  private final String datasetId;
039
040  /**
041   * Parses a datasetKey which can be either a compound external key or a simple UUID for registered datasets.
042   *
043   * @param key a simple registered dataset uuid key or an external compound dataset key
044   *
045   * @return a valid DatasetKey instance
046   *
047   * @throws IllegalArgumentException for invalid external or registered dataset keys
048   */
049  public static DatasetKey fromString(String key) {
050    Objects.requireNonNull(key);
051    if (key.length() == UUID_LENGTH) {
052      // a registered dataset key
053      return new DatasetKey(UUID.fromString(key));
054
055    } else if (key.length() > EXTERNAL_KEY_DATASET_ID_START_INDEX && DELIMITER == key.charAt(UUID_LENGTH)) {
056      // an external dataset key
057      return new DatasetKey(UUID.fromString(key.substring(0, UUID_LENGTH)),
058        key.substring(EXTERNAL_KEY_DATASET_ID_START_INDEX));
059    }
060
061    throw new IllegalArgumentException("Invalid dataset key " + key);
062  }
063
064  /**
065   * Constructor for a registered dataset key.
066   */
067  public DatasetKey(UUID datasetKey) {
068    this.registryKey = Objects.requireNonNull(datasetKey);
069    this.datasetId = null;
070  }
071
072  /**
073   * Constructor for an external dataset key.
074   *
075   * @param networkKey of the originating network
076   * @param datasetId  the local dataset id within the network
077   */
078  public DatasetKey(UUID networkKey, String datasetId) {
079    this.registryKey = Objects.requireNonNull(networkKey);
080    this.datasetId = datasetId.trim();
081    if (StringUtils.isEmpty(this.datasetId)) {
082      throw new IllegalArgumentException("datasetId has to have non whitespace characters");
083    }
084  }
085
086  /**
087   * A registered UUID of either a dataset or the network of origin in the case of external datasets.
088   *
089   * @return the registered network or dataset key
090   */
091  public UUID getRegistryKey() {
092    return registryKey;
093  }
094
095  /**
096   * @return the local identifier of an external dataset key or null if its a registered dataset
097   */
098  public String getDatasetId() {
099    return datasetId;
100  }
101
102  public boolean isExternalKey() {
103    return datasetId != null;
104  }
105
106  /**
107   * Generates the serialized dataset key as used in the {@link org.gbif.api.model.registry.Dataset} class.
108   *
109   * @return the serialized dataset key
110   */
111  public String toDatasetKey() {
112    if (isExternalKey()) {
113      return registryKey.toString() + DELIMITER + datasetId;
114    }
115    return registryKey.toString();
116  }
117
118
119}