001package org.gbif.api.util;
002
003import java.util.UUID;
004
005import com.google.common.base.Preconditions;
006import com.google.common.base.Strings;
007
008/**
009 * A typed dataset key for both registered and external datasets.
010 * External dataset keys are compound keys based on the originating network UUID key and a free String based
011 * local identifier. The compound external datasetKey is structured as follows in its serialized form:
012 * <pre>{NETWORK_KEY}:{DATASET_ID}</pre>
013 *
014 * This class is intended as a utility class, lacks mutability and therefore is not suitable serialization via Jackson!
015 */
016public class DatasetKey {
017
018  private static final int UUID_LENGTH = 36;
019  private static final int EXTERNAL_KEY_DATASET_ID_START_INDEX = UUID_LENGTH + 1;
020  private static final char DELIMITER = ':';
021
022  private final UUID registryKey;
023  private final String datasetId;
024
025
026  /**
027   * Parses a datasetKey which can be either a compound external key or a simple UUID for registered datasets.
028   *
029   * @param key a simple registered dataset uuid key or an external compound dataset key
030   *
031   * @return a valid DatasetKey instance
032   *
033   * @throws IllegalArgumentException for invalid external or registered dataset keys
034   */
035  public static DatasetKey fromString(String key) {
036    Preconditions.checkNotNull(key);
037    if (key.length() == UUID_LENGTH) {
038      // a registered dataset key
039      return new DatasetKey(UUID.fromString(key));
040
041    } else if (key.length() > EXTERNAL_KEY_DATASET_ID_START_INDEX && DELIMITER == key.charAt(UUID_LENGTH)) {
042      // an external dataset key
043      return new DatasetKey(UUID.fromString(key.substring(0, UUID_LENGTH)),
044        key.substring(EXTERNAL_KEY_DATASET_ID_START_INDEX));
045    }
046
047    throw new IllegalArgumentException("Invalid dataset key " + key);
048  }
049
050  /**
051   * Constructor for a registered dataset key.
052   */
053  public DatasetKey(UUID datasetKey) {
054    this.registryKey = Preconditions.checkNotNull(datasetKey);
055    this.datasetId = null;
056  }
057
058  /**
059   * Constructor for an external dataset key.
060   *
061   * @param networkKey of the originating network
062   * @param datasetId  the local dataset id within the network
063   */
064  public DatasetKey(UUID networkKey, String datasetId) {
065    this.registryKey = Preconditions.checkNotNull(networkKey);
066    this.datasetId = datasetId.trim();
067    if (Strings.isNullOrEmpty(this.datasetId)) {
068      throw new IllegalArgumentException("datasetId has to have non whitespace characters");
069    }
070  }
071
072  /**
073   * A registered UUID of either a dataset or the network of origin in the case of external datasets.
074   *
075   * @return the registered network or dataset key
076   */
077  public UUID getRegistryKey() {
078    return registryKey;
079  }
080
081  /**
082   * @return the local identifier of an external dataset key or null if its a registered dataset
083   */
084  public String getDatasetId() {
085    return datasetId;
086  }
087
088  public boolean isExternalKey() {
089    return datasetId != null;
090  }
091
092  /**
093   * Generates the serialized dataset key as used in the {@link org.gbif.api.model.registry.Dataset} class.
094   *
095   * @return the serialized dataset key
096   */
097  public String toDatasetKey() {
098    if (isExternalKey()) {
099      return registryKey.toString() + DELIMITER + datasetId;
100    }
101    return registryKey.toString();
102  }
103
104
105}