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