// Copyright 2017 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.rdap; import static google.registry.rdap.RdapIcannStandardInformation.POSSIBLY_INCOMPLETE_NOTICES; import static google.registry.rdap.RdapIcannStandardInformation.TRUNCATION_NOTICES; import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import google.registry.rdap.RdapDataStructures.Link; import google.registry.rdap.RdapDataStructures.Notice; import google.registry.rdap.RdapObjectClasses.BoilerplateType; import google.registry.rdap.RdapObjectClasses.RdapDomain; import google.registry.rdap.RdapObjectClasses.RdapEntity; import google.registry.rdap.RdapObjectClasses.RdapNameserver; import google.registry.rdap.RdapObjectClasses.ReplyPayloadBase; import java.net.URI; import java.util.Optional; /** * Holds domain, nameserver and entity search results. * *

We need to know not only the list of things we found, but also whether the result set was * truncated to the limit. If it is, we must add the ICANN-mandated notice to that effect. */ @AutoValue abstract class RdapSearchResults { /** * Responding To Searches defined in 8 of RFC7483. */ abstract static class BaseSearchResponse extends ReplyPayloadBase { abstract IncompletenessWarningType incompletenessWarningType(); abstract ImmutableMap navigationLinks(); @JsonableElement("notices") ImmutableList getIncompletenessWarnings() { switch (incompletenessWarningType()) { case TRUNCATED: return TRUNCATION_NOTICES; case MIGHT_BE_INCOMPLETE: return POSSIBLY_INCOMPLETE_NOTICES; case COMPLETE: break; } return ImmutableList.of(); } /** * Creates a JSON object containing a notice with page navigation links. * *

At the moment, only a next page link is supported. Other types of links (e.g. previous * page) could be added in the future, but it's not clear how to generate such links, given the * way we are querying the database. * *

This isn't part of the spec. */ @JsonableElement("notices[]") Optional getNavigationNotice() { if (navigationLinks().isEmpty()) { return Optional.empty(); } Notice.Builder builder = Notice.builder().setTitle("Navigation Links").setDescription("Links to related pages."); navigationLinks().forEach((name, uri) -> builder.linksBuilder() .add(Link.builder() .setRel(name) .setHref(uri.toString()) .setType("application/rdap+json") .build())); return Optional.of(builder.build()); } BaseSearchResponse(BoilerplateType boilerplateType) { super(boilerplateType); } abstract static class Builder> { abstract ImmutableMap.Builder navigationLinksBuilder(); abstract B setIncompletenessWarningType(IncompletenessWarningType type); @SuppressWarnings("unchecked") B setNextPageUri(URI uri) { navigationLinksBuilder().put("next", uri); return (B) this; } } } @AutoValue abstract static class DomainSearchResponse extends BaseSearchResponse { @JsonableElement abstract ImmutableList domainSearchResults(); DomainSearchResponse() { super(BoilerplateType.DOMAIN); } static Builder builder() { return new AutoValue_RdapSearchResults_DomainSearchResponse.Builder(); } @AutoValue.Builder abstract static class Builder extends BaseSearchResponse.Builder { abstract ImmutableList.Builder domainSearchResultsBuilder(); abstract DomainSearchResponse build(); } } @AutoValue abstract static class EntitySearchResponse extends BaseSearchResponse { @JsonableElement public abstract ImmutableList entitySearchResults(); EntitySearchResponse() { super(BoilerplateType.ENTITY); } static Builder builder() { return new AutoValue_RdapSearchResults_EntitySearchResponse.Builder(); } @AutoValue.Builder abstract static class Builder extends BaseSearchResponse.Builder { abstract ImmutableList.Builder entitySearchResultsBuilder(); abstract EntitySearchResponse build(); } } @AutoValue abstract static class NameserverSearchResponse extends BaseSearchResponse { @JsonableElement public abstract ImmutableList nameserverSearchResults(); NameserverSearchResponse() { super(BoilerplateType.NAMESERVER); } static Builder builder() { return new AutoValue_RdapSearchResults_NameserverSearchResponse.Builder(); } @AutoValue.Builder abstract static class Builder extends BaseSearchResponse.Builder { abstract ImmutableList.Builder nameserverSearchResultsBuilder(); abstract NameserverSearchResponse build(); } } enum IncompletenessWarningType { /** Result set is complete. */ COMPLETE, /** Result set has been limited to the maximum size. */ TRUNCATED, /** * Result set might be missing data because the first step of a two-step query returned a data * set that was limited in size. */ MIGHT_BE_INCOMPLETE } }