001package org.gbif.api.vocabulary;
002
003import org.gbif.api.util.VocabularyUtils;
004
005import javax.annotation.Nullable;
006
007import com.google.common.base.Optional;
008import com.google.common.base.Strings;
009import org.apache.commons.lang3.StringUtils;
010
011/**
012 * Enumeration of the set of licenses GBIF supports for applying to a dataset. The license provides a standardised way
013 * to define appropriate uses of a dataset.
014 * </br>
015 * GBIF's recommended best practice is to use the most recent license version, which for CC-BY and CC-BY-NC is 4.0.
016 * This is in line with the recommendation from Creative Commons.
017 * The ordinal number in the Enum implicitly defines the level of restriction, see LicenseTest.
018 *
019 * @see <a href="https://creativecommons.org/faq/#why-should-i-use-the-latest-version-of-the-creative-commons-licenses">Creative
020 * Commons recommendation</a>
021 * @see <a href="http://www.gbif.org/terms/licences">GBIF Licensing</a>
022 */
023public enum License {
024
025  /**
026   * Creative Commons Zero / Public Domain version 1.0. Technically a waiver, not a license.
027   *
028   * @see <a href="http://creativecommons.org/publicdomain/zero/1.0/legalcode">legal document</a>
029   */
030  CC0_1_0("Public Domain (CC0 1.0)", "http://creativecommons.org/publicdomain/zero/1.0/legalcode"),
031  /**
032   * Creative Commons Attribution version 4.0.
033   *
034   * @see <a href="http://creativecommons.org/licenses/by/4.0/legalcode">legal document</a>
035   */
036  CC_BY_4_0("Creative Commons Attribution (CC-BY) 4.0", "http://creativecommons.org/licenses/by/4.0/legalcode"),
037  /**
038   * Creative Commons Attribution-NonCommercial version 4.0.
039   *
040   * @see <a href="http://creativecommons.org/licenses/by-nc/4.0/legalcode">legal document</a>
041   */
042  CC_BY_NC_4_0("Creative Commons Attribution Non Commercial (CC-BY-NC) 4.0", "http://creativecommons.org/licenses/by-nc/4.0/legalcode"),
043  /**
044   * No license has been specified.
045   */
046  UNSPECIFIED(null, null),
047  /**
048   * A license not supported by GBIF.
049   */
050  UNSUPPORTED(null, null);
051
052
053  private final String licenseTitle;
054  private final String licenseUrl;
055
056  /**
057   * FIXME returning Guava Optional will cause issues, Java 8 Optional should be returned.
058   * Get an {@link License} from its name as String.
059   *
060   * @return instance of com.google.common.base.Optional, never null
061   */
062  public static Optional<License> fromString(String license) {
063    return VocabularyUtils.lookup(license, License.class);
064  }
065
066  /**
067   * FIXME returning Guava Optional will cause issues, Java 8 Optional should be returned.
068   * Lookup a License by either its a) legal code URL or b) human readable summary URL.
069   * For any parsing see LicenseParser in GBIF parsers project.
070   *
071   * @param licenseUrl the case insensitive URL for the license.
072   *
073   * @return instance of com.google.common.base.Optional, never null
074   */
075  public static Optional<License> fromLicenseUrl(String licenseUrl) {
076    if (!Strings.isNullOrEmpty(licenseUrl)) {
077      licenseUrl = licenseUrl.trim().toLowerCase();
078      licenseUrl = StringUtils.removeEnd(licenseUrl, "/");
079
080      // do lookup by legal code URL or human readable summary URL (excluding "/legalcode")
081      for (License license : License.values()) {
082        if (license.getLicenseUrl() != null && (licenseUrl.equals(license.getLicenseUrl())
083                || license.getLicenseUrl().startsWith(licenseUrl))) {
084          return Optional.fromNullable(license);
085        }
086      }
087    }
088    return Optional.absent();
089  }
090
091  /**
092   * Get the most restrictive license between the 2 provided licenses.
093   * If one or the two licenses are null or not concrete, this method returns the fallback License.
094   *
095   * @param fallback License to return if one or the two licenses are null or not concrete
096   *
097   * @return the most restrictive License or the fallback License
098   */
099  public static License getMostRestrictive(License license1, License license2, License fallback) {
100    if (license1 == null || license2 == null || !license1.isConcrete() || !license2.isConcrete()) {
101      return fallback;
102    }
103    return (license1.compareTo(license2) > 0) ? license1 : license2;
104  }
105
106  License(@Nullable String licenseTitle, @Nullable String licenseUrl) {
107    this.licenseTitle = licenseTitle;
108    // ensure license information is kept in lowercase internally
109    if (licenseUrl != null) {
110      this.licenseUrl = licenseUrl.toLowerCase();
111    } else {
112      this.licenseUrl = null;
113    }
114  }
115
116  /**
117   * @return the License URL
118   */
119  public String getLicenseUrl() {
120    return licenseUrl;
121  }
122
123  /**
124   * @return the License title
125   */
126  public String getLicenseTitle() {
127    return licenseTitle;
128  }
129
130  /**
131   * Indicates if a license is a concrete license (true) or an abstracted license (false) like
132   * UNSPECIFIED or UNSUPPORTED.
133   * @return the license if concrete or not
134   */
135  public boolean isConcrete() {
136    return licenseUrl != null;
137  }
138}