From dcceb0d49a002627c9ea84306476f181044aaa9e Mon Sep 17 00:00:00 2001 From: Shicong Huang Date: Mon, 26 Aug 2019 18:30:51 -0400 Subject: [PATCH] Add sql schema and entity class for ClaimsList (#227) --- .../registry/schema/tmch/ClaimsList.java | 96 +++++++++++++++++++ .../main/resources/sql/schema/claims_list.sql | 27 ++++++ settings.gradle | 1 + 3 files changed, 124 insertions(+) create mode 100644 core/src/main/java/google/registry/schema/tmch/ClaimsList.java create mode 100644 db/src/main/resources/sql/schema/claims_list.sql diff --git a/core/src/main/java/google/registry/schema/tmch/ClaimsList.java b/core/src/main/java/google/registry/schema/tmch/ClaimsList.java new file mode 100644 index 00000000000..3ef3135dcf2 --- /dev/null +++ b/core/src/main/java/google/registry/schema/tmch/ClaimsList.java @@ -0,0 +1,96 @@ +// Copyright 2019 The Nomulus Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package google.registry.schema.tmch; + +import static com.google.common.base.Preconditions.checkState; + +import java.time.ZonedDateTime; +import java.util.Map; +import java.util.Optional; +import javax.persistence.CollectionTable; +import javax.persistence.Column; +import javax.persistence.ElementCollection; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.MapKeyColumn; +import javax.persistence.Table; + +/** + * A list of TMCH claims labels and their associated claims keys. + * + *

Note that the primary key of this entity is {@link #revisionId}, which is auto-generated by + * the database. So, if a retry of insertion happens after the previous attempt unexpectedly + * succeeds, we will end up with having two exact same claims list with only different {@link + * #revisionId}. However, this is not an actual problem because we only use the claims list with + * highest {@link #revisionId}. + */ +@Entity +@Table(name = "ClaimsList") +public class ClaimsList { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "revision_id") + private Long revisionId; + + @Column(name = "creation_timestamp", nullable = false) + private ZonedDateTime creationTimestamp; + + @ElementCollection + @CollectionTable( + name = "ClaimsEntry", + joinColumns = @JoinColumn(name = "revision_id", referencedColumnName = "revision_id")) + @MapKeyColumn(name = "domain_label", nullable = false) + @Column(name = "claim_key", nullable = false) + private Map labelsToKeys; + + private ClaimsList(ZonedDateTime creationTimestamp, Map labelsToKeys) { + this.creationTimestamp = creationTimestamp; + this.labelsToKeys = labelsToKeys; + } + + // Hibernate requires this default constructor. + private ClaimsList() {} + + /** Constructs a {@link ClaimsList} object. */ + public static ClaimsList create( + ZonedDateTime creationTimestamp, Map labelsToKeys) { + return new ClaimsList(creationTimestamp, labelsToKeys); + } + + /** Returns the revision id of this claims list, or throws exception if it is null. */ + public Long getRevisionId() { + checkState( + revisionId != null, "revisionId is null because it is not persisted in the database"); + return revisionId; + } + + /** Returns the creation time of this claims list. */ + public ZonedDateTime getCreationTimestamp() { + return creationTimestamp; + } + + /** Returns an {@link Map} mapping domain label to its lookup key. */ + public Map getLabelsToKeys() { + return labelsToKeys; + } + + /** Returns the claim key for a given domain if there is one, empty otherwise. */ + public Optional getClaimKey(String label) { + return Optional.ofNullable(labelsToKeys.get(label)); + } +} diff --git a/db/src/main/resources/sql/schema/claims_list.sql b/db/src/main/resources/sql/schema/claims_list.sql new file mode 100644 index 00000000000..c73ccadb20f --- /dev/null +++ b/db/src/main/resources/sql/schema/claims_list.sql @@ -0,0 +1,27 @@ +-- Copyright 2019 The Nomulus Authors. All Rights Reserved. +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. + +CREATE TABLE `ClaimsList` ( + revision_id BIGSERIAL NOT NULL, + creation_timestamp TIMESTAMPTZ NOT NULL, + PRIMARY KEY (revision_id) +); + +CREATE TABLE `ClaimsEntry` ( + revision_id BIGSERIAL NOT NULL, + claim_key TEXT NOT NULL, + domain_label TEXT NOT NULL, + PRIMARY KEY (revision_id, domain_label), + FOREIGN KEY (revision_id) REFERENCES `ClaimsList`(revision_id) +); diff --git a/settings.gradle b/settings.gradle index 9b2d11de8da..e229618ada1 100644 --- a/settings.gradle +++ b/settings.gradle @@ -28,6 +28,7 @@ if (pluginsUrl) { rootProject.name = 'nomulus' include 'core' +include 'db' include 'prober' include 'proxy' include 'third_party'