You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@iceberg.apache.org by GitBox <gi...@apache.org> on 2022/02/04 00:12:43 UTC

[GitHub] [iceberg] kbendick opened a new pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

kbendick opened a new pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037


   This PR introduces some of the request and response objects from the REST catalog spec, as well as a set of Jackson based serializers & deserializers that can be used to read and write some of the components as JSON.
   
   Opening this PR to get some initial request / responses that are already defined in the spec under review as well as helping provide some serializers for some components using Jackson, which are needed in the Trino project.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r807437847



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/CreateNamespaceRequest.java
##########
@@ -0,0 +1,128 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.exceptions.ValidationException;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.util.ImmutablesUtil;
+
+/**
+ * A REST request to create a namespace, with an optional set of properties.
+ * The server might also add properties, such as `last_modified_time` etc.
+ */
+public class CreateNamespaceRequest {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public CreateNamespaceRequest() {
+    // Needed for Jackson Deserialization.
+  }
+
+  private CreateNamespaceRequest(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+    validate();
+  }
+
+  CreateNamespaceRequest validate() {
+    ValidationException.check(namespace != null && !namespace.isEmpty(),
+        "Cannot build a request to create a namespace without specifying the namespace");
+    return this;
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }

Review comment:
       Minor: This seems like an odd location for a `builder()` factory method. I normally put these just above the builder class.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: [WIP] REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r806466808



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/UpdateNamespacePropertiesRequest.java
##########
@@ -0,0 +1,161 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.exceptions.ValidationException;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
+
+/**
+ * A REST request to set and/or remove properties on a namespace.
+ * <p>
+ * The request body specifies a list of properties to remove and a map
+ * of key value pairs to update.
+ * <p>
+ * Properties that are not in the request are not modified or removed by this call.
+ * Server implementations are not required to support namespace properties.
+ */
+public class UpdateNamespacePropertiesRequest {
+
+  private List<String> removals;
+  private Map<String, String> updates;
+
+  public UpdateNamespacePropertiesRequest() {
+    // Required for Jackson deserialization.
+  }
+
+  private UpdateNamespacePropertiesRequest(List<String> removals, Map<String, String> updates) {
+    this.removals = removals;
+    this.updates = updates;
+    validate();
+  }
+
+  UpdateNamespacePropertiesRequest validate() {
+    ValidationException.check((this.removals != null && !this.removals.isEmpty()) ||
+            (this.updates != null && !this.updates.isEmpty()),
+        "Cannot create a request to update a namespace's properties without specifying any props to update or remove");
+    return this;
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public List<String> removals() {
+    return removals != null ? ImmutableList.copyOf(removals) : Collections.emptyList();
+  }
+
+  public Map<String, String> updates() {
+    return updates != null ? ImmutableMap.copyOf(updates) : Collections.emptyMap();
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+
+    UpdateNamespacePropertiesRequest that = (UpdateNamespacePropertiesRequest) o;
+    return Objects.equals(removals, that.removals) && Objects.equals(updates, that.updates);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(removals, updates);
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("removals", removals)
+        .add("updates", updates)
+        .toString();
+  }
+
+  public static class Builder {
+    private ImmutableSet.Builder<String> removalsBuilder;
+    private ImmutableMap.Builder<String, String> updatesBuilder;
+
+    private Builder() {
+    }
+
+    public Builder remove(String removal) {
+      ensureRemovalsInitialized();
+      removalsBuilder.add(removal);
+      return this;
+    }
+
+    public Builder removeAll(Iterable<String> removals) {
+      ensureRemovalsInitialized();
+      removalsBuilder.addAll(removals);
+      return this;
+    }
+
+    public Builder update(String key, String value) {
+      ensureUpdatesInitialized();
+      updatesBuilder.put(key, value);
+      return this;
+    }
+
+    public Builder updateAll(Map<String, String> updates) {
+      ensureUpdatesInitialized();
+      updatesBuilder.putAll(updates);
+      return this;
+    }
+
+    private void ensureRemovalsInitialized() {
+      if (removalsBuilder == null) {
+        removalsBuilder = ImmutableSet.builder();
+      }
+    }

Review comment:
       Lazily instantiated so that we serialize null vs empty in a way that will match what is parsed with equals. Accessor methods return immutable copies, so null values are tolerated.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r801023328



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/CreateNamespaceRequest.java
##########
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.Joiner;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.Maps;
+
+/**
+ * A REST request to create a namespace, with an optional set of properties.
+ * The server might also add properties, such as `last_modified_time` etc.
+ */
+public class CreateNamespaceRequest {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public CreateNamespaceRequest() {
+    // Required for serialization

Review comment:
       Updated the comment.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r801157688



##########
File path: core/src/main/java/org/apache/iceberg/rest/RESTJacksonModule.java
##########
@@ -0,0 +1,174 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import java.io.IOException;
+import org.apache.iceberg.PartitionSpec;
+import org.apache.iceberg.PartitionSpecParser;
+import org.apache.iceberg.Schema;
+import org.apache.iceberg.SchemaParser;
+import org.apache.iceberg.SortOrder;
+import org.apache.iceberg.SortOrderParser;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.catalog.TableIdentifier;
+
+public class RESTJacksonModule {
+
+  private RESTJacksonModule() {
+  }
+
+  public static void registerAll(ObjectMapper mapper) {
+    SimpleModule module = new SimpleModule();
+    module
+        .addSerializer(TableIdentifier.class, new TableIdentifierSerializer())
+        .addDeserializer(TableIdentifier.class, new TableIdentifierDeserializer())
+        .addSerializer(Namespace.class, new NamespaceSerializer())
+        .addDeserializer(Namespace.class, new NamespaceDeserializer())
+        .addSerializer(Schema.class, new SchemaSerializer())
+        .addDeserializer(Schema.class, new SchemaDeserializer())
+        .addSerializer(PartitionSpec.class, new PartitionSpecSerializer())
+        .addDeserializer(PartitionSpec.class, new PartitionSpecDeserializer())
+        .addSerializer(SortOrder.class, new SortOrderSerializer())
+        .addDeserializer(SortOrder.class, new SortOrderDeserializer());
+    mapper.registerModule(module);
+  }
+
+  public static class NamespaceDeserializer extends JsonDeserializer<Namespace> {
+    @Override
+    public Namespace deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
+      JsonNode jsonNode = p.getCodec().readTree(p);
+      return namespaceFromNode(p, jsonNode);
+    }
+  }
+
+  public static class NamespaceSerializer extends JsonSerializer<Namespace> {
+    @Override
+    public void serialize(Namespace namespace, JsonGenerator gen, SerializerProvider serializers)
+        throws IOException {
+      String[] parts = namespace.levels();
+      gen.writeArray(parts, 0, parts.length);
+    }
+  }
+
+  public static class TableIdentifierDeserializer extends JsonDeserializer<TableIdentifier> {
+    @Override
+    public TableIdentifier deserialize(JsonParser p, DeserializationContext ctxt)
+        throws IOException {
+      JsonNode jsonNode = p.getCodec().readTree(p);
+      if (!jsonNode.isObject()) {
+        throw new JsonParseException(p, "TableIdentifier must be an object: " + jsonNode);
+      }
+      ObjectNode objectNode = (ObjectNode) jsonNode;
+      Namespace namespace = namespaceFromNode(p, objectNode.get("namespace"));
+      String name = objectNode.get("name").asText();
+      return TableIdentifier.of(namespace, name);
+    }
+  }
+
+  private static Namespace namespaceFromNode(JsonParser parser, JsonNode jsonNode) throws IOException {
+    if (!jsonNode.isArray()) {
+      throw new JsonParseException(parser, "Namespace must be an array: " + jsonNode);
+    }
+    ArrayNode arrayNode = (ArrayNode) jsonNode;
+    String[] levels = new String[arrayNode.size()];
+    for (int i = 0; i < levels.length; i++) {
+      levels[i] = arrayNode.get(i).asText();
+    }
+    return Namespace.of(levels);
+  }
+
+  public static class TableIdentifierSerializer extends JsonSerializer<TableIdentifier> {
+    @Override
+    public void serialize(
+        TableIdentifier identifier, JsonGenerator gen, SerializerProvider serializers)
+        throws IOException {
+      gen.writeStartObject();

Review comment:
       Not sure where my original comment went, so repeating it here.
   
   I had originally done it that way, but last minute made a change. I was going to just use `TableIdentifierParser`, because `Namespace` is just an array of strings. However, if Trino needs it then that's a different story.
   
   I'll work on adding the `*Parser` back in for `TableIdentifier` (and possibly for `Namespace` as it sounds like Trino will need it).




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r799764690



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/CreateNamespaceRequest.java
##########
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+
+/**
+ * A REST request to create a namespace, with an optional set of properties.
+ * The server might also add properties, such as `last_modified_time` etc.
+ */
+public class CreateNamespaceRequest {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public CreateNamespaceRequest() {
+    // Required for Jackson deserialization
+  }
+
+  private CreateNamespaceRequest(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public Namespace namespace() {
+    return namespace;
+  }
+
+  public Map<String, String> properties() {
+    return ImmutableMap.copyOf(properties);
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("namespace", namespace)
+        .add("properties", properties)
+        .toString();
+  }
+
+  public static class Builder {
+    private Namespace namespace;
+    private ImmutableMap.Builder<String, String> properties = ImmutableMap.builder();
+
+    private Builder() {
+    }
+
+    public Builder withNamespace(Namespace ns) {
+      this.namespace = ns;
+      return this;
+    }
+
+    public Builder withProperties(Map<String, String> props) {
+      this.properties.putAll(props);
+      return this;
+    }
+
+    public CreateNamespaceRequest build() {
+      Preconditions.checkArgument(
+          namespace != null && !namespace.isEmpty(),
+          "Cannot build a response to create a namespace without specifying the namespace");

Review comment:
       I'll be adding more unit tests for the non-happy paths. I removed some of the tests I had for preconditions (as some were determined to not be needed) and I might have accidentally removed this one. I'll find where I stashed it and add it in if needed (there's also been thought given to removing the `Preconditions` to provide more flexibility to implementors). 👍 




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] jackye1995 commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
jackye1995 commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r800915283



##########
File path: core/src/main/java/org/apache/iceberg/rest/RESTJacksonModule.java
##########
@@ -0,0 +1,174 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import java.io.IOException;
+import org.apache.iceberg.PartitionSpec;
+import org.apache.iceberg.PartitionSpecParser;
+import org.apache.iceberg.Schema;
+import org.apache.iceberg.SchemaParser;
+import org.apache.iceberg.SortOrder;
+import org.apache.iceberg.SortOrderParser;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.catalog.TableIdentifier;
+
+public class RESTJacksonModule {
+
+  private RESTJacksonModule() {
+  }
+
+  public static void registerAll(ObjectMapper mapper) {
+    SimpleModule module = new SimpleModule();
+    module
+        .addSerializer(TableIdentifier.class, new TableIdentifierSerializer())
+        .addDeserializer(TableIdentifier.class, new TableIdentifierDeserializer())
+        .addSerializer(Namespace.class, new NamespaceSerializer())
+        .addDeserializer(Namespace.class, new NamespaceDeserializer())
+        .addSerializer(Schema.class, new SchemaSerializer())
+        .addDeserializer(Schema.class, new SchemaDeserializer())
+        .addSerializer(PartitionSpec.class, new PartitionSpecSerializer())
+        .addDeserializer(PartitionSpec.class, new PartitionSpecDeserializer())
+        .addSerializer(SortOrder.class, new SortOrderSerializer())
+        .addDeserializer(SortOrder.class, new SortOrderDeserializer());
+    mapper.registerModule(module);
+  }
+
+  public static class NamespaceDeserializer extends JsonDeserializer<Namespace> {
+    @Override
+    public Namespace deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
+      JsonNode jsonNode = p.getCodec().readTree(p);
+      return namespaceFromNode(p, jsonNode);
+    }
+  }
+
+  public static class NamespaceSerializer extends JsonSerializer<Namespace> {
+    @Override
+    public void serialize(Namespace namespace, JsonGenerator gen, SerializerProvider serializers)
+        throws IOException {
+      String[] parts = namespace.levels();
+      gen.writeArray(parts, 0, parts.length);
+    }
+  }
+
+  public static class TableIdentifierDeserializer extends JsonDeserializer<TableIdentifier> {
+    @Override
+    public TableIdentifier deserialize(JsonParser p, DeserializationContext ctxt)
+        throws IOException {
+      JsonNode jsonNode = p.getCodec().readTree(p);
+      if (!jsonNode.isObject()) {
+        throw new JsonParseException(p, "TableIdentifier must be an object: " + jsonNode);
+      }
+      ObjectNode objectNode = (ObjectNode) jsonNode;
+      Namespace namespace = namespaceFromNode(p, objectNode.get("namespace"));
+      String name = objectNode.get("name").asText();
+      return TableIdentifier.of(namespace, name);
+    }
+  }
+
+  private static Namespace namespaceFromNode(JsonParser parser, JsonNode jsonNode) throws IOException {
+    if (!jsonNode.isArray()) {
+      throw new JsonParseException(parser, "Namespace must be an array: " + jsonNode);
+    }
+    ArrayNode arrayNode = (ArrayNode) jsonNode;
+    String[] levels = new String[arrayNode.size()];
+    for (int i = 0; i < levels.length; i++) {
+      levels[i] = arrayNode.get(i).asText();
+    }
+    return Namespace.of(levels);
+  }
+
+  public static class TableIdentifierSerializer extends JsonSerializer<TableIdentifier> {
+    @Override
+    public void serialize(
+        TableIdentifier identifier, JsonGenerator gen, SerializerProvider serializers)
+        throws IOException {
+      gen.writeStartObject();

Review comment:
       I wonder if we should keep the consistency here: schema, partition spec and sort order all have their own `Parser` that is Iceberg's bridge for JSON serde. Should we also first have `TableIdentifierParser`, `NamespaceParser` (or maybe just everything in 1 parser class is fine...) and then have these Jackson specific serializers. This would also help Trino/Presto integration because registering a Jackson serializer is not an option.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r809460592



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/UpdateNamespacePropertiesRequest.java
##########
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.List;
+import java.util.Map;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
+
+/**
+ * A REST request to set and/or remove properties on a namespace.
+ * <p>
+ * The request body specifies a list of properties to remove and a map
+ * of key value pairs to update.
+ * <p>
+ * Properties that are not in the request are not modified or removed by this call.
+ * Server implementations are not required to support namespace properties.
+ */
+public class UpdateNamespacePropertiesRequest {
+
+  private List<String> removals;
+  private Map<String, String> updates;
+
+  public UpdateNamespacePropertiesRequest() {
+    // Required for Jackson deserialization.
+  }
+
+  private UpdateNamespacePropertiesRequest(List<String> removals, Map<String, String> updates) {
+    this.removals = removals;
+    this.updates = updates;
+    validate();
+  }
+
+  UpdateNamespacePropertiesRequest validate() {
+    Preconditions.checkArgument((removals != null && !removals.isEmpty()) || (updates != null && !updates.isEmpty()),
+        "Cannot create a request to update a namespace's properties without specifying any props to update or remove");
+    return this;
+  }
+
+  public List<String> removals() {
+    return removals == null ? ImmutableList.of() : removals;
+  }
+
+  public Map<String, String> updates() {
+    return updates == null ? ImmutableMap.of() : updates;
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("removals", removals)
+        .add("updates", updates)
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public static class Builder {
+    private final ImmutableSet.Builder<String> removalsBuilder = ImmutableSet.builder();
+    private final ImmutableMap.Builder<String, String> updatesBuilder = ImmutableMap.builder();
+
+    private Builder() {
+    }
+
+    public Builder remove(String removal) {
+      Preconditions.checkNotNull(removal,
+          "Cannot pass null key to remove to UpdateNamespacePropertiesRequest.Builder");
+      removalsBuilder.add(removal);
+      return this;
+    }
+
+    public Builder removeAll(Iterable<String> removals) {
+      Preconditions.checkNotNull(removals,
+          "Cannot pass null removals to UpdateNamespacePropertiesRequest.Builder");

Review comment:
       How about "Invalid list of properties to remove: null".




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r809458038



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/UpdateNamespacePropertiesRequest.java
##########
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.List;
+import java.util.Map;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
+
+/**
+ * A REST request to set and/or remove properties on a namespace.
+ * <p>
+ * The request body specifies a list of properties to remove and a map
+ * of key value pairs to update.
+ * <p>
+ * Properties that are not in the request are not modified or removed by this call.
+ * Server implementations are not required to support namespace properties.

Review comment:
       This last paragraph is okay, but I would usually not include these here because they aren't relevant to correctly creating the request. The first one is debatable since it covers how to use the request, but the second is a higher level concern. I would omit these because they will be documented elsewhere and having them here means another place we need to locate and update if anything changes.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r809546336



##########
File path: core/src/test/java/org/apache/iceberg/rest/requests/TestUpdateNamespacePropertiesRequest.java
##########
@@ -0,0 +1,162 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import java.util.List;
+import java.util.Map;
+import org.apache.iceberg.AssertHelpers;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.rest.RequestResponseTestBase;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestUpdateNamespacePropertiesRequest extends RequestResponseTestBase<UpdateNamespacePropertiesRequest> {
+
+  /* Values used to fill in request fields */
+  private static final Map<String, String> UPDATES = ImmutableMap.of("owner", "Hank");
+  private static final List<String> REMOVALS = ImmutableList.of("foo", "bar");
+  private static final Map<String, String> EMPTY_UPDATES = ImmutableMap.of();
+  private static final List<String> EMPTY_REMOVALS = ImmutableList.of();
+
+
+  @Test
+  public void testRoundTripSerDe() throws JsonProcessingException {
+    // Full request
+    String fullJson = "{\"removals\":[\"foo\",\"bar\"],\"updates\":{\"owner\":\"Hank\"}}";
+    assertRoundTripSerializesEquallyFrom(
+        fullJson, UpdateNamespacePropertiesRequest.builder().updateAll(UPDATES).removeAll(REMOVALS).build());
+
+    // Only updates
+    String emptyRemoval = "{\"removals\":[],\"updates\":{\"owner\":\"Hank\"}}";
+    assertRoundTripSerializesEquallyFrom(
+        emptyRemoval, UpdateNamespacePropertiesRequest.builder().updateAll(UPDATES).removeAll(EMPTY_REMOVALS).build());
+
+    assertRoundTripSerializesEquallyFrom(
+        emptyRemoval, UpdateNamespacePropertiesRequest.builder().update("owner", "Hank").build());
+
+    // Only removals
+    String emptyUpdates = "{\"removals\":[\"foo\",\"bar\"],\"updates\":{}}";
+    assertRoundTripSerializesEquallyFrom(
+        emptyUpdates, UpdateNamespacePropertiesRequest.builder().removeAll(REMOVALS).updateAll(EMPTY_UPDATES).build());
+
+    assertRoundTripSerializesEquallyFrom(
+        emptyUpdates, UpdateNamespacePropertiesRequest.builder().remove("foo").remove("bar").build());
+  }
+
+  @Test
+  // Test cases that can't be constructed with our Builder class e2e but that will parse correctly
+  public void testCanDeserializeWithoutDefaultValues() throws JsonProcessingException {
+    // `removals` is left empty.
+    UpdateNamespacePropertiesRequest noRemovals = UpdateNamespacePropertiesRequest.builder().updateAll(UPDATES).build();
+    String jsonWithNullRemovals = "{\"removals\":null,\"updates\":{\"owner\":\"Hank\"}}";
+    UpdateNamespacePropertiesRequest parsed = deserialize(jsonWithNullRemovals);
+    assertEquals(parsed, noRemovals);
+
+    // `removals` is missing from the JSON.
+    String jsonWithMissingRemovals = "{\"updates\":{\"owner\":\"Hank\"}}";
+    assertEquals(deserialize(jsonWithMissingRemovals), noRemovals);
+
+    UpdateNamespacePropertiesRequest noUpdates = UpdateNamespacePropertiesRequest.builder().removeAll(REMOVALS).build();
+    String jsonWithNullUpdates = "{\"removals\":[\"foo\",\"bar\"],\"updates\":null}";
+    assertEquals(deserialize(jsonWithNullUpdates), noUpdates);
+  }
+
+  @Test
+  public void testParseInvalidJson() {
+    // Invalid top-level types
+    String jsonInvalidTypeOnRemovalField =
+        "{\"removals\":{\"foo\":\"bar\"},\"updates\":{\"owner\":\"Hank\"}}";
+    AssertHelpers.assertThrows(
+        "A JSON request with an invalid type for one of the fields should fail to parse",
+        JsonProcessingException.class,
+        () -> deserialize(jsonInvalidTypeOnRemovalField).validate()
+    );
+
+    String jsonInvalidTypeOnUpdatesField =
+        "{\"removals\":[\"foo\":\"bar\"],\"updates\":[\"owner\"]}";
+    AssertHelpers.assertThrows(
+        "A JSON value with an invalid type for one of the fields should fail to parse",
+        JsonProcessingException.class,
+        () -> deserialize(jsonInvalidTypeOnUpdatesField).validate()
+    );
+
+    // Valid top-level (array) types, but at least one entry in the list is not the expected type
+    // NOTE: non-string values that are integral types will still parse into a string list.
+    //    e.g. { removals: [ "foo", "bar", 1234 ] } will parse correctly.

Review comment:
       So far I've tested floats and ints (so JSON number types). Maps / arrays in the JSON will throw, but I'm guessing that Jackson is just calling `.asText()` or something on others.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r809541866



##########
File path: core/src/test/java/org/apache/iceberg/rest/requests/TestUpdateNamespacePropertiesRequest.java
##########
@@ -0,0 +1,162 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import java.util.List;
+import java.util.Map;
+import org.apache.iceberg.AssertHelpers;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.rest.RequestResponseTestBase;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestUpdateNamespacePropertiesRequest extends RequestResponseTestBase<UpdateNamespacePropertiesRequest> {
+
+  /* Values used to fill in request fields */
+  private static final Map<String, String> UPDATES = ImmutableMap.of("owner", "Hank");
+  private static final List<String> REMOVALS = ImmutableList.of("foo", "bar");
+  private static final Map<String, String> EMPTY_UPDATES = ImmutableMap.of();
+  private static final List<String> EMPTY_REMOVALS = ImmutableList.of();
+
+
+  @Test
+  public void testRoundTripSerDe() throws JsonProcessingException {
+    // Full request
+    String fullJson = "{\"removals\":[\"foo\",\"bar\"],\"updates\":{\"owner\":\"Hank\"}}";
+    assertRoundTripSerializesEquallyFrom(
+        fullJson, UpdateNamespacePropertiesRequest.builder().updateAll(UPDATES).removeAll(REMOVALS).build());
+
+    // Only updates
+    String emptyRemoval = "{\"removals\":[],\"updates\":{\"owner\":\"Hank\"}}";
+    assertRoundTripSerializesEquallyFrom(
+        emptyRemoval, UpdateNamespacePropertiesRequest.builder().updateAll(UPDATES).removeAll(EMPTY_REMOVALS).build());
+
+    assertRoundTripSerializesEquallyFrom(
+        emptyRemoval, UpdateNamespacePropertiesRequest.builder().update("owner", "Hank").build());
+
+    // Only removals
+    String emptyUpdates = "{\"removals\":[\"foo\",\"bar\"],\"updates\":{}}";
+    assertRoundTripSerializesEquallyFrom(
+        emptyUpdates, UpdateNamespacePropertiesRequest.builder().removeAll(REMOVALS).updateAll(EMPTY_UPDATES).build());
+
+    assertRoundTripSerializesEquallyFrom(
+        emptyUpdates, UpdateNamespacePropertiesRequest.builder().remove("foo").remove("bar").build());
+  }
+
+  @Test
+  // Test cases that can't be constructed with our Builder class e2e but that will parse correctly
+  public void testCanDeserializeWithoutDefaultValues() throws JsonProcessingException {
+    // `removals` is left empty.
+    UpdateNamespacePropertiesRequest noRemovals = UpdateNamespacePropertiesRequest.builder().updateAll(UPDATES).build();
+    String jsonWithNullRemovals = "{\"removals\":null,\"updates\":{\"owner\":\"Hank\"}}";
+    UpdateNamespacePropertiesRequest parsed = deserialize(jsonWithNullRemovals);
+    assertEquals(parsed, noRemovals);
+
+    // `removals` is missing from the JSON.
+    String jsonWithMissingRemovals = "{\"updates\":{\"owner\":\"Hank\"}}";
+    assertEquals(deserialize(jsonWithMissingRemovals), noRemovals);
+
+    UpdateNamespacePropertiesRequest noUpdates = UpdateNamespacePropertiesRequest.builder().removeAll(REMOVALS).build();
+    String jsonWithNullUpdates = "{\"removals\":[\"foo\",\"bar\"],\"updates\":null}";
+    assertEquals(deserialize(jsonWithNullUpdates), noUpdates);

Review comment:
       Added an test case for that.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r808552274



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/CreateNamespaceRequest.java
##########
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.exceptions.ValidationException;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+
+/**
+ * A REST request to create a namespace, with an optional set of properties.
+ * The server might also add properties, such as `last_modified_time` etc.
+ */
+public class CreateNamespaceRequest {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public CreateNamespaceRequest() {
+    // Needed for Jackson Deserialization.
+  }
+
+  private CreateNamespaceRequest(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+    validate();
+  }
+
+  /**
+   * This function needs to be called after reading in JSON from another source, to ensure
+   * that null values are assigned to their respective defaults where needed, wrap collections
+   * in their Immutable variants, and that required fields are correct.
+   * @return normalized version of this {@link CreateNamespaceRequest}
+   */
+  CreateNamespaceRequest validate() {
+    this.properties = properties == null ? ImmutableMap.of() : ImmutableMap.copyOf(properties);
+    ValidationException.check(namespace != null && !namespace.isEmpty(),
+        "Cannot build a request to create a namespace without specifying the namespace");
+    return this;
+  }
+
+  public Namespace namespace() {
+    return namespace;
+  }
+
+  public Map<String, String> properties() {
+    return properties;

Review comment:
       Updated.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r809547621



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/UpdateNamespacePropertiesResponse.java
##########
@@ -0,0 +1,174 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.List;
+import java.util.Objects;
+import org.apache.iceberg.exceptions.ValidationException;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
+import org.apache.iceberg.util.ImmutablesUtil;
+
+/**
+ * A REST response to a request to set and/or remove properties on a namespace.
+ */
+public class UpdateNamespacePropertiesResponse {
+
+  // List of namespace property keys that were removed
+  private List<String> removed;
+  // List of namespace property keys that were added or updated
+  private List<String> updated;
+  // List of properties that were requested for removal that were not found in the namespace's properties
+  private List<String> missing;
+
+  public UpdateNamespacePropertiesResponse() {
+    // Required for Jackson deserialization
+  }
+
+  private UpdateNamespacePropertiesResponse(List<String> removed, List<String> updated, List<String> missing) {
+    this.removed = removed;
+    this.updated = updated;
+    this.missing = missing;
+    validate();
+  }
+
+  UpdateNamespacePropertiesResponse validate() {
+    ValidationException.check((removed != null && !this.removed.isEmpty()) ||
+        (updated != null && !updated.isEmpty()) || (missing != null && !missing.isEmpty()),
+        "Cannot create a response to update namespace properties if all of the fields are missing or empty");

Review comment:
       I would think we'd return an `ErrorResponse` in that situation though, no?
   
   That might be something we need to add an error case in the spec for.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810394110



##########
File path: core/src/test/java/org/apache/iceberg/rest/responses/TestDropNamespaceResponse.java
##########
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import org.apache.iceberg.AssertHelpers;
+import org.apache.iceberg.rest.RequestResponseTestBase;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestDropNamespaceResponse extends RequestResponseTestBase<DropNamespaceResponse> {
+
+  @Test
+  public void testRoundTripSerDe() throws JsonProcessingException {
+    assertRoundTripSerializesEquallyFrom(
+        "{\"dropped\":true}", DropNamespaceResponse.builder().dropped(true).build());
+
+    assertRoundTripSerializesEquallyFrom(
+        "{\"dropped\":false}", DropNamespaceResponse.builder().dropped(false).build());
+  }
+
+  @Test
+  public void testFailParsingWhenNullOrEmptyJson() {
+    String nullJson = null;
+    AssertHelpers.assertThrows("DropNamespaceResponse should fail to deserialize from a null JSON string",
+        IllegalArgumentException.class,
+        () ->  deserialize(nullJson));

Review comment:
       Similarly, empty string `""` throws an exception from Jackson of `"No content to map due to end-of-input"`. I can add it in so it's clear it came from Jackson if we'd like.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810547497



##########
File path: core/src/test/java/org/apache/iceberg/catalog/TestTableIdentifierParser.java
##########
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.catalog;
+
+import org.apache.iceberg.AssertHelpers;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestTableIdentifierParser {
+
+  @Test
+  public void testTableIdentifierToJson() {
+    String json = "{\"namespace\":[\"accounting\",\"tax\"],\"name\":\"paid\"}";
+    TableIdentifier identifier = TableIdentifier.of(Namespace.of("accounting", "tax"), "paid");
+    Assert.assertEquals("Should be able to serialize a table identifier with both namespace and name",
+        json, TableIdentifierParser.toJson(identifier));
+
+    TableIdentifier identifierWithEmptyNamespace = TableIdentifier.of(Namespace.empty(), "paid");
+    String jsonWithEmptyNamespace = "{\"namespace\":[],\"name\":\"paid\"}";
+    Assert.assertEquals("Should be able to serialize a table identifier that uses the empty namespace",
+        jsonWithEmptyNamespace, TableIdentifierParser.toJson(identifierWithEmptyNamespace));
+  }
+
+  @Test
+  public void testTableIdentifierFromJson() {
+    String json = "{\"namespace\":[\"accounting\",\"tax\"],\"name\":\"paid\"}";
+    TableIdentifier identifier = TableIdentifier.of(Namespace.of("accounting", "tax"), "paid");
+    Assert.assertEquals("Should be able to deserialize a valid table identifier",
+        identifier, TableIdentifierParser.fromJson(json));
+
+    TableIdentifier identifierWithEmptyNamespace = TableIdentifier.of(Namespace.empty(), "paid");
+    String jsonWithEmptyNamespace = "{\"namespace\":[],\"name\":\"paid\"}";
+    Assert.assertEquals("Should be able to deserialize a valid multi-level table identifier",
+        identifierWithEmptyNamespace, TableIdentifierParser.fromJson(jsonWithEmptyNamespace));
+  }
+
+  @Test
+  public void testFailParsingWhenNullOrEmptyJson() {
+    String nullJson = null;
+    AssertHelpers.assertThrows("TableIdentifierParser should fail to deserialize null JSON string",
+        IllegalArgumentException.class, "Cannot parse table identifier from invalid JSON: null",
+        () ->  TableIdentifierParser.fromJson(nullJson));
+
+    String emptyString = "";
+    AssertHelpers.assertThrows("TableIdentifierParser should fail to deserialize an empty string",
+        IllegalArgumentException.class, "Cannot parse table identifier from invalid JSON: ''",
+        () ->  TableIdentifierParser.fromJson(emptyString));
+
+    String emptyJson = "{}";
+    AssertHelpers.assertThrows("TableIdentifierParser should fail to deserialize an empty JSON string",
+        IllegalArgumentException.class, "Cannot parse missing list namespace",
+        () ->  TableIdentifierParser.fromJson(emptyJson));
+
+    String emptyJsonArray = "[]";
+    AssertHelpers.assertThrows("TableIdentifierParser should fail to deserialize an empty JSON array",
+        IllegalArgumentException.class, "Cannot parse missing or non-object table identifier: []",
+        () ->  TableIdentifierParser.fromJson(emptyJsonArray));
+  }
+
+  @Test
+  public void testFailParsingWhenMissingRequiredFields() {
+    String identifierMissingName = "{\"namespace\":[\"accounting\",\"tax\"]}";
+    AssertHelpers.assertThrows("TableIdentifierParser should fail to deserialize table with missing name",
+        IllegalArgumentException.class, "Cannot parse missing string name",
+        () ->  TableIdentifierParser.fromJson(identifierMissingName));
+
+    String identifierMissingNamespace = "{\"name\":\"paid\"}";
+    AssertHelpers.assertThrows("TableIdentifierParser should fail to deserialize table with missing namespace",
+        IllegalArgumentException.class, "Cannot parse missing list namespace",

Review comment:
       Should this be supported and create an empty namespace?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r811439128



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/UpdateNamespacePropertiesResponse.java
##########
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Collection;
+import java.util.List;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
+
+/**
+ * A REST response to a request to set and/or remove properties on a namespace.
+ */
+public class UpdateNamespacePropertiesResponse {
+
+  // List of namespace property keys that were removed
+  private List<String> removed;
+  // List of namespace property keys that were added or updated
+  private List<String> updated;
+  // List of properties that were requested for removal that were not found in the namespace's properties
+  private List<String> missing;
+
+  public UpdateNamespacePropertiesResponse() {
+    // Required for Jackson deserialization
+  }
+
+  private UpdateNamespacePropertiesResponse(List<String> removed, List<String> updated, List<String> missing) {
+    this.removed = removed;
+    this.updated = updated;
+    this.missing = missing;
+    validate();
+  }
+
+  UpdateNamespacePropertiesResponse validate() {
+    Preconditions.checkArgument(removed != null || updated != null  || missing != null,
+        "Cannot create a response to update namespace properties if all fields are missing");
+    return this;
+  }
+
+  public List<String> removed() {
+    return removed != null ? removed : ImmutableList.of();
+  }
+
+  public List<String> updated() {
+    return updated != null ? updated : ImmutableList.of();
+  }
+
+  public List<String> missing() {
+    return missing != null ? missing : ImmutableList.of();
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("removed", removed)
+        .add("updates", updated)
+        .add("missing", missing)
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public static class Builder {
+    private final ImmutableSet.Builder<String> removedBuilder = ImmutableSet.builder();
+    private final ImmutableSet.Builder<String> updatedBuilder = ImmutableSet.builder();
+    private final ImmutableSet.Builder<String> missingBuilder = ImmutableSet.builder();
+
+    private Builder() {
+    }
+
+    public Builder addMissing(String key) {
+      Preconditions.checkNotNull(key, "Invalid property to add to missing properties: null");

Review comment:
       Fixed!

##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/UpdateNamespacePropertiesResponse.java
##########
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Collection;
+import java.util.List;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
+
+/**
+ * A REST response to a request to set and/or remove properties on a namespace.
+ */
+public class UpdateNamespacePropertiesResponse {
+
+  // List of namespace property keys that were removed
+  private List<String> removed;
+  // List of namespace property keys that were added or updated
+  private List<String> updated;
+  // List of properties that were requested for removal that were not found in the namespace's properties
+  private List<String> missing;
+
+  public UpdateNamespacePropertiesResponse() {
+    // Required for Jackson deserialization
+  }
+
+  private UpdateNamespacePropertiesResponse(List<String> removed, List<String> updated, List<String> missing) {
+    this.removed = removed;
+    this.updated = updated;
+    this.missing = missing;
+    validate();
+  }
+
+  UpdateNamespacePropertiesResponse validate() {
+    Preconditions.checkArgument(removed != null || updated != null  || missing != null,
+        "Cannot create a response to update namespace properties if all fields are missing");

Review comment:
       Agreed and fixed.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r811458880



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/GetNamespaceResponse.java
##########
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.Maps;
+
+/**
+ * Represents a REST response to fetch a namespace and its metadata properties
+ */
+public class GetNamespaceResponse {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public GetNamespaceResponse() {
+    // Required for Jackson deserialization
+  }
+
+  private GetNamespaceResponse(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+    validate();
+  }
+
+  GetNamespaceResponse validate() {
+    Preconditions.checkArgument(namespace != null,
+        "Cannot build a response to get a null namespace");
+    return this;
+  }
+
+  public Namespace namespace() {
+    return namespace;
+  }
+
+  public Map<String, String> properties() {
+    return properties != null ? properties : ImmutableMap.of();
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("namespace", namespace)
+        .add("properties", properties)
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  static class Builder {
+    private Namespace namespace;
+    private final ImmutableMap.Builder<String, String> properties =  ImmutableMap.builder();
+
+    private Builder() {
+    }
+
+    public Builder withNamespace(Namespace ns) {
+      Preconditions.checkNotNull(ns, "Invalid namespace to have requested: null");

Review comment:
       Omitted




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r811459335



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/ListNamespacesResponse.java
##########
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Collection;
+import java.util.List;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+
+public class ListNamespacesResponse {
+
+  private List<Namespace> namespaces;
+
+  public ListNamespacesResponse() {
+    // Required for Jackson deserialization
+  }
+
+  private ListNamespacesResponse(List<Namespace> namespaces) {
+    this.namespaces = namespaces;
+    validate();
+  }
+
+  ListNamespacesResponse validate() {
+    Preconditions.checkArgument(namespaces != null,
+        "Cannot create a response to a list namespaces request without a non-null list of namespaces");
+    return this;
+  }
+
+
+  public List<Namespace> namespaces() {
+    return namespaces != null ? namespaces : ImmutableList.of();
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("namespaces", namespaces())
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  static class Builder {
+    private final ImmutableList.Builder<Namespace> namespaces = ImmutableList.builder();
+
+    private Builder() {
+    }
+
+    public Builder add(Namespace toAdd) {
+      Preconditions.checkNotNull(toAdd,
+          "Invalid namespace to list: null");

Review comment:
       Updated




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r811458647



##########
File path: core/src/main/java/org/apache/iceberg/util/JsonUtil.java
##########
@@ -117,6 +127,31 @@ public static String getStringOrNull(String property, JsonNode node) {
     return builder.build();
   }
 
+  public static Map<String, String> getStringMapOrNull(String property, JsonNode node) {
+    if (!node.has(property)) {
+      return null;
+    }
+
+    JsonNode pNode = node.get(property);
+    if (pNode == null || pNode.isNull()) {
+      return null;
+    }
+
+    Preconditions.checkArgument(pNode.isObject(),
+        "Cannot parse %s from non-object value: %s", property, pNode);
+    return buildStringMapFromJsonNodeObject(pNode);
+  }
+
+  private static Map<String, String> buildStringMapFromJsonNodeObject(JsonNode pNode) {
+    ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
+    Iterator<String> fields = pNode.fieldNames();
+    while (fields.hasNext()) {
+      String field = fields.next();
+      builder.put(field, getString(field, pNode));
+    }
+    return builder.build();

Review comment:
       Removed this function as `getStringMapOrNull` wound up not being needed.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810398919



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/UpdateNamespacePropertiesRequest.java
##########
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.List;
+import java.util.Map;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
+
+/**
+ * A REST request to set and/or remove properties on a namespace.
+ * <p>
+ * The request body specifies a list of properties to remove and a map
+ * of key value pairs to update.
+ * <p>
+ * Properties that are not in the request are not modified or removed by this call.
+ * Server implementations are not required to support namespace properties.
+ */
+public class UpdateNamespacePropertiesRequest {
+
+  private List<String> removals;
+  private Map<String, String> updates;
+
+  public UpdateNamespacePropertiesRequest() {
+    // Required for Jackson deserialization.
+  }
+
+  private UpdateNamespacePropertiesRequest(List<String> removals, Map<String, String> updates) {
+    this.removals = removals;
+    this.updates = updates;
+    validate();
+  }
+
+  UpdateNamespacePropertiesRequest validate() {
+    Preconditions.checkArgument((removals != null && !removals.isEmpty()) || (updates != null && !updates.isEmpty()),

Review comment:
       Updated to just check that at least one is non-null.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810396893



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/DropNamespaceResponse.java
##########
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Objects;
+import org.apache.iceberg.exceptions.ValidationException;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+
+/**
+ * Represents a REST response to drop a namespace.
+ * <p>
+ * The server may choose to return an error if the namespace is not empty.
+ */
+public class DropNamespaceResponse {
+
+  // For Jackson to properly fail when deserializing, this needs to be boxed.
+  // Otherwise, the boolean is parsed according to "loose" javascript JSON rules.
+  private Boolean dropped;
+
+  public DropNamespaceResponse() {
+    // Required for Jackson deserialization
+  }
+
+  private DropNamespaceResponse(Boolean dropped) {

Review comment:
       Oh and I can update the constructor to use unboxed values up until the class field, which needs to be boxed due to deserialization.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810547041



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/ListTablesResponse.java
##########
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Collection;
+import java.util.List;
+import org.apache.iceberg.catalog.TableIdentifier;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+
+/**
+ * A list of table identifiers in a given namespace.
+ */
+public class ListTablesResponse {
+
+  private List<TableIdentifier> identifiers;
+
+  public ListTablesResponse() {
+    // Required for Jackson deserialization
+  }
+
+  private ListTablesResponse(List<TableIdentifier> identifiers) {
+    this.identifiers = identifiers;
+    validate();
+  }
+
+  ListTablesResponse validate() {
+    Preconditions.checkArgument(identifiers != null,
+        "Cannot build a response to list tables without a non-null list of table identifiers");
+    return this;
+  }
+
+  public List<TableIdentifier> identifiers() {
+    return identifiers != null ? identifiers : ImmutableList.of();
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("identifiers", identifiers)
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  static class Builder {
+    private final ImmutableList.Builder<TableIdentifier> identifiers = ImmutableList.builder();
+
+    private Builder() {
+    }
+
+    public Builder add(TableIdentifier toAdd) {
+      Preconditions.checkNotNull(toAdd, "Invalid table to list: null");

Review comment:
       This isn't a table being listed, right? I think it should be `Invalid table identifier: null`

##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/ListTablesResponse.java
##########
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Collection;
+import java.util.List;
+import org.apache.iceberg.catalog.TableIdentifier;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+
+/**
+ * A list of table identifiers in a given namespace.
+ */
+public class ListTablesResponse {
+
+  private List<TableIdentifier> identifiers;
+
+  public ListTablesResponse() {
+    // Required for Jackson deserialization
+  }
+
+  private ListTablesResponse(List<TableIdentifier> identifiers) {
+    this.identifiers = identifiers;
+    validate();
+  }
+
+  ListTablesResponse validate() {
+    Preconditions.checkArgument(identifiers != null,
+        "Cannot build a response to list tables without a non-null list of table identifiers");
+    return this;
+  }
+
+  public List<TableIdentifier> identifiers() {
+    return identifiers != null ? identifiers : ImmutableList.of();
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("identifiers", identifiers)
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  static class Builder {
+    private final ImmutableList.Builder<TableIdentifier> identifiers = ImmutableList.builder();
+
+    private Builder() {
+    }
+
+    public Builder add(TableIdentifier toAdd) {
+      Preconditions.checkNotNull(toAdd, "Invalid table to list: null");
+      identifiers.add(toAdd);
+      return this;
+    }
+
+    public Builder addAll(Collection<TableIdentifier> toAdd) {
+      Preconditions.checkNotNull(toAdd, "Invalid collection of tables to list: null");
+      Preconditions.checkArgument(!toAdd.contains(null),
+          "Invalid table in collection of tables to list: null");

Review comment:
       Invalid table identifier: null




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810547136



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/UpdateNamespacePropertiesResponse.java
##########
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Collection;
+import java.util.List;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
+
+/**
+ * A REST response to a request to set and/or remove properties on a namespace.
+ */
+public class UpdateNamespacePropertiesResponse {
+
+  // List of namespace property keys that were removed
+  private List<String> removed;
+  // List of namespace property keys that were added or updated
+  private List<String> updated;
+  // List of properties that were requested for removal that were not found in the namespace's properties
+  private List<String> missing;
+
+  public UpdateNamespacePropertiesResponse() {
+    // Required for Jackson deserialization
+  }
+
+  private UpdateNamespacePropertiesResponse(List<String> removed, List<String> updated, List<String> missing) {
+    this.removed = removed;
+    this.updated = updated;
+    this.missing = missing;
+    validate();
+  }
+
+  UpdateNamespacePropertiesResponse validate() {
+    Preconditions.checkArgument(removed != null || updated != null  || missing != null,
+        "Cannot create a response to update namespace properties if all fields are missing");

Review comment:
       I think this check isn't needed either. If we are going to allow any of them to be omitted or null, then we should just allow them all to be. Especially because this is a response object and an empty request may result in an empty response.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810546811



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/DropNamespaceResponse.java
##########
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+
+/**
+ * Represents a REST response to drop a namespace.
+ * <p>
+ * The server may choose to return an error if the namespace is not empty.
+ */
+public class DropNamespaceResponse {
+
+  // For Jackson to properly fail when deserializing, this needs to be boxed.
+  // Otherwise, the boolean is parsed according to "loose" javascript JSON rules.
+  private Boolean dropped;
+
+  public DropNamespaceResponse() {
+    // Required for Jackson deserialization
+  }
+
+  private DropNamespaceResponse(boolean dropped) {
+    this.dropped = dropped;
+    validate();
+  }
+
+  DropNamespaceResponse validate() {
+    Preconditions.checkArgument(dropped != null,
+        "Cannot instantiate a response to dropping a namespace with missing field: dropped");

Review comment:
       Cannot instantiate? This is already instantiated. I think this should be `"Invalid response, missing field: dropped"`
   
   This is the kind of context that I think gets in the way. My guess is that this was an error message that hasn't been updated after some refactoring. It's easy to have that happen, which is why it's a good idea to omit context that isn't needed.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r799076875



##########
File path: core/src/main/java/org/apache/iceberg/rest/RESTJacksonModule.java
##########
@@ -0,0 +1,183 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import java.io.IOException;
+import org.apache.iceberg.PartitionSpec;
+import org.apache.iceberg.PartitionSpecParser;
+import org.apache.iceberg.Schema;
+import org.apache.iceberg.SchemaParser;
+import org.apache.iceberg.SortOrder;
+import org.apache.iceberg.SortOrderParser;
+import org.apache.iceberg.TableMetadata;
+import org.apache.iceberg.TableMetadataParser;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.catalog.TableIdentifier;
+
+public class RESTJacksonModule {
+
+  private RESTJacksonModule() {
+  }
+
+  public static void registerAll(ObjectMapper mapper) {
+    SimpleModule module = new SimpleModule();
+    module
+        .addSerializer(TableIdentifier.class, new TableIdentifierSerializer())
+        .addDeserializer(TableIdentifier.class, new TableIdentifierDeserializer())
+        .addSerializer(Namespace.class, new NamespaceSerializer())
+        .addDeserializer(Namespace.class, new NamespaceDeserializer())
+        .addSerializer(Schema.class, new SchemaSerializer())
+        .addDeserializer(Schema.class, new SchemaDeserializer())
+        .addSerializer(PartitionSpec.class, new PartitionSpecSerializer())
+        .addDeserializer(PartitionSpec.class, new PartitionSpecDeserializer())
+        .addSerializer(SortOrder.class, new SortOrderSerializer())
+        .addDeserializer(SortOrder.class, new SortOrderDeserializer());
+    mapper.registerModule(module);
+
+    mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE);
+    mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);

Review comment:
       Can you help me understand what these configurations are doing?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r799086663



##########
File path: core/src/test/java/org/apache/iceberg/rest/requests/TestCreateNamespaceRequest.java
##########
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.util.JsonUtil;
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+
+public class TestCreateNamespaceRequest {
+
+  private static final ObjectMapper MAPPER = JsonUtil.withRESTComponents();
+
+  // Non-empty
+  private static final String JSON_REQUEST_STRING =
+      "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{\"owner\":\"Hank\"}}";
+  private static final Namespace NAMESPACE = Namespace.of("accounting", "tax");
+  private static final Map<String, String> PROPERTIES = ImmutableMap.of("owner", "Hank");
+
+  // Empty - The response requires a non-empty namespace
+  private static final String JSON_REQUEST_NO_PROPERTIES =
+      "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{}}";
+
+  @Test
+  public void testDeserialize() throws JsonProcessingException {
+    CreateNamespaceRequest expected = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .withProperties(PROPERTIES)
+        .build();
+
+    CreateNamespaceRequest actual = MAPPER.readValue(JSON_REQUEST_STRING, CreateNamespaceRequest.class);
+
+    assertSame(expected, actual);
+  }
+
+  @Test
+  public void testDeserializeNoProperties() throws JsonProcessingException {
+    CreateNamespaceRequest expected = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .build();
+
+    CreateNamespaceRequest actual = MAPPER.readValue(JSON_REQUEST_NO_PROPERTIES, CreateNamespaceRequest.class);
+
+    assertSame(expected, actual);
+  }
+
+  @Test
+  public void testSerialize() throws JsonProcessingException {
+    CreateNamespaceRequest req = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .withProperties(PROPERTIES)
+        .build();
+
+    Assertions.assertThat(MAPPER.writeValueAsString(req))
+        .isEqualTo(JSON_REQUEST_STRING);
+  }
+
+  @Test
+  public void testSerializeNoProperties() throws JsonProcessingException {
+    CreateNamespaceRequest req = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .build();
+
+    Assertions.assertThat(MAPPER.writeValueAsString(req))
+        .isEqualTo(JSON_REQUEST_NO_PROPERTIES);
+  }
+
+  private static void assertSame(CreateNamespaceRequest expected, CreateNamespaceRequest actual) {

Review comment:
       I think this should be `assertEquals` rather than `assertSame`. `Assert.assertSame` in the JUnit API tests object identity, not equality and I think we should use the same definition.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r809487122



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/UpdateNamespacePropertiesRequest.java
##########
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.List;
+import java.util.Map;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
+
+/**
+ * A REST request to set and/or remove properties on a namespace.
+ * <p>
+ * The request body specifies a list of properties to remove and a map
+ * of key value pairs to update.
+ * <p>
+ * Properties that are not in the request are not modified or removed by this call.
+ * Server implementations are not required to support namespace properties.

Review comment:
       I did pull this from the OpenAPI doc, so it is indeed in two places. Will remove.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r809462186



##########
File path: core/src/test/java/org/apache/iceberg/rest/requests/TestUpdateNamespacePropertiesRequest.java
##########
@@ -0,0 +1,162 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import java.util.List;
+import java.util.Map;
+import org.apache.iceberg.AssertHelpers;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.rest.RequestResponseTestBase;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestUpdateNamespacePropertiesRequest extends RequestResponseTestBase<UpdateNamespacePropertiesRequest> {
+
+  /* Values used to fill in request fields */
+  private static final Map<String, String> UPDATES = ImmutableMap.of("owner", "Hank");
+  private static final List<String> REMOVALS = ImmutableList.of("foo", "bar");
+  private static final Map<String, String> EMPTY_UPDATES = ImmutableMap.of();
+  private static final List<String> EMPTY_REMOVALS = ImmutableList.of();
+
+
+  @Test
+  public void testRoundTripSerDe() throws JsonProcessingException {
+    // Full request
+    String fullJson = "{\"removals\":[\"foo\",\"bar\"],\"updates\":{\"owner\":\"Hank\"}}";
+    assertRoundTripSerializesEquallyFrom(
+        fullJson, UpdateNamespacePropertiesRequest.builder().updateAll(UPDATES).removeAll(REMOVALS).build());
+
+    // Only updates
+    String emptyRemoval = "{\"removals\":[],\"updates\":{\"owner\":\"Hank\"}}";
+    assertRoundTripSerializesEquallyFrom(
+        emptyRemoval, UpdateNamespacePropertiesRequest.builder().updateAll(UPDATES).removeAll(EMPTY_REMOVALS).build());
+
+    assertRoundTripSerializesEquallyFrom(
+        emptyRemoval, UpdateNamespacePropertiesRequest.builder().update("owner", "Hank").build());
+
+    // Only removals
+    String emptyUpdates = "{\"removals\":[\"foo\",\"bar\"],\"updates\":{}}";
+    assertRoundTripSerializesEquallyFrom(
+        emptyUpdates, UpdateNamespacePropertiesRequest.builder().removeAll(REMOVALS).updateAll(EMPTY_UPDATES).build());
+
+    assertRoundTripSerializesEquallyFrom(
+        emptyUpdates, UpdateNamespacePropertiesRequest.builder().remove("foo").remove("bar").build());
+  }
+
+  @Test
+  // Test cases that can't be constructed with our Builder class e2e but that will parse correctly
+  public void testCanDeserializeWithoutDefaultValues() throws JsonProcessingException {
+    // `removals` is left empty.
+    UpdateNamespacePropertiesRequest noRemovals = UpdateNamespacePropertiesRequest.builder().updateAll(UPDATES).build();
+    String jsonWithNullRemovals = "{\"removals\":null,\"updates\":{\"owner\":\"Hank\"}}";
+    UpdateNamespacePropertiesRequest parsed = deserialize(jsonWithNullRemovals);
+    assertEquals(parsed, noRemovals);
+
+    // `removals` is missing from the JSON.
+    String jsonWithMissingRemovals = "{\"updates\":{\"owner\":\"Hank\"}}";
+    assertEquals(deserialize(jsonWithMissingRemovals), noRemovals);
+
+    UpdateNamespacePropertiesRequest noUpdates = UpdateNamespacePropertiesRequest.builder().removeAll(REMOVALS).build();
+    String jsonWithNullUpdates = "{\"removals\":[\"foo\",\"bar\"],\"updates\":null}";
+    assertEquals(deserialize(jsonWithNullUpdates), noUpdates);

Review comment:
       What about `updates` is missing?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r809456341



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/GetNamespaceResponse.java
##########
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.exceptions.ValidationException;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.util.ImmutablesUtil;
+
+/**
+ * Represents a REST response to fetch namespace metadata.
+ * <p>
+ * The properties returned should include all the user provided properties from the
+ * request, as well as any server-side added properties.
+ */
+public class GetNamespaceResponse {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public GetNamespaceResponse() {
+    // Required for Jackson deserialization
+  }
+
+  private GetNamespaceResponse(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+    validate();
+  }
+
+  GetNamespaceResponse validate() {
+    ValidationException.check(namespace != null && !namespace.isEmpty(),
+        "Cannot build a response to get a namespace without specifying the namespace");
+    return this;
+  }
+
+  public Namespace namespace() {
+    return namespace;
+  }
+
+  public Map<String, String> properties() {
+    return ImmutablesUtil.nullSafeCopyOf(properties);
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  @Override
+  public boolean equals(Object o) {

Review comment:
       Ah, I thought you said that this was updated, but it looks like it hasn't been so I'll stop leaving comments on it.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810395067



##########
File path: core/src/test/java/org/apache/iceberg/rest/responses/TestDropNamespaceResponse.java
##########
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import org.apache.iceberg.AssertHelpers;
+import org.apache.iceberg.rest.RequestResponseTestBase;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestDropNamespaceResponse extends RequestResponseTestBase<DropNamespaceResponse> {
+
+  @Test
+  public void testRoundTripSerDe() throws JsonProcessingException {
+    assertRoundTripSerializesEquallyFrom(
+        "{\"dropped\":true}", DropNamespaceResponse.builder().dropped(true).build());
+
+    assertRoundTripSerializesEquallyFrom(
+        "{\"dropped\":false}", DropNamespaceResponse.builder().dropped(false).build());
+  }
+
+  @Test
+  public void testFailParsingWhenNullOrEmptyJson() {
+    String nullJson = null;
+    AssertHelpers.assertThrows("DropNamespaceResponse should fail to deserialize from a null JSON string",
+        IllegalArgumentException.class,
+        () ->  deserialize(nullJson));
+
+    String emptyString = "";
+    AssertHelpers.assertThrows("DropNamespaceResponse should fail to deserialize empty string as JSON",
+        JsonProcessingException.class,
+        () ->  deserialize(emptyString));
+
+    String emptyJson = "{}";
+    AssertHelpers.assertThrows(
+        "DropNamespaceResponse should fail to deserialize and validate if missing the field `dropped`",
+        IllegalArgumentException.class,
+        "Cannot instantiate a response to dropping a namespace with missing field(s): `dropped`",
+        () -> deserialize(emptyJson));
+  }
+
+  @Test
+  public void testFailWhenFieldsHaveInvalidValues() {
+    String invalidJsonWithStringType = "{\"dropped\":\"421\"}";

Review comment:
       Added a test with null. It throws upon calling `validate`.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810398509



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/GetNamespaceResponse.java
##########
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.exceptions.ValidationException;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.util.ImmutablesUtil;
+
+/**
+ * Represents a REST response to fetch namespace metadata.
+ * <p>
+ * The properties returned should include all the user provided properties from the
+ * request, as well as any server-side added properties.
+ */
+public class GetNamespaceResponse {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public GetNamespaceResponse() {
+    // Required for Jackson deserialization
+  }
+
+  private GetNamespaceResponse(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+    validate();
+  }
+
+  GetNamespaceResponse validate() {
+    ValidationException.check(namespace != null && !namespace.isEmpty(),
+        "Cannot build a response to get a namespace without specifying the namespace");
+    return this;
+  }
+
+  public Namespace namespace() {
+    return namespace;
+  }
+
+  public Map<String, String> properties() {
+    return ImmutablesUtil.nullSafeCopyOf(properties);

Review comment:
       Not anymore!




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r811411736



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/UpdateNamespacePropertiesRequest.java
##########
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
+import org.apache.iceberg.relocated.com.google.common.collect.Maps;
+
+/**
+ * A REST request to set and/or remove properties on a namespace.
+ */
+public class UpdateNamespacePropertiesRequest {
+
+  private List<String> removals;
+  private Map<String, String> updates;
+
+  public UpdateNamespacePropertiesRequest() {
+    // Required for Jackson deserialization.
+  }
+
+  private UpdateNamespacePropertiesRequest(List<String> removals, Map<String, String> updates) {
+    this.removals = removals;
+    this.updates = updates;
+    validate();
+  }
+
+  UpdateNamespacePropertiesRequest validate() {
+    Preconditions.checkArgument(removals != null || updates != null,
+        "Invalid value for update namespace properties request: at least one of updates and removals must be non-null");
+    return this;
+  }
+
+  public List<String> removals() {
+    return removals == null ? ImmutableList.of() : removals;
+  }
+
+  public Map<String, String> updates() {
+    return updates == null ? ImmutableMap.of() : updates;
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("removals", removals)
+        .add("updates", updates)
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public static class Builder {
+    private final ImmutableSet.Builder<String> removalsBuilder = ImmutableSet.builder();
+    private final ImmutableMap.Builder<String, String> updatesBuilder = ImmutableMap.builder();
+
+    private Builder() {
+    }
+
+    public Builder remove(String removal) {
+      Preconditions.checkNotNull(removal,
+          "Invalid property to remove: null");
+      removalsBuilder.add(removal);
+      return this;
+    }
+
+    public Builder removeAll(Collection<String> removals) {
+      Preconditions.checkNotNull(removals,
+          "Invalid list of properties to remove: null");
+      Preconditions.checkArgument(!removals.contains(null),
+          "Invalid value in list of properties to remove: null");

Review comment:
       Updated.

##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/UpdateNamespacePropertiesRequest.java
##########
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
+import org.apache.iceberg.relocated.com.google.common.collect.Maps;
+
+/**
+ * A REST request to set and/or remove properties on a namespace.
+ */
+public class UpdateNamespacePropertiesRequest {
+
+  private List<String> removals;
+  private Map<String, String> updates;
+
+  public UpdateNamespacePropertiesRequest() {
+    // Required for Jackson deserialization.
+  }
+
+  private UpdateNamespacePropertiesRequest(List<String> removals, Map<String, String> updates) {
+    this.removals = removals;
+    this.updates = updates;
+    validate();
+  }
+
+  UpdateNamespacePropertiesRequest validate() {
+    Preconditions.checkArgument(removals != null || updates != null,
+        "Invalid value for update namespace properties request: at least one of updates and removals must be non-null");
+    return this;
+  }
+
+  public List<String> removals() {
+    return removals == null ? ImmutableList.of() : removals;
+  }
+
+  public Map<String, String> updates() {
+    return updates == null ? ImmutableMap.of() : updates;
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("removals", removals)
+        .add("updates", updates)
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public static class Builder {
+    private final ImmutableSet.Builder<String> removalsBuilder = ImmutableSet.builder();
+    private final ImmutableMap.Builder<String, String> updatesBuilder = ImmutableMap.builder();
+
+    private Builder() {
+    }
+
+    public Builder remove(String removal) {
+      Preconditions.checkNotNull(removal,
+          "Invalid property to remove: null");
+      removalsBuilder.add(removal);
+      return this;
+    }
+
+    public Builder removeAll(Collection<String> removals) {
+      Preconditions.checkNotNull(removals,
+          "Invalid list of properties to remove: null");
+      Preconditions.checkArgument(!removals.contains(null),
+          "Invalid value in list of properties to remove: null");
+      removalsBuilder.addAll(removals);
+      return this;
+    }
+
+    public Builder update(String key, String value) {
+      Preconditions.checkNotNull(key,
+          "Invalid property to update: null");
+      Preconditions.checkNotNull(value,
+          "Invalid value to update for key [%s]: null. Use remove instead", key);
+      updatesBuilder.put(key, value);
+      return this;
+    }
+
+    public Builder updateAll(Map<String, String> updates) {
+      Preconditions.checkNotNull(updates,
+          "Invalid collection of properties to update: null");
+      Preconditions.checkArgument(!updates.containsKey(null),
+          "Invalid property in collection of properties to update: null");

Review comment:
       Updated.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r811441577



##########
File path: core/src/test/java/org/apache/iceberg/catalog/TestTableIdentifierParser.java
##########
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.catalog;
+
+import org.apache.iceberg.AssertHelpers;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestTableIdentifierParser {
+
+  @Test
+  public void testTableIdentifierToJson() {
+    String json = "{\"namespace\":[\"accounting\",\"tax\"],\"name\":\"paid\"}";
+    TableIdentifier identifier = TableIdentifier.of(Namespace.of("accounting", "tax"), "paid");
+    Assert.assertEquals("Should be able to serialize a table identifier with both namespace and name",
+        json, TableIdentifierParser.toJson(identifier));
+
+    TableIdentifier identifierWithEmptyNamespace = TableIdentifier.of(Namespace.empty(), "paid");
+    String jsonWithEmptyNamespace = "{\"namespace\":[],\"name\":\"paid\"}";
+    Assert.assertEquals("Should be able to serialize a table identifier that uses the empty namespace",
+        jsonWithEmptyNamespace, TableIdentifierParser.toJson(identifierWithEmptyNamespace));
+  }
+
+  @Test
+  public void testTableIdentifierFromJson() {
+    String json = "{\"namespace\":[\"accounting\",\"tax\"],\"name\":\"paid\"}";
+    TableIdentifier identifier = TableIdentifier.of(Namespace.of("accounting", "tax"), "paid");
+    Assert.assertEquals("Should be able to deserialize a valid table identifier",
+        identifier, TableIdentifierParser.fromJson(json));
+
+    TableIdentifier identifierWithEmptyNamespace = TableIdentifier.of(Namespace.empty(), "paid");
+    String jsonWithEmptyNamespace = "{\"namespace\":[],\"name\":\"paid\"}";
+    Assert.assertEquals("Should be able to deserialize a valid multi-level table identifier",
+        identifierWithEmptyNamespace, TableIdentifierParser.fromJson(jsonWithEmptyNamespace));
+  }
+
+  @Test
+  public void testFailParsingWhenNullOrEmptyJson() {
+    String nullJson = null;
+    AssertHelpers.assertThrows("TableIdentifierParser should fail to deserialize null JSON string",
+        IllegalArgumentException.class, "Cannot parse table identifier from invalid JSON: null",
+        () ->  TableIdentifierParser.fromJson(nullJson));
+
+    String emptyString = "";
+    AssertHelpers.assertThrows("TableIdentifierParser should fail to deserialize an empty string",
+        IllegalArgumentException.class, "Cannot parse table identifier from invalid JSON: ''",
+        () ->  TableIdentifierParser.fromJson(emptyString));
+
+    String emptyJson = "{}";
+    AssertHelpers.assertThrows("TableIdentifierParser should fail to deserialize an empty JSON string",
+        IllegalArgumentException.class, "Cannot parse missing list namespace",
+        () ->  TableIdentifierParser.fromJson(emptyJson));
+
+    String emptyJsonArray = "[]";
+    AssertHelpers.assertThrows("TableIdentifierParser should fail to deserialize an empty JSON array",
+        IllegalArgumentException.class, "Cannot parse missing or non-object table identifier: []",
+        () ->  TableIdentifierParser.fromJson(emptyJsonArray));
+  }
+
+  @Test
+  public void testFailParsingWhenMissingRequiredFields() {
+    String identifierMissingName = "{\"namespace\":[\"accounting\",\"tax\"]}";
+    AssertHelpers.assertThrows("TableIdentifierParser should fail to deserialize table with missing name",
+        IllegalArgumentException.class, "Cannot parse missing string name",
+        () ->  TableIdentifierParser.fromJson(identifierMissingName));
+
+    String identifierMissingNamespace = "{\"name\":\"paid\"}";
+    AssertHelpers.assertThrows("TableIdentifierParser should fail to deserialize table with missing namespace",
+        IllegalArgumentException.class, "Cannot parse missing list namespace",

Review comment:
       Yeah I think so. There could be cases where the caller doesn't easily know the current namespace and we might still want to construct a `TableIdentifier` then etc.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r811441809



##########
File path: core/src/main/java/org/apache/iceberg/util/JsonUtil.java
##########
@@ -129,6 +130,42 @@ public static String getStringOrNull(String property, JsonNode node) {
     return builder.build();
   }
 
+  public static Map<String, String> getStringMapOrNull(String property, JsonNode node) {
+    if (!node.has(property)) {
+      return null;
+    }
+
+    JsonNode pNode = node.get(property);
+    if (pNode == null || pNode.isNull()) {
+      return null;
+    }
+
+    Preconditions.checkArgument(pNode.isObject(),
+        "Cannot parse %s from non-object value: %s", property, pNode);
+    return buildStringMapFromJsonNodeObject(pNode);
+  }
+
+  private static Map<String, String> buildStringMapFromJsonNodeObject(JsonNode pNode) {
+    ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
+    Iterator<String> fields = pNode.fieldNames();
+    while (fields.hasNext()) {
+      String field = fields.next();
+      builder.put(field, getString(field, pNode));
+    }
+    return builder.build();
+  }
+
+  public static String[] getStringArray(JsonNode node) {
+    Preconditions.checkArgument(node != null && !node.isNull() && node.isArray(),
+        "Cannot parse string array from non-array value: %s", node);

Review comment:
       Omitted and updated tests.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r809492179



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/UpdateNamespacePropertiesRequest.java
##########
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.List;
+import java.util.Map;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
+
+/**
+ * A REST request to set and/or remove properties on a namespace.
+ * <p>
+ * The request body specifies a list of properties to remove and a map
+ * of key value pairs to update.
+ * <p>
+ * Properties that are not in the request are not modified or removed by this call.
+ * Server implementations are not required to support namespace properties.
+ */
+public class UpdateNamespacePropertiesRequest {
+
+  private List<String> removals;
+  private Map<String, String> updates;
+
+  public UpdateNamespacePropertiesRequest() {
+    // Required for Jackson deserialization.
+  }
+
+  private UpdateNamespacePropertiesRequest(List<String> removals, Map<String, String> updates) {
+    this.removals = removals;
+    this.updates = updates;
+    validate();
+  }
+
+  UpdateNamespacePropertiesRequest validate() {
+    Preconditions.checkArgument((removals != null && !removals.isEmpty()) || (updates != null && !updates.isEmpty()),

Review comment:
       OH actually, they're potentially `null` when deserialized via Jacksoon. That's why removals or updates can be null.
   
   From the builder, they should never be null.
   
   I added a test case with the builder where both fields are empty and hit this exception.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810546934



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/ListNamespacesResponse.java
##########
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Collection;
+import java.util.List;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+
+public class ListNamespacesResponse {
+
+  private List<Namespace> namespaces;
+
+  public ListNamespacesResponse() {
+    // Required for Jackson deserialization
+  }
+
+  private ListNamespacesResponse(List<Namespace> namespaces) {
+    this.namespaces = namespaces;
+    validate();
+  }
+
+  ListNamespacesResponse validate() {
+    Preconditions.checkArgument(namespaces != null,
+        "Cannot create a response to a list namespaces request without a non-null list of namespaces");
+    return this;
+  }
+
+
+  public List<Namespace> namespaces() {
+    return namespaces != null ? namespaces : ImmutableList.of();
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("namespaces", namespaces())
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  static class Builder {
+    private final ImmutableList.Builder<Namespace> namespaces = ImmutableList.builder();
+
+    private Builder() {
+    }
+
+    public Builder add(Namespace toAdd) {
+      Preconditions.checkNotNull(toAdd,
+          "Invalid namespace to list: null");
+      namespaces.add(toAdd);
+      return this;
+    }
+
+    public Builder addAll(Collection<Namespace> toAdd) {
+      Preconditions.checkNotNull(toAdd,
+          "Invalid collection of namespaces to list: null");
+      Preconditions.checkArgument(!toAdd.contains(null),
+          "Invalid namespace in collection of namespaces to list: null");

Review comment:
       Invalid namespace: null

##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/ListNamespacesResponse.java
##########
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Collection;
+import java.util.List;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+
+public class ListNamespacesResponse {
+
+  private List<Namespace> namespaces;
+
+  public ListNamespacesResponse() {
+    // Required for Jackson deserialization
+  }
+
+  private ListNamespacesResponse(List<Namespace> namespaces) {
+    this.namespaces = namespaces;
+    validate();
+  }
+
+  ListNamespacesResponse validate() {
+    Preconditions.checkArgument(namespaces != null,
+        "Cannot create a response to a list namespaces request without a non-null list of namespaces");
+    return this;
+  }
+
+
+  public List<Namespace> namespaces() {
+    return namespaces != null ? namespaces : ImmutableList.of();
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("namespaces", namespaces())
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  static class Builder {
+    private final ImmutableList.Builder<Namespace> namespaces = ImmutableList.builder();
+
+    private Builder() {
+    }
+
+    public Builder add(Namespace toAdd) {
+      Preconditions.checkNotNull(toAdd,
+          "Invalid namespace to list: null");
+      namespaces.add(toAdd);
+      return this;
+    }
+
+    public Builder addAll(Collection<Namespace> toAdd) {
+      Preconditions.checkNotNull(toAdd,
+          "Invalid collection of namespaces to list: null");

Review comment:
       Invalid namespace list: null




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810545920



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/UpdateNamespacePropertiesRequest.java
##########
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
+import org.apache.iceberg.relocated.com.google.common.collect.Maps;
+
+/**
+ * A REST request to set and/or remove properties on a namespace.
+ */
+public class UpdateNamespacePropertiesRequest {
+
+  private List<String> removals;
+  private Map<String, String> updates;
+
+  public UpdateNamespacePropertiesRequest() {
+    // Required for Jackson deserialization.
+  }
+
+  private UpdateNamespacePropertiesRequest(List<String> removals, Map<String, String> updates) {
+    this.removals = removals;
+    this.updates = updates;
+    validate();
+  }
+
+  UpdateNamespacePropertiesRequest validate() {
+    Preconditions.checkArgument(removals != null || updates != null,
+        "Invalid value for update namespace properties request: at least one of updates and removals must be non-null");
+    return this;
+  }
+
+  public List<String> removals() {
+    return removals == null ? ImmutableList.of() : removals;
+  }
+
+  public Map<String, String> updates() {
+    return updates == null ? ImmutableMap.of() : updates;
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("removals", removals)
+        .add("updates", updates)
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public static class Builder {
+    private final ImmutableSet.Builder<String> removalsBuilder = ImmutableSet.builder();
+    private final ImmutableMap.Builder<String, String> updatesBuilder = ImmutableMap.builder();
+
+    private Builder() {
+    }
+
+    public Builder remove(String removal) {
+      Preconditions.checkNotNull(removal,
+          "Invalid property to remove: null");
+      removalsBuilder.add(removal);
+      return this;
+    }
+
+    public Builder removeAll(Collection<String> removals) {
+      Preconditions.checkNotNull(removals,
+          "Invalid list of properties to remove: null");
+      Preconditions.checkArgument(!removals.contains(null),
+          "Invalid value in list of properties to remove: null");
+      removalsBuilder.addAll(removals);
+      return this;
+    }
+
+    public Builder update(String key, String value) {
+      Preconditions.checkNotNull(key,
+          "Invalid property to update: null");
+      Preconditions.checkNotNull(value,
+          "Invalid value to update for key [%s]: null. Use remove instead", key);
+      updatesBuilder.put(key, value);
+      return this;
+    }
+
+    public Builder updateAll(Map<String, String> updates) {
+      Preconditions.checkNotNull(updates,
+          "Invalid collection of properties to update: null");
+      Preconditions.checkArgument(!updates.containsKey(null),
+          "Invalid property in collection of properties to update: null");

Review comment:
       Same here. I'd probably say "Invalid property to update: null"




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810546447



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/CreateNamespaceResponse.java
##########
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.Maps;
+
+/**
+ * Represents a REST response for a request to create a namespace / database.
+ */
+public class CreateNamespaceResponse {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public CreateNamespaceResponse() {
+    // Required for Jackson deserialization.
+  }
+
+  private CreateNamespaceResponse(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+    validate();
+  }
+
+  CreateNamespaceResponse validate() {
+    Preconditions.checkArgument(
+        namespace != null && !namespace.isEmpty(),
+        "Cannot build a response to create a namespace without specifying the namespace");
+    return this;
+  }
+
+  public Namespace namespace() {
+    return namespace;
+  }
+
+  public Map<String, String> properties() {
+    return properties != null ? properties : ImmutableMap.of();
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("namespace", namespace)
+        .add("properties", properties)
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  static class Builder {
+    private Namespace namespace;
+    private final ImmutableMap.Builder<String, String> properties = ImmutableMap.builder();
+
+    private Builder() {
+    }
+
+    public Builder withNamespace(Namespace ns) {
+      Preconditions.checkNotNull(ns, "Invalid namespace to have created: null");

Review comment:
       I think "Invalid namespace: null" is sufficient. No need for extra context here that is clear from the stack trace.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r799086048



##########
File path: core/src/test/java/org/apache/iceberg/rest/requests/TestCreateNamespaceRequest.java
##########
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.util.JsonUtil;
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+
+public class TestCreateNamespaceRequest {
+
+  private static final ObjectMapper MAPPER = JsonUtil.withRESTComponents();
+
+  // Non-empty
+  private static final String JSON_REQUEST_STRING =
+      "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{\"owner\":\"Hank\"}}";
+  private static final Namespace NAMESPACE = Namespace.of("accounting", "tax");
+  private static final Map<String, String> PROPERTIES = ImmutableMap.of("owner", "Hank");
+
+  // Empty - The response requires a non-empty namespace
+  private static final String JSON_REQUEST_NO_PROPERTIES =
+      "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{}}";
+
+  @Test
+  public void testDeserialize() throws JsonProcessingException {
+    CreateNamespaceRequest expected = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .withProperties(PROPERTIES)
+        .build();
+
+    CreateNamespaceRequest actual = MAPPER.readValue(JSON_REQUEST_STRING, CreateNamespaceRequest.class);
+
+    assertSame(expected, actual);
+  }
+
+  @Test
+  public void testDeserializeNoProperties() throws JsonProcessingException {
+    CreateNamespaceRequest expected = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .build();
+
+    CreateNamespaceRequest actual = MAPPER.readValue(JSON_REQUEST_NO_PROPERTIES, CreateNamespaceRequest.class);
+
+    assertSame(expected, actual);
+  }
+
+  @Test
+  public void testSerialize() throws JsonProcessingException {
+    CreateNamespaceRequest req = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .withProperties(PROPERTIES)
+        .build();
+
+    Assertions.assertThat(MAPPER.writeValueAsString(req))
+        .isEqualTo(JSON_REQUEST_STRING);
+  }
+
+  @Test
+  public void testSerializeNoProperties() throws JsonProcessingException {
+    CreateNamespaceRequest req = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .build();
+
+    Assertions.assertThat(MAPPER.writeValueAsString(req))
+        .isEqualTo(JSON_REQUEST_NO_PROPERTIES);
+  }
+
+  private static void assertSame(CreateNamespaceRequest expected, CreateNamespaceRequest actual) {
+    Assertions.assertThat(actual)
+        .satisfies(req -> {
+          Assertions.assertThat(req.namespace()).isNotNull().isEqualTo(expected.namespace());
+          Assertions.assertThat(req.properties()).isNotNull().isEqualTo(expected.properties());
+        });
+
+    // Ensure that this function is updated if new fields are added to the class.
+    // Avoids adding equals / hashCode method just for test purposes.
+    String[] allFields = {"namespace", "properties"};
+    Assertions.assertThat(actual)
+        .hasOnlyFields(allFields);
+    Assertions.assertThat(expected)
+        .hasOnlyFields(allFields);

Review comment:
       I would put this assertion in a separate test. The result is going to be the same for all instances of the object, right? So we don't need to check both expected and actual, nor do we need to do it when comparing expected and actual.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] danielcweeks commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
danielcweeks commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r799094191



##########
File path: core/src/main/java/org/apache/iceberg/rest/RESTJacksonModule.java
##########
@@ -0,0 +1,183 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import java.io.IOException;
+import org.apache.iceberg.PartitionSpec;
+import org.apache.iceberg.PartitionSpecParser;
+import org.apache.iceberg.Schema;
+import org.apache.iceberg.SchemaParser;
+import org.apache.iceberg.SortOrder;
+import org.apache.iceberg.SortOrderParser;
+import org.apache.iceberg.TableMetadata;
+import org.apache.iceberg.TableMetadataParser;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.catalog.TableIdentifier;
+
+public class RESTJacksonModule {
+
+  private RESTJacksonModule() {
+  }
+
+  public static void registerAll(ObjectMapper mapper) {
+    SimpleModule module = new SimpleModule();
+    module
+        .addSerializer(TableIdentifier.class, new TableIdentifierSerializer())
+        .addDeserializer(TableIdentifier.class, new TableIdentifierDeserializer())
+        .addSerializer(Namespace.class, new NamespaceSerializer())
+        .addDeserializer(Namespace.class, new NamespaceDeserializer())
+        .addSerializer(Schema.class, new SchemaSerializer())
+        .addDeserializer(Schema.class, new SchemaDeserializer())
+        .addSerializer(PartitionSpec.class, new PartitionSpecSerializer())
+        .addDeserializer(PartitionSpec.class, new PartitionSpecDeserializer())
+        .addSerializer(SortOrder.class, new SortOrderSerializer())
+        .addDeserializer(SortOrder.class, new SortOrderDeserializer());
+    mapper.registerModule(module);
+
+    mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE);
+    mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);

Review comment:
       These are a workaround for Jackson since Iceberg doesn't use the standard `get/set` bean notation.  This allows Jackson to work with the fields more directly and not require custom serializers (with basically a ton of boilerplate code) for all of the request/response objects. 




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r799092284



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/UpdateNamespacePropertiesRequest.java
##########
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.List;
+import java.util.Map;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
+
+/**
+ * A REST request to set and/or remove properties on a namespace.
+ * <p/>
+ * The request body specifies a list of properties to remove and a map
+ * of key value pairs to update.
+ * <p/>
+ * Properties that are not in the request are not modified or removed by this call.
+ * Server implementations are not required to support namespace properties.
+ */
+public class UpdateNamespacePropertiesRequest {
+
+  private List<String> removals;
+  private Map<String, String> updates;
+
+  public UpdateNamespacePropertiesRequest() {
+    // Required for Jackson
+  }
+
+  private UpdateNamespacePropertiesRequest(List<String> removals, Map<String, String> updates) {
+    this.removals = removals;
+    this.updates = updates;
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public List<String> removals() {
+    return ImmutableList.copyOf(removals);
+  }
+
+  public Map<String, String> updates() {
+    return ImmutableMap.copyOf(updates);
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("removals", removals())
+        .add("updates", updates())
+        .toString();
+  }
+
+  public static class Builder {
+    private final ImmutableSet.Builder<String> removalsBuilder;
+    private final ImmutableMap.Builder<String, String> updatesBuilder;
+
+    private Builder() {
+      this.removalsBuilder = ImmutableSet.builder();
+      this.updatesBuilder = ImmutableMap.builder();
+    }
+
+    public Builder withRemoval(String removal) {
+      removalsBuilder.add(removal);
+      return this;
+    }
+
+    public Builder withRemovals(Iterable<String> removals) {
+      removalsBuilder.addAll(removals);
+      return this;
+    }
+
+    public Builder withUpdate(String key, String value) {
+      updatesBuilder.put(key, value);
+      return this;
+    }
+
+    public Builder withUpdates(Map<String, String> updates) {
+      updatesBuilder.putAll(updates);
+      return this;
+    }
+
+    public UpdateNamespacePropertiesRequest build() {
+      List<String> removals = removalsBuilder.build().asList();
+      Map<String, String> updates = updatesBuilder.build();
+      Preconditions.checkState(
+          !removals.isEmpty() || !updates.isEmpty(),
+          "Cannot create a request to update a namespace's properties without any properties to remove or update.");

Review comment:
       I'd probably remove these. The requests are likely to be built and automated. Better to have an `isEmpty` method on the request, but I probably wouldn't do that either.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r808556343



##########
File path: core/src/test/java/org/apache/iceberg/rest/requests/TestCreateNamespaceRequest.java
##########
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import java.util.Map;
+import org.apache.iceberg.AssertHelpers;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.rest.RequestResponseTestBase;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestCreateNamespaceRequest extends RequestResponseTestBase<CreateNamespaceRequest> {
+
+  /* Values used to fill in request fields */
+  private static final Namespace NAMESPACE = Namespace.of("accounting", "tax");
+  private static final Map<String, String> PROPERTIES = ImmutableMap.of("owner", "Hank");
+  private static final Map<String, String> EMPTY_PROPERTIES = ImmutableMap.of();
+
+  @Test
+  // Test cases that are JSON that can be created via the Builder
+  public void testRoundTripSerDe() throws JsonProcessingException {
+    String fullJson = "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{\"owner\":\"Hank\"}}";
+    CreateNamespaceRequest req = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE).setProperties(PROPERTIES).build();
+    assertRoundTripSerializesEquallyFrom(fullJson, req);
+
+    String jsonEmptyProperties = "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{}}";
+    CreateNamespaceRequest reqWithExplicitEmptyProperties = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE).setProperties(EMPTY_PROPERTIES).build();
+    assertRoundTripSerializesEquallyFrom(jsonEmptyProperties, reqWithExplicitEmptyProperties);
+
+    CreateNamespaceRequest reqWithImplicitEmptyProperties = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE).build();
+    assertRoundTripSerializesEquallyFrom(jsonEmptyProperties, reqWithImplicitEmptyProperties);
+  }
+
+  @Test
+  // Test cases that can't be constructed with our Builder class but that will parse correctly
+  public void testCanDeserializeWithoutDefaultValues() throws JsonProcessingException {
+    CreateNamespaceRequest req = CreateNamespaceRequest.builder().withNamespace(NAMESPACE).build();
+    String jsonWithNullProperties = "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":null}";
+    assertEquals(deserialize(jsonWithNullProperties), req);
+
+    String jsonWithMissingProperties = "{\"namespace\":[\"accounting\",\"tax\"]}";
+    assertEquals(deserialize(jsonWithMissingProperties), req);
+  }
+
+  @Test
+  public void testDeserializeInvalidRequest() {
+    String jsonIncorrectTypeForNamespace = "{\"namespace\":\"accounting%00tax\",\"properties\":null}";
+    AssertHelpers.assertThrows(
+        "A JSON request with incorrect types for fields should fail to deserialize and validate",
+        JsonProcessingException.class,
+        "Cannot parse string array from non-array value",
+        () -> deserialize(jsonIncorrectTypeForNamespace).validate()
+    );
+
+    String jsonIncorrectTypeForProperties = "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":[]}";
+    AssertHelpers.assertThrows(
+        "A JSON request with incorrect types for fields should fail to parse and validate",
+        JsonProcessingException.class,
+        () -> deserialize(jsonIncorrectTypeForProperties).validate()
+    );
+
+    String jsonMisspelledKeys = "{\"namepsace\":[\"accounting\",\"tax\"],\"propertiezzzz\":{\"owner\":\"Hank\"}}";
+    AssertHelpers.assertThrows(
+        "A JSON request with the keys spelled incorrectly should fail to deserialize and validate",
+        JsonProcessingException.class,
+        () -> deserialize(jsonMisspelledKeys).validate()

Review comment:
       Would be nice to have error message validation.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r801136476



##########
File path: core/src/test/java/org/apache/iceberg/rest/requests/TestCreateNamespaceRequest.java
##########
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.util.JsonUtil;
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+
+public class TestCreateNamespaceRequest {

Review comment:
       Added a few tests for malformed.
   
   Specifically added:
   - an empty json
   - (String) null - simulating if the response entity has no body at all
   -  fields are spelled incorrectly
   - `namespace` / `properties` have fields that aren't the correct type.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r801035192



##########
File path: core/src/test/java/org/apache/iceberg/rest/requests/TestCreateNamespaceRequest.java
##########
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.util.JsonUtil;
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+
+public class TestCreateNamespaceRequest {
+
+  private static final ObjectMapper MAPPER = JsonUtil.withRESTComponents();
+
+  // Non-empty
+  private static final String JSON_REQUEST_STRING =
+      "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{\"owner\":\"Hank\"}}";
+  private static final Namespace NAMESPACE = Namespace.of("accounting", "tax");
+  private static final Map<String, String> PROPERTIES = ImmutableMap.of("owner", "Hank");
+
+  // Empty - The response requires a non-empty namespace
+  private static final String JSON_REQUEST_NO_PROPERTIES =

Review comment:
       Updated




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r801205387



##########
File path: core/src/test/java/org/apache/iceberg/rest/requests/TestCreateNamespaceRequest.java
##########
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.util.JsonUtil;
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+
+public class TestCreateNamespaceRequest {

Review comment:
       If we're good with the tests, I'll start adding them to more of the request / response objects.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r801204513



##########
File path: core/src/main/java/org/apache/iceberg/catalog/TableIdentifierParser.java
##########
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.catalog;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.JsonNode;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.UncheckedIOException;
+import java.util.List;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.util.JsonUtil;
+
+/**
+ * Parses TableIdentifiers from a JSON representation, which is the JSON
+ * representation utilized in the REST catalog.
+ * <p>
+ * For TableIdentifier.of("dogs", "owners.and.handlers", "food"), we'd have
+ * the following JSON representation, where the dot character of an
+ * individual level is in the namespace is replaced by the null byte character.
+ * <pre>
+ * {
+ *   "namespace": ["dogs", "owners.and.handlers"],
+ *   "name": "food"
+ * }
+ * </pre>
+ */
+public class TableIdentifierParser {
+
+  private static final String NAMESPACE = "namespace";
+  private static final String NAME = "name";
+
+  private TableIdentifierParser() {
+  }
+
+  public static String toJson(TableIdentifier identifier) {
+    return toJson(identifier, false);
+  }
+
+  public static String toJson(TableIdentifier identifier, boolean pretty) {
+    try {
+      StringWriter writer = new StringWriter();
+      JsonGenerator generator = JsonUtil.factory().createGenerator(writer);
+      if (pretty) {
+        generator.useDefaultPrettyPrinter();
+      }
+      toJson(identifier, generator);
+      generator.flush();
+      return writer.toString();
+    } catch (IOException e) {
+      throw new UncheckedIOException(String.format("Failed to write json for: %s", identifier), e);
+    }
+  }
+
+  public static void toJson(TableIdentifier identifier, JsonGenerator generator) throws IOException {
+    generator.writeStartObject();
+    generator.writeFieldName(NAMESPACE);
+    generator.writeArray(identifier.namespace().levels(), 0, identifier.namespace().length());
+    generator.writeStringField(NAME, identifier.name());
+    generator.writeEndObject();
+  }
+
+  public static TableIdentifier fromJson(String json) {
+    Preconditions.checkArgument(json != null && !json.isEmpty(),
+        "Cannot parse table identifier from invalid JSON: %s", json);
+    try {
+      return fromJson(JsonUtil.mapper().readValue(json, JsonNode.class));
+    } catch (IOException e) {
+      throw new UncheckedIOException(String.format("Cannot parse table identifier from invalid JSON: %s", json), e);
+    }
+  }
+
+  public static TableIdentifier fromJson(JsonNode node) {
+    Preconditions.checkArgument(node != null && !node.isNull() && node.isObject(),
+        "Cannot parse missing or non-object table identifier: %s", node);
+    List<String> levels = JsonUtil.getStringList(NAMESPACE, node);
+    String tableName = JsonUtil.getString(NAME, node);
+    Namespace namespace = Namespace.of(levels.toArray(new String[0]));
+    return TableIdentifier.of(namespace, tableName);
+  }
+}

Review comment:
       I can move the `TableIdentifierParser` and associated tests into another PR if that would be helpful @jackye1995.
   
   I'm also thinking that `NamespaceParser` would in fact be needed, because of the way explicitly write `startObject` and `endObject` when generating json.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r802070019



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/CreateNamespaceRequest.java
##########
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+
+/**
+ * A REST request to create a namespace, with an optional set of properties.

Review comment:
       I opened an issue to follow up on this. Since the class names currently match up with the class names in the spec, I think we can handle that as a follow up (I genuinely need to see in which ways is that possible - though maybe somebody else knows better already).
   
   https://github.com/apache/iceberg/issues/4068




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r801126914



##########
File path: core/src/test/java/org/apache/iceberg/rest/requests/TestCreateNamespaceRequest.java
##########
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.util.JsonUtil;
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+
+public class TestCreateNamespaceRequest {
+
+  private static final ObjectMapper MAPPER = JsonUtil.withRESTComponents();
+
+  private static final String[] ALL_FIELDS_FROM_SPEC = { "namespace", "properties" };
+
+  /* Values used to fill in request fields */
+  private static final Namespace NAMESPACE = Namespace.of("accounting", "tax");
+  private static final Map<String, String> PROPERTIES = ImmutableMap.of("owner", "Hank");
+
+  /* JSON of requests */
+  private static final String JSON_REQUEST =
+      "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{\"owner\":\"Hank\"}}";
+  private static final String JSON_REQUEST_EMPTY_PROPERTIES =
+      "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{}}";
+
+  @Test
+  public void testDeserialize() throws JsonProcessingException {
+    CreateNamespaceRequest expected = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .withProperties(PROPERTIES)
+        .build();
+
+    CreateNamespaceRequest actual = MAPPER.readValue(JSON_REQUEST, CreateNamespaceRequest.class);
+
+    assertEquals(expected, actual);
+    assertHasOnlyKnownFields(expected);
+    assertHasOnlyKnownFields(actual);
+  }
+
+  @Test
+  public void testDeserializeEmptyProperties() throws JsonProcessingException {
+    CreateNamespaceRequest expected = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .build();
+
+    CreateNamespaceRequest actual = MAPPER.readValue(JSON_REQUEST_EMPTY_PROPERTIES, CreateNamespaceRequest.class);
+
+    assertEquals(expected, actual);
+    assertHasOnlyKnownFields(expected);
+    assertHasOnlyKnownFields(actual);
+  }
+
+  @Test
+  public void testSerialize() throws JsonProcessingException {
+    CreateNamespaceRequest req = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .withProperties(PROPERTIES)
+        .build();
+
+    Assertions.assertThat(MAPPER.writeValueAsString(req))
+        .isEqualTo(JSON_REQUEST);
+  }
+
+  @Test
+  public void testSerializeEmptyProperties() throws JsonProcessingException {
+    CreateNamespaceRequest req = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .build();
+
+    Assertions.assertThat(MAPPER.writeValueAsString(req))
+        .isEqualTo(JSON_REQUEST_EMPTY_PROPERTIES);
+  }
+
+  private static void assertEquals(CreateNamespaceRequest expected, CreateNamespaceRequest actual) {
+    Assertions.assertThat(actual.namespace()).isEqualTo(expected.namespace());

Review comment:
       Yeah I agree. I changed it to simply implement `equals` (and `hashCode`). Now none of the tests will have this `assertEquals` method, just use the `equals` defined on the class.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r801016104



##########
File path: core/src/main/java/org/apache/iceberg/rest/RESTJacksonModule.java
##########
@@ -0,0 +1,183 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import java.io.IOException;
+import org.apache.iceberg.PartitionSpec;
+import org.apache.iceberg.PartitionSpecParser;
+import org.apache.iceberg.Schema;
+import org.apache.iceberg.SchemaParser;
+import org.apache.iceberg.SortOrder;
+import org.apache.iceberg.SortOrderParser;
+import org.apache.iceberg.TableMetadata;
+import org.apache.iceberg.TableMetadataParser;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.catalog.TableIdentifier;
+
+public class RESTJacksonModule {

Review comment:
       Agreed. It was originally `Module` in the Jackson sense, as I was going to export the `Module` for others to add. But decided that it was easier to contain inside a method for people.
   
   Will rename.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r806235353



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/CreateNamespaceRequest.java
##########
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import com.fasterxml.jackson.annotation.JsonProperty;

Review comment:
       So I realized the issue. We can't validate the input if we just let Jackson infer things.
   
   For example, if a server sends a `CreateNamespaceResponse` of `{ }`, it will not fail on deserialization and we will get `CreateNamespaceResponse(namespace=null, properties=null)`.
   
   The annotations force it to go through the constructor, which is where we throw if the required / not-null field `namespace` isn't found.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r805405846



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/CreateNamespaceRequest.java
##########
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import com.fasterxml.jackson.annotation.JsonProperty;

Review comment:
       Annotation classes are ignored if they are not present in the classpath. Relying on annotations brings in a new class of problems caused by the end user messing up their classpath, so I am strongly in favor of avoiding them. If Jackson can infer everything that we need it to without them, then we can use that inference. Otherwise I think we should make serialization more explicit.
   
   I believe that we don't currently use Jackson annotations, so this change would also require updating all of our runtime Jars and their licenses.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r807421743



##########
File path: core/src/main/java/org/apache/iceberg/catalog/TableIdentifierParser.java
##########
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.catalog;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.JsonNode;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.UncheckedIOException;
+import java.util.List;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.util.JsonUtil;
+
+/**
+ * Parses TableIdentifiers from a JSON representation, which is the JSON
+ * representation utilized in the REST catalog.
+ * <p>
+ * For TableIdentifier.of("dogs", "owners.and.handlers", "food"), we'd have
+ * the following JSON representation, where the dot character of an
+ * individual level is in the namespace is replaced by the null byte character.
+ * <pre>
+ * {
+ *   "namespace": ["dogs", "owners.and.handlers"],
+ *   "name": "food"
+ * }
+ * </pre>
+ */
+public class TableIdentifierParser {
+
+  private static final String NAMESPACE = "namespace";
+  private static final String NAME = "name";
+
+  private TableIdentifierParser() {
+  }
+
+  public static String toJson(TableIdentifier identifier) {
+    return toJson(identifier, false);
+  }
+
+  public static String toJson(TableIdentifier identifier, boolean pretty) {
+    try {
+      StringWriter writer = new StringWriter();
+      JsonGenerator generator = JsonUtil.factory().createGenerator(writer);
+      if (pretty) {
+        generator.useDefaultPrettyPrinter();
+      }
+      toJson(identifier, generator);
+      generator.flush();
+      return writer.toString();
+    } catch (IOException e) {
+      throw new UncheckedIOException(String.format("Failed to write json for: %s", identifier), e);
+    }
+  }
+
+  public static void toJson(TableIdentifier identifier, JsonGenerator generator) throws IOException {

Review comment:
       Here's the code that calls it: https://github.com/apache/iceberg/pull/4037/files#diff-ba7699a6ab80be9031fd6324b347a087f10646d57339a47339f60699a6bf4b37R103-R109




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r808451957



##########
File path: core/src/test/java/org/apache/iceberg/rest/requests/TestCreateNamespaceRequest.java
##########
@@ -0,0 +1,143 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.util.Map;
+import org.apache.iceberg.AssertHelpers;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.exceptions.ValidationException;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.rest.RESTUtil;
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+
+public class TestCreateNamespaceRequest {
+
+  private static final ObjectMapper MAPPER = RESTUtil.mapper();
+
+  private static final String[] ALL_FIELDS_FROM_SPEC = { "namespace", "properties" };
+
+  /* Values used to fill in request fields */
+  private static final Namespace NAMESPACE = Namespace.of("accounting", "tax");
+  private static final Map<String, String> PROPERTIES = ImmutableMap.of("owner", "Hank");
+  private static final Map<String, String> EMPTY_PROPERTIES = ImmutableMap.of();
+
+  @Test
+  // Test cases that are JSON that can be created via the Builder
+  public void testRoundTripSerDe() throws JsonProcessingException {
+    String fullJson = "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{\"owner\":\"Hank\"}}";
+    CreateNamespaceRequest req = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE).setProperties(PROPERTIES).build();
+    assertRoundTripSerDe(fullJson, req);
+
+    String jsonEmptyProperties = "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{}}";
+    CreateNamespaceRequest reqWithExplicitEmptyProperties = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE).setProperties(EMPTY_PROPERTIES).build();
+    assertRoundTripSerDe(jsonEmptyProperties, reqWithExplicitEmptyProperties);
+
+    CreateNamespaceRequest reqWithImplicitEmptyProperties = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE).build();
+    assertRoundTripSerDe(jsonEmptyProperties, reqWithImplicitEmptyProperties);
+  }
+
+  @Test
+  // Test cases that can't be constructed with our Builder class but that will parse correctly
+  // and can be compared with our builder after calling `validate` to normalize the parsed object.
+  public void testRoundTripSerDeAfterEnsureRequirements() throws JsonProcessingException {
+    String jsonWithNullProperties = "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":null}";
+    CreateNamespaceRequest req = CreateNamespaceRequest.builder().withNamespace(NAMESPACE).build();
+    assertDeserializesEquallyAfterValidation(jsonWithNullProperties, req);
+  }
+
+  @Test
+  public void testDeserializeInvalidRequest() {
+    String jsonIncorrectTypeForNamespace = "{\"namespace\":\"accounting%00tax\",\"properties\":null}";
+    AssertHelpers.assertThrows(
+        "A JSON request with incorrect types for fields should fail to deserialize and validate",
+        JsonProcessingException.class,
+        "Namespace must be an array",
+        () -> MAPPER.readValue(jsonIncorrectTypeForNamespace, CreateNamespaceRequest.class).validate()
+    );
+
+    String jsonIncorrectTypeForProperties = "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":[]}";
+    AssertHelpers.assertThrows(
+        "A JSON request with incorrect types for fields should fail to parse and validate",
+        JsonProcessingException.class,
+        () -> MAPPER.readValue(jsonIncorrectTypeForProperties, CreateNamespaceRequest.class).validate()
+    );
+
+    String jsonMisspelledKeys = "{\"namepsace\":[\"accounting\",\"tax\"],\"propertiezzzz\":{\"owner\":\"Hank\"}}";
+    AssertHelpers.assertThrows(
+        "A JSON request with the keys spelled incorrectly should fail to deserialize and validate",
+        JsonProcessingException.class,
+        () -> MAPPER.readValue(jsonMisspelledKeys, CreateNamespaceRequest.class).validate()
+    );
+
+    String emptyJson = "{}";
+    AssertHelpers.assertThrows(
+        "An empty JSON object should not parse into a CreateNamespaceRequest instance that passes validation",
+        ValidationException.class,
+        () -> MAPPER.readValue(emptyJson, CreateNamespaceRequest.class).validate()
+    );
+
+    AssertHelpers.assertThrows(
+        "An empty JSON request should fail to deserialize",
+        IllegalArgumentException.class,
+        () -> MAPPER.readValue((String) null, CreateNamespaceRequest.class).validate()
+    );
+  }
+
+  @Test
+  public void testHasOnlyKnownFields() {
+    // This test ensures that only the fields that are expected (from the spec) are found on the class.
+    // If new fields are added to the spec, they should be added to the ALL_FIELDS_FROM_SPEC constant.
+    CreateNamespaceRequest req = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .setProperties(PROPERTIES)
+        .build();
+
+    Assertions.assertThat(req)
+        .hasOnlyFields(ALL_FIELDS_FROM_SPEC);
+  }
+
+  // For testing JSON that could be generated by our Builder
+  private void assertRoundTripSerDe(String json, CreateNamespaceRequest expected) throws JsonProcessingException {

Review comment:
       I think you can make `expected` an object and pass that to the object mapper so that these can be shared across test classes.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r808453374



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/CreateNamespaceRequest.java
##########
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.exceptions.ValidationException;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+
+/**
+ * A REST request to create a namespace, with an optional set of properties.
+ * The server might also add properties, such as `last_modified_time` etc.
+ */
+public class CreateNamespaceRequest {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public CreateNamespaceRequest() {
+    // Needed for Jackson Deserialization.
+  }
+
+  private CreateNamespaceRequest(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+    validate();
+  }
+
+  /**
+   * This function needs to be called after reading in JSON from another source, to ensure
+   * that null values are assigned to their respective defaults where needed, wrap collections
+   * in their Immutable variants, and that required fields are correct.
+   * @return normalized version of this {@link CreateNamespaceRequest}
+   */
+  CreateNamespaceRequest validate() {
+    this.properties = properties == null ? ImmutableMap.of() : ImmutableMap.copyOf(properties);
+    ValidationException.check(namespace != null && !namespace.isEmpty(),
+        "Cannot build a request to create a namespace without specifying the namespace");
+    return this;
+  }
+
+  public Namespace namespace() {
+    return namespace;
+  }
+
+  public Map<String, String> properties() {
+    return properties;

Review comment:
       Default properties here rather than modifying the object.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r811426474



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/CreateNamespaceResponse.java
##########
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.Maps;
+
+/**
+ * Represents a REST response for a request to create a namespace / database.
+ */
+public class CreateNamespaceResponse {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public CreateNamespaceResponse() {
+    // Required for Jackson deserialization.
+  }
+
+  private CreateNamespaceResponse(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+    validate();
+  }
+
+  CreateNamespaceResponse validate() {
+    Preconditions.checkArgument(
+        namespace != null && !namespace.isEmpty(),
+        "Cannot build a response to create a namespace without specifying the namespace");

Review comment:
       Updated to simply check for null and use the simplified language.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r811439833



##########
File path: core/src/main/java/org/apache/iceberg/util/JsonUtil.java
##########
@@ -129,6 +130,42 @@ public static String getStringOrNull(String property, JsonNode node) {
     return builder.build();
   }
 
+  public static Map<String, String> getStringMapOrNull(String property, JsonNode node) {
+    if (!node.has(property)) {
+      return null;
+    }
+
+    JsonNode pNode = node.get(property);
+    if (pNode == null || pNode.isNull()) {
+      return null;
+    }
+
+    Preconditions.checkArgument(pNode.isObject(),
+        "Cannot parse %s from non-object value: %s", property, pNode);

Review comment:
       The idea was to leave `buildStringMap...` with no precodition checks, and then have the individual `getStringMap` and `getStringMapOrNull` call out to that function after doing their preconditions check.
   
   I left the current implementation of `getStringMap` as is to minimize the diff, but I can either:




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue merged pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue merged pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037


   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810547584



##########
File path: core/src/test/java/org/apache/iceberg/rest/requests/TestUpdateNamespacePropertiesRequest.java
##########
@@ -0,0 +1,232 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import java.util.List;
+import java.util.Map;
+import org.apache.iceberg.AssertHelpers;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.Lists;
+import org.apache.iceberg.relocated.com.google.common.collect.Maps;
+import org.apache.iceberg.relocated.com.google.common.collect.Sets;
+import org.apache.iceberg.rest.RequestResponseTestBase;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestUpdateNamespacePropertiesRequest extends RequestResponseTestBase<UpdateNamespacePropertiesRequest> {
+
+  /* Values used to fill in request fields */
+  private static final Map<String, String> UPDATES = ImmutableMap.of("owner", "Hank");
+  private static final List<String> REMOVALS = ImmutableList.of("foo", "bar");
+  private static final Map<String, String> EMPTY_UPDATES = ImmutableMap.of();
+  private static final List<String> EMPTY_REMOVALS = ImmutableList.of();
+

Review comment:
       Nit: extra newline.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810268713



##########
File path: core/src/test/java/org/apache/iceberg/rest/requests/TestCreateNamespaceRequest.java
##########
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import java.util.Map;
+import org.apache.iceberg.AssertHelpers;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.rest.RequestResponseTestBase;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestCreateNamespaceRequest extends RequestResponseTestBase<CreateNamespaceRequest> {
+
+  /* Values used to fill in request fields */
+  private static final Namespace NAMESPACE = Namespace.of("accounting", "tax");
+  private static final Map<String, String> PROPERTIES = ImmutableMap.of("owner", "Hank");
+  private static final Map<String, String> EMPTY_PROPERTIES = ImmutableMap.of();
+
+  @Test
+  // Test cases that are JSON that can be created via the Builder
+  public void testRoundTripSerDe() throws JsonProcessingException {
+    String fullJson = "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{\"owner\":\"Hank\"}}";
+    CreateNamespaceRequest req = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE).setProperties(PROPERTIES).build();
+    assertRoundTripSerializesEquallyFrom(fullJson, req);
+
+    String jsonEmptyProperties = "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{}}";
+    CreateNamespaceRequest reqWithExplicitEmptyProperties = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE).setProperties(EMPTY_PROPERTIES).build();
+    assertRoundTripSerializesEquallyFrom(jsonEmptyProperties, reqWithExplicitEmptyProperties);
+
+    CreateNamespaceRequest reqWithImplicitEmptyProperties = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE).build();
+    assertRoundTripSerializesEquallyFrom(jsonEmptyProperties, reqWithImplicitEmptyProperties);
+  }
+
+  @Test
+  // Test cases that can't be constructed with our Builder class but that will parse correctly
+  public void testCanDeserializeWithoutDefaultValues() throws JsonProcessingException {
+    CreateNamespaceRequest req = CreateNamespaceRequest.builder().withNamespace(NAMESPACE).build();
+    String jsonWithNullProperties = "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":null}";
+    assertEquals(deserialize(jsonWithNullProperties), req);
+
+    String jsonWithMissingProperties = "{\"namespace\":[\"accounting\",\"tax\"]}";
+    assertEquals(deserialize(jsonWithMissingProperties), req);
+  }
+
+  @Test
+  public void testDeserializeInvalidRequest() {
+    String jsonIncorrectTypeForNamespace = "{\"namespace\":\"accounting%00tax\",\"properties\":null}";
+    AssertHelpers.assertThrows(
+        "A JSON request with incorrect types for fields should fail to deserialize and validate",
+        JsonProcessingException.class,
+        "Cannot parse string array from non-array value",
+        () -> deserialize(jsonIncorrectTypeForNamespace).validate()
+    );
+
+    String jsonIncorrectTypeForProperties = "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":[]}";
+    AssertHelpers.assertThrows(
+        "A JSON request with incorrect types for fields should fail to parse and validate",
+        JsonProcessingException.class,
+        () -> deserialize(jsonIncorrectTypeForProperties).validate()
+    );
+
+    String jsonMisspelledKeys = "{\"namepsace\":[\"accounting\",\"tax\"],\"propertiezzzz\":{\"owner\":\"Hank\"}}";
+    AssertHelpers.assertThrows(
+        "A JSON request with the keys spelled incorrectly should fail to deserialize and validate",
+        JsonProcessingException.class,
+        () -> deserialize(jsonMisspelledKeys).validate()

Review comment:
       I've added in error message validation. But I didn't put it in some places where the error message comes form Jackson. I can do so if you'd like.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810363592



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/CreateNamespaceRequest.java
##########
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+
+/**
+ * A REST request to create a namespace, with an optional set of properties.

Review comment:
       I'll move this conversation over to the ticket 👍 




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810393259



##########
File path: core/src/test/java/org/apache/iceberg/rest/responses/TestCreateNamespaceResponse.java
##########
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import java.util.Map;
+import org.apache.iceberg.AssertHelpers;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.rest.RequestResponseTestBase;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestCreateNamespaceResponse extends RequestResponseTestBase<CreateNamespaceResponse> {
+
+  /* Values used to fill in response fields */
+  private static final Namespace NAMESPACE = Namespace.of("accounting", "tax");
+  private static final Map<String, String> PROPERTIES = ImmutableMap.of("owner", "Hank");
+  private static final Map<String, String> EMPTY_PROPERTIES = ImmutableMap.of();
+
+  @Test
+  // Test cases that are JSON that can be created via the Builder
+  public void testRoundTripSerDe() throws JsonProcessingException {
+    String fullJson = "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{\"owner\":\"Hank\"}}";
+    CreateNamespaceResponse req = CreateNamespaceResponse
+        .builder().withNamespace(NAMESPACE).setProperties(PROPERTIES).build();
+    assertRoundTripSerializesEquallyFrom(fullJson, req);
+
+    String jsonEmptyProperties = "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{}}";
+    CreateNamespaceResponse responseWithExplicitEmptyProperties = CreateNamespaceResponse.builder()
+        .withNamespace(NAMESPACE).setProperties(EMPTY_PROPERTIES).build();
+    assertRoundTripSerializesEquallyFrom(jsonEmptyProperties, responseWithExplicitEmptyProperties);
+
+    CreateNamespaceResponse responseWithImplicitEmptyProperties = CreateNamespaceResponse.builder()
+        .withNamespace(NAMESPACE).build();
+    assertRoundTripSerializesEquallyFrom(jsonEmptyProperties, responseWithImplicitEmptyProperties);
+  }
+
+  @Test

Review comment:
       Added!




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810397949



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/DropNamespaceResponse.java
##########
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Objects;
+import org.apache.iceberg.exceptions.ValidationException;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+
+/**
+ * Represents a REST response to drop a namespace.
+ * <p>
+ * The server may choose to return an error if the namespace is not empty.
+ */
+public class DropNamespaceResponse {
+
+  // For Jackson to properly fail when deserializing, this needs to be boxed.
+  // Otherwise, the boolean is parsed according to "loose" javascript JSON rules.
+  private Boolean dropped;
+
+  public DropNamespaceResponse() {
+    // Required for Jackson deserialization
+  }
+
+  private DropNamespaceResponse(Boolean dropped) {
+    this.dropped = dropped;
+    validate();
+  }
+
+  DropNamespaceResponse validate() {
+    // Use `checkArguemt` so it will throw IllegalArgumentException, just like the other responses
+    Preconditions.checkArgument(dropped != null,
+        "Cannot instantiate a response to dropping a namespace with missing field(s): `dropped`");
+    return this;
+  }
+
+  public boolean isDropped() {
+    return dropped;
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("dropped", dropped)
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public static class Builder {
+    private Boolean dropped = false;
+
+    private Builder() {
+    }
+
+    public Builder dropped(Boolean isDropped) {
+      this.dropped = isDropped;
+      return this;
+    }
+
+    public DropNamespaceResponse build() {
+      return new DropNamespaceResponse(dropped);

Review comment:
       I made it a primitive so the null check isn't needed.
   
   My one concern is that people might just call `DropNamespaceResponse.builder().build()`, and wind up with the default (`false`). What do you think?
   
   The class level field outside of the builder has to be boxed either way, so it wouldn't be the end of the world if the builder were boxed too.
   
   




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810546280



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/CreateNamespaceResponse.java
##########
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.Maps;
+
+/**
+ * Represents a REST response for a request to create a namespace / database.
+ */
+public class CreateNamespaceResponse {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public CreateNamespaceResponse() {
+    // Required for Jackson deserialization.
+  }
+
+  private CreateNamespaceResponse(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+    validate();
+  }
+
+  CreateNamespaceResponse validate() {
+    Preconditions.checkArgument(
+        namespace != null && !namespace.isEmpty(),
+        "Cannot build a response to create a namespace without specifying the namespace");

Review comment:
       These messages are okay, but I typically prefer a more direct statement that is simpler to parse. This says "build" when this is really a validation and says "without specifying the namespace", which is a long way to say it is either null or empty. It is also inaccurate for empty namespaces because the namespace was included, it just makes no sense.
   
   I think the best way to fix this is to remove the empty check and just check for null, with a simple error message: "Invalid namespace: null".




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810547327



##########
File path: core/src/main/java/org/apache/iceberg/util/JsonUtil.java
##########
@@ -129,6 +130,42 @@ public static String getStringOrNull(String property, JsonNode node) {
     return builder.build();
   }
 
+  public static Map<String, String> getStringMapOrNull(String property, JsonNode node) {
+    if (!node.has(property)) {
+      return null;
+    }
+
+    JsonNode pNode = node.get(property);
+    if (pNode == null || pNode.isNull()) {
+      return null;
+    }
+
+    Preconditions.checkArgument(pNode.isObject(),
+        "Cannot parse %s from non-object value: %s", property, pNode);
+    return buildStringMapFromJsonNodeObject(pNode);
+  }
+
+  private static Map<String, String> buildStringMapFromJsonNodeObject(JsonNode pNode) {
+    ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
+    Iterator<String> fields = pNode.fieldNames();
+    while (fields.hasNext()) {
+      String field = fields.next();
+      builder.put(field, getString(field, pNode));
+    }
+    return builder.build();
+  }
+
+  public static String[] getStringArray(JsonNode node) {
+    Preconditions.checkArgument(node != null && !node.isNull() && node.isArray(),
+        "Cannot parse string array from non-array value: %s", node);

Review comment:
       I think "value" can be omitted.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r799076344



##########
File path: core/src/main/java/org/apache/iceberg/rest/RESTJacksonModule.java
##########
@@ -0,0 +1,183 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import java.io.IOException;
+import org.apache.iceberg.PartitionSpec;
+import org.apache.iceberg.PartitionSpecParser;
+import org.apache.iceberg.Schema;
+import org.apache.iceberg.SchemaParser;
+import org.apache.iceberg.SortOrder;
+import org.apache.iceberg.SortOrderParser;
+import org.apache.iceberg.TableMetadata;
+import org.apache.iceberg.TableMetadataParser;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.catalog.TableIdentifier;
+
+public class RESTJacksonModule {

Review comment:
       I think there's probably a better name for this module. Using "Jackson" ties this to the implementation, which we probably don't want. And "module" seems like an extra word that isn't carrying a lot of meaning, to me at least. It looks like this is probably related to how Jackson is configured?
   
   How about `RESTSerializers` instead?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r799079885



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/CreateNamespaceRequest.java
##########
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.Joiner;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.Maps;
+
+/**
+ * A REST request to create a namespace, with an optional set of properties.
+ * The server might also add properties, such as `last_modified_time` etc.
+ */
+public class CreateNamespaceRequest {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public CreateNamespaceRequest() {
+    // Required for serialization
+  }
+
+  private CreateNamespaceRequest(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public Namespace namespace() {
+    return namespace;
+  }
+
+  public Map<String, String> properties() {
+    return ImmutableMap.copyOf(properties);
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("namespace", namespace)
+        .add("properties", properties())
+        .toString();
+  }
+
+  public static class Builder {
+    private final ImmutableList.Builder<String> namespaceBuilder;
+    private final ImmutableMap.Builder<String, String> propertiesBuilder;
+
+    private Builder() {
+      this.namespaceBuilder = ImmutableList.builder();
+      this.propertiesBuilder = ImmutableMap.builder();
+    }
+
+    public Builder withNamespace(Namespace namespace) {
+      this.namespaceBuilder.add(namespace.levels());

Review comment:
       Why not just copy the namespace levels? It looks like this would continue adding to the namespace every time `withNamespace` is called, rather than setting the namespace?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r799091186



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/UpdateNamespacePropertiesResponse.java
##########
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.List;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
+
+/**
+ * A REST response to a request to set and/or remove properties on a namespace.
+ */
+public class UpdateNamespacePropertiesResponse {
+
+  // List of namespace property keys that were removed
+  private List<String> removed;
+  // List of namesspace property keys that were added or updated
+  private List<String> updated;
+  // List of properties that were requested for removal that were not found in the namespace's properties
+  private List<String> missing;
+
+  public UpdateNamespacePropertiesResponse() {
+    // Required for Jackson
+  }
+
+  private UpdateNamespacePropertiesResponse(List<String> removed, List<String> updated, List<String> missing) {
+    this.removed = removed;
+    this.updated = updated;
+    this.missing = missing;
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public List<String> removed() {
+    return ImmutableList.copyOf(removed);
+  }
+
+  public List<String> updated() {
+    return ImmutableList.copyOf(updated);
+  }
+
+  public List<String> missing() {
+    return ImmutableList.copyOf(missing);
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("removed", removed())
+        .add("updates", updated())
+        .add("missing", missing())
+        .toString();
+  }
+
+  public static class Builder {
+    private final ImmutableSet.Builder<String> removedBuilder = ImmutableSet.builder();
+    private final ImmutableSet.Builder<String> updatedBuilder = ImmutableSet.builder();
+    private final ImmutableSet.Builder<String> missingBuilder = ImmutableSet.builder();
+
+    private Builder() {
+    }
+
+    public Builder withMissing(String key) {
+      missingBuilder.add(key);
+      return this;
+    }
+
+    public Builder withMissing(Iterable<String> missing) {

Review comment:
       addMissing / addRemoved / addUpdated?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r799093411



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/CreateNamespaceRequest.java
##########
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.Joiner;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.Maps;
+
+/**
+ * A REST request to create a namespace, with an optional set of properties.
+ * The server might also add properties, such as `last_modified_time` etc.
+ */
+public class CreateNamespaceRequest {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public CreateNamespaceRequest() {
+    // Required for serialization
+  }
+
+  private CreateNamespaceRequest(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public Namespace namespace() {
+    return namespace;
+  }
+
+  public Map<String, String> properties() {
+    return ImmutableMap.copyOf(properties);
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("namespace", namespace)
+        .add("properties", properties())
+        .toString();
+  }
+
+  public static class Builder {
+    private final ImmutableList.Builder<String> namespaceBuilder;
+    private final ImmutableMap.Builder<String, String> propertiesBuilder;
+
+    private Builder() {
+      this.namespaceBuilder = ImmutableList.builder();
+      this.propertiesBuilder = ImmutableMap.builder();
+    }
+
+    public Builder withNamespace(Namespace namespace) {
+      this.namespaceBuilder.add(namespace.levels());

Review comment:
       Yeah this one is strange for sure. I'm going to use what's in `GetNamespaceRequest`.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r811416929



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/UpdateNamespacePropertiesRequest.java
##########
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
+import org.apache.iceberg.relocated.com.google.common.collect.Maps;
+
+/**
+ * A REST request to set and/or remove properties on a namespace.
+ */
+public class UpdateNamespacePropertiesRequest {
+
+  private List<String> removals;
+  private Map<String, String> updates;
+
+  public UpdateNamespacePropertiesRequest() {
+    // Required for Jackson deserialization.
+  }
+
+  private UpdateNamespacePropertiesRequest(List<String> removals, Map<String, String> updates) {
+    this.removals = removals;
+    this.updates = updates;
+    validate();
+  }
+
+  UpdateNamespacePropertiesRequest validate() {
+    Preconditions.checkArgument(removals != null || updates != null,
+        "Invalid value for update namespace properties request: at least one of updates and removals must be non-null");

Review comment:
       Removed the check entirely and added test cases for this.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810545940



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/UpdateNamespacePropertiesRequest.java
##########
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
+import org.apache.iceberg.relocated.com.google.common.collect.Maps;
+
+/**
+ * A REST request to set and/or remove properties on a namespace.
+ */
+public class UpdateNamespacePropertiesRequest {
+
+  private List<String> removals;
+  private Map<String, String> updates;
+
+  public UpdateNamespacePropertiesRequest() {
+    // Required for Jackson deserialization.
+  }
+
+  private UpdateNamespacePropertiesRequest(List<String> removals, Map<String, String> updates) {
+    this.removals = removals;
+    this.updates = updates;
+    validate();
+  }
+
+  UpdateNamespacePropertiesRequest validate() {
+    Preconditions.checkArgument(removals != null || updates != null,
+        "Invalid value for update namespace properties request: at least one of updates and removals must be non-null");
+    return this;
+  }
+
+  public List<String> removals() {
+    return removals == null ? ImmutableList.of() : removals;
+  }
+
+  public Map<String, String> updates() {
+    return updates == null ? ImmutableMap.of() : updates;
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("removals", removals)
+        .add("updates", updates)
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public static class Builder {
+    private final ImmutableSet.Builder<String> removalsBuilder = ImmutableSet.builder();
+    private final ImmutableMap.Builder<String, String> updatesBuilder = ImmutableMap.builder();
+
+    private Builder() {
+    }
+
+    public Builder remove(String removal) {
+      Preconditions.checkNotNull(removal,
+          "Invalid property to remove: null");
+      removalsBuilder.add(removal);
+      return this;
+    }
+
+    public Builder removeAll(Collection<String> removals) {
+      Preconditions.checkNotNull(removals,
+          "Invalid list of properties to remove: null");
+      Preconditions.checkArgument(!removals.contains(null),
+          "Invalid value in list of properties to remove: null");
+      removalsBuilder.addAll(removals);
+      return this;
+    }
+
+    public Builder update(String key, String value) {
+      Preconditions.checkNotNull(key,
+          "Invalid property to update: null");
+      Preconditions.checkNotNull(value,
+          "Invalid value to update for key [%s]: null. Use remove instead", key);
+      updatesBuilder.put(key, value);
+      return this;
+    }
+
+    public Builder updateAll(Map<String, String> updates) {
+      Preconditions.checkNotNull(updates,
+          "Invalid collection of properties to update: null");
+      Preconditions.checkArgument(!updates.containsKey(null),
+          "Invalid property in collection of properties to update: null");
+      Preconditions.checkArgument(!updates.containsValue(null),
+          "Invalid value to update for properties %s: null. Use remove instead",
+          Maps.filterValues(updates, Objects::isNull).keySet());

Review comment:
       Nice!




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810546494



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/CreateNamespaceResponse.java
##########
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.Maps;
+
+/**
+ * Represents a REST response for a request to create a namespace / database.
+ */
+public class CreateNamespaceResponse {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public CreateNamespaceResponse() {
+    // Required for Jackson deserialization.
+  }
+
+  private CreateNamespaceResponse(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+    validate();
+  }
+
+  CreateNamespaceResponse validate() {
+    Preconditions.checkArgument(
+        namespace != null && !namespace.isEmpty(),
+        "Cannot build a response to create a namespace without specifying the namespace");
+    return this;
+  }
+
+  public Namespace namespace() {
+    return namespace;
+  }
+
+  public Map<String, String> properties() {
+    return properties != null ? properties : ImmutableMap.of();
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("namespace", namespace)
+        .add("properties", properties)
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  static class Builder {
+    private Namespace namespace;
+    private final ImmutableMap.Builder<String, String> properties = ImmutableMap.builder();
+
+    private Builder() {
+    }
+
+    public Builder withNamespace(Namespace ns) {
+      Preconditions.checkNotNull(ns, "Invalid namespace to have created: null");
+      this.namespace = ns;
+      return this;
+    }
+
+    public Builder setProperties(Map<String, String> props) {
+      Preconditions.checkNotNull(props,
+          "Invalid collection of properties to have set: null");
+      Preconditions.checkArgument(!props.containsKey(null),
+          "Invalid property in collection of properties to have set: null");
+      Preconditions.checkArgument(!props.containsValue(null),
+          "Invalid value to have set for properties %s: null", Maps.filterValues(props, Objects::isNull).keySet());

Review comment:
       I think that `ImmutableMap` will check for null keys and values and reject them. But it's perfectly fine to have a check here as well.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810547154



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/UpdateNamespacePropertiesResponse.java
##########
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Collection;
+import java.util.List;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
+
+/**
+ * A REST response to a request to set and/or remove properties on a namespace.
+ */
+public class UpdateNamespacePropertiesResponse {
+
+  // List of namespace property keys that were removed
+  private List<String> removed;
+  // List of namespace property keys that were added or updated
+  private List<String> updated;
+  // List of properties that were requested for removal that were not found in the namespace's properties
+  private List<String> missing;
+
+  public UpdateNamespacePropertiesResponse() {
+    // Required for Jackson deserialization
+  }
+
+  private UpdateNamespacePropertiesResponse(List<String> removed, List<String> updated, List<String> missing) {
+    this.removed = removed;
+    this.updated = updated;
+    this.missing = missing;
+    validate();
+  }
+
+  UpdateNamespacePropertiesResponse validate() {
+    Preconditions.checkArgument(removed != null || updated != null  || missing != null,
+        "Cannot create a response to update namespace properties if all fields are missing");
+    return this;
+  }
+
+  public List<String> removed() {
+    return removed != null ? removed : ImmutableList.of();
+  }
+
+  public List<String> updated() {
+    return updated != null ? updated : ImmutableList.of();
+  }
+
+  public List<String> missing() {
+    return missing != null ? missing : ImmutableList.of();
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("removed", removed)
+        .add("updates", updated)
+        .add("missing", missing)
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public static class Builder {
+    private final ImmutableSet.Builder<String> removedBuilder = ImmutableSet.builder();
+    private final ImmutableSet.Builder<String> updatedBuilder = ImmutableSet.builder();
+    private final ImmutableSet.Builder<String> missingBuilder = ImmutableSet.builder();
+
+    private Builder() {
+    }
+
+    public Builder addMissing(String key) {
+      Preconditions.checkNotNull(key, "Invalid property to add to missing properties: null");

Review comment:
       Same with error messages in this class.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810546044



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/UpdateNamespacePropertiesRequest.java
##########
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
+import org.apache.iceberg.relocated.com.google.common.collect.Maps;
+
+/**
+ * A REST request to set and/or remove properties on a namespace.
+ */
+public class UpdateNamespacePropertiesRequest {
+
+  private List<String> removals;
+  private Map<String, String> updates;
+
+  public UpdateNamespacePropertiesRequest() {
+    // Required for Jackson deserialization.
+  }
+
+  private UpdateNamespacePropertiesRequest(List<String> removals, Map<String, String> updates) {
+    this.removals = removals;
+    this.updates = updates;
+    validate();
+  }
+
+  UpdateNamespacePropertiesRequest validate() {
+    Preconditions.checkArgument(removals != null || updates != null,
+        "Invalid value for update namespace properties request: at least one of updates and removals must be non-null");

Review comment:
       This check is strange to me. If it is okay to use `null` and replace it with an empty list, then why isn't it okay to do that for both removals and updates? I think the motivation is to avoid the case where both are empty, but that's not what this is checking.
   
   If it is okay for one to be null, then I'd allow both to be.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r811409714



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/UpdateNamespacePropertiesRequest.java
##########
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
+import org.apache.iceberg.relocated.com.google.common.collect.Maps;
+
+/**
+ * A REST request to set and/or remove properties on a namespace.
+ */
+public class UpdateNamespacePropertiesRequest {
+
+  private List<String> removals;
+  private Map<String, String> updates;
+
+  public UpdateNamespacePropertiesRequest() {
+    // Required for Jackson deserialization.
+  }
+
+  private UpdateNamespacePropertiesRequest(List<String> removals, Map<String, String> updates) {
+    this.removals = removals;
+    this.updates = updates;
+    validate();
+  }
+
+  UpdateNamespacePropertiesRequest validate() {
+    Preconditions.checkArgument(removals != null || updates != null,
+        "Invalid value for update namespace properties request: at least one of updates and removals must be non-null");
+    return this;
+  }
+
+  public List<String> removals() {
+    return removals == null ? ImmutableList.of() : removals;
+  }
+
+  public Map<String, String> updates() {
+    return updates == null ? ImmutableMap.of() : updates;
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("removals", removals)
+        .add("updates", updates)
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public static class Builder {
+    private final ImmutableSet.Builder<String> removalsBuilder = ImmutableSet.builder();
+    private final ImmutableMap.Builder<String, String> updatesBuilder = ImmutableMap.builder();
+
+    private Builder() {
+    }
+
+    public Builder remove(String removal) {
+      Preconditions.checkNotNull(removal,
+          "Invalid property to remove: null");
+      removalsBuilder.add(removal);
+      return this;
+    }
+
+    public Builder removeAll(Collection<String> removals) {
+      Preconditions.checkNotNull(removals,
+          "Invalid list of properties to remove: null");
+      Preconditions.checkArgument(!removals.contains(null),
+          "Invalid value in list of properties to remove: null");

Review comment:
       Ok. I'll update all of the ones that reference things like `list of properties` and `collection of properties` to try to use the same string message throughout.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r811449767



##########
File path: core/src/test/java/org/apache/iceberg/rest/RESTUtil.java
##########
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.core.JsonFactory;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class RESTUtil {

Review comment:
       Currently, we will need some sort of separate class to support the object mapper's configuration (at least at present).
   
   But I can update this for now to be moved into `RequestResponseTestBase` and then when we get to that point, if we need a separate object mapper etc, then we can deal with it.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r811473387



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/UpdateNamespacePropertiesRequest.java
##########
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
+import org.apache.iceberg.relocated.com.google.common.collect.Maps;
+
+/**
+ * A REST request to set and/or remove properties on a namespace.
+ */
+public class UpdateNamespacePropertiesRequest {
+
+  private List<String> removals;
+  private Map<String, String> updates;
+
+  public UpdateNamespacePropertiesRequest() {
+    // Required for Jackson deserialization.
+  }
+
+  private UpdateNamespacePropertiesRequest(List<String> removals, Map<String, String> updates) {
+    this.removals = removals;
+    this.updates = updates;
+    validate();
+  }
+
+  UpdateNamespacePropertiesRequest validate() {
+    return this;
+  }
+
+  public List<String> removals() {
+    return removals == null ? ImmutableList.of() : removals;
+  }
+
+  public Map<String, String> updates() {
+    return updates == null ? ImmutableMap.of() : updates;
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("removals", removals)
+        .add("updates", updates)
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public static class Builder {
+    private final ImmutableSet.Builder<String> removalsBuilder = ImmutableSet.builder();
+    private final ImmutableMap.Builder<String, String> updatesBuilder = ImmutableMap.builder();
+
+    private Builder() {
+    }
+
+    public Builder remove(String removal) {
+      Preconditions.checkNotNull(removal,
+          "Invalid property to remove: null");
+      removalsBuilder.add(removal);
+      return this;
+    }
+
+    public Builder removeAll(Collection<String> removals) {

Review comment:
       We can change this in a follow-up.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r811468662



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/GetNamespaceResponse.java
##########
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.Maps;
+
+/**
+ * Represents a REST response to fetch a namespace and its metadata properties
+ */
+public class GetNamespaceResponse {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public GetNamespaceResponse() {
+    // Required for Jackson deserialization
+  }
+
+  private GetNamespaceResponse(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+    validate();
+  }
+
+  GetNamespaceResponse validate() {
+    Preconditions.checkArgument(namespace != null, "Invalid namespace: null");
+    return this;
+  }
+
+  public Namespace namespace() {
+    return namespace;
+  }
+
+  public Map<String, String> properties() {
+    return properties != null ? properties : ImmutableMap.of();
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("namespace", namespace)
+        .add("properties", properties)
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  static class Builder {
+    private Namespace namespace;
+    private final ImmutableMap.Builder<String, String> properties =  ImmutableMap.builder();
+
+    private Builder() {
+    }
+
+    public Builder withNamespace(Namespace ns) {
+      Preconditions.checkNotNull(ns, "Invalid namespace: null");
+      namespace = ns;
+      return this;
+    }
+
+    public Builder setProperties(Map<String, String> props) {
+      Preconditions.checkNotNull(props,
+          "Invalid collection of properties: null");
+      Preconditions.checkArgument(!props.containsKey(null),
+          "Invalid property in collection of namespace properties: null");
+      Preconditions.checkArgument(!props.containsValue(null),
+          "Invalid value for properties %s: null",

Review comment:
       Oh, I see. This is a set of properties with `null`.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r811466565



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/UpdateNamespacePropertiesRequest.java
##########
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
+import org.apache.iceberg.relocated.com.google.common.collect.Maps;
+
+/**
+ * A REST request to set and/or remove properties on a namespace.
+ */
+public class UpdateNamespacePropertiesRequest {
+
+  private List<String> removals;
+  private Map<String, String> updates;
+
+  public UpdateNamespacePropertiesRequest() {
+    // Required for Jackson deserialization.
+  }
+
+  private UpdateNamespacePropertiesRequest(List<String> removals, Map<String, String> updates) {
+    this.removals = removals;
+    this.updates = updates;
+    validate();
+  }
+
+  UpdateNamespacePropertiesRequest validate() {
+    return this;
+  }
+
+  public List<String> removals() {
+    return removals == null ? ImmutableList.of() : removals;
+  }
+
+  public Map<String, String> updates() {
+    return updates == null ? ImmutableMap.of() : updates;
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("removals", removals)
+        .add("updates", updates)
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public static class Builder {
+    private final ImmutableSet.Builder<String> removalsBuilder = ImmutableSet.builder();
+    private final ImmutableMap.Builder<String, String> updatesBuilder = ImmutableMap.builder();
+
+    private Builder() {
+    }
+
+    public Builder remove(String removal) {
+      Preconditions.checkNotNull(removal,
+          "Invalid property to remove: null");

Review comment:
       Looks like this one was missed, too.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r801030357



##########
File path: core/src/test/java/org/apache/iceberg/rest/requests/TestCreateNamespaceRequest.java
##########
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.util.JsonUtil;
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+
+public class TestCreateNamespaceRequest {
+
+  private static final ObjectMapper MAPPER = JsonUtil.withRESTComponents();
+
+  // Non-empty
+  private static final String JSON_REQUEST_STRING =
+      "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{\"owner\":\"Hank\"}}";
+  private static final Namespace NAMESPACE = Namespace.of("accounting", "tax");
+  private static final Map<String, String> PROPERTIES = ImmutableMap.of("owner", "Hank");
+
+  // Empty - The response requires a non-empty namespace
+  private static final String JSON_REQUEST_NO_PROPERTIES =
+      "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{}}";
+
+  @Test
+  public void testDeserialize() throws JsonProcessingException {
+    CreateNamespaceRequest expected = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .withProperties(PROPERTIES)
+        .build();
+
+    CreateNamespaceRequest actual = MAPPER.readValue(JSON_REQUEST_STRING, CreateNamespaceRequest.class);
+
+    assertSame(expected, actual);
+  }
+
+  @Test
+  public void testDeserializeNoProperties() throws JsonProcessingException {
+    CreateNamespaceRequest expected = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .build();
+
+    CreateNamespaceRequest actual = MAPPER.readValue(JSON_REQUEST_NO_PROPERTIES, CreateNamespaceRequest.class);
+
+    assertSame(expected, actual);
+  }
+
+  @Test
+  public void testSerialize() throws JsonProcessingException {
+    CreateNamespaceRequest req = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .withProperties(PROPERTIES)
+        .build();
+
+    Assertions.assertThat(MAPPER.writeValueAsString(req))
+        .isEqualTo(JSON_REQUEST_STRING);
+  }
+
+  @Test
+  public void testSerializeNoProperties() throws JsonProcessingException {
+    CreateNamespaceRequest req = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .build();
+
+    Assertions.assertThat(MAPPER.writeValueAsString(req))
+        .isEqualTo(JSON_REQUEST_NO_PROPERTIES);
+  }
+
+  private static void assertSame(CreateNamespaceRequest expected, CreateNamespaceRequest actual) {
+    Assertions.assertThat(actual)
+        .satisfies(req -> {
+          Assertions.assertThat(req.namespace()).isNotNull().isEqualTo(expected.namespace());
+          Assertions.assertThat(req.properties()).isNotNull().isEqualTo(expected.properties());
+        });
+
+    // Ensure that this function is updated if new fields are added to the class.
+    // Avoids adding equals / hashCode method just for test purposes.
+    String[] allFields = {"namespace", "properties"};
+    Assertions.assertThat(actual)
+        .hasOnlyFields(allFields);
+    Assertions.assertThat(expected)
+        .hasOnlyFields(allFields);

Review comment:
       Good point. I'll do it in just a separate test, one time.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r801034377



##########
File path: core/src/test/java/org/apache/iceberg/rest/requests/TestCreateNamespaceRequest.java
##########
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.util.JsonUtil;
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+
+public class TestCreateNamespaceRequest {
+
+  private static final ObjectMapper MAPPER = JsonUtil.withRESTComponents();
+
+  // Non-empty
+  private static final String JSON_REQUEST_STRING =
+      "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{\"owner\":\"Hank\"}}";
+  private static final Namespace NAMESPACE = Namespace.of("accounting", "tax");
+  private static final Map<String, String> PROPERTIES = ImmutableMap.of("owner", "Hank");
+
+  // Empty - The response requires a non-empty namespace
+  private static final String JSON_REQUEST_NO_PROPERTIES =
+      "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{}}";
+
+  @Test
+  public void testDeserialize() throws JsonProcessingException {
+    CreateNamespaceRequest expected = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .withProperties(PROPERTIES)
+        .build();
+
+    CreateNamespaceRequest actual = MAPPER.readValue(JSON_REQUEST_STRING, CreateNamespaceRequest.class);
+
+    assertSame(expected, actual);
+  }
+
+  @Test
+  public void testDeserializeNoProperties() throws JsonProcessingException {
+    CreateNamespaceRequest expected = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .build();
+
+    CreateNamespaceRequest actual = MAPPER.readValue(JSON_REQUEST_NO_PROPERTIES, CreateNamespaceRequest.class);
+
+    assertSame(expected, actual);
+  }
+
+  @Test
+  public void testSerialize() throws JsonProcessingException {
+    CreateNamespaceRequest req = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .withProperties(PROPERTIES)
+        .build();
+
+    Assertions.assertThat(MAPPER.writeValueAsString(req))
+        .isEqualTo(JSON_REQUEST_STRING);
+  }
+
+  @Test
+  public void testSerializeNoProperties() throws JsonProcessingException {
+    CreateNamespaceRequest req = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .build();
+
+    Assertions.assertThat(MAPPER.writeValueAsString(req))
+        .isEqualTo(JSON_REQUEST_NO_PROPERTIES);
+  }
+
+  private static void assertSame(CreateNamespaceRequest expected, CreateNamespaceRequest actual) {
+    Assertions.assertThat(actual)
+        .satisfies(req -> {
+          Assertions.assertThat(req.namespace()).isNotNull().isEqualTo(expected.namespace());
+          Assertions.assertThat(req.properties()).isNotNull().isEqualTo(expected.properties());

Review comment:
       Removed to not use `satisfies`. I'd hoped that would provide more benefit than it did. Will remove the other `satisfies` instances as well.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r802045370



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/CreateNamespaceResponse.java
##########
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.Maps;
+
+/**
+ * Represents a REST response for a request to create a namespace / database.
+ * <p>
+ * The properties returned should include all the user provided properties from the
+ * request, as well as any server-side added properties.
+ * <p>
+ * Example server-side added properties can be implementation specific, but might include
+ * such things as `created_at` or `owner`.

Review comment:
       This has been merged.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810302277



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/UpdateNamespacePropertiesResponse.java
##########
@@ -0,0 +1,174 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.List;
+import java.util.Objects;
+import org.apache.iceberg.exceptions.ValidationException;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
+import org.apache.iceberg.util.ImmutablesUtil;
+
+/**
+ * A REST response to a request to set and/or remove properties on a namespace.
+ */
+public class UpdateNamespacePropertiesResponse {
+
+  // List of namespace property keys that were removed
+  private List<String> removed;
+  // List of namespace property keys that were added or updated
+  private List<String> updated;
+  // List of properties that were requested for removal that were not found in the namespace's properties
+  private List<String> missing;
+
+  public UpdateNamespacePropertiesResponse() {
+    // Required for Jackson deserialization
+  }
+
+  private UpdateNamespacePropertiesResponse(List<String> removed, List<String> updated, List<String> missing) {
+    this.removed = removed;
+    this.updated = updated;
+    this.missing = missing;
+    validate();
+  }
+
+  UpdateNamespacePropertiesResponse validate() {
+    ValidationException.check((removed != null && !this.removed.isEmpty()) ||
+        (updated != null && !updated.isEmpty()) || (missing != null && !missing.isEmpty()),
+        "Cannot create a response to update namespace properties if all of the fields are missing or empty");

Review comment:
       Actually, I can see an empty response being valid. For example, if the user's empty `UpdateNamespacePropertiesRequest` was sent as a way to implicitly update a server added field of `last_updated_at` or something.
   
   Changed to just ensure at least one is non-null.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810387372



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/CreateNamespaceResponse.java
##########
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+
+/**
+ * Represents a REST response for a request to create a namespace / database.
+ * <p>
+ * The properties returned should include all the user provided properties from the
+ * request, as well as any server-side added properties.
+ * <p>
+ * Example server-side added properties can be implementation specific, but might include
+ * such things as `created_at` or `owner`.
+ */
+public class CreateNamespaceResponse {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public CreateNamespaceResponse() {
+    // Required for Jackson deserialization.
+  }
+
+  private CreateNamespaceResponse(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+    validate();
+  }
+
+  // Used to check if the object is valid. This method is necessary
+  // because we let Jackson fill in the values automatically, so precondition
+  // checks aren't made.
+  //
+  // This function should be called any time this value is deserialized / instantiated.

Review comment:
       Removed as the comments add more confusion than they likely help.
   
   And if people use the `Builder`,  it should be impossible to instantiate a value that doesn't pass `validate`.
   
   This is only to handle corner cases of JSON coming in unexpected (but arguably still acceptable) ways.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r809454909



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/GetNamespaceResponse.java
##########
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.exceptions.ValidationException;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.util.ImmutablesUtil;
+
+/**
+ * Represents a REST response to fetch namespace metadata.
+ * <p>
+ * The properties returned should include all the user provided properties from the
+ * request, as well as any server-side added properties.

Review comment:
       Aren't the server-side added properties only something that `CreateNamespaceResponse` cares about? For get, those are the properties of the namespace. We don't need to make a distinction based on who set the properties.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r808552019



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/CreateNamespaceRequest.java
##########
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.exceptions.ValidationException;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+
+/**
+ * A REST request to create a namespace, with an optional set of properties.
+ * The server might also add properties, such as `last_modified_time` etc.
+ */
+public class CreateNamespaceRequest {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public CreateNamespaceRequest() {
+    // Needed for Jackson Deserialization.
+  }
+
+  private CreateNamespaceRequest(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+    validate();
+  }
+
+  /**
+   * This function needs to be called after reading in JSON from another source, to ensure
+   * that null values are assigned to their respective defaults where needed, wrap collections
+   * in their Immutable variants, and that required fields are correct.
+   * @return normalized version of this {@link CreateNamespaceRequest}
+   */
+  CreateNamespaceRequest validate() {
+    this.properties = properties == null ? ImmutableMap.of() : ImmutableMap.copyOf(properties);
+    ValidationException.check(namespace != null && !namespace.isEmpty(),
+        "Cannot build a request to create a namespace without specifying the namespace");

Review comment:
       Updated to use `Preconditions`.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810398806



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/GetNamespaceResponse.java
##########
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.exceptions.ValidationException;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.util.ImmutablesUtil;
+
+/**
+ * Represents a REST response to fetch namespace metadata.
+ * <p>
+ * The properties returned should include all the user provided properties from the
+ * request, as well as any server-side added properties.
+ */
+public class GetNamespaceResponse {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public GetNamespaceResponse() {
+    // Required for Jackson deserialization
+  }
+
+  private GetNamespaceResponse(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+    validate();
+  }
+
+  GetNamespaceResponse validate() {
+    ValidationException.check(namespace != null && !namespace.isEmpty(),
+        "Cannot build a response to get a namespace without specifying the namespace");

Review comment:
       Updated!




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r799101328



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/UpdateNamespacePropertiesResponse.java
##########
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.List;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
+
+/**
+ * A REST response to a request to set and/or remove properties on a namespace.
+ */
+public class UpdateNamespacePropertiesResponse {
+
+  // List of namespace property keys that were removed
+  private List<String> removed;
+  // List of namesspace property keys that were added or updated
+  private List<String> updated;
+  // List of properties that were requested for removal that were not found in the namespace's properties
+  private List<String> missing;
+
+  public UpdateNamespacePropertiesResponse() {
+    // Required for Jackson
+  }
+
+  private UpdateNamespacePropertiesResponse(List<String> removed, List<String> updated, List<String> missing) {
+    this.removed = removed;
+    this.updated = updated;
+    this.missing = missing;
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public List<String> removed() {
+    return ImmutableList.copyOf(removed);
+  }
+
+  public List<String> updated() {
+    return ImmutableList.copyOf(updated);
+  }
+
+  public List<String> missing() {
+    return ImmutableList.copyOf(missing);
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("removed", removed())
+        .add("updates", updated())
+        .add("missing", missing())
+        .toString();
+  }
+
+  public static class Builder {
+    private final ImmutableSet.Builder<String> removedBuilder = ImmutableSet.builder();
+    private final ImmutableSet.Builder<String> updatedBuilder = ImmutableSet.builder();
+    private final ImmutableSet.Builder<String> missingBuilder = ImmutableSet.builder();
+
+    private Builder() {
+    }
+
+    public Builder withMissing(String key) {
+      missingBuilder.add(key);
+      return this;
+    }
+
+    public Builder withMissing(Iterable<String> missing) {

Review comment:
       Good call.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r799085359



##########
File path: core/src/test/java/org/apache/iceberg/rest/requests/TestCreateNamespaceRequest.java
##########
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.util.JsonUtil;
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+
+public class TestCreateNamespaceRequest {
+
+  private static final ObjectMapper MAPPER = JsonUtil.withRESTComponents();
+
+  // Non-empty
+  private static final String JSON_REQUEST_STRING =
+      "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{\"owner\":\"Hank\"}}";
+  private static final Namespace NAMESPACE = Namespace.of("accounting", "tax");
+  private static final Map<String, String> PROPERTIES = ImmutableMap.of("owner", "Hank");
+
+  // Empty - The response requires a non-empty namespace
+  private static final String JSON_REQUEST_NO_PROPERTIES =
+      "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{}}";
+
+  @Test
+  public void testDeserialize() throws JsonProcessingException {
+    CreateNamespaceRequest expected = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .withProperties(PROPERTIES)
+        .build();
+
+    CreateNamespaceRequest actual = MAPPER.readValue(JSON_REQUEST_STRING, CreateNamespaceRequest.class);
+
+    assertSame(expected, actual);
+  }
+
+  @Test
+  public void testDeserializeNoProperties() throws JsonProcessingException {
+    CreateNamespaceRequest expected = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .build();
+
+    CreateNamespaceRequest actual = MAPPER.readValue(JSON_REQUEST_NO_PROPERTIES, CreateNamespaceRequest.class);
+
+    assertSame(expected, actual);
+  }
+
+  @Test
+  public void testSerialize() throws JsonProcessingException {
+    CreateNamespaceRequest req = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .withProperties(PROPERTIES)
+        .build();
+
+    Assertions.assertThat(MAPPER.writeValueAsString(req))
+        .isEqualTo(JSON_REQUEST_STRING);
+  }
+
+  @Test
+  public void testSerializeNoProperties() throws JsonProcessingException {
+    CreateNamespaceRequest req = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .build();
+
+    Assertions.assertThat(MAPPER.writeValueAsString(req))
+        .isEqualTo(JSON_REQUEST_NO_PROPERTIES);
+  }
+
+  private static void assertSame(CreateNamespaceRequest expected, CreateNamespaceRequest actual) {
+    Assertions.assertThat(actual)
+        .satisfies(req -> {
+          Assertions.assertThat(req.namespace()).isNotNull().isEqualTo(expected.namespace());
+          Assertions.assertThat(req.properties()).isNotNull().isEqualTo(expected.properties());

Review comment:
       Looks like you can call these directly rather than using satisfies.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r799764690



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/CreateNamespaceRequest.java
##########
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+
+/**
+ * A REST request to create a namespace, with an optional set of properties.
+ * The server might also add properties, such as `last_modified_time` etc.
+ */
+public class CreateNamespaceRequest {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public CreateNamespaceRequest() {
+    // Required for Jackson deserialization
+  }
+
+  private CreateNamespaceRequest(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public Namespace namespace() {
+    return namespace;
+  }
+
+  public Map<String, String> properties() {
+    return ImmutableMap.copyOf(properties);
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("namespace", namespace)
+        .add("properties", properties)
+        .toString();
+  }
+
+  public static class Builder {
+    private Namespace namespace;
+    private ImmutableMap.Builder<String, String> properties = ImmutableMap.builder();
+
+    private Builder() {
+    }
+
+    public Builder withNamespace(Namespace ns) {
+      this.namespace = ns;
+      return this;
+    }
+
+    public Builder withProperties(Map<String, String> props) {
+      this.properties.putAll(props);
+      return this;
+    }
+
+    public CreateNamespaceRequest build() {
+      Preconditions.checkArgument(
+          namespace != null && !namespace.isEmpty(),
+          "Cannot build a response to create a namespace without specifying the namespace");

Review comment:
       I'll be adding more unit tests for the non-happy paths. I removed some of the tests I had for preconditions (as some of the preconditions were determined to not be needed) and I might have accidentally removed this one. I'll find where I stashed it and add it in if needed (there's also been thought given to removing the `Preconditions` to provide more flexibility to implementors). 👍 
   
   But agree on the non-happy path testing. I didn't want to clutter the PR too much at first in case things needed to get majorly updated.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r799782812



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/CreateNamespaceResponse.java
##########
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.Maps;
+
+/**
+ * Represents a REST response for a request to create a namespace / database.
+ * <p>
+ * The properties returned should include all the user provided properties from the
+ * request, as well as any server-side added properties.
+ * <p>
+ * Example server-side added properties can be implementation specific, but might include
+ * such things as `created_at` or `owner`.

Review comment:
       Opened a PR to update the spec: https://github.com/apache/iceberg/pull/4039




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r801136476



##########
File path: core/src/test/java/org/apache/iceberg/rest/requests/TestCreateNamespaceRequest.java
##########
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.util.JsonUtil;
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+
+public class TestCreateNamespaceRequest {

Review comment:
       Added a few tests for malformed.
   
   Specifically added:
   - an empty json
   - (String) null - simulating if the response entity has no body at all
   -  fields are spelled incorrectly
   - `namespace` / `properties` have fields that aren't the correct type (invalid data)
   
   I agree that extra fields should just be ignored.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r801148700



##########
File path: rest_docs/rest-catalog-open-api.yaml
##########
@@ -29,34 +29,39 @@ info:
     Defines the specification for the first version of the REST Catalog API.
     Implementations should ideally support both Iceberg table specs v1 and v2, with priority given to v2.
 servers:
-  - url: "{scheme}://{host}/{basePath}"
+  - url: '{scheme}://{host}/{basePath}'

Review comment:
       These have been removed. Sorry about that!




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r807421354



##########
File path: core/src/main/java/org/apache/iceberg/catalog/TableIdentifierParser.java
##########
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.catalog;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.JsonNode;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.UncheckedIOException;
+import java.util.List;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.util.JsonUtil;
+
+/**
+ * Parses TableIdentifiers from a JSON representation, which is the JSON
+ * representation utilized in the REST catalog.
+ * <p>
+ * For TableIdentifier.of("dogs", "owners.and.handlers", "food"), we'd have
+ * the following JSON representation, where the dot character of an
+ * individual level is in the namespace is replaced by the null byte character.
+ * <pre>
+ * {
+ *   "namespace": ["dogs", "owners.and.handlers"],
+ *   "name": "food"
+ * }
+ * </pre>
+ */
+public class TableIdentifierParser {
+
+  private static final String NAMESPACE = "namespace";
+  private static final String NAME = "name";
+
+  private TableIdentifierParser() {
+  }
+
+  public static String toJson(TableIdentifier identifier) {
+    return toJson(identifier, false);
+  }
+
+  public static String toJson(TableIdentifier identifier, boolean pretty) {
+    try {
+      StringWriter writer = new StringWriter();
+      JsonGenerator generator = JsonUtil.factory().createGenerator(writer);
+      if (pretty) {
+        generator.useDefaultPrettyPrinter();
+      }
+      toJson(identifier, generator);
+      generator.flush();
+      return writer.toString();
+    } catch (IOException e) {
+      throw new UncheckedIOException(String.format("Failed to write json for: %s", identifier), e);
+    }
+  }
+
+  public static void toJson(TableIdentifier identifier, JsonGenerator generator) throws IOException {

Review comment:
       Presently it's used in `org.apache.iceberg.rest.RESTSerializers`, so it can't be made package-private as is.
   
   The `JsonSerializer<TableIdentifier>` (and corresponding Deserializer) could be moved into another class that is public, which calls into this one that is package private? 
   




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r807442815



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/CreateNamespaceRequest.java
##########
@@ -0,0 +1,128 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.exceptions.ValidationException;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.util.ImmutablesUtil;
+
+/**
+ * A REST request to create a namespace, with an optional set of properties.
+ * The server might also add properties, such as `last_modified_time` etc.
+ */
+public class CreateNamespaceRequest {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public CreateNamespaceRequest() {
+    // Needed for Jackson Deserialization.
+  }
+
+  private CreateNamespaceRequest(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+    validate();
+  }
+
+  CreateNamespaceRequest validate() {
+    ValidationException.check(namespace != null && !namespace.isEmpty(),
+        "Cannot build a request to create a namespace without specifying the namespace");
+    return this;
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public Namespace namespace() {
+    return namespace;
+  }
+
+  public Map<String, String> properties() {
+    return ImmutablesUtil.nullSafeCopyOf(properties);
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("namespace", namespace)
+        .add("properties", properties)
+        .toString();
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+
+    CreateNamespaceRequest request = (CreateNamespaceRequest) o;
+    return namespace.equals(request.namespace) && Objects.equals(properties, request.properties);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(namespace, properties);
+  }
+
+  public static class Builder {
+    private Namespace namespace;
+    private ImmutableMap.Builder<String, String> properties;
+
+    private Builder() {
+    }
+
+    public Builder withNamespace(Namespace ns) {
+      this.namespace = ns;
+      return this;
+    }
+
+    public Builder setProperties(Map<String, String> props) {

Review comment:
       This doesn't work like the other builders where we have, for example, `update` and `updateAll` that don't replace the entire map.
   
   I would say that if you pass `null` here then this method should fail with a `NullPointerException` in `properties.putAll`.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r807437227



##########
File path: core/src/main/java/org/apache/iceberg/rest/RESTUtils.java
##########
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.core.JsonFactory;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class RESTUtils {

Review comment:
       Most util classes in the codebase use a singular `Util` suffix. Not a big deal, but it would be nice to match.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r807441925



##########
File path: core/src/main/java/org/apache/iceberg/rest/RESTUtils.java
##########
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.core.JsonFactory;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class RESTUtils {
+
+  private RESTUtils() {
+  }

Review comment:
       This class appears to only be used in tests. Is it necessary to make it public?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] jackye1995 commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
jackye1995 commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r800918343



##########
File path: rest_docs/rest-catalog-open-api.yaml
##########
@@ -29,34 +29,39 @@ info:
     Defines the specification for the first version of the REST Catalog API.
     Implementations should ideally support both Iceberg table specs v1 and v2, with priority given to v2.
 servers:
-  - url: "{scheme}://{host}/{basePath}"
+  - url: '{scheme}://{host}/{basePath}'

Review comment:
       can we have a separated PR just for this to fix the quotation and other unrelated stuffs?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: [WIP] REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r807382003



##########
File path: core/src/main/java/org/apache/iceberg/catalog/TableIdentifierParser.java
##########
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.catalog;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.JsonNode;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.UncheckedIOException;
+import java.util.List;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.util.JsonUtil;
+
+/**
+ * Parses TableIdentifiers from a JSON representation, which is the JSON
+ * representation utilized in the REST catalog.
+ * <p>
+ * For TableIdentifier.of("dogs", "owners.and.handlers", "food"), we'd have
+ * the following JSON representation, where the dot character of an
+ * individual level is in the namespace is replaced by the null byte character.
+ * <pre>
+ * {
+ *   "namespace": ["dogs", "owners.and.handlers"],
+ *   "name": "food"
+ * }
+ * </pre>
+ */
+public class TableIdentifierParser {
+
+  private static final String NAMESPACE = "namespace";
+  private static final String NAME = "name";
+
+  private TableIdentifierParser() {
+  }
+
+  public static String toJson(TableIdentifier identifier) {
+    return toJson(identifier, false);
+  }
+
+  public static String toJson(TableIdentifier identifier, boolean pretty) {
+    try {
+      StringWriter writer = new StringWriter();
+      JsonGenerator generator = JsonUtil.factory().createGenerator(writer);
+      if (pretty) {
+        generator.useDefaultPrettyPrinter();
+      }
+      toJson(identifier, generator);
+      generator.flush();
+      return writer.toString();
+    } catch (IOException e) {
+      throw new UncheckedIOException(String.format("Failed to write json for: %s", identifier), e);
+    }
+  }
+
+  public static void toJson(TableIdentifier identifier, JsonGenerator generator) throws IOException {

Review comment:
       I don't think this should be `public` because we don't want to leak Jackson in our API. Can it be private or package-private?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r809495576



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/UpdateNamespacePropertiesRequest.java
##########
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.List;
+import java.util.Map;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
+
+/**
+ * A REST request to set and/or remove properties on a namespace.
+ * <p>
+ * The request body specifies a list of properties to remove and a map
+ * of key value pairs to update.
+ * <p>
+ * Properties that are not in the request are not modified or removed by this call.
+ * Server implementations are not required to support namespace properties.
+ */
+public class UpdateNamespacePropertiesRequest {
+
+  private List<String> removals;
+  private Map<String, String> updates;
+
+  public UpdateNamespacePropertiesRequest() {
+    // Required for Jackson deserialization.
+  }
+
+  private UpdateNamespacePropertiesRequest(List<String> removals, Map<String, String> updates) {
+    this.removals = removals;
+    this.updates = updates;
+    validate();
+  }
+
+  UpdateNamespacePropertiesRequest validate() {
+    Preconditions.checkArgument((removals != null && !removals.isEmpty()) || (updates != null && !updates.isEmpty()),
+        "Cannot create a request to update a namespace's properties without specifying any props to update or remove");
+    return this;
+  }
+
+  public List<String> removals() {
+    return removals == null ? ImmutableList.of() : removals;
+  }
+
+  public Map<String, String> updates() {
+    return updates == null ? ImmutableMap.of() : updates;
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("removals", removals)
+        .add("updates", updates)
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public static class Builder {
+    private final ImmutableSet.Builder<String> removalsBuilder = ImmutableSet.builder();
+    private final ImmutableMap.Builder<String, String> updatesBuilder = ImmutableMap.builder();
+
+    private Builder() {
+    }
+
+    public Builder remove(String removal) {
+      Preconditions.checkNotNull(removal,
+          "Cannot pass null key to remove to UpdateNamespacePropertiesRequest.Builder");

Review comment:
       Updated.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r808440390



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/CreateNamespaceRequest.java
##########
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.exceptions.ValidationException;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+
+/**
+ * A REST request to create a namespace, with an optional set of properties.
+ * The server might also add properties, such as `last_modified_time` etc.
+ */
+public class CreateNamespaceRequest {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public CreateNamespaceRequest() {
+    // Needed for Jackson Deserialization.
+  }
+
+  private CreateNamespaceRequest(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+    validate();
+  }
+
+  /**
+   * This function needs to be called after reading in JSON from another source, to ensure
+   * that null values are assigned to their respective defaults where needed, wrap collections
+   * in their Immutable variants, and that required fields are correct.
+   * @return normalized version of this {@link CreateNamespaceRequest}
+   */
+  CreateNamespaceRequest validate() {
+    this.properties = properties == null ? ImmutableMap.of() : ImmutableMap.copyOf(properties);
+    ValidationException.check(namespace != null && !namespace.isEmpty(),
+        "Cannot build a request to create a namespace without specifying the namespace");
+    return this;
+  }
+
+  public Namespace namespace() {
+    return namespace;
+  }
+
+  public Map<String, String> properties() {
+    return properties;
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("namespace", namespace)
+        .add("properties", properties)
+        .toString();
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+
+    CreateNamespaceRequest request = (CreateNamespaceRequest) o;
+    return namespace.equals(request.namespace) && Objects.equals(properties, request.properties);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(namespace, properties);
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public static class Builder {
+    private Namespace namespace;
+    private final ImmutableMap.Builder<String, String> properties = ImmutableMap.builder();
+
+    private Builder() {
+    }
+
+    public Builder withNamespace(Namespace ns) {
+      this.namespace = ns;
+      return this;
+    }
+
+    public Builder setProperties(Map<String, String> props) {
+      ValidationException.check(props != null,
+          "Cannot pass null properties to CreateNamespaceRequest.Builder");
+      properties.putAll(props);
+      return this;
+    }
+
+    public CreateNamespaceRequest build() {
+      return new CreateNamespaceRequest(namespace, properties.build());

Review comment:
       Add a precondition that namespace is not null?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810276788



##########
File path: core/src/main/java/org/apache/iceberg/catalog/TableIdentifierParser.java
##########
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.catalog;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.JsonNode;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.UncheckedIOException;
+import java.util.List;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.util.JsonUtil;
+
+/**
+ * Parses TableIdentifiers from a JSON representation, which is the JSON
+ * representation utilized in the REST catalog.
+ * <p>
+ * For TableIdentifier.of("dogs", "owners.and.handlers", "food"), we'd have
+ * the following JSON representation, where the dot character of an
+ * individual level is in the namespace is replaced by the null byte character.
+ * <pre>
+ * {
+ *   "namespace": ["dogs", "owners.and.handlers"],
+ *   "name": "food"
+ * }
+ * </pre>
+ */
+public class TableIdentifierParser {
+
+  private static final String NAMESPACE = "namespace";
+  private static final String NAME = "name";
+
+  private TableIdentifierParser() {
+  }
+
+  public static String toJson(TableIdentifier identifier) {
+    return toJson(identifier, false);
+  }
+
+  public static String toJson(TableIdentifier identifier, boolean pretty) {
+    try {
+      StringWriter writer = new StringWriter();
+      JsonGenerator generator = JsonUtil.factory().createGenerator(writer);
+      if (pretty) {
+        generator.useDefaultPrettyPrinter();
+      }
+      toJson(identifier, generator);
+      generator.flush();
+      return writer.toString();
+    } catch (IOException e) {
+      throw new UncheckedIOException(String.format("Failed to write json for: %s", identifier), e);
+    }
+  }
+
+  public static void toJson(TableIdentifier identifier, JsonGenerator generator) throws IOException {
+    generator.writeStartObject();
+    generator.writeFieldName(NAMESPACE);
+    generator.writeArray(identifier.namespace().levels(), 0, identifier.namespace().length());
+    generator.writeStringField(NAME, identifier.name());
+    generator.writeEndObject();
+  }
+
+  public static TableIdentifier fromJson(String json) {
+    Preconditions.checkArgument(json != null && !json.isEmpty(),
+        "Cannot parse table identifier from invalid JSON: %s", json);

Review comment:
       Good point. This is actually chekcking if the table identifier json is simply the empty string, but I am not allowing for / testing for a table identifier that uses the empty namespace.
   
   Updating and testing for that.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810398213



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/DropNamespaceResponse.java
##########
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Objects;
+import org.apache.iceberg.exceptions.ValidationException;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+
+/**
+ * Represents a REST response to drop a namespace.
+ * <p>
+ * The server may choose to return an error if the namespace is not empty.
+ */
+public class DropNamespaceResponse {
+
+  // For Jackson to properly fail when deserializing, this needs to be boxed.
+  // Otherwise, the boolean is parsed according to "loose" javascript JSON rules.
+  private Boolean dropped;
+
+  public DropNamespaceResponse() {
+    // Required for Jackson deserialization
+  }
+
+  private DropNamespaceResponse(Boolean dropped) {
+    this.dropped = dropped;
+    validate();
+  }
+
+  DropNamespaceResponse validate() {
+    // Use `checkArguemt` so it will throw IllegalArgumentException, just like the other responses
+    Preconditions.checkArgument(dropped != null,
+        "Cannot instantiate a response to dropping a namespace with missing field(s): `dropped`");
+    return this;
+  }
+
+  public boolean isDropped() {
+    return dropped;
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("dropped", dropped)
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public static class Builder {
+    private Boolean dropped = false;
+
+    private Builder() {
+    }
+
+    public Builder dropped(Boolean isDropped) {

Review comment:
       Updated.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r808551731



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/CreateNamespaceRequest.java
##########
@@ -0,0 +1,128 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.exceptions.ValidationException;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.util.ImmutablesUtil;
+
+/**
+ * A REST request to create a namespace, with an optional set of properties.
+ * The server might also add properties, such as `last_modified_time` etc.
+ */
+public class CreateNamespaceRequest {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public CreateNamespaceRequest() {
+    // Needed for Jackson Deserialization.
+  }
+
+  private CreateNamespaceRequest(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+    validate();
+  }
+
+  CreateNamespaceRequest validate() {
+    ValidationException.check(namespace != null && !namespace.isEmpty(),
+        "Cannot build a request to create a namespace without specifying the namespace");
+    return this;
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public Namespace namespace() {
+    return namespace;
+  }
+
+  public Map<String, String> properties() {
+    return ImmutablesUtil.nullSafeCopyOf(properties);
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("namespace", namespace)
+        .add("properties", properties)
+        .toString();
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+
+    CreateNamespaceRequest request = (CreateNamespaceRequest) o;
+    return namespace.equals(request.namespace) && Objects.equals(properties, request.properties);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(namespace, properties);
+  }
+
+  public static class Builder {
+    private Namespace namespace;
+    private ImmutableMap.Builder<String, String> properties;
+
+    private Builder() {
+    }
+
+    public Builder withNamespace(Namespace ns) {
+      this.namespace = ns;
+      return this;
+    }
+
+    public Builder setProperties(Map<String, String> props) {

Review comment:
       Updated to NPE via `Preconditions.checkNotNull`.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r809451663



##########
File path: core/src/test/java/org/apache/iceberg/rest/responses/TestCreateNamespaceResponse.java
##########
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import java.util.Map;
+import org.apache.iceberg.AssertHelpers;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.rest.RequestResponseTestBase;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestCreateNamespaceResponse extends RequestResponseTestBase<CreateNamespaceResponse> {
+
+  /* Values used to fill in response fields */
+  private static final Namespace NAMESPACE = Namespace.of("accounting", "tax");
+  private static final Map<String, String> PROPERTIES = ImmutableMap.of("owner", "Hank");
+  private static final Map<String, String> EMPTY_PROPERTIES = ImmutableMap.of();
+
+  @Test
+  // Test cases that are JSON that can be created via the Builder
+  public void testRoundTripSerDe() throws JsonProcessingException {
+    String fullJson = "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{\"owner\":\"Hank\"}}";
+    CreateNamespaceResponse req = CreateNamespaceResponse
+        .builder().withNamespace(NAMESPACE).setProperties(PROPERTIES).build();
+    assertRoundTripSerializesEquallyFrom(fullJson, req);
+
+    String jsonEmptyProperties = "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{}}";
+    CreateNamespaceResponse responseWithExplicitEmptyProperties = CreateNamespaceResponse.builder()
+        .withNamespace(NAMESPACE).setProperties(EMPTY_PROPERTIES).build();
+    assertRoundTripSerializesEquallyFrom(jsonEmptyProperties, responseWithExplicitEmptyProperties);
+
+    CreateNamespaceResponse responseWithImplicitEmptyProperties = CreateNamespaceResponse.builder()
+        .withNamespace(NAMESPACE).build();
+    assertRoundTripSerializesEquallyFrom(jsonEmptyProperties, responseWithImplicitEmptyProperties);
+  }
+
+  @Test

Review comment:
       It looks like there's no equivalent here of the `testCanDeserializeWithoutDefaultValues` for `CreateNamespaceRequest`. Is that different for the response?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810399061



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/UpdateNamespacePropertiesRequest.java
##########
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.List;
+import java.util.Map;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
+
+/**
+ * A REST request to set and/or remove properties on a namespace.
+ * <p>
+ * The request body specifies a list of properties to remove and a map
+ * of key value pairs to update.
+ * <p>
+ * Properties that are not in the request are not modified or removed by this call.
+ * Server implementations are not required to support namespace properties.

Review comment:
       Removed.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810391506



##########
File path: core/src/test/java/org/apache/iceberg/rest/requests/TestCreateNamespaceRequest.java
##########
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.util.JsonUtil;
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+
+public class TestCreateNamespaceRequest {
+
+  private static final ObjectMapper MAPPER = JsonUtil.withRESTComponents();
+
+  private static final String[] ALL_FIELDS_FROM_SPEC = { "namespace", "properties" };
+
+  /* Values used to fill in request fields */
+  private static final Namespace NAMESPACE = Namespace.of("accounting", "tax");
+  private static final Map<String, String> PROPERTIES = ImmutableMap.of("owner", "Hank");
+
+  /* JSON of requests */
+  private static final String JSON_REQUEST =
+      "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{\"owner\":\"Hank\"}}";
+  private static final String JSON_REQUEST_EMPTY_PROPERTIES =
+      "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{}}";
+
+  @Test
+  public void testDeserialize() throws JsonProcessingException {
+    CreateNamespaceRequest expected = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .withProperties(PROPERTIES)
+        .build();
+
+    CreateNamespaceRequest actual = MAPPER.readValue(JSON_REQUEST, CreateNamespaceRequest.class);
+
+    assertEquals(expected, actual);
+    assertHasOnlyKnownFields(expected);
+    assertHasOnlyKnownFields(actual);
+  }
+
+  @Test
+  public void testDeserializeEmptyProperties() throws JsonProcessingException {
+    CreateNamespaceRequest expected = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .build();
+
+    CreateNamespaceRequest actual = MAPPER.readValue(JSON_REQUEST_EMPTY_PROPERTIES, CreateNamespaceRequest.class);
+
+    assertEquals(expected, actual);
+    assertHasOnlyKnownFields(expected);
+    assertHasOnlyKnownFields(actual);
+  }
+
+  @Test
+  public void testSerialize() throws JsonProcessingException {
+    CreateNamespaceRequest req = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .withProperties(PROPERTIES)
+        .build();
+
+    Assertions.assertThat(MAPPER.writeValueAsString(req))
+        .isEqualTo(JSON_REQUEST);
+  }
+
+  @Test
+  public void testSerializeEmptyProperties() throws JsonProcessingException {
+    CreateNamespaceRequest req = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .build();
+
+    Assertions.assertThat(MAPPER.writeValueAsString(req))
+        .isEqualTo(JSON_REQUEST_EMPTY_PROPERTIES);
+  }
+
+  private static void assertEquals(CreateNamespaceRequest expected, CreateNamespaceRequest actual) {
+    Assertions.assertThat(actual.namespace()).isEqualTo(expected.namespace());

Review comment:
       So implementing `equals` lead to having to jump through a lot of hoops to ensure the builder couldn't create values with `null` where not accessed (and lazily instantiate a number of things).
   
   Long story short, it lead to writing a lot of code that was more to get tests to pass than for the class to work. So I've extracted out an abstract base test class, and then it required the implementation of `assertEquals`. It also still checks that it knows of all fields. So if somebody adds a field, it will be caught by the test.
   
   I can show you further, but it was definitely uglier due to comparing `null` with empty collections (`null` coming from deserialization and empty collections coming from the builder by default).




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810386822



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/CreateNamespaceResponse.java
##########
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+
+/**
+ * Represents a REST response for a request to create a namespace / database.
+ * <p>
+ * The properties returned should include all the user provided properties from the
+ * request, as well as any server-side added properties.
+ * <p>
+ * Example server-side added properties can be implementation specific, but might include
+ * such things as `created_at` or `owner`.
+ */
+public class CreateNamespaceResponse {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public CreateNamespaceResponse() {
+    // Required for Jackson deserialization.
+  }
+
+  private CreateNamespaceResponse(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+    validate();
+  }
+
+  // Used to check if the object is valid. This method is necessary
+  // because we let Jackson fill in the values automatically, so precondition

Review comment:
       Yeah removed. These aren't necessary.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r811412445



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/UpdateNamespacePropertiesRequest.java
##########
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
+import org.apache.iceberg.relocated.com.google.common.collect.Maps;
+
+/**
+ * A REST request to set and/or remove properties on a namespace.
+ */
+public class UpdateNamespacePropertiesRequest {
+
+  private List<String> removals;
+  private Map<String, String> updates;
+
+  public UpdateNamespacePropertiesRequest() {
+    // Required for Jackson deserialization.
+  }
+
+  private UpdateNamespacePropertiesRequest(List<String> removals, Map<String, String> updates) {
+    this.removals = removals;
+    this.updates = updates;
+    validate();
+  }
+
+  UpdateNamespacePropertiesRequest validate() {
+    Preconditions.checkArgument(removals != null || updates != null,
+        "Invalid value for update namespace properties request: at least one of updates and removals must be non-null");

Review comment:
       Yeah I agree. And the original motivation was to disallow requests that I thought didn't make sense, but if the server is updating properties itself on every update properties call, such as a `last_updated_at` timestamp, then an empty request would be valid. We shouldn't disallow that.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r811449680



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/DropNamespaceResponse.java
##########
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Objects;
+import org.apache.iceberg.exceptions.ValidationException;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+
+/**
+ * Represents a REST response to drop a namespace.
+ * <p>
+ * The server may choose to return an error if the namespace is not empty.
+ */
+public class DropNamespaceResponse {
+
+  // For Jackson to properly fail when deserializing, this needs to be boxed.
+  // Otherwise, the boolean is parsed according to "loose" javascript JSON rules.
+  private Boolean dropped;
+
+  public DropNamespaceResponse() {
+    // Required for Jackson deserialization
+  }
+
+  private DropNamespaceResponse(Boolean dropped) {
+    this.dropped = dropped;
+    validate();
+  }
+
+  DropNamespaceResponse validate() {
+    // Use `checkArguemt` so it will throw IllegalArgumentException, just like the other responses
+    Preconditions.checkArgument(dropped != null,
+        "Cannot instantiate a response to dropping a namespace with missing field(s): `dropped`");
+    return this;
+  }
+
+  public boolean isDropped() {
+    return dropped;
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("dropped", dropped)
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public static class Builder {
+    private Boolean dropped = false;
+
+    private Builder() {
+    }
+
+    public Builder dropped(Boolean isDropped) {
+      this.dropped = isDropped;
+      return this;
+    }
+
+    public DropNamespaceResponse build() {
+      return new DropNamespaceResponse(dropped);

Review comment:
       Yeah, that's why I suggested checking whether dropped is null. I think you want to catch when `dropped` wasn't configured.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r811469449



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/UpdateNamespacePropertiesRequest.java
##########
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
+import org.apache.iceberg.relocated.com.google.common.collect.Maps;
+
+/**
+ * A REST request to set and/or remove properties on a namespace.
+ */
+public class UpdateNamespacePropertiesRequest {
+
+  private List<String> removals;
+  private Map<String, String> updates;
+
+  public UpdateNamespacePropertiesRequest() {
+    // Required for Jackson deserialization.
+  }
+
+  private UpdateNamespacePropertiesRequest(List<String> removals, Map<String, String> updates) {
+    this.removals = removals;
+    this.updates = updates;
+    validate();
+  }
+
+  UpdateNamespacePropertiesRequest validate() {
+    return this;
+  }
+
+  public List<String> removals() {
+    return removals == null ? ImmutableList.of() : removals;
+  }
+
+  public Map<String, String> updates() {
+    return updates == null ? ImmutableMap.of() : updates;
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("removals", removals)
+        .add("updates", updates)
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public static class Builder {
+    private final ImmutableSet.Builder<String> removalsBuilder = ImmutableSet.builder();
+    private final ImmutableMap.Builder<String, String> updatesBuilder = ImmutableMap.builder();
+
+    private Builder() {
+    }
+
+    public Builder remove(String removal) {
+      Preconditions.checkNotNull(removal,
+          "Invalid property to remove: null");
+      removalsBuilder.add(removal);
+      return this;
+    }
+
+    public Builder removeAll(Collection<String> removals) {

Review comment:
       Wasn't this an Iterable<String> before?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r811427587



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/DropNamespaceResponse.java
##########
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+
+/**
+ * Represents a REST response to drop a namespace.
+ * <p>
+ * The server may choose to return an error if the namespace is not empty.
+ */
+public class DropNamespaceResponse {
+
+  // For Jackson to properly fail when deserializing, this needs to be boxed.
+  // Otherwise, the boolean is parsed according to "loose" javascript JSON rules.
+  private Boolean dropped;
+
+  public DropNamespaceResponse() {
+    // Required for Jackson deserialization
+  }
+
+  private DropNamespaceResponse(boolean dropped) {
+    this.dropped = dropped;
+    validate();
+  }
+
+  DropNamespaceResponse validate() {
+    Preconditions.checkArgument(dropped != null,
+        "Cannot instantiate a response to dropping a namespace with missing field: dropped");

Review comment:
       Updated.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#issuecomment-1047317828


   Thanks, @kbendick! I think this covers all of the review items so I'll merge this. I'm sure there will be stuff to fix in follow ups, but it's good to get this in and be able to build on top of it. Thanks!


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r799078763



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/CreateNamespaceRequest.java
##########
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.Joiner;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.Maps;
+
+/**
+ * A REST request to create a namespace, with an optional set of properties.
+ * The server might also add properties, such as `last_modified_time` etc.
+ */
+public class CreateNamespaceRequest {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public CreateNamespaceRequest() {
+    // Required for serialization

Review comment:
       Do you mean deserialization?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r799100113



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/ListTablesResponse.java
##########
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Collection;
+import java.util.List;
+import org.apache.iceberg.catalog.TableIdentifier;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+
+/**
+ * A list of table identifiers, parsed from a REST response to a request for listing tables
+ * in a given namespace.
+ */
+public class ListTablesResponse {
+
+  private List<TableIdentifier> identifiers;
+
+  public ListTablesResponse() {
+    // Required for Jackson
+  }
+
+  private ListTablesResponse(List<TableIdentifier> identifiers) {
+    this.identifiers = identifiers;
+  }
+
+  public List<TableIdentifier> identifiers() {
+    return ImmutableList.copyOf(identifiers);
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("identifiers", identifiers())
+        .toString();
+  }
+
+  public static class Builder {
+    private final ImmutableList.Builder<TableIdentifier> identifiers = ImmutableList.builder();
+
+    private Builder() {
+    }
+
+    public Builder withIdentifiers(Collection<TableIdentifier> toAdd) {

Review comment:
       Agreed and updated




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r799084763



##########
File path: core/src/test/java/org/apache/iceberg/rest/requests/TestCreateNamespaceRequest.java
##########
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.util.JsonUtil;
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+
+public class TestCreateNamespaceRequest {
+
+  private static final ObjectMapper MAPPER = JsonUtil.withRESTComponents();
+
+  // Non-empty
+  private static final String JSON_REQUEST_STRING =
+      "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{\"owner\":\"Hank\"}}";
+  private static final Namespace NAMESPACE = Namespace.of("accounting", "tax");
+  private static final Map<String, String> PROPERTIES = ImmutableMap.of("owner", "Hank");
+
+  // Empty - The response requires a non-empty namespace
+  private static final String JSON_REQUEST_NO_PROPERTIES =
+      "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{}}";
+
+  @Test
+  public void testDeserialize() throws JsonProcessingException {
+    CreateNamespaceRequest expected = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .withProperties(PROPERTIES)
+        .build();
+
+    CreateNamespaceRequest actual = MAPPER.readValue(JSON_REQUEST_STRING, CreateNamespaceRequest.class);
+
+    assertSame(expected, actual);
+  }
+
+  @Test
+  public void testDeserializeNoProperties() throws JsonProcessingException {
+    CreateNamespaceRequest expected = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .build();
+
+    CreateNamespaceRequest actual = MAPPER.readValue(JSON_REQUEST_NO_PROPERTIES, CreateNamespaceRequest.class);
+
+    assertSame(expected, actual);
+  }
+
+  @Test
+  public void testSerialize() throws JsonProcessingException {

Review comment:
       This is good because if we're relying on Jackson to automatically decide how to serialize a payload, we need to ensure that it matches the spec.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r799076344



##########
File path: core/src/main/java/org/apache/iceberg/rest/RESTJacksonModule.java
##########
@@ -0,0 +1,183 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import java.io.IOException;
+import org.apache.iceberg.PartitionSpec;
+import org.apache.iceberg.PartitionSpecParser;
+import org.apache.iceberg.Schema;
+import org.apache.iceberg.SchemaParser;
+import org.apache.iceberg.SortOrder;
+import org.apache.iceberg.SortOrderParser;
+import org.apache.iceberg.TableMetadata;
+import org.apache.iceberg.TableMetadataParser;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.catalog.TableIdentifier;
+
+public class RESTJacksonModule {

Review comment:
       I think there's probably a better name for this module. Using "Jackson" ties this to the implementation, which we probably don't want. And "module" seems like an extra word that isn't carrying a lot of meaning, to me at least.
   
   How about `RESTSerializers` instead?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r799075359



##########
File path: core/src/main/java/org/apache/iceberg/util/JsonUtil.java
##########
@@ -117,6 +127,31 @@ public static String getStringOrNull(String property, JsonNode node) {
     return builder.build();
   }
 
+  public static Map<String, String> getStringMapOrNull(String property, JsonNode node) {
+    if (!node.has(property)) {
+      return null;
+    }
+
+    JsonNode pNode = node.get(property);
+    if (pNode == null || pNode.isNull()) {
+      return null;
+    }
+
+    Preconditions.checkArgument(pNode.isObject(),
+        "Cannot parse %s from non-object value: %s", property, pNode);
+    return buildStringMapFromJsonNodeObject(pNode);
+  }
+
+  private static Map<String, String> buildStringMapFromJsonNodeObject(JsonNode pNode) {
+    ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
+    Iterator<String> fields = pNode.fieldNames();
+    while (fields.hasNext()) {
+      String field = fields.next();
+      builder.put(field, getString(field, pNode));
+    }
+    return builder.build();

Review comment:
       This function is written such that it can be used in `getStringMap` and the differences between `getStringMap` and `getStringMapOrNull` would be in precondition checks, but I chose not to make that change to the existing code for now.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r809460305



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/UpdateNamespacePropertiesRequest.java
##########
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.List;
+import java.util.Map;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
+
+/**
+ * A REST request to set and/or remove properties on a namespace.
+ * <p>
+ * The request body specifies a list of properties to remove and a map
+ * of key value pairs to update.
+ * <p>
+ * Properties that are not in the request are not modified or removed by this call.
+ * Server implementations are not required to support namespace properties.
+ */
+public class UpdateNamespacePropertiesRequest {
+
+  private List<String> removals;
+  private Map<String, String> updates;
+
+  public UpdateNamespacePropertiesRequest() {
+    // Required for Jackson deserialization.
+  }
+
+  private UpdateNamespacePropertiesRequest(List<String> removals, Map<String, String> updates) {
+    this.removals = removals;
+    this.updates = updates;
+    validate();
+  }
+
+  UpdateNamespacePropertiesRequest validate() {
+    Preconditions.checkArgument((removals != null && !removals.isEmpty()) || (updates != null && !updates.isEmpty()),
+        "Cannot create a request to update a namespace's properties without specifying any props to update or remove");
+    return this;
+  }
+
+  public List<String> removals() {
+    return removals == null ? ImmutableList.of() : removals;
+  }
+
+  public Map<String, String> updates() {
+    return updates == null ? ImmutableMap.of() : updates;
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("removals", removals)
+        .add("updates", updates)
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public static class Builder {
+    private final ImmutableSet.Builder<String> removalsBuilder = ImmutableSet.builder();
+    private final ImmutableMap.Builder<String, String> updatesBuilder = ImmutableMap.builder();
+
+    private Builder() {
+    }
+
+    public Builder remove(String removal) {
+      Preconditions.checkNotNull(removal,
+          "Cannot pass null key to remove to UpdateNamespacePropertiesRequest.Builder");

Review comment:
       I usually avoid adding class names in error messages. Classes are part of the trace information anyway, so it will be clear where this happened. Not including it means not needing to update it if names change later. And it makes the error message easier to understand: "Invalid property to remove: null".
   
   I would also not refer to this as "key" because these are properties.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r809463996



##########
File path: core/src/test/java/org/apache/iceberg/rest/requests/TestUpdateNamespacePropertiesRequest.java
##########
@@ -0,0 +1,162 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import java.util.List;
+import java.util.Map;
+import org.apache.iceberg.AssertHelpers;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.rest.RequestResponseTestBase;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestUpdateNamespacePropertiesRequest extends RequestResponseTestBase<UpdateNamespacePropertiesRequest> {
+
+  /* Values used to fill in request fields */
+  private static final Map<String, String> UPDATES = ImmutableMap.of("owner", "Hank");
+  private static final List<String> REMOVALS = ImmutableList.of("foo", "bar");
+  private static final Map<String, String> EMPTY_UPDATES = ImmutableMap.of();
+  private static final List<String> EMPTY_REMOVALS = ImmutableList.of();
+
+
+  @Test
+  public void testRoundTripSerDe() throws JsonProcessingException {
+    // Full request
+    String fullJson = "{\"removals\":[\"foo\",\"bar\"],\"updates\":{\"owner\":\"Hank\"}}";
+    assertRoundTripSerializesEquallyFrom(
+        fullJson, UpdateNamespacePropertiesRequest.builder().updateAll(UPDATES).removeAll(REMOVALS).build());
+
+    // Only updates
+    String emptyRemoval = "{\"removals\":[],\"updates\":{\"owner\":\"Hank\"}}";
+    assertRoundTripSerializesEquallyFrom(
+        emptyRemoval, UpdateNamespacePropertiesRequest.builder().updateAll(UPDATES).removeAll(EMPTY_REMOVALS).build());
+
+    assertRoundTripSerializesEquallyFrom(
+        emptyRemoval, UpdateNamespacePropertiesRequest.builder().update("owner", "Hank").build());
+
+    // Only removals
+    String emptyUpdates = "{\"removals\":[\"foo\",\"bar\"],\"updates\":{}}";
+    assertRoundTripSerializesEquallyFrom(
+        emptyUpdates, UpdateNamespacePropertiesRequest.builder().removeAll(REMOVALS).updateAll(EMPTY_UPDATES).build());
+
+    assertRoundTripSerializesEquallyFrom(
+        emptyUpdates, UpdateNamespacePropertiesRequest.builder().remove("foo").remove("bar").build());
+  }
+
+  @Test
+  // Test cases that can't be constructed with our Builder class e2e but that will parse correctly
+  public void testCanDeserializeWithoutDefaultValues() throws JsonProcessingException {
+    // `removals` is left empty.
+    UpdateNamespacePropertiesRequest noRemovals = UpdateNamespacePropertiesRequest.builder().updateAll(UPDATES).build();
+    String jsonWithNullRemovals = "{\"removals\":null,\"updates\":{\"owner\":\"Hank\"}}";
+    UpdateNamespacePropertiesRequest parsed = deserialize(jsonWithNullRemovals);
+    assertEquals(parsed, noRemovals);
+
+    // `removals` is missing from the JSON.
+    String jsonWithMissingRemovals = "{\"updates\":{\"owner\":\"Hank\"}}";
+    assertEquals(deserialize(jsonWithMissingRemovals), noRemovals);
+
+    UpdateNamespacePropertiesRequest noUpdates = UpdateNamespacePropertiesRequest.builder().removeAll(REMOVALS).build();
+    String jsonWithNullUpdates = "{\"removals\":[\"foo\",\"bar\"],\"updates\":null}";
+    assertEquals(deserialize(jsonWithNullUpdates), noUpdates);
+  }
+
+  @Test
+  public void testParseInvalidJson() {
+    // Invalid top-level types
+    String jsonInvalidTypeOnRemovalField =
+        "{\"removals\":{\"foo\":\"bar\"},\"updates\":{\"owner\":\"Hank\"}}";
+    AssertHelpers.assertThrows(
+        "A JSON request with an invalid type for one of the fields should fail to parse",
+        JsonProcessingException.class,
+        () -> deserialize(jsonInvalidTypeOnRemovalField).validate()
+    );
+
+    String jsonInvalidTypeOnUpdatesField =
+        "{\"removals\":[\"foo\":\"bar\"],\"updates\":[\"owner\"]}";
+    AssertHelpers.assertThrows(
+        "A JSON value with an invalid type for one of the fields should fail to parse",
+        JsonProcessingException.class,
+        () -> deserialize(jsonInvalidTypeOnUpdatesField).validate()
+    );
+
+    // Valid top-level (array) types, but at least one entry in the list is not the expected type
+    // NOTE: non-string values that are integral types will still parse into a string list.
+    //    e.g. { removals: [ "foo", "bar", 1234 ] } will parse correctly.

Review comment:
       Just integral types? I don't really think this matters but I'm curious.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r809486999



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/UpdateNamespacePropertiesRequest.java
##########
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.List;
+import java.util.Map;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
+
+/**
+ * A REST request to set and/or remove properties on a namespace.
+ * <p>
+ * The request body specifies a list of properties to remove and a map
+ * of key value pairs to update.
+ * <p>
+ * Properties that are not in the request are not modified or removed by this call.
+ * Server implementations are not required to support namespace properties.
+ */
+public class UpdateNamespacePropertiesRequest {
+
+  private List<String> removals;
+  private Map<String, String> updates;
+
+  public UpdateNamespacePropertiesRequest() {
+    // Required for Jackson deserialization.
+  }
+
+  private UpdateNamespacePropertiesRequest(List<String> removals, Map<String, String> updates) {
+    this.removals = removals;
+    this.updates = updates;
+    validate();
+  }
+
+  UpdateNamespacePropertiesRequest validate() {
+    Preconditions.checkArgument((removals != null && !removals.isEmpty()) || (updates != null && !updates.isEmpty()),

Review comment:
       Good call on separate checks. That would make things a lot easier.
   




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810364701



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/UpdateNamespacePropertiesRequest.java
##########
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.List;
+import java.util.Map;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
+
+/**
+ * A REST request to set and/or remove properties on a namespace.
+ * <p>
+ * The request body specifies a list of properties to remove and a map
+ * of key value pairs to update.
+ * <p>
+ * Properties that are not in the request are not modified or removed by this call.
+ * Server implementations are not required to support namespace properties.
+ */
+public class UpdateNamespacePropertiesRequest {
+
+  private List<String> removals;
+  private Map<String, String> updates;
+
+  public UpdateNamespacePropertiesRequest() {
+    // Required for Jackson deserialization.
+  }
+
+  private UpdateNamespacePropertiesRequest(List<String> removals, Map<String, String> updates) {
+    this.removals = removals;
+    this.updates = updates;
+    validate();
+  }
+
+  UpdateNamespacePropertiesRequest validate() {
+    Preconditions.checkArgument((removals != null && !removals.isEmpty()) || (updates != null && !updates.isEmpty()),

Review comment:
       Actually on thinking on it more, based on the same logic as `UpdateNamesapcePropertiesResponse`, I agree we should just check that at least one is not null.
   
   People might choose to utilize an empty update properties request to tell the server to perform server-side handled property updates (such as something like the server will update "last_updated_at" or something on every `UpdateNamespacePropertiesRequest`).
   
   That specific situation might not be the best idea, but I agree that we shouldn't be overly strict to disallow these situations.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810393720



##########
File path: core/src/test/java/org/apache/iceberg/rest/responses/TestDropNamespaceResponse.java
##########
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import org.apache.iceberg.AssertHelpers;
+import org.apache.iceberg.rest.RequestResponseTestBase;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestDropNamespaceResponse extends RequestResponseTestBase<DropNamespaceResponse> {
+
+  @Test
+  public void testRoundTripSerDe() throws JsonProcessingException {
+    assertRoundTripSerializesEquallyFrom(
+        "{\"dropped\":true}", DropNamespaceResponse.builder().dropped(true).build());
+
+    assertRoundTripSerializesEquallyFrom(
+        "{\"dropped\":false}", DropNamespaceResponse.builder().dropped(false).build());
+  }
+
+  @Test
+  public void testFailParsingWhenNullOrEmptyJson() {
+    String nullJson = null;
+    AssertHelpers.assertThrows("DropNamespaceResponse should fail to deserialize from a null JSON string",
+        IllegalArgumentException.class,
+        () ->  deserialize(nullJson));

Review comment:
       This exception message comes from Jackson and is `"argument "content" is null"`. I can add it in just so we know it came from Jackson, but it's not the most useful.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810409383



##########
File path: core/src/test/java/org/apache/iceberg/rest/responses/TestDropNamespaceResponse.java
##########
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import org.apache.iceberg.AssertHelpers;
+import org.apache.iceberg.rest.RequestResponseTestBase;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestDropNamespaceResponse extends RequestResponseTestBase<DropNamespaceResponse> {
+
+  @Test
+  public void testRoundTripSerDe() throws JsonProcessingException {
+    assertRoundTripSerializesEquallyFrom(
+        "{\"dropped\":true}", DropNamespaceResponse.builder().dropped(true).build());
+
+    assertRoundTripSerializesEquallyFrom(
+        "{\"dropped\":false}", DropNamespaceResponse.builder().dropped(false).build());
+  }
+
+  @Test
+  public void testFailParsingWhenNullOrEmptyJson() {
+    String nullJson = null;
+    AssertHelpers.assertThrows("DropNamespaceResponse should fail to deserialize from a null JSON string",
+        IllegalArgumentException.class,
+        () ->  deserialize(nullJson));

Review comment:
       I added them in so it would be clear where they came from.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r801126914



##########
File path: core/src/test/java/org/apache/iceberg/rest/requests/TestCreateNamespaceRequest.java
##########
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.util.JsonUtil;
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+
+public class TestCreateNamespaceRequest {
+
+  private static final ObjectMapper MAPPER = JsonUtil.withRESTComponents();
+
+  private static final String[] ALL_FIELDS_FROM_SPEC = { "namespace", "properties" };
+
+  /* Values used to fill in request fields */
+  private static final Namespace NAMESPACE = Namespace.of("accounting", "tax");
+  private static final Map<String, String> PROPERTIES = ImmutableMap.of("owner", "Hank");
+
+  /* JSON of requests */
+  private static final String JSON_REQUEST =
+      "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{\"owner\":\"Hank\"}}";
+  private static final String JSON_REQUEST_EMPTY_PROPERTIES =
+      "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{}}";
+
+  @Test
+  public void testDeserialize() throws JsonProcessingException {
+    CreateNamespaceRequest expected = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .withProperties(PROPERTIES)
+        .build();
+
+    CreateNamespaceRequest actual = MAPPER.readValue(JSON_REQUEST, CreateNamespaceRequest.class);
+
+    assertEquals(expected, actual);
+    assertHasOnlyKnownFields(expected);
+    assertHasOnlyKnownFields(actual);
+  }
+
+  @Test
+  public void testDeserializeEmptyProperties() throws JsonProcessingException {
+    CreateNamespaceRequest expected = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .build();
+
+    CreateNamespaceRequest actual = MAPPER.readValue(JSON_REQUEST_EMPTY_PROPERTIES, CreateNamespaceRequest.class);
+
+    assertEquals(expected, actual);
+    assertHasOnlyKnownFields(expected);
+    assertHasOnlyKnownFields(actual);
+  }
+
+  @Test
+  public void testSerialize() throws JsonProcessingException {
+    CreateNamespaceRequest req = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .withProperties(PROPERTIES)
+        .build();
+
+    Assertions.assertThat(MAPPER.writeValueAsString(req))
+        .isEqualTo(JSON_REQUEST);
+  }
+
+  @Test
+  public void testSerializeEmptyProperties() throws JsonProcessingException {
+    CreateNamespaceRequest req = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .build();
+
+    Assertions.assertThat(MAPPER.writeValueAsString(req))
+        .isEqualTo(JSON_REQUEST_EMPTY_PROPERTIES);
+  }
+
+  private static void assertEquals(CreateNamespaceRequest expected, CreateNamespaceRequest actual) {
+    Assertions.assertThat(actual.namespace()).isEqualTo(expected.namespace());

Review comment:
       Yeah I agree. I changed it to simply implement `equals` (and `hashCode`).




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r802047039



##########
File path: core/src/main/java/org/apache/iceberg/rest/RESTJacksonModule.java
##########
@@ -0,0 +1,174 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import java.io.IOException;
+import org.apache.iceberg.PartitionSpec;
+import org.apache.iceberg.PartitionSpecParser;
+import org.apache.iceberg.Schema;
+import org.apache.iceberg.SchemaParser;
+import org.apache.iceberg.SortOrder;
+import org.apache.iceberg.SortOrderParser;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.catalog.TableIdentifier;
+
+public class RESTJacksonModule {
+
+  private RESTJacksonModule() {
+  }
+
+  public static void registerAll(ObjectMapper mapper) {
+    SimpleModule module = new SimpleModule();
+    module
+        .addSerializer(TableIdentifier.class, new TableIdentifierSerializer())
+        .addDeserializer(TableIdentifier.class, new TableIdentifierDeserializer())
+        .addSerializer(Namespace.class, new NamespaceSerializer())
+        .addDeserializer(Namespace.class, new NamespaceDeserializer())
+        .addSerializer(Schema.class, new SchemaSerializer())
+        .addDeserializer(Schema.class, new SchemaDeserializer())
+        .addSerializer(PartitionSpec.class, new PartitionSpecSerializer())
+        .addDeserializer(PartitionSpec.class, new PartitionSpecDeserializer())
+        .addSerializer(SortOrder.class, new SortOrderSerializer())
+        .addDeserializer(SortOrder.class, new SortOrderDeserializer());
+    mapper.registerModule(module);
+  }
+
+  public static class NamespaceDeserializer extends JsonDeserializer<Namespace> {
+    @Override
+    public Namespace deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
+      JsonNode jsonNode = p.getCodec().readTree(p);
+      return namespaceFromNode(p, jsonNode);
+    }
+  }
+
+  public static class NamespaceSerializer extends JsonSerializer<Namespace> {
+    @Override
+    public void serialize(Namespace namespace, JsonGenerator gen, SerializerProvider serializers)
+        throws IOException {
+      String[] parts = namespace.levels();
+      gen.writeArray(parts, 0, parts.length);
+    }
+  }
+
+  public static class TableIdentifierDeserializer extends JsonDeserializer<TableIdentifier> {
+    @Override
+    public TableIdentifier deserialize(JsonParser p, DeserializationContext ctxt)
+        throws IOException {
+      JsonNode jsonNode = p.getCodec().readTree(p);
+      if (!jsonNode.isObject()) {
+        throw new JsonParseException(p, "TableIdentifier must be an object: " + jsonNode);
+      }
+      ObjectNode objectNode = (ObjectNode) jsonNode;
+      Namespace namespace = namespaceFromNode(p, objectNode.get("namespace"));
+      String name = objectNode.get("name").asText();
+      return TableIdentifier.of(namespace, name);
+    }
+  }
+
+  private static Namespace namespaceFromNode(JsonParser parser, JsonNode jsonNode) throws IOException {
+    if (!jsonNode.isArray()) {
+      throw new JsonParseException(parser, "Namespace must be an array: " + jsonNode);
+    }
+    ArrayNode arrayNode = (ArrayNode) jsonNode;
+    String[] levels = new String[arrayNode.size()];
+    for (int i = 0; i < levels.length; i++) {
+      levels[i] = arrayNode.get(i).asText();
+    }
+    return Namespace.of(levels);
+  }
+
+  public static class TableIdentifierSerializer extends JsonSerializer<TableIdentifier> {
+    @Override
+    public void serialize(
+        TableIdentifier identifier, JsonGenerator gen, SerializerProvider serializers)
+        throws IOException {
+      gen.writeStartObject();

Review comment:
       I added `TableIdentifierParser` and a suite of tests for it that are similar to the ones used in the recent `SnapshotsRefParser` PR.
   
   I might move that to its own PR so it can be merged sooner.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r806210962



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/CreateNamespaceRequest.java
##########
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import com.fasterxml.jackson.annotation.JsonProperty;

Review comment:
       Let me check if Jackson can infer everything. I don't think it can - which is why I added these in."
   
   I would be in favor of the more explicit SerDe as well given what's mentioned above (or using a library to generate the classes for us would be my preferred approach but I know that comes with its own set of issues).




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: [WIP] REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r807238610



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/CreateNamespaceRequest.java
##########
@@ -0,0 +1,130 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.exceptions.ValidationException;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.rest.RESTUtils;
+
+/**
+ * A REST request to create a namespace, with an optional set of properties.
+ * The server might also add properties, such as `last_modified_time` etc.
+ */
+public class CreateNamespaceRequest {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public CreateNamespaceRequest() {
+    // Needed for Jackson Deserialization.
+  }
+
+  private CreateNamespaceRequest(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+    validate();
+  }
+
+  CreateNamespaceRequest validate() {
+    ValidationException.check(namespace != null && !namespace.isEmpty(),
+        "Cannot build a request to create a namespace without specifying the namespace");
+    return this;
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public Namespace namespace() {
+    return namespace;
+  }
+
+  public Map<String, String> properties() {
+    return RESTUtils.emptyOrImmutableMap(properties);
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("namespace", namespace)
+        .add("properties", properties)
+        .toString();
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+
+    CreateNamespaceRequest request = (CreateNamespaceRequest) o;
+    return namespace.equals(request.namespace) && Objects.equals(properties, request.properties);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(namespace, properties);
+  }
+
+  public static class Builder {
+    private Namespace namespace;
+    private ImmutableMap.Builder<String, String> properties;
+
+    private Builder() {
+    }
+
+    public Builder withNamespace(Namespace ns) {
+      this.namespace = ns;
+      return this;
+    }
+
+    public Builder setProperties(Map<String, String> props) {
+      // ImmutableMap.Builder will throw on a null map, so we allow for overwriting
+      // with null.... possibly we should throw instead so people don't use the builder improperly?
+      if (props == null) {
+        properties = null;
+        return this;
+      }

Review comment:
       ImmutableMap.Builder will throw on a null map, so this allows for overwriting with `null`.
   
   Possibly we should throw instead so people don't use the builder improperly?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r807436414



##########
File path: core/src/main/java/org/apache/iceberg/rest/RESTSerializers.java
##########
@@ -0,0 +1,162 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import java.io.IOException;
+import org.apache.iceberg.PartitionSpec;
+import org.apache.iceberg.PartitionSpecParser;
+import org.apache.iceberg.Schema;
+import org.apache.iceberg.SchemaParser;
+import org.apache.iceberg.SortOrder;
+import org.apache.iceberg.SortOrderParser;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.catalog.TableIdentifier;
+import org.apache.iceberg.catalog.TableIdentifierParser;
+
+public class RESTSerializers {
+
+  private RESTSerializers() {
+  }
+
+  public static void registerAll(ObjectMapper mapper) {
+    SimpleModule module = new SimpleModule();
+    module
+        .addSerializer(TableIdentifier.class, new TableIdentifierSerializer())
+        .addDeserializer(TableIdentifier.class, new TableIdentifierDeserializer())
+        .addSerializer(Namespace.class, new NamespaceSerializer())
+        .addDeserializer(Namespace.class, new NamespaceDeserializer())
+        .addSerializer(Schema.class, new SchemaSerializer())
+        .addDeserializer(Schema.class, new SchemaDeserializer())
+        .addSerializer(PartitionSpec.class, new PartitionSpecSerializer())
+        .addDeserializer(PartitionSpec.class, new PartitionSpecDeserializer())
+        .addSerializer(SortOrder.class, new SortOrderSerializer())
+        .addDeserializer(SortOrder.class, new SortOrderDeserializer());
+    mapper.registerModule(module);
+  }
+
+  public static class NamespaceDeserializer extends JsonDeserializer<Namespace> {
+    @Override
+    public Namespace deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
+      JsonNode jsonNode = p.getCodec().readTree(p);
+      return namespaceFromNode(p, jsonNode);
+    }
+  }
+
+  public static class NamespaceSerializer extends JsonSerializer<Namespace> {
+    @Override
+    public void serialize(Namespace namespace, JsonGenerator gen, SerializerProvider serializers)
+        throws IOException {
+      String[] parts = namespace.levels();
+      gen.writeArray(parts, 0, parts.length);
+    }
+  }
+
+  private static Namespace namespaceFromNode(JsonParser parser, JsonNode jsonNode) throws IOException {
+    if (!jsonNode.isArray()) {
+      throw new JsonParseException(parser, "Namespace must be an array: " + jsonNode);
+    }
+    ArrayNode arrayNode = (ArrayNode) jsonNode;
+    String[] levels = new String[arrayNode.size()];
+    for (int i = 0; i < levels.length; i++) {
+      levels[i] = arrayNode.get(i).asText();
+    }

Review comment:
       It looks like this could be put in `JsonUtil` as `getStringArray`.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r807426532



##########
File path: core/src/main/java/org/apache/iceberg/catalog/TableIdentifierParser.java
##########
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.catalog;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.JsonNode;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.UncheckedIOException;
+import java.util.List;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.util.JsonUtil;
+
+/**
+ * Parses TableIdentifiers from a JSON representation, which is the JSON
+ * representation utilized in the REST catalog.
+ * <p>
+ * For TableIdentifier.of("dogs", "owners.and.handlers", "food"), we'd have
+ * the following JSON representation, where the dot character of an
+ * individual level is in the namespace is replaced by the null byte character.
+ * <pre>
+ * {
+ *   "namespace": ["dogs", "owners.and.handlers"],
+ *   "name": "food"
+ * }
+ * </pre>
+ */
+public class TableIdentifierParser {
+
+  private static final String NAMESPACE = "namespace";
+  private static final String NAME = "name";
+
+  private TableIdentifierParser() {
+  }
+
+  public static String toJson(TableIdentifier identifier) {
+    return toJson(identifier, false);
+  }
+
+  public static String toJson(TableIdentifier identifier, boolean pretty) {
+    try {
+      StringWriter writer = new StringWriter();
+      JsonGenerator generator = JsonUtil.factory().createGenerator(writer);
+      if (pretty) {
+        generator.useDefaultPrettyPrinter();
+      }
+      toJson(identifier, generator);
+      generator.flush();
+      return writer.toString();
+    } catch (IOException e) {
+      throw new UncheckedIOException(String.format("Failed to write json for: %s", identifier), e);
+    }
+  }
+
+  public static void toJson(TableIdentifier identifier, JsonGenerator generator) throws IOException {

Review comment:
       `TableMetadataParser` has the same `public` type signature in it as well.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810546926



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/ListNamespacesResponse.java
##########
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Collection;
+import java.util.List;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+
+public class ListNamespacesResponse {
+
+  private List<Namespace> namespaces;
+
+  public ListNamespacesResponse() {
+    // Required for Jackson deserialization
+  }
+
+  private ListNamespacesResponse(List<Namespace> namespaces) {
+    this.namespaces = namespaces;
+    validate();
+  }
+
+  ListNamespacesResponse validate() {
+    Preconditions.checkArgument(namespaces != null,
+        "Cannot create a response to a list namespaces request without a non-null list of namespaces");
+    return this;
+  }
+
+
+  public List<Namespace> namespaces() {
+    return namespaces != null ? namespaces : ImmutableList.of();
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("namespaces", namespaces())
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  static class Builder {
+    private final ImmutableList.Builder<Namespace> namespaces = ImmutableList.builder();
+
+    private Builder() {
+    }
+
+    public Builder add(Namespace toAdd) {
+      Preconditions.checkNotNull(toAdd,
+          "Invalid namespace to list: null");

Review comment:
       `Invalid namespace: null`




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r811443745



##########
File path: core/src/test/java/org/apache/iceberg/catalog/TestTableIdentifierParser.java
##########
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.catalog;
+
+import org.apache.iceberg.AssertHelpers;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestTableIdentifierParser {
+
+  @Test
+  public void testTableIdentifierToJson() {
+    String json = "{\"namespace\":[\"accounting\",\"tax\"],\"name\":\"paid\"}";
+    TableIdentifier identifier = TableIdentifier.of(Namespace.of("accounting", "tax"), "paid");
+    Assert.assertEquals("Should be able to serialize a table identifier with both namespace and name",
+        json, TableIdentifierParser.toJson(identifier));
+
+    TableIdentifier identifierWithEmptyNamespace = TableIdentifier.of(Namespace.empty(), "paid");
+    String jsonWithEmptyNamespace = "{\"namespace\":[],\"name\":\"paid\"}";
+    Assert.assertEquals("Should be able to serialize a table identifier that uses the empty namespace",
+        jsonWithEmptyNamespace, TableIdentifierParser.toJson(identifierWithEmptyNamespace));
+  }
+
+  @Test
+  public void testTableIdentifierFromJson() {
+    String json = "{\"namespace\":[\"accounting\",\"tax\"],\"name\":\"paid\"}";
+    TableIdentifier identifier = TableIdentifier.of(Namespace.of("accounting", "tax"), "paid");
+    Assert.assertEquals("Should be able to deserialize a valid table identifier",
+        identifier, TableIdentifierParser.fromJson(json));
+
+    TableIdentifier identifierWithEmptyNamespace = TableIdentifier.of(Namespace.empty(), "paid");
+    String jsonWithEmptyNamespace = "{\"namespace\":[],\"name\":\"paid\"}";
+    Assert.assertEquals("Should be able to deserialize a valid multi-level table identifier",
+        identifierWithEmptyNamespace, TableIdentifierParser.fromJson(jsonWithEmptyNamespace));
+  }
+
+  @Test
+  public void testFailParsingWhenNullOrEmptyJson() {
+    String nullJson = null;
+    AssertHelpers.assertThrows("TableIdentifierParser should fail to deserialize null JSON string",
+        IllegalArgumentException.class, "Cannot parse table identifier from invalid JSON: null",
+        () ->  TableIdentifierParser.fromJson(nullJson));
+
+    String emptyString = "";
+    AssertHelpers.assertThrows("TableIdentifierParser should fail to deserialize an empty string",
+        IllegalArgumentException.class, "Cannot parse table identifier from invalid JSON: ''",
+        () ->  TableIdentifierParser.fromJson(emptyString));
+
+    String emptyJson = "{}";
+    AssertHelpers.assertThrows("TableIdentifierParser should fail to deserialize an empty JSON string",
+        IllegalArgumentException.class, "Cannot parse missing list namespace",
+        () ->  TableIdentifierParser.fromJson(emptyJson));
+
+    String emptyJsonArray = "[]";
+    AssertHelpers.assertThrows("TableIdentifierParser should fail to deserialize an empty JSON array",
+        IllegalArgumentException.class, "Cannot parse missing or non-object table identifier: []",
+        () ->  TableIdentifierParser.fromJson(emptyJsonArray));
+  }
+
+  @Test
+  public void testFailParsingWhenMissingRequiredFields() {
+    String identifierMissingName = "{\"namespace\":[\"accounting\",\"tax\"]}";
+    AssertHelpers.assertThrows("TableIdentifierParser should fail to deserialize table with missing name",
+        IllegalArgumentException.class, "Cannot parse missing string name",
+        () ->  TableIdentifierParser.fromJson(identifierMissingName));
+
+    String identifierMissingNamespace = "{\"name\":\"paid\"}";
+    AssertHelpers.assertThrows("TableIdentifierParser should fail to deserialize table with missing namespace",
+        IllegalArgumentException.class, "Cannot parse missing list namespace",

Review comment:
       Actually, `TableIdentifier`'s constructor doesn't allow the empty namespace. Maybe that should be updated too?
   
   https://github.com/apache/iceberg/blob/674dcf1c2e3cb0444a183c55a24b521e297880de/api/src/main/java/org/apache/iceberg/catalog/TableIdentifier.java#L54-L59




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] jackye1995 commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
jackye1995 commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r800911888



##########
File path: core/src/main/java/org/apache/iceberg/rest/RESTJacksonModule.java
##########
@@ -0,0 +1,183 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import java.io.IOException;
+import org.apache.iceberg.PartitionSpec;
+import org.apache.iceberg.PartitionSpecParser;
+import org.apache.iceberg.Schema;
+import org.apache.iceberg.SchemaParser;
+import org.apache.iceberg.SortOrder;
+import org.apache.iceberg.SortOrderParser;
+import org.apache.iceberg.TableMetadata;
+import org.apache.iceberg.TableMetadataParser;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.catalog.TableIdentifier;
+
+public class RESTJacksonModule {

Review comment:
       +1, Module has a specific meaning in jackson https://fasterxml.github.io/jackson-databind/javadoc/2.7/com/fasterxml/jackson/databind/Module.html




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r801022475



##########
File path: core/src/main/java/org/apache/iceberg/rest/RESTJacksonModule.java
##########
@@ -0,0 +1,183 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import java.io.IOException;
+import org.apache.iceberg.PartitionSpec;
+import org.apache.iceberg.PartitionSpecParser;
+import org.apache.iceberg.Schema;
+import org.apache.iceberg.SchemaParser;
+import org.apache.iceberg.SortOrder;
+import org.apache.iceberg.SortOrderParser;
+import org.apache.iceberg.TableMetadata;
+import org.apache.iceberg.TableMetadataParser;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.catalog.TableIdentifier;
+
+public class RESTJacksonModule {
+
+  private RESTJacksonModule() {
+  }
+
+  public static void registerAll(ObjectMapper mapper) {
+    SimpleModule module = new SimpleModule();
+    module
+        .addSerializer(TableIdentifier.class, new TableIdentifierSerializer())
+        .addDeserializer(TableIdentifier.class, new TableIdentifierDeserializer())
+        .addSerializer(Namespace.class, new NamespaceSerializer())
+        .addDeserializer(Namespace.class, new NamespaceDeserializer())
+        .addSerializer(Schema.class, new SchemaSerializer())
+        .addDeserializer(Schema.class, new SchemaDeserializer())
+        .addSerializer(PartitionSpec.class, new PartitionSpecSerializer())
+        .addDeserializer(PartitionSpec.class, new PartitionSpecDeserializer())
+        .addSerializer(SortOrder.class, new SortOrderSerializer())
+        .addDeserializer(SortOrder.class, new SortOrderDeserializer());
+    mapper.registerModule(module);
+
+    mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE);
+    mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);

Review comment:
       Added the comment that Dan made almost word for word, though it lives in `JsonUtil` now. Open to moving the visibility changing back into this class and changing the comment as well.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r800241620



##########
File path: core/src/test/java/org/apache/iceberg/rest/requests/TestCreateNamespaceRequest.java
##########
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.util.JsonUtil;
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+
+public class TestCreateNamespaceRequest {

Review comment:
       * null/empty JSON - I agree we should make sure that required fields are present
   * JSON with extra fields - I think extra fields should be ignored by the client so that we can evolve the payloads. Clients shouldn't fail if the service returns extra fields, and services shouldn't necessarily fail if the client sends extra fields.
   * JSON with invalid data - I agree




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r801156915



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/CreateNamespaceRequest.java
##########
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+
+/**
+ * A REST request to create a namespace, with an optional set of properties.

Review comment:
       Earnest question: what should we say it maps to? The name? The name is the same as the classes in the OpenAPI spec. Is there something else we should link to?
   
   As for actually linking, I agree that would be better though I'm not sure if it's doable. I'll look into it, but I suspect that it's not.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r801110282



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/UpdateNamespacePropertiesRequest.java
##########
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.List;
+import java.util.Map;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
+
+/**
+ * A REST request to set and/or remove properties on a namespace.
+ * <p/>
+ * The request body specifies a list of properties to remove and a map
+ * of key value pairs to update.
+ * <p/>
+ * Properties that are not in the request are not modified or removed by this call.
+ * Server implementations are not required to support namespace properties.
+ */
+public class UpdateNamespacePropertiesRequest {
+
+  private List<String> removals;
+  private Map<String, String> updates;
+
+  public UpdateNamespacePropertiesRequest() {
+    // Required for Jackson
+  }
+
+  private UpdateNamespacePropertiesRequest(List<String> removals, Map<String, String> updates) {
+    this.removals = removals;
+    this.updates = updates;
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public List<String> removals() {
+    return ImmutableList.copyOf(removals);
+  }
+
+  public Map<String, String> updates() {
+    return ImmutableMap.copyOf(updates);
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("removals", removals())
+        .add("updates", updates())
+        .toString();
+  }
+
+  public static class Builder {
+    private final ImmutableSet.Builder<String> removalsBuilder;
+    private final ImmutableMap.Builder<String, String> updatesBuilder;
+
+    private Builder() {
+      this.removalsBuilder = ImmutableSet.builder();
+      this.updatesBuilder = ImmutableMap.builder();
+    }
+
+    public Builder withRemoval(String removal) {
+      removalsBuilder.add(removal);
+      return this;
+    }
+
+    public Builder withRemovals(Iterable<String> removals) {
+      removalsBuilder.addAll(removals);
+      return this;
+    }
+
+    public Builder withUpdate(String key, String value) {

Review comment:
       Updated!




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r809500612



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/UpdateNamespacePropertiesRequest.java
##########
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.List;
+import java.util.Map;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
+
+/**
+ * A REST request to set and/or remove properties on a namespace.
+ * <p>
+ * The request body specifies a list of properties to remove and a map
+ * of key value pairs to update.
+ * <p>
+ * Properties that are not in the request are not modified or removed by this call.
+ * Server implementations are not required to support namespace properties.
+ */
+public class UpdateNamespacePropertiesRequest {
+
+  private List<String> removals;
+  private Map<String, String> updates;
+
+  public UpdateNamespacePropertiesRequest() {
+    // Required for Jackson deserialization.
+  }
+
+  private UpdateNamespacePropertiesRequest(List<String> removals, Map<String, String> updates) {
+    this.removals = removals;
+    this.updates = updates;
+    validate();
+  }
+
+  UpdateNamespacePropertiesRequest validate() {
+    Preconditions.checkArgument((removals != null && !removals.isEmpty()) || (updates != null && !updates.isEmpty()),
+        "Cannot create a request to update a namespace's properties without specifying any props to update or remove");
+    return this;
+  }
+
+  public List<String> removals() {
+    return removals == null ? ImmutableList.of() : removals;
+  }
+
+  public Map<String, String> updates() {
+    return updates == null ? ImmutableMap.of() : updates;
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("removals", removals)
+        .add("updates", updates)
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public static class Builder {
+    private final ImmutableSet.Builder<String> removalsBuilder = ImmutableSet.builder();
+    private final ImmutableMap.Builder<String, String> updatesBuilder = ImmutableMap.builder();
+
+    private Builder() {
+    }
+
+    public Builder remove(String removal) {
+      Preconditions.checkNotNull(removal,
+          "Cannot pass null key to remove to UpdateNamespacePropertiesRequest.Builder");
+      removalsBuilder.add(removal);
+      return this;
+    }
+
+    public Builder removeAll(Iterable<String> removals) {
+      Preconditions.checkNotNull(removals,
+          "Cannot pass null removals to UpdateNamespacePropertiesRequest.Builder");
+      removalsBuilder.addAll(removals);
+      return this;
+    }
+
+    public Builder update(String key, String value) {
+      Preconditions.checkNotNull(key,
+          "Cannot pass null key to update to UpdateNamespacePropertiesRequest.Builder");
+      Preconditions.checkNotNull(value,
+          "Cannot pass null value to update in UpdateNamespacePropertiesRequest.Builder. Use remove instead");
+      updatesBuilder.put(key, value);
+      return this;
+    }
+
+    public Builder updateAll(Map<String, String> updates) {
+      Preconditions.checkNotNull(updates,
+          "Cannot pass null updates to UpdateNamespacePropertiesRequest.Builder");

Review comment:
       Yeah, throw `IllegalArgumentException`




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r808428620



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/CreateNamespaceRequest.java
##########
@@ -0,0 +1,128 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.exceptions.ValidationException;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.util.ImmutablesUtil;
+
+/**
+ * A REST request to create a namespace, with an optional set of properties.
+ * The server might also add properties, such as `last_modified_time` etc.
+ */
+public class CreateNamespaceRequest {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public CreateNamespaceRequest() {
+    // Needed for Jackson Deserialization.
+  }
+
+  private CreateNamespaceRequest(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+    validate();
+  }
+
+  CreateNamespaceRequest validate() {
+    ValidationException.check(namespace != null && !namespace.isEmpty(),
+        "Cannot build a request to create a namespace without specifying the namespace");
+    return this;
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public Namespace namespace() {
+    return namespace;
+  }
+
+  public Map<String, String> properties() {
+    return ImmutablesUtil.nullSafeCopyOf(properties);
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("namespace", namespace)
+        .add("properties", properties)
+        .toString();
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+
+    CreateNamespaceRequest request = (CreateNamespaceRequest) o;
+    return namespace.equals(request.namespace) && Objects.equals(properties, request.properties);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(namespace, properties);
+  }
+
+  public static class Builder {
+    private Namespace namespace;
+    private ImmutableMap.Builder<String, String> properties;
+
+    private Builder() {
+    }
+
+    public Builder withNamespace(Namespace ns) {
+      this.namespace = ns;
+      return this;
+    }
+
+    public Builder setProperties(Map<String, String> props) {

Review comment:
       I updated it to a `ValidationException` before I saw this. Can change to an NPE if you'd like.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r809495224



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/UpdateNamespacePropertiesRequest.java
##########
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.List;
+import java.util.Map;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
+
+/**
+ * A REST request to set and/or remove properties on a namespace.
+ * <p>
+ * The request body specifies a list of properties to remove and a map
+ * of key value pairs to update.
+ * <p>
+ * Properties that are not in the request are not modified or removed by this call.
+ * Server implementations are not required to support namespace properties.
+ */
+public class UpdateNamespacePropertiesRequest {
+
+  private List<String> removals;
+  private Map<String, String> updates;
+
+  public UpdateNamespacePropertiesRequest() {
+    // Required for Jackson deserialization.
+  }
+
+  private UpdateNamespacePropertiesRequest(List<String> removals, Map<String, String> updates) {
+    this.removals = removals;
+    this.updates = updates;
+    validate();
+  }
+
+  UpdateNamespacePropertiesRequest validate() {
+    Preconditions.checkArgument((removals != null && !removals.isEmpty()) || (updates != null && !updates.isEmpty()),
+        "Cannot create a request to update a namespace's properties without specifying any props to update or remove");
+    return this;
+  }
+
+  public List<String> removals() {
+    return removals == null ? ImmutableList.of() : removals;
+  }
+
+  public Map<String, String> updates() {
+    return updates == null ? ImmutableMap.of() : updates;
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("removals", removals)
+        .add("updates", updates)
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public static class Builder {
+    private final ImmutableSet.Builder<String> removalsBuilder = ImmutableSet.builder();
+    private final ImmutableMap.Builder<String, String> updatesBuilder = ImmutableMap.builder();
+
+    private Builder() {
+    }
+
+    public Builder remove(String removal) {
+      Preconditions.checkNotNull(removal,
+          "Cannot pass null key to remove to UpdateNamespacePropertiesRequest.Builder");
+      removalsBuilder.add(removal);
+      return this;
+    }
+
+    public Builder removeAll(Iterable<String> removals) {
+      Preconditions.checkNotNull(removals,
+          "Cannot pass null removals to UpdateNamespacePropertiesRequest.Builder");

Review comment:
       Updated!




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r809377749



##########
File path: core/src/main/java/org/apache/iceberg/catalog/TableIdentifierParser.java
##########
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.catalog;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.JsonNode;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.UncheckedIOException;
+import java.util.List;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.util.JsonUtil;
+
+/**
+ * Parses TableIdentifiers from a JSON representation, which is the JSON
+ * representation utilized in the REST catalog.
+ * <p>
+ * For TableIdentifier.of("dogs", "owners.and.handlers", "food"), we'd have
+ * the following JSON representation, where the dot character of an
+ * individual level is in the namespace is replaced by the null byte character.
+ * <pre>
+ * {
+ *   "namespace": ["dogs", "owners.and.handlers"],
+ *   "name": "food"
+ * }
+ * </pre>
+ */
+public class TableIdentifierParser {
+
+  private static final String NAMESPACE = "namespace";
+  private static final String NAME = "name";
+
+  private TableIdentifierParser() {
+  }
+
+  public static String toJson(TableIdentifier identifier) {
+    return toJson(identifier, false);
+  }
+
+  public static String toJson(TableIdentifier identifier, boolean pretty) {
+    try {
+      StringWriter writer = new StringWriter();
+      JsonGenerator generator = JsonUtil.factory().createGenerator(writer);
+      if (pretty) {
+        generator.useDefaultPrettyPrinter();
+      }
+      toJson(identifier, generator);
+      generator.flush();
+      return writer.toString();
+    } catch (IOException e) {
+      throw new UncheckedIOException(String.format("Failed to write json for: %s", identifier), e);
+    }
+  }
+
+  public static void toJson(TableIdentifier identifier, JsonGenerator generator) throws IOException {
+    generator.writeStartObject();
+    generator.writeFieldName(NAMESPACE);
+    generator.writeArray(identifier.namespace().levels(), 0, identifier.namespace().length());
+    generator.writeStringField(NAME, identifier.name());
+    generator.writeEndObject();
+  }
+
+  public static TableIdentifier fromJson(String json) {
+    Preconditions.checkArgument(json != null && !json.isEmpty(),
+        "Cannot parse table identifier from invalid JSON: %s", json);

Review comment:
       I think it's fine to catch empty namespace in the `CreateNamespaceRequest` object, but this should allow an empty namespace because it is a valid thing. You can have tables in the catalog root, so their namespaces are empty.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r809456001



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/GetNamespaceResponse.java
##########
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.exceptions.ValidationException;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.util.ImmutablesUtil;
+
+/**
+ * Represents a REST response to fetch namespace metadata.
+ * <p>
+ * The properties returned should include all the user provided properties from the
+ * request, as well as any server-side added properties.
+ */
+public class GetNamespaceResponse {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public GetNamespaceResponse() {
+    // Required for Jackson deserialization
+  }
+
+  private GetNamespaceResponse(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+    validate();
+  }
+
+  GetNamespaceResponse validate() {
+    ValidationException.check(namespace != null && !namespace.isEmpty(),
+        "Cannot build a response to get a namespace without specifying the namespace");
+    return this;
+  }
+
+  public Namespace namespace() {
+    return namespace;
+  }
+
+  public Map<String, String> properties() {
+    return ImmutablesUtil.nullSafeCopyOf(properties);

Review comment:
       Looks like this still uses `nullSafeCopyOf`, which can probably be removed since it isn't used elsewhere.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r802052124



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/DropNamespaceResponse.java
##########
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.Objects;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+
+/**
+ * Represents a REST response to drop a namespace.
+ * <p>
+ * The server may choose to return an error if the namespace is not empty.
+ */
+public class DropNamespaceResponse {
+
+  // For Jackson to properly fail when deserialziing, this needs to be boxed.
+  private Boolean dropped;
+
+  private DropNamespaceResponse(@JsonProperty("dropped") Boolean dropped) {
+    Preconditions.checkNotNull(dropped,
+        "Cannot instantiate a response to dropping a namespace with missing fields");
+    this.dropped = dropped;
+  }

Review comment:
       The way Jackson handles this with the current `visibilityModifiers` based approach for deserialization, things like `{ "dropped": 123 }` still deserialize as though they were `{dropped: true}`.
   
   Presumably anything that's truthy, but boxing `this.dropped` from primitive `boolean` helped somewhat (at least with strings). I'll add more tests.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r802045201



##########
File path: core/src/test/java/org/apache/iceberg/rest/requests/TestCreateNamespaceRequest.java
##########
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.util.JsonUtil;
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+
+public class TestCreateNamespaceRequest {
+
+  private static final ObjectMapper MAPPER = JsonUtil.withRESTComponents();
+
+  // Non-empty
+  private static final String JSON_REQUEST_STRING =
+      "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{\"owner\":\"Hank\"}}";
+  private static final Namespace NAMESPACE = Namespace.of("accounting", "tax");
+  private static final Map<String, String> PROPERTIES = ImmutableMap.of("owner", "Hank");
+
+  // Empty - The response requires a non-empty namespace
+  private static final String JSON_REQUEST_NO_PROPERTIES =
+      "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{}}";
+
+  @Test
+  public void testDeserialize() throws JsonProcessingException {
+    CreateNamespaceRequest expected = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .withProperties(PROPERTIES)
+        .build();
+
+    CreateNamespaceRequest actual = MAPPER.readValue(JSON_REQUEST_STRING, CreateNamespaceRequest.class);
+
+    assertSame(expected, actual);
+  }
+
+  @Test
+  public void testDeserializeNoProperties() throws JsonProcessingException {

Review comment:
       Ok. Great. I've updated the constructors to default `null` / missing to empty map.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r807441166



##########
File path: core/src/test/java/org/apache/iceberg/rest/requests/TestCreateNamespaceRequest.java
##########
@@ -0,0 +1,128 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.util.Map;
+import org.apache.iceberg.AssertHelpers;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.exceptions.ValidationException;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.rest.RESTUtils;
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+
+public class TestCreateNamespaceRequest {
+
+  private static final ObjectMapper MAPPER = RESTUtils.mapper();
+
+  private static final String[] ALL_FIELDS_FROM_SPEC = { "namespace", "properties" };
+
+  /* Values used to fill in request fields */
+  private static final Namespace NAMESPACE = Namespace.of("accounting", "tax");
+  private static final Map<String, String> PROPERTIES = ImmutableMap.of("owner", "Hank");
+  private static final Map<String, String> EMPTY_PROPERTIES = ImmutableMap.of();
+
+  @Test
+  public void testValidSerDe() throws JsonProcessingException {
+    Map<String, CreateNamespaceRequest> toTest = ImmutableMap.of(
+        // Full response
+        "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{\"owner\":\"Hank\"}}",
+        builder().withNamespace(NAMESPACE).setProperties(PROPERTIES).build(),
+        "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":null}",
+        builder().withNamespace(NAMESPACE).build(),
+        "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{}}",
+        builder().withNamespace(NAMESPACE).setProperties(EMPTY_PROPERTIES).build());
+
+    for (Map.Entry<String, CreateNamespaceRequest> testCase : toTest.entrySet()) {
+      String json = testCase.getKey();
+      CreateNamespaceRequest req = testCase.getValue();
+      assertSerializes(req, json);
+      assertDeserializes(json, req);
+    }
+  }
+
+  @Test
+  public void testDeserializeInvalidRequest() {
+    String jsonIncorrectTypeForNamespace = "{\"namespace\":\"accounting%00tax\",\"properties\":null}";
+    AssertHelpers.assertThrows(
+        "A JSON request with incorrect types for fields should fail to deserialize and validate",
+        JsonProcessingException.class,
+        "Namespace must be an array",
+        () -> MAPPER.readValue(jsonIncorrectTypeForNamespace, CreateNamespaceRequest.class).validate()
+    );
+
+    String jsonIncorrectTypeForProperties = "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":[]}";
+    AssertHelpers.assertThrows(
+        "A JSON request with incorrect types for fields should fail to parse and validate",
+        JsonProcessingException.class,
+        () -> MAPPER.readValue(jsonIncorrectTypeForProperties, CreateNamespaceRequest.class).validate()
+    );
+
+    String jsonMisspelledKeys = "{\"namepsace\":[\"accounting\",\"tax\"],\"propertiezzzz\":{\"owner\":\"Hank\"}}";
+    AssertHelpers.assertThrows(
+        "A JSON request with the keys spelled incorrectly should fail to deserialize and validate",
+        JsonProcessingException.class,
+        () -> MAPPER.readValue(jsonMisspelledKeys, CreateNamespaceRequest.class).validate()

Review comment:
       What fails about this? Is it that there are unknown keys in the request?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r805405846



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/CreateNamespaceRequest.java
##########
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import com.fasterxml.jackson.annotation.JsonProperty;

Review comment:
       Annotation classes are ignored if they are not present in the classpath. Relying on annotations brings in a new class of problems caused by the end user messing up their classpath, so I am strongly in favor of avoiding them. If Jackson can infer everything that we need it to without them, then we can use that inference. Otherwise I think we should make serialization more explicit.
   
   I believe that we don't currently use Jackson annotations, so this change would also require updating all of our runtime Jars and their licenses.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810396401



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/DropNamespaceResponse.java
##########
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Objects;
+import org.apache.iceberg.exceptions.ValidationException;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+
+/**
+ * Represents a REST response to drop a namespace.
+ * <p>
+ * The server may choose to return an error if the namespace is not empty.
+ */
+public class DropNamespaceResponse {
+
+  // For Jackson to properly fail when deserializing, this needs to be boxed.
+  // Otherwise, the boolean is parsed according to "loose" javascript JSON rules.
+  private Boolean dropped;
+
+  public DropNamespaceResponse() {
+    // Required for Jackson deserialization
+  }
+
+  private DropNamespaceResponse(Boolean dropped) {

Review comment:
       It has to stay boxed for the time being. At least at the class level.
   
   When I test with the json `{dropped: null}`, there's no failure on deserialization (nor any way to validate the failure because it just sets it to false).
   
   I'll update the builder and the constructor arguments though to use primitives until the class level field is hit.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810546934



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/ListNamespacesResponse.java
##########
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Collection;
+import java.util.List;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+
+public class ListNamespacesResponse {
+
+  private List<Namespace> namespaces;
+
+  public ListNamespacesResponse() {
+    // Required for Jackson deserialization
+  }
+
+  private ListNamespacesResponse(List<Namespace> namespaces) {
+    this.namespaces = namespaces;
+    validate();
+  }
+
+  ListNamespacesResponse validate() {
+    Preconditions.checkArgument(namespaces != null,
+        "Cannot create a response to a list namespaces request without a non-null list of namespaces");
+    return this;
+  }
+
+
+  public List<Namespace> namespaces() {
+    return namespaces != null ? namespaces : ImmutableList.of();
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("namespaces", namespaces())
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  static class Builder {
+    private final ImmutableList.Builder<Namespace> namespaces = ImmutableList.builder();
+
+    private Builder() {
+    }
+
+    public Builder add(Namespace toAdd) {
+      Preconditions.checkNotNull(toAdd,
+          "Invalid namespace to list: null");
+      namespaces.add(toAdd);
+      return this;
+    }
+
+    public Builder addAll(Collection<Namespace> toAdd) {
+      Preconditions.checkNotNull(toAdd,
+          "Invalid collection of namespaces to list: null");
+      Preconditions.checkArgument(!toAdd.contains(null),
+          "Invalid namespace in collection of namespaces to list: null");

Review comment:
       Invalid namespace list: null




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810546891



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/GetNamespaceResponse.java
##########
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.Maps;
+
+/**
+ * Represents a REST response to fetch a namespace and its metadata properties
+ */
+public class GetNamespaceResponse {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public GetNamespaceResponse() {
+    // Required for Jackson deserialization
+  }
+
+  private GetNamespaceResponse(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+    validate();
+  }
+
+  GetNamespaceResponse validate() {
+    Preconditions.checkArgument(namespace != null,
+        "Cannot build a response to get a null namespace");

Review comment:
       Invalid namespace: null.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r811421473



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/CreateNamespaceResponse.java
##########
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.Maps;
+
+/**
+ * Represents a REST response for a request to create a namespace / database.
+ */
+public class CreateNamespaceResponse {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public CreateNamespaceResponse() {
+    // Required for Jackson deserialization.
+  }
+
+  private CreateNamespaceResponse(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+    validate();
+  }
+
+  CreateNamespaceResponse validate() {
+    Preconditions.checkArgument(
+        namespace != null && !namespace.isEmpty(),
+        "Cannot build a response to create a namespace without specifying the namespace");

Review comment:
       Yeah that sounds good to me. And the empty namespace should probably be allowed, in case people want to model something using it (or there are situations where it's safe to omit... which would probably depend on the server implementation but isn't something we should disallow).




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810395491



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/DropNamespaceResponse.java
##########
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Objects;
+import org.apache.iceberg.exceptions.ValidationException;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+
+/**
+ * Represents a REST response to drop a namespace.
+ * <p>
+ * The server may choose to return an error if the namespace is not empty.
+ */
+public class DropNamespaceResponse {
+
+  // For Jackson to properly fail when deserializing, this needs to be boxed.
+  // Otherwise, the boolean is parsed according to "loose" javascript JSON rules.
+  private Boolean dropped;
+
+  public DropNamespaceResponse() {
+    // Required for Jackson deserialization
+  }
+
+  private DropNamespaceResponse(Boolean dropped) {

Review comment:
       It's boxed so that Jackson will return `null` for cases that don't parse (or its missing), so we can validate on that. Whereas a primitive would potentially default to `false`.
   
   But since things have changed, let me see if I can make this a primitive.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r811467916



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/GetNamespaceResponse.java
##########
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.Maps;
+
+/**
+ * Represents a REST response to fetch a namespace and its metadata properties
+ */
+public class GetNamespaceResponse {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public GetNamespaceResponse() {
+    // Required for Jackson deserialization
+  }
+
+  private GetNamespaceResponse(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+    validate();
+  }
+
+  GetNamespaceResponse validate() {
+    Preconditions.checkArgument(namespace != null, "Invalid namespace: null");
+    return this;
+  }
+
+  public Namespace namespace() {
+    return namespace;
+  }
+
+  public Map<String, String> properties() {
+    return properties != null ? properties : ImmutableMap.of();
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("namespace", namespace)
+        .add("properties", properties)
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  static class Builder {
+    private Namespace namespace;
+    private final ImmutableMap.Builder<String, String> properties =  ImmutableMap.builder();
+
+    private Builder() {
+    }
+
+    public Builder withNamespace(Namespace ns) {
+      Preconditions.checkNotNull(ns, "Invalid namespace: null");
+      namespace = ns;
+      return this;
+    }
+
+    public Builder setProperties(Map<String, String> props) {
+      Preconditions.checkNotNull(props,
+          "Invalid collection of properties: null");
+      Preconditions.checkArgument(!props.containsKey(null),
+          "Invalid property in collection of namespace properties: null");
+      Preconditions.checkArgument(!props.containsValue(null),
+          "Invalid value for properties %s: null",

Review comment:
       Invalid value for property, not properties.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r811448169



##########
File path: core/src/test/java/org/apache/iceberg/catalog/TestTableIdentifierParser.java
##########
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.catalog;
+
+import org.apache.iceberg.AssertHelpers;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestTableIdentifierParser {
+
+  @Test
+  public void testTableIdentifierToJson() {
+    String json = "{\"namespace\":[\"accounting\",\"tax\"],\"name\":\"paid\"}";
+    TableIdentifier identifier = TableIdentifier.of(Namespace.of("accounting", "tax"), "paid");
+    Assert.assertEquals("Should be able to serialize a table identifier with both namespace and name",
+        json, TableIdentifierParser.toJson(identifier));
+
+    TableIdentifier identifierWithEmptyNamespace = TableIdentifier.of(Namespace.empty(), "paid");
+    String jsonWithEmptyNamespace = "{\"namespace\":[],\"name\":\"paid\"}";
+    Assert.assertEquals("Should be able to serialize a table identifier that uses the empty namespace",
+        jsonWithEmptyNamespace, TableIdentifierParser.toJson(identifierWithEmptyNamespace));
+  }
+
+  @Test
+  public void testTableIdentifierFromJson() {
+    String json = "{\"namespace\":[\"accounting\",\"tax\"],\"name\":\"paid\"}";
+    TableIdentifier identifier = TableIdentifier.of(Namespace.of("accounting", "tax"), "paid");
+    Assert.assertEquals("Should be able to deserialize a valid table identifier",
+        identifier, TableIdentifierParser.fromJson(json));
+
+    TableIdentifier identifierWithEmptyNamespace = TableIdentifier.of(Namespace.empty(), "paid");
+    String jsonWithEmptyNamespace = "{\"namespace\":[],\"name\":\"paid\"}";
+    Assert.assertEquals("Should be able to deserialize a valid multi-level table identifier",
+        identifierWithEmptyNamespace, TableIdentifierParser.fromJson(jsonWithEmptyNamespace));
+  }
+
+  @Test
+  public void testFailParsingWhenNullOrEmptyJson() {
+    String nullJson = null;
+    AssertHelpers.assertThrows("TableIdentifierParser should fail to deserialize null JSON string",
+        IllegalArgumentException.class, "Cannot parse table identifier from invalid JSON: null",
+        () ->  TableIdentifierParser.fromJson(nullJson));
+
+    String emptyString = "";
+    AssertHelpers.assertThrows("TableIdentifierParser should fail to deserialize an empty string",
+        IllegalArgumentException.class, "Cannot parse table identifier from invalid JSON: ''",
+        () ->  TableIdentifierParser.fromJson(emptyString));
+
+    String emptyJson = "{}";
+    AssertHelpers.assertThrows("TableIdentifierParser should fail to deserialize an empty JSON string",
+        IllegalArgumentException.class, "Cannot parse missing list namespace",
+        () ->  TableIdentifierParser.fromJson(emptyJson));
+
+    String emptyJsonArray = "[]";
+    AssertHelpers.assertThrows("TableIdentifierParser should fail to deserialize an empty JSON array",
+        IllegalArgumentException.class, "Cannot parse missing or non-object table identifier: []",
+        () ->  TableIdentifierParser.fromJson(emptyJsonArray));
+  }
+
+  @Test
+  public void testFailParsingWhenMissingRequiredFields() {
+    String identifierMissingName = "{\"namespace\":[\"accounting\",\"tax\"]}";
+    AssertHelpers.assertThrows("TableIdentifierParser should fail to deserialize table with missing name",
+        IllegalArgumentException.class, "Cannot parse missing string name",
+        () ->  TableIdentifierParser.fromJson(identifierMissingName));
+
+    String identifierMissingNamespace = "{\"name\":\"paid\"}";
+    AssertHelpers.assertThrows("TableIdentifierParser should fail to deserialize table with missing namespace",
+        IllegalArgumentException.class, "Cannot parse missing list namespace",

Review comment:
       Ok. Updated so that missing AND null `namespace` is implicitly converted to the empty namespace on parsing.
   
   Let me know if you want me to update it at all.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r799078495



##########
File path: core/src/main/java/org/apache/iceberg/rest/RESTJacksonModule.java
##########
@@ -0,0 +1,183 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import java.io.IOException;
+import org.apache.iceberg.PartitionSpec;
+import org.apache.iceberg.PartitionSpecParser;
+import org.apache.iceberg.Schema;
+import org.apache.iceberg.SchemaParser;
+import org.apache.iceberg.SortOrder;
+import org.apache.iceberg.SortOrderParser;
+import org.apache.iceberg.TableMetadata;
+import org.apache.iceberg.TableMetadataParser;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.catalog.TableIdentifier;
+
+public class RESTJacksonModule {
+
+  private RESTJacksonModule() {
+  }
+
+  public static void registerAll(ObjectMapper mapper) {
+    SimpleModule module = new SimpleModule();
+    module
+        .addSerializer(TableIdentifier.class, new TableIdentifierSerializer())
+        .addDeserializer(TableIdentifier.class, new TableIdentifierDeserializer())
+        .addSerializer(Namespace.class, new NamespaceSerializer())
+        .addDeserializer(Namespace.class, new NamespaceDeserializer())
+        .addSerializer(Schema.class, new SchemaSerializer())
+        .addDeserializer(Schema.class, new SchemaDeserializer())
+        .addSerializer(PartitionSpec.class, new PartitionSpecSerializer())
+        .addDeserializer(PartitionSpec.class, new PartitionSpecDeserializer())
+        .addSerializer(SortOrder.class, new SortOrderSerializer())
+        .addDeserializer(SortOrder.class, new SortOrderDeserializer());
+    mapper.registerModule(module);
+
+    mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE);
+    mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
+  }
+
+  public static class NamespaceDeserializer extends JsonDeserializer<Namespace> {
+    @Override
+    public Namespace deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
+      JsonNode jsonNode = p.getCodec().readTree(p);
+      return namespaceFromNode(p, jsonNode);
+    }
+  }
+
+  public static class NamespaceSerializer extends JsonSerializer<Namespace> {
+    @Override
+    public void serialize(Namespace namespace, JsonGenerator gen, SerializerProvider serializers)
+        throws IOException {
+      String[] parts = namespace.levels();
+      gen.writeArray(parts, 0, parts.length);
+    }
+  }
+
+  public static class TableIdentifierDeserializer extends JsonDeserializer<TableIdentifier> {
+    @Override
+    public TableIdentifier deserialize(JsonParser p, DeserializationContext ctxt)
+        throws IOException {
+      JsonNode jsonNode = p.getCodec().readTree(p);
+      if (!jsonNode.isObject()) {
+        throw new JsonParseException(p, "TableIdentifier must be an object: " + jsonNode);
+      }
+      ObjectNode objectNode = (ObjectNode) jsonNode;
+      Namespace namespace = namespaceFromNode(p, objectNode.get("namespace"));
+      String name = objectNode.get("name").asText();
+      return TableIdentifier.of(namespace, name);
+    }
+  }
+
+  private static Namespace namespaceFromNode(JsonParser parser, JsonNode jsonNode) throws IOException {
+    if (!jsonNode.isArray()) {
+      throw new JsonParseException(parser, "Namespace must be an array: " + jsonNode);
+    }
+    ArrayNode arrayNode = (ArrayNode) jsonNode;
+    String[] levels = new String[arrayNode.size()];
+    for (int i = 0; i < levels.length; i++) {
+      levels[i] = arrayNode.get(i).asText();
+    }
+    return Namespace.of(levels);
+  }
+
+  public static class TableIdentifierSerializer extends JsonSerializer<TableIdentifier> {
+    @Override
+    public void serialize(
+        TableIdentifier identifier, JsonGenerator gen, SerializerProvider serializers)
+        throws IOException {
+      gen.writeStartObject();
+      gen.writeFieldName("namespace");
+      String[] levels = identifier.namespace().levels();
+      gen.writeArray(levels, 0, levels.length);
+      gen.writeStringField("name", identifier.name());
+      gen.writeEndObject();
+    }
+  }
+
+  public static class SchemaDeserializer extends JsonDeserializer<Schema> {
+    @Override
+    public Schema deserialize(JsonParser p, DeserializationContext context) throws IOException {
+      JsonNode jsonNode = p.getCodec().readTree(p);
+      Schema schema = SchemaParser.fromJson(jsonNode);
+      context.setAttribute("schema", schema);

Review comment:
       What is the scope of the context that this is modifying?
   
   Does the schema need to be deserialized before the partition spec?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r799087424



##########
File path: core/src/test/java/org/apache/iceberg/rest/requests/TestCreateNamespaceRequest.java
##########
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.util.JsonUtil;
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+
+public class TestCreateNamespaceRequest {
+
+  private static final ObjectMapper MAPPER = JsonUtil.withRESTComponents();
+
+  // Non-empty
+  private static final String JSON_REQUEST_STRING =
+      "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{\"owner\":\"Hank\"}}";
+  private static final Namespace NAMESPACE = Namespace.of("accounting", "tax");
+  private static final Map<String, String> PROPERTIES = ImmutableMap.of("owner", "Hank");
+
+  // Empty - The response requires a non-empty namespace
+  private static final String JSON_REQUEST_NO_PROPERTIES =
+      "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{}}";
+
+  @Test
+  public void testDeserialize() throws JsonProcessingException {
+    CreateNamespaceRequest expected = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .withProperties(PROPERTIES)
+        .build();
+
+    CreateNamespaceRequest actual = MAPPER.readValue(JSON_REQUEST_STRING, CreateNamespaceRequest.class);
+
+    assertSame(expected, actual);
+  }
+
+  @Test
+  public void testDeserializeNoProperties() throws JsonProcessingException {

Review comment:
       I think we need to test 3 things: missing `properties`, `properties` that is explicitly null, and empty properties.
   
   On the serialization side, it's perfectly fine if no properties are serialized as an empty map only.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r799091018



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/UpdateNamespacePropertiesResponse.java
##########
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.List;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
+
+/**
+ * A REST response to a request to set and/or remove properties on a namespace.
+ */
+public class UpdateNamespacePropertiesResponse {
+
+  // List of namespace property keys that were removed
+  private List<String> removed;
+  // List of namesspace property keys that were added or updated
+  private List<String> updated;
+  // List of properties that were requested for removal that were not found in the namespace's properties
+  private List<String> missing;
+
+  public UpdateNamespacePropertiesResponse() {
+    // Required for Jackson
+  }
+
+  private UpdateNamespacePropertiesResponse(List<String> removed, List<String> updated, List<String> missing) {
+    this.removed = removed;
+    this.updated = updated;
+    this.missing = missing;
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public List<String> removed() {
+    return ImmutableList.copyOf(removed);
+  }
+
+  public List<String> updated() {
+    return ImmutableList.copyOf(updated);
+  }
+
+  public List<String> missing() {
+    return ImmutableList.copyOf(missing);
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("removed", removed())
+        .add("updates", updated())
+        .add("missing", missing())

Review comment:
       No need to use the methods here. It will just create a useless empty list.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r799090186



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/ListTablesResponse.java
##########
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Collection;
+import java.util.List;
+import org.apache.iceberg.catalog.TableIdentifier;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+
+/**
+ * A list of table identifiers, parsed from a REST response to a request for listing tables
+ * in a given namespace.
+ */
+public class ListTablesResponse {
+
+  private List<TableIdentifier> identifiers;
+
+  public ListTablesResponse() {
+    // Required for Jackson
+  }
+
+  private ListTablesResponse(List<TableIdentifier> identifiers) {
+    this.identifiers = identifiers;
+  }
+
+  public List<TableIdentifier> identifiers() {
+    return ImmutableList.copyOf(identifiers);
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("identifiers", identifiers())
+        .toString();
+  }
+
+  public static class Builder {
+    private final ImmutableList.Builder<TableIdentifier> identifiers = ImmutableList.builder();
+
+    private Builder() {
+    }
+
+    public Builder withIdentifiers(Collection<TableIdentifier> toAdd) {

Review comment:
       add / addAll?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r801144888



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/CreateNamespaceRequest.java
##########
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+
+/**
+ * A REST request to create a namespace, with an optional set of properties.
+ * The server might also add properties, such as `last_modified_time` etc.
+ */
+public class CreateNamespaceRequest {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public CreateNamespaceRequest() {
+    // Required for Jackson deserialization
+  }
+
+  private CreateNamespaceRequest(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public Namespace namespace() {
+    return namespace;
+  }
+
+  public Map<String, String> properties() {
+    return ImmutableMap.copyOf(properties);
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("namespace", namespace)
+        .add("properties", properties)
+        .toString();
+  }
+
+  public static class Builder {
+    private Namespace namespace;
+    private ImmutableMap.Builder<String, String> properties = ImmutableMap.builder();
+
+    private Builder() {
+    }
+
+    public Builder withNamespace(Namespace ns) {
+      this.namespace = ns;
+      return this;
+    }
+
+    public Builder withProperties(Map<String, String> props) {
+      this.properties.putAll(props);
+      return this;
+    }
+
+    public CreateNamespaceRequest build() {
+      Preconditions.checkArgument(
+          namespace != null && !namespace.isEmpty(),
+          "Cannot build a response to create a namespace without specifying the namespace");

Review comment:
       This specific Precondition was moved to the constructor (so that Jackson would go through the same path), but I have asserted on the message.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r801029893



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/CreateNamespaceRequest.java
##########
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+
+/**
+ * A REST request to create a namespace, with an optional set of properties.
+ * The server might also add properties, such as `last_modified_time` etc.
+ */
+public class CreateNamespaceRequest {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public CreateNamespaceRequest() {
+    // Required for serialization
+  }
+
+  private CreateNamespaceRequest(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public Namespace namespace() {
+    return namespace;
+  }
+
+  public Map<String, String> properties() {
+    return ImmutableMap.copyOf(properties);
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("namespace", namespace)
+        .add("properties", properties())
+        .toString();
+  }
+
+  public static class Builder {
+    private final ImmutableList.Builder<String> namespaceBuilder;
+    private final ImmutableMap.Builder<String, String> propertiesBuilder;
+
+    private Builder() {
+      this.namespaceBuilder = ImmutableList.builder();
+      this.propertiesBuilder = ImmutableMap.builder();
+    }
+
+    public Builder withNamespace(Namespace namespace) {
+      this.namespaceBuilder.add(namespace.levels());
+      return this;
+    }
+
+    public Builder withProperties(Map<String, String> properties) {

Review comment:
       Updated (and added a check for `null` on the input as well as I see people do that sometimes in tests etc).




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] jackye1995 commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
jackye1995 commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r800915283



##########
File path: core/src/main/java/org/apache/iceberg/rest/RESTJacksonModule.java
##########
@@ -0,0 +1,174 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import java.io.IOException;
+import org.apache.iceberg.PartitionSpec;
+import org.apache.iceberg.PartitionSpecParser;
+import org.apache.iceberg.Schema;
+import org.apache.iceberg.SchemaParser;
+import org.apache.iceberg.SortOrder;
+import org.apache.iceberg.SortOrderParser;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.catalog.TableIdentifier;
+
+public class RESTJacksonModule {
+
+  private RESTJacksonModule() {
+  }
+
+  public static void registerAll(ObjectMapper mapper) {
+    SimpleModule module = new SimpleModule();
+    module
+        .addSerializer(TableIdentifier.class, new TableIdentifierSerializer())
+        .addDeserializer(TableIdentifier.class, new TableIdentifierDeserializer())
+        .addSerializer(Namespace.class, new NamespaceSerializer())
+        .addDeserializer(Namespace.class, new NamespaceDeserializer())
+        .addSerializer(Schema.class, new SchemaSerializer())
+        .addDeserializer(Schema.class, new SchemaDeserializer())
+        .addSerializer(PartitionSpec.class, new PartitionSpecSerializer())
+        .addDeserializer(PartitionSpec.class, new PartitionSpecDeserializer())
+        .addSerializer(SortOrder.class, new SortOrderSerializer())
+        .addDeserializer(SortOrder.class, new SortOrderDeserializer());
+    mapper.registerModule(module);
+  }
+
+  public static class NamespaceDeserializer extends JsonDeserializer<Namespace> {
+    @Override
+    public Namespace deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
+      JsonNode jsonNode = p.getCodec().readTree(p);
+      return namespaceFromNode(p, jsonNode);
+    }
+  }
+
+  public static class NamespaceSerializer extends JsonSerializer<Namespace> {
+    @Override
+    public void serialize(Namespace namespace, JsonGenerator gen, SerializerProvider serializers)
+        throws IOException {
+      String[] parts = namespace.levels();
+      gen.writeArray(parts, 0, parts.length);
+    }
+  }
+
+  public static class TableIdentifierDeserializer extends JsonDeserializer<TableIdentifier> {
+    @Override
+    public TableIdentifier deserialize(JsonParser p, DeserializationContext ctxt)
+        throws IOException {
+      JsonNode jsonNode = p.getCodec().readTree(p);
+      if (!jsonNode.isObject()) {
+        throw new JsonParseException(p, "TableIdentifier must be an object: " + jsonNode);
+      }
+      ObjectNode objectNode = (ObjectNode) jsonNode;
+      Namespace namespace = namespaceFromNode(p, objectNode.get("namespace"));
+      String name = objectNode.get("name").asText();
+      return TableIdentifier.of(namespace, name);
+    }
+  }
+
+  private static Namespace namespaceFromNode(JsonParser parser, JsonNode jsonNode) throws IOException {
+    if (!jsonNode.isArray()) {
+      throw new JsonParseException(parser, "Namespace must be an array: " + jsonNode);
+    }
+    ArrayNode arrayNode = (ArrayNode) jsonNode;
+    String[] levels = new String[arrayNode.size()];
+    for (int i = 0; i < levels.length; i++) {
+      levels[i] = arrayNode.get(i).asText();
+    }
+    return Namespace.of(levels);
+  }
+
+  public static class TableIdentifierSerializer extends JsonSerializer<TableIdentifier> {
+    @Override
+    public void serialize(
+        TableIdentifier identifier, JsonGenerator gen, SerializerProvider serializers)
+        throws IOException {
+      gen.writeStartObject();

Review comment:
       I wonder if we should keep the consistency here: schema, partition spec and sort order all have their own `Parser` that is Iceberg's bridge for JSON serde. Should we also first have `TableIdentifierParser`, `NamespaceParser` and then have these Jackson specific serializers. This would also help Trino/Presto integration because registering a Jackson serializer is not an option.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r801021903



##########
File path: core/src/main/java/org/apache/iceberg/rest/RESTJacksonModule.java
##########
@@ -0,0 +1,183 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import java.io.IOException;
+import org.apache.iceberg.PartitionSpec;
+import org.apache.iceberg.PartitionSpecParser;
+import org.apache.iceberg.Schema;
+import org.apache.iceberg.SchemaParser;
+import org.apache.iceberg.SortOrder;
+import org.apache.iceberg.SortOrderParser;
+import org.apache.iceberg.TableMetadata;
+import org.apache.iceberg.TableMetadataParser;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.catalog.TableIdentifier;
+
+public class RESTJacksonModule {

Review comment:
       Renamed to `RESTSerializers`.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r801146322



##########
File path: rest_docs/rest-catalog-open-api.yaml
##########
@@ -29,34 +29,39 @@ info:
     Defines the specification for the first version of the REST Catalog API.
     Implementations should ideally support both Iceberg table specs v1 and v2, with priority given to v2.
 servers:
-  - url: "{scheme}://{host}/{basePath}"
+  - url: '{scheme}://{host}/{basePath}'

Review comment:
       Oh yeah. I don't even know how those changes got into this branch. I'll definitely revert them 👍 




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r803041412



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/CreateNamespaceResponse.java
##########
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.Maps;
+
+/**
+ * Represents a REST response for a request to create a namespace / database.
+ * <p>
+ * The properties returned should include all the user provided properties from the
+ * request, as well as any server-side added properties.
+ * <p>
+ * Example server-side added properties can be implementation specific, but might include
+ * such things as `created_at` or `owner`.
+ */
+public class CreateNamespaceResponse {

Review comment:
       Closing this as we've decided to keep the responses separate for now.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810301422



##########
File path: core/src/test/java/org/apache/iceberg/rest/requests/TestUpdateNamespacePropertiesRequest.java
##########
@@ -0,0 +1,162 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import java.util.List;
+import java.util.Map;
+import org.apache.iceberg.AssertHelpers;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.rest.RequestResponseTestBase;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestUpdateNamespacePropertiesRequest extends RequestResponseTestBase<UpdateNamespacePropertiesRequest> {
+
+  /* Values used to fill in request fields */
+  private static final Map<String, String> UPDATES = ImmutableMap.of("owner", "Hank");
+  private static final List<String> REMOVALS = ImmutableList.of("foo", "bar");
+  private static final Map<String, String> EMPTY_UPDATES = ImmutableMap.of();
+  private static final List<String> EMPTY_REMOVALS = ImmutableList.of();
+
+
+  @Test
+  public void testRoundTripSerDe() throws JsonProcessingException {
+    // Full request
+    String fullJson = "{\"removals\":[\"foo\",\"bar\"],\"updates\":{\"owner\":\"Hank\"}}";
+    assertRoundTripSerializesEquallyFrom(
+        fullJson, UpdateNamespacePropertiesRequest.builder().updateAll(UPDATES).removeAll(REMOVALS).build());
+
+    // Only updates
+    String emptyRemoval = "{\"removals\":[],\"updates\":{\"owner\":\"Hank\"}}";
+    assertRoundTripSerializesEquallyFrom(
+        emptyRemoval, UpdateNamespacePropertiesRequest.builder().updateAll(UPDATES).removeAll(EMPTY_REMOVALS).build());
+
+    assertRoundTripSerializesEquallyFrom(
+        emptyRemoval, UpdateNamespacePropertiesRequest.builder().update("owner", "Hank").build());
+
+    // Only removals
+    String emptyUpdates = "{\"removals\":[\"foo\",\"bar\"],\"updates\":{}}";
+    assertRoundTripSerializesEquallyFrom(
+        emptyUpdates, UpdateNamespacePropertiesRequest.builder().removeAll(REMOVALS).updateAll(EMPTY_UPDATES).build());
+
+    assertRoundTripSerializesEquallyFrom(
+        emptyUpdates, UpdateNamespacePropertiesRequest.builder().remove("foo").remove("bar").build());
+  }
+
+  @Test
+  // Test cases that can't be constructed with our Builder class e2e but that will parse correctly
+  public void testCanDeserializeWithoutDefaultValues() throws JsonProcessingException {
+    // `removals` is left empty.
+    UpdateNamespacePropertiesRequest noRemovals = UpdateNamespacePropertiesRequest.builder().updateAll(UPDATES).build();
+    String jsonWithNullRemovals = "{\"removals\":null,\"updates\":{\"owner\":\"Hank\"}}";
+    UpdateNamespacePropertiesRequest parsed = deserialize(jsonWithNullRemovals);
+    assertEquals(parsed, noRemovals);
+
+    // `removals` is missing from the JSON.
+    String jsonWithMissingRemovals = "{\"updates\":{\"owner\":\"Hank\"}}";
+    assertEquals(deserialize(jsonWithMissingRemovals), noRemovals);
+
+    UpdateNamespacePropertiesRequest noUpdates = UpdateNamespacePropertiesRequest.builder().removeAll(REMOVALS).build();
+    String jsonWithNullUpdates = "{\"removals\":[\"foo\",\"bar\"],\"updates\":null}";
+    assertEquals(deserialize(jsonWithNullUpdates), noUpdates);
+  }
+
+  @Test
+  public void testParseInvalidJson() {
+    // Invalid top-level types
+    String jsonInvalidTypeOnRemovalField =
+        "{\"removals\":{\"foo\":\"bar\"},\"updates\":{\"owner\":\"Hank\"}}";
+    AssertHelpers.assertThrows(
+        "A JSON request with an invalid type for one of the fields should fail to parse",
+        JsonProcessingException.class,
+        () -> deserialize(jsonInvalidTypeOnRemovalField).validate()
+    );
+
+    String jsonInvalidTypeOnUpdatesField =
+        "{\"removals\":[\"foo\":\"bar\"],\"updates\":[\"owner\"]}";
+    AssertHelpers.assertThrows(
+        "A JSON value with an invalid type for one of the fields should fail to parse",
+        JsonProcessingException.class,
+        () -> deserialize(jsonInvalidTypeOnUpdatesField).validate()
+    );
+
+    // Valid top-level (array) types, but at least one entry in the list is not the expected type
+    // NOTE: non-string values that are integral types will still parse into a string list.
+    //    e.g. { removals: [ "foo", "bar", 1234 ] } will parse correctly.
+    String invalidJsonWrongTypeInRemovalsList =
+        "{\"removals\":[\"foo\",\"bar\", {\"owner\": \"Hank\"}],\"updates\":{\"owner\":\"Hank\"}}";
+    AssertHelpers.assertThrows(
+        "A JSON value with an invalid type inside one of the list fields should fail to parse",
+        JsonProcessingException.class,
+        () -> deserialize(invalidJsonWrongTypeInRemovalsList).validate()
+    );
+
+    // All fields are valid types, but all are empty
+    String jsonWithAllFieldsAsEmptyCollection =
+        "{\"removals\":[],\"updates\":{}}";
+    AssertHelpers.assertThrows(
+        "A JSON value with empty collections for all fields should fail to parse and validate",
+        IllegalArgumentException.class,
+        "Cannot create a request to update a namespace's properties without specifying any props to update or remove",
+        () -> deserialize(jsonWithAllFieldsAsEmptyCollection).validate()
+    );
+
+    String emptyJson = "{}";
+    AssertHelpers.assertThrows(
+        "An empty JSON should fail to parse",
+        IllegalArgumentException.class,
+        "Cannot create a request to update a namespace's properties without specifying any props to update or remove",
+        () -> deserialize(emptyJson).validate()
+    );
+
+    String nullJson = null;
+    AssertHelpers.assertThrows(
+        "A null JSON should fail to parse",
+        IllegalArgumentException.class,
+        () -> deserialize(nullJson).validate()
+    );
+  }
+
+  @Override
+  public String[] allFieldsFromSpec() {
+    return new String[] { "updates", "removals" };
+  }
+
+  @Override
+  public UpdateNamespacePropertiesRequest createExampleInstance() {
+    return UpdateNamespacePropertiesRequest.builder()
+        .updateAll(UPDATES)
+        .removeAll(REMOVALS)
+        .build();
+  }
+
+  @Override
+  public void assertEquals(UpdateNamespacePropertiesRequest actual, UpdateNamespacePropertiesRequest expected) {
+    Assert.assertEquals("Properties to update should be equal", actual.updates(), expected.updates());
+    Assert.assertEquals("Properties to remove should be equal", actual.removals(), expected.removals());

Review comment:
       Changed to use a Set. I also changed some other list comparison ones to use a set as well.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810301110



##########
File path: core/src/test/java/org/apache/iceberg/rest/requests/TestCreateNamespaceRequest.java
##########
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import java.util.Map;
+import org.apache.iceberg.AssertHelpers;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.rest.RequestResponseTestBase;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestCreateNamespaceRequest extends RequestResponseTestBase<CreateNamespaceRequest> {
+
+  /* Values used to fill in request fields */
+  private static final Namespace NAMESPACE = Namespace.of("accounting", "tax");
+  private static final Map<String, String> PROPERTIES = ImmutableMap.of("owner", "Hank");
+  private static final Map<String, String> EMPTY_PROPERTIES = ImmutableMap.of();
+
+  @Test
+  // Test cases that are JSON that can be created via the Builder
+  public void testRoundTripSerDe() throws JsonProcessingException {
+    String fullJson = "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{\"owner\":\"Hank\"}}";
+    CreateNamespaceRequest req = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE).setProperties(PROPERTIES).build();
+    assertRoundTripSerializesEquallyFrom(fullJson, req);
+
+    String jsonEmptyProperties = "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{}}";
+    CreateNamespaceRequest reqWithExplicitEmptyProperties = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE).setProperties(EMPTY_PROPERTIES).build();
+    assertRoundTripSerializesEquallyFrom(jsonEmptyProperties, reqWithExplicitEmptyProperties);
+
+    CreateNamespaceRequest reqWithImplicitEmptyProperties = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE).build();
+    assertRoundTripSerializesEquallyFrom(jsonEmptyProperties, reqWithImplicitEmptyProperties);
+  }
+
+  @Test
+  // Test cases that can't be constructed with our Builder class but that will parse correctly
+  public void testCanDeserializeWithoutDefaultValues() throws JsonProcessingException {
+    CreateNamespaceRequest req = CreateNamespaceRequest.builder().withNamespace(NAMESPACE).build();
+    String jsonWithNullProperties = "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":null}";
+    assertEquals(deserialize(jsonWithNullProperties), req);
+
+    String jsonWithMissingProperties = "{\"namespace\":[\"accounting\",\"tax\"]}";
+    assertEquals(deserialize(jsonWithMissingProperties), req);
+  }
+
+  @Test
+  public void testDeserializeInvalidRequest() {
+    String jsonIncorrectTypeForNamespace = "{\"namespace\":\"accounting%00tax\",\"properties\":null}";
+    AssertHelpers.assertThrows(
+        "A JSON request with incorrect types for fields should fail to deserialize and validate",
+        JsonProcessingException.class,
+        "Cannot parse string array from non-array value",
+        () -> deserialize(jsonIncorrectTypeForNamespace).validate()
+    );
+
+    String jsonIncorrectTypeForProperties = "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":[]}";
+    AssertHelpers.assertThrows(
+        "A JSON request with incorrect types for fields should fail to parse and validate",
+        JsonProcessingException.class,
+        () -> deserialize(jsonIncorrectTypeForProperties).validate()
+    );
+
+    String jsonMisspelledKeys = "{\"namepsace\":[\"accounting\",\"tax\"],\"propertiezzzz\":{\"owner\":\"Hank\"}}";
+    AssertHelpers.assertThrows(
+        "A JSON request with the keys spelled incorrectly should fail to deserialize and validate",
+        JsonProcessingException.class,
+        () -> deserialize(jsonMisspelledKeys).validate()

Review comment:
       Added an exception message here of `"Unrecognized field \"namepsace\""`.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810391733



##########
File path: core/src/test/java/org/apache/iceberg/rest/requests/TestCreateNamespaceRequest.java
##########
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.util.JsonUtil;
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+
+public class TestCreateNamespaceRequest {
+
+  private static final ObjectMapper MAPPER = JsonUtil.withRESTComponents();
+
+  private static final String[] ALL_FIELDS_FROM_SPEC = { "namespace", "properties" };
+
+  /* Values used to fill in request fields */
+  private static final Namespace NAMESPACE = Namespace.of("accounting", "tax");
+  private static final Map<String, String> PROPERTIES = ImmutableMap.of("owner", "Hank");
+
+  /* JSON of requests */
+  private static final String JSON_REQUEST =
+      "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{\"owner\":\"Hank\"}}";
+  private static final String JSON_REQUEST_EMPTY_PROPERTIES =
+      "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{}}";
+
+  @Test
+  public void testDeserialize() throws JsonProcessingException {
+    CreateNamespaceRequest expected = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .withProperties(PROPERTIES)
+        .build();
+
+    CreateNamespaceRequest actual = MAPPER.readValue(JSON_REQUEST, CreateNamespaceRequest.class);
+
+    assertEquals(expected, actual);
+    assertHasOnlyKnownFields(expected);
+    assertHasOnlyKnownFields(actual);
+  }
+
+  @Test
+  public void testDeserializeEmptyProperties() throws JsonProcessingException {
+    CreateNamespaceRequest expected = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .build();
+
+    CreateNamespaceRequest actual = MAPPER.readValue(JSON_REQUEST_EMPTY_PROPERTIES, CreateNamespaceRequest.class);
+
+    assertEquals(expected, actual);
+    assertHasOnlyKnownFields(expected);
+    assertHasOnlyKnownFields(actual);
+  }
+
+  @Test
+  public void testSerialize() throws JsonProcessingException {
+    CreateNamespaceRequest req = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .withProperties(PROPERTIES)
+        .build();
+
+    Assertions.assertThat(MAPPER.writeValueAsString(req))
+        .isEqualTo(JSON_REQUEST);
+  }
+
+  @Test
+  public void testSerializeEmptyProperties() throws JsonProcessingException {
+    CreateNamespaceRequest req = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .build();
+
+    Assertions.assertThat(MAPPER.writeValueAsString(req))
+        .isEqualTo(JSON_REQUEST_EMPTY_PROPERTIES);
+  }
+
+  private static void assertEquals(CreateNamespaceRequest expected, CreateNamespaceRequest actual) {
+    Assertions.assertThat(actual.namespace()).isEqualTo(expected.namespace());

Review comment:
       Another comment about it: https://github.com/apache/iceberg/pull/4037#discussion_r808449734




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r809496116



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/UpdateNamespacePropertiesRequest.java
##########
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.List;
+import java.util.Map;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
+
+/**
+ * A REST request to set and/or remove properties on a namespace.
+ * <p>
+ * The request body specifies a list of properties to remove and a map
+ * of key value pairs to update.
+ * <p>
+ * Properties that are not in the request are not modified or removed by this call.
+ * Server implementations are not required to support namespace properties.
+ */
+public class UpdateNamespacePropertiesRequest {
+
+  private List<String> removals;
+  private Map<String, String> updates;
+
+  public UpdateNamespacePropertiesRequest() {
+    // Required for Jackson deserialization.
+  }
+
+  private UpdateNamespacePropertiesRequest(List<String> removals, Map<String, String> updates) {
+    this.removals = removals;
+    this.updates = updates;
+    validate();
+  }
+
+  UpdateNamespacePropertiesRequest validate() {
+    Preconditions.checkArgument((removals != null && !removals.isEmpty()) || (updates != null && !updates.isEmpty()),
+        "Cannot create a request to update a namespace's properties without specifying any props to update or remove");
+    return this;
+  }
+
+  public List<String> removals() {
+    return removals == null ? ImmutableList.of() : removals;
+  }
+
+  public Map<String, String> updates() {
+    return updates == null ? ImmutableMap.of() : updates;
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("removals", removals)
+        .add("updates", updates)
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public static class Builder {
+    private final ImmutableSet.Builder<String> removalsBuilder = ImmutableSet.builder();
+    private final ImmutableMap.Builder<String, String> updatesBuilder = ImmutableMap.builder();
+
+    private Builder() {
+    }
+
+    public Builder remove(String removal) {
+      Preconditions.checkNotNull(removal,
+          "Cannot pass null key to remove to UpdateNamespacePropertiesRequest.Builder");
+      removalsBuilder.add(removal);
+      return this;
+    }
+
+    public Builder removeAll(Iterable<String> removals) {
+      Preconditions.checkNotNull(removals,
+          "Cannot pass null removals to UpdateNamespacePropertiesRequest.Builder");
+      removalsBuilder.addAll(removals);
+      return this;
+    }
+
+    public Builder update(String key, String value) {
+      Preconditions.checkNotNull(key,
+          "Cannot pass null key to update to UpdateNamespacePropertiesRequest.Builder");
+      Preconditions.checkNotNull(value,
+          "Cannot pass null value to update in UpdateNamespacePropertiesRequest.Builder. Use remove instead");
+      updatesBuilder.put(key, value);
+      return this;
+    }
+
+    public Builder updateAll(Map<String, String> updates) {
+      Preconditions.checkNotNull(updates,
+          "Cannot pass null updates to UpdateNamespacePropertiesRequest.Builder");

Review comment:
       Ah good call. Should we filter them out or throw? I would assume throw.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810546994



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/ListTablesResponse.java
##########
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Collection;
+import java.util.List;
+import org.apache.iceberg.catalog.TableIdentifier;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+
+/**
+ * A list of table identifiers in a given namespace.
+ */
+public class ListTablesResponse {
+
+  private List<TableIdentifier> identifiers;
+
+  public ListTablesResponse() {
+    // Required for Jackson deserialization
+  }
+
+  private ListTablesResponse(List<TableIdentifier> identifiers) {
+    this.identifiers = identifiers;
+    validate();
+  }
+
+  ListTablesResponse validate() {
+    Preconditions.checkArgument(identifiers != null,
+        "Cannot build a response to list tables without a non-null list of table identifiers");

Review comment:
       Invalid identifier list: null




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810398622



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/GetNamespaceResponse.java
##########
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.exceptions.ValidationException;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.util.ImmutablesUtil;
+
+/**
+ * Represents a REST response to fetch namespace metadata.
+ * <p>
+ * The properties returned should include all the user provided properties from the
+ * request, as well as any server-side added properties.
+ */
+public class GetNamespaceResponse {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public GetNamespaceResponse() {
+    // Required for Jackson deserialization
+  }
+
+  private GetNamespaceResponse(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+    validate();
+  }
+
+  GetNamespaceResponse validate() {
+    ValidationException.check(namespace != null && !namespace.isEmpty(),
+        "Cannot build a response to get a namespace without specifying the namespace");
+    return this;
+  }
+
+  public Namespace namespace() {
+    return namespace;
+  }
+
+  public Map<String, String> properties() {
+    return ImmutablesUtil.nullSafeCopyOf(properties);
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  @Override
+  public boolean equals(Object o) {

Review comment:
       No worries. It's updated now!




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810398394



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/GetNamespaceResponse.java
##########
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.exceptions.ValidationException;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.util.ImmutablesUtil;
+
+/**
+ * Represents a REST response to fetch namespace metadata.
+ * <p>
+ * The properties returned should include all the user provided properties from the
+ * request, as well as any server-side added properties.

Review comment:
       Made the javadoc much more simple and removed this.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810547062



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/ListTablesResponse.java
##########
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Collection;
+import java.util.List;
+import org.apache.iceberg.catalog.TableIdentifier;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+
+/**
+ * A list of table identifiers in a given namespace.
+ */
+public class ListTablesResponse {
+
+  private List<TableIdentifier> identifiers;
+
+  public ListTablesResponse() {
+    // Required for Jackson deserialization
+  }
+
+  private ListTablesResponse(List<TableIdentifier> identifiers) {
+    this.identifiers = identifiers;
+    validate();
+  }
+
+  ListTablesResponse validate() {
+    Preconditions.checkArgument(identifiers != null,
+        "Cannot build a response to list tables without a non-null list of table identifiers");
+    return this;
+  }
+
+  public List<TableIdentifier> identifiers() {
+    return identifiers != null ? identifiers : ImmutableList.of();
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("identifiers", identifiers)
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  static class Builder {
+    private final ImmutableList.Builder<TableIdentifier> identifiers = ImmutableList.builder();
+
+    private Builder() {
+    }
+
+    public Builder add(TableIdentifier toAdd) {
+      Preconditions.checkNotNull(toAdd, "Invalid table to list: null");
+      identifiers.add(toAdd);
+      return this;
+    }
+
+    public Builder addAll(Collection<TableIdentifier> toAdd) {
+      Preconditions.checkNotNull(toAdd, "Invalid collection of tables to list: null");

Review comment:
       Invalid table identifier list: null




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r808449734



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/CreateNamespaceRequest.java
##########
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.exceptions.ValidationException;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+
+/**
+ * A REST request to create a namespace, with an optional set of properties.
+ * The server might also add properties, such as `last_modified_time` etc.
+ */
+public class CreateNamespaceRequest {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public CreateNamespaceRequest() {
+    // Needed for Jackson Deserialization.
+  }
+
+  private CreateNamespaceRequest(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+    validate();
+  }
+
+  /**
+   * This function needs to be called after reading in JSON from another source, to ensure
+   * that null values are assigned to their respective defaults where needed, wrap collections
+   * in their Immutable variants, and that required fields are correct.
+   * @return normalized version of this {@link CreateNamespaceRequest}
+   */
+  CreateNamespaceRequest validate() {
+    this.properties = properties == null ? ImmutableMap.of() : ImmutableMap.copyOf(properties);
+    ValidationException.check(namespace != null && !namespace.isEmpty(),
+        "Cannot build a request to create a namespace without specifying the namespace");
+    return this;
+  }
+
+  public Namespace namespace() {
+    return namespace;
+  }
+
+  public Map<String, String> properties() {
+    return properties;
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("namespace", namespace)
+        .add("properties", properties)
+        .toString();
+  }
+
+  @Override
+  public boolean equals(Object o) {

Review comment:
       Since this led to modifying the object inside of `validate`, I think it is better to remove `equals` and `hashCode` and default to `ImmutableMap.of()` in the `properties` getter. You can add `assertEquals` in the tests to reuse code.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r808449008



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/CreateNamespaceRequest.java
##########
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.exceptions.ValidationException;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+
+/**
+ * A REST request to create a namespace, with an optional set of properties.
+ * The server might also add properties, such as `last_modified_time` etc.
+ */
+public class CreateNamespaceRequest {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public CreateNamespaceRequest() {
+    // Needed for Jackson Deserialization.
+  }
+
+  private CreateNamespaceRequest(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+    validate();
+  }
+
+  /**
+   * This function needs to be called after reading in JSON from another source, to ensure
+   * that null values are assigned to their respective defaults where needed, wrap collections
+   * in their Immutable variants, and that required fields are correct.
+   * @return normalized version of this {@link CreateNamespaceRequest}
+   */
+  CreateNamespaceRequest validate() {
+    this.properties = properties == null ? ImmutableMap.of() : ImmutableMap.copyOf(properties);
+    ValidationException.check(namespace != null && !namespace.isEmpty(),
+        "Cannot build a request to create a namespace without specifying the namespace");

Review comment:
       I'd probably use Preconditions.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r809453112



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/DropNamespaceResponse.java
##########
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Objects;
+import org.apache.iceberg.exceptions.ValidationException;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+
+/**
+ * Represents a REST response to drop a namespace.
+ * <p>
+ * The server may choose to return an error if the namespace is not empty.
+ */
+public class DropNamespaceResponse {
+
+  // For Jackson to properly fail when deserializing, this needs to be boxed.
+  // Otherwise, the boolean is parsed according to "loose" javascript JSON rules.
+  private Boolean dropped;
+
+  public DropNamespaceResponse() {
+    // Required for Jackson deserialization
+  }
+
+  private DropNamespaceResponse(Boolean dropped) {
+    this.dropped = dropped;
+    validate();
+  }
+
+  DropNamespaceResponse validate() {
+    // Use `checkArguemt` so it will throw IllegalArgumentException, just like the other responses
+    Preconditions.checkArgument(dropped != null,
+        "Cannot instantiate a response to dropping a namespace with missing field(s): `dropped`");
+    return this;
+  }
+
+  public boolean isDropped() {
+    return dropped;
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("dropped", dropped)
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public static class Builder {
+    private Boolean dropped = false;
+
+    private Builder() {
+    }
+
+    public Builder dropped(Boolean isDropped) {
+      this.dropped = isDropped;
+      return this;
+    }
+
+    public DropNamespaceResponse build() {
+      return new DropNamespaceResponse(dropped);

Review comment:
       This should check that `dropped` is not null. Even if JSON deserialization can produce invalid responses, the builder should not.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r809452367



##########
File path: core/src/test/java/org/apache/iceberg/rest/responses/TestDropNamespaceResponse.java
##########
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import org.apache.iceberg.AssertHelpers;
+import org.apache.iceberg.rest.RequestResponseTestBase;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestDropNamespaceResponse extends RequestResponseTestBase<DropNamespaceResponse> {
+
+  @Test
+  public void testRoundTripSerDe() throws JsonProcessingException {
+    assertRoundTripSerializesEquallyFrom(
+        "{\"dropped\":true}", DropNamespaceResponse.builder().dropped(true).build());
+
+    assertRoundTripSerializesEquallyFrom(
+        "{\"dropped\":false}", DropNamespaceResponse.builder().dropped(false).build());
+  }
+
+  @Test
+  public void testFailParsingWhenNullOrEmptyJson() {
+    String nullJson = null;
+    AssertHelpers.assertThrows("DropNamespaceResponse should fail to deserialize from a null JSON string",
+        IllegalArgumentException.class,
+        () ->  deserialize(nullJson));
+
+    String emptyString = "";
+    AssertHelpers.assertThrows("DropNamespaceResponse should fail to deserialize empty string as JSON",
+        JsonProcessingException.class,
+        () ->  deserialize(emptyString));
+
+    String emptyJson = "{}";
+    AssertHelpers.assertThrows(
+        "DropNamespaceResponse should fail to deserialize and validate if missing the field `dropped`",
+        IllegalArgumentException.class,
+        "Cannot instantiate a response to dropping a namespace with missing field(s): `dropped`",
+        () -> deserialize(emptyJson));
+  }
+
+  @Test
+  public void testFailWhenFieldsHaveInvalidValues() {
+    String invalidJsonWithStringType = "{\"dropped\":\"421\"}";

Review comment:
       What happens when the value is `null`?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r809449339



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/CreateNamespaceResponse.java
##########
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+
+/**
+ * Represents a REST response for a request to create a namespace / database.
+ * <p>
+ * The properties returned should include all the user provided properties from the
+ * request, as well as any server-side added properties.
+ * <p>
+ * Example server-side added properties can be implementation specific, but might include
+ * such things as `created_at` or `owner`.
+ */
+public class CreateNamespaceResponse {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public CreateNamespaceResponse() {
+    // Required for Jackson deserialization.
+  }
+
+  private CreateNamespaceResponse(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+    validate();
+  }
+
+  // Used to check if the object is valid. This method is necessary
+  // because we let Jackson fill in the values automatically, so precondition
+  // checks aren't made.
+  //
+  // This function should be called any time this value is deserialized / instantiated.

Review comment:
       Comments like this beg the question: why not ensure it is always called? And that's simply complexity that we don't want. I would probably remove this.
   
   Also, if it is something that needs to be said, then it is better to add it as Javadoc so that people see it.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r811439833



##########
File path: core/src/main/java/org/apache/iceberg/util/JsonUtil.java
##########
@@ -129,6 +130,42 @@ public static String getStringOrNull(String property, JsonNode node) {
     return builder.build();
   }
 
+  public static Map<String, String> getStringMapOrNull(String property, JsonNode node) {
+    if (!node.has(property)) {
+      return null;
+    }
+
+    JsonNode pNode = node.get(property);
+    if (pNode == null || pNode.isNull()) {
+      return null;
+    }
+
+    Preconditions.checkArgument(pNode.isObject(),
+        "Cannot parse %s from non-object value: %s", property, pNode);

Review comment:
       The idea was to leave `buildStringMap...` with no precodition checks, and then have the individual `getStringMap` and `getStringMapOrNull` call out to that function after doing their preconditions check.
   
   I left the current implementation of `getStringMap` as is to minimize the diff, but I can either:
   1) Update them both to use `buildStringMap...` and handle their own preconditions check.
   2) Make the update as requested here.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r811465971



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/CreateNamespaceRequest.java
##########
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.exceptions.ValidationException;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+
+/**
+ * A REST request to create a namespace, with an optional set of properties.
+ * The server might also add properties, such as `last_modified_time` etc.
+ */
+public class CreateNamespaceRequest {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public CreateNamespaceRequest() {
+    // Needed for Jackson Deserialization.
+  }
+
+  private CreateNamespaceRequest(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+    validate();
+  }
+
+  /**
+   * This function needs to be called after reading in JSON from another source, to ensure
+   * that null values are assigned to their respective defaults where needed, wrap collections
+   * in their Immutable variants, and that required fields are correct.
+   * @return normalized version of this {@link CreateNamespaceRequest}
+   */
+  CreateNamespaceRequest validate() {
+    this.properties = properties == null ? ImmutableMap.of() : ImmutableMap.copyOf(properties);
+    ValidationException.check(namespace != null && !namespace.isEmpty(),
+        "Cannot build a request to create a namespace without specifying the namespace");

Review comment:
       Even if this isn't a valid request, I think the error should be more clear. If the namespace was present and is empty, then this shouldn't say that it wasn't specified.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] nastra commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
nastra commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r799329632



##########
File path: core/src/test/java/org/apache/iceberg/rest/requests/TestCreateNamespaceRequest.java
##########
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.util.JsonUtil;
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+
+public class TestCreateNamespaceRequest {
+
+  private static final ObjectMapper MAPPER = JsonUtil.withRESTComponents();
+
+  private static final String[] ALL_FIELDS_FROM_SPEC = { "namespace", "properties" };
+
+  /* Values used to fill in request fields */
+  private static final Namespace NAMESPACE = Namespace.of("accounting", "tax");
+  private static final Map<String, String> PROPERTIES = ImmutableMap.of("owner", "Hank");
+
+  /* JSON of requests */
+  private static final String JSON_REQUEST =
+      "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{\"owner\":\"Hank\"}}";
+  private static final String JSON_REQUEST_EMPTY_PROPERTIES =
+      "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{}}";
+
+  @Test
+  public void testDeserialize() throws JsonProcessingException {
+    CreateNamespaceRequest expected = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .withProperties(PROPERTIES)
+        .build();
+
+    CreateNamespaceRequest actual = MAPPER.readValue(JSON_REQUEST, CreateNamespaceRequest.class);
+
+    assertEquals(expected, actual);
+    assertHasOnlyKnownFields(expected);
+    assertHasOnlyKnownFields(actual);
+  }
+
+  @Test
+  public void testDeserializeEmptyProperties() throws JsonProcessingException {
+    CreateNamespaceRequest expected = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .build();
+
+    CreateNamespaceRequest actual = MAPPER.readValue(JSON_REQUEST_EMPTY_PROPERTIES, CreateNamespaceRequest.class);
+
+    assertEquals(expected, actual);
+    assertHasOnlyKnownFields(expected);
+    assertHasOnlyKnownFields(actual);
+  }
+
+  @Test
+  public void testSerialize() throws JsonProcessingException {
+    CreateNamespaceRequest req = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .withProperties(PROPERTIES)
+        .build();
+
+    Assertions.assertThat(MAPPER.writeValueAsString(req))
+        .isEqualTo(JSON_REQUEST);
+  }
+
+  @Test
+  public void testSerializeEmptyProperties() throws JsonProcessingException {
+    CreateNamespaceRequest req = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .build();
+
+    Assertions.assertThat(MAPPER.writeValueAsString(req))
+        .isEqualTo(JSON_REQUEST_EMPTY_PROPERTIES);
+  }
+
+  private static void assertEquals(CreateNamespaceRequest expected, CreateNamespaceRequest actual) {
+    Assertions.assertThat(actual.namespace()).isEqualTo(expected.namespace());

Review comment:
       just wondering whether it would make sense to have `CreateNamespaceRequest` just implement `equals()` rather than having to do it in test code?

##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/CreateNamespaceRequest.java
##########
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+
+/**
+ * A REST request to create a namespace, with an optional set of properties.
+ * The server might also add properties, such as `last_modified_time` etc.
+ */
+public class CreateNamespaceRequest {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public CreateNamespaceRequest() {
+    // Required for Jackson deserialization
+  }
+
+  private CreateNamespaceRequest(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public Namespace namespace() {
+    return namespace;
+  }
+
+  public Map<String, String> properties() {
+    return ImmutableMap.copyOf(properties);
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("namespace", namespace)
+        .add("properties", properties)
+        .toString();
+  }
+
+  public static class Builder {
+    private Namespace namespace;
+    private ImmutableMap.Builder<String, String> properties = ImmutableMap.builder();
+
+    private Builder() {
+    }
+
+    public Builder withNamespace(Namespace ns) {
+      this.namespace = ns;
+      return this;
+    }
+
+    public Builder withProperties(Map<String, String> props) {
+      this.properties.putAll(props);
+      return this;
+    }
+
+    public CreateNamespaceRequest build() {
+      Preconditions.checkArgument(
+          namespace != null && !namespace.isEmpty(),
+          "Cannot build a response to create a namespace without specifying the namespace");

Review comment:
       do we need a unit test for this maybe? I know this is implicitly tested in the happy path, but I believe we should still test the non-happy path  and verify that we're getting the error message that we're expecting

##########
File path: core/src/test/java/org/apache/iceberg/rest/requests/TestCreateNamespaceRequest.java
##########
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.util.JsonUtil;
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+
+public class TestCreateNamespaceRequest {

Review comment:
       just curious whether it would make sense to test more non-happy paths, where you're passing:
   * a null/empty json
   * a json with fields that that Ser/De components don't understand (think about somebody mistyping `namespace` or `properties`)
   * a json where `namespace` / `properties` get strings that they can't interpret (such as numbers)




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] danielcweeks commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
danielcweeks commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r799095408



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/CreateNamespaceResponse.java
##########
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.Maps;
+
+/**
+ * Represents a REST response for a request to create a namespace / database.
+ * <p>
+ * The properties returned should include all the user provided properties from the
+ * request, as well as any server-side added properties.
+ * <p>
+ * Example server-side added properties can be implementation specific, but might include
+ * such things as `created_at` or `owner`.
+ */
+public class CreateNamespaceResponse {

Review comment:
       I think it's fair to separate the two as the may evolve independently over time.  I'd prefer not to try optimizing by reusing request/response objects.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r799099972



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/ListNamespacesResponse.java
##########
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Collection;
+import java.util.List;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+
+public class ListNamespacesResponse {
+  private List<Namespace> namespaces;
+
+  public ListNamespacesResponse() {
+    // Required for Jackson
+  }
+
+  private ListNamespacesResponse(List<Namespace> namespaces) {
+    this.namespaces = namespaces;
+  }
+
+  public List<Namespace> namespaces() {
+    return ImmutableList.copyOf(namespaces);
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("namespaces", namespaces())
+        .toString();
+  }
+
+  public static class Builder {
+    private final ImmutableList.Builder<Namespace> namespaces = ImmutableList.builder();
+
+    private Builder() {
+    }
+
+    public Builder withNamespaces(Collection<Namespace> toAdd) {

Review comment:
       Updated.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r799083721



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/CreateNamespaceRequest.java
##########
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+
+/**
+ * A REST request to create a namespace, with an optional set of properties.
+ * The server might also add properties, such as `last_modified_time` etc.
+ */
+public class CreateNamespaceRequest {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public CreateNamespaceRequest() {
+    // Required for serialization
+  }
+
+  private CreateNamespaceRequest(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public Namespace namespace() {
+    return namespace;
+  }
+
+  public Map<String, String> properties() {
+    return ImmutableMap.copyOf(properties);
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("namespace", namespace)
+        .add("properties", properties())
+        .toString();
+  }
+
+  public static class Builder {
+    private final ImmutableList.Builder<String> namespaceBuilder;
+    private final ImmutableMap.Builder<String, String> propertiesBuilder;
+
+    private Builder() {
+      this.namespaceBuilder = ImmutableList.builder();
+      this.propertiesBuilder = ImmutableMap.builder();
+    }
+
+    public Builder withNamespace(Namespace namespace) {
+      this.namespaceBuilder.add(namespace.levels());
+      return this;
+    }
+
+    public Builder withProperties(Map<String, String> properties) {

Review comment:
       I don't think it's clear from the name that this is not replacing the set of properties. I think a verb like `set` would fix this. For example, `setProperties(map)` implies to me that you're adding all the new properties and not removing anything.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r799089191



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/CreateNamespaceResponse.java
##########
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.Maps;
+
+/**
+ * Represents a REST response for a request to create a namespace / database.
+ * <p>
+ * The properties returned should include all the user provided properties from the
+ * request, as well as any server-side added properties.
+ * <p>
+ * Example server-side added properties can be implementation specific, but might include
+ * such things as `created_at` or `owner`.
+ */
+public class CreateNamespaceResponse {

Review comment:
       Can we use `GetNamespaceResponse` for this as well? They're exactly the same thing.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r801110486



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/CreateNamespaceResponse.java
##########
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.Maps;
+
+/**
+ * Represents a REST response for a request to create a namespace / database.
+ * <p>
+ * The properties returned should include all the user provided properties from the
+ * request, as well as any server-side added properties.
+ * <p>
+ * Example server-side added properties can be implementation specific, but might include
+ * such things as `created_at` or `owner`.
+ */
+public class CreateNamespaceResponse {
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public CreateNamespaceResponse() {
+    // Required for Jackson
+  }
+
+  private CreateNamespaceResponse(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+  }
+
+  public Namespace namespace() {
+    return namespace;
+  }
+
+  public Map<String, String> properties() {
+    return ImmutableMap.copyOf(properties);
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("namespace", namespace)
+        .add("properties", properties())
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public static class Builder {

Review comment:
       Reused!




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r800241620



##########
File path: core/src/test/java/org/apache/iceberg/rest/requests/TestCreateNamespaceRequest.java
##########
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.util.JsonUtil;
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+
+public class TestCreateNamespaceRequest {

Review comment:
       * null/empty JSON - I agree we should make sure that required fields are present
   * JSON with extra fields - I think extra fields should be ignored by the client so that we can evolve the payloads. Clients shouldn't fail if the service returns extra fields, and services shouldn't necessarily fail if the client sends extra fields.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r806210962



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/CreateNamespaceRequest.java
##########
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import com.fasterxml.jackson.annotation.JsonProperty;

Review comment:
       Let me check if Jackson can infer everything.
   
   I would be in favor of the more explicit SerDe as well given what's mentioned above (or using a library to generate the classes for us would be my preferred approach but I know that comes with its own set of issues).




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r807441925



##########
File path: core/src/main/java/org/apache/iceberg/rest/RESTUtils.java
##########
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.core.JsonFactory;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class RESTUtils {
+
+  private RESTUtils() {
+  }

Review comment:
       This class appears to only be used in tests. Is it necessary to make it public or part of src/main?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: [WIP] REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r807241456



##########
File path: core/src/test/java/org/apache/iceberg/rest/responses/TestUpdateNamespacePropertiesResponse.java
##########
@@ -0,0 +1,174 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.util.List;
+import java.util.Map;
+import org.apache.iceberg.AssertHelpers;
+import org.apache.iceberg.exceptions.ValidationException;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.util.JsonUtil;
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+
+public class TestUpdateNamespacePropertiesResponse {
+
+  private static final ObjectMapper MAPPER = JsonUtil.withRESTComponents();
+
+  private static final String[] ALL_FIELDS_FROM_SPEC = { "updated", "removed", "missing" };
+
+  /* Values used to fill in response fields */
+  private static final List<String> UPDATED = ImmutableList.of("owner");
+  private static final List<String> REMOVED = ImmutableList.of("foo");
+  private static final List<String> MISSING = ImmutableList.of("bar");
+
+  @Test
+  public void testValidSerDe() throws JsonProcessingException {
+    Map<String, UpdateNamespacePropertiesResponse> toTest = ImmutableMap.of(
+        // Full response
+        "{\"removed\":[\"foo\"],\"updated\":[\"owner\"],\"missing\":[\"bar\"]}",
+        builder().addUpdated(UPDATED).addRemoved(REMOVED).addMissing(MISSING).build(),
+        // Only updated
+        "{\"removed\":null,\"updated\":[\"owner\"],\"missing\":null}",
+        builder().addUpdated(UPDATED).build(),
+        "{\"removed\":[],\"updated\":[\"owner\"],\"missing\":[]}",
+        builder().addUpdated(UPDATED).addMissing(ImmutableList.of()).addRemoved(ImmutableList.of()).build(),
+        // Only removed
+        "{\"removed\":[\"foo\"],\"updated\":null,\"missing\":null}",
+        builder().addRemoved(REMOVED).build(),
+        "{\"removed\":[\"foo\"],\"updated\":[],\"missing\":[]}",
+        builder().addRemoved(REMOVED).addMissing(ImmutableList.of()).addUpdated(ImmutableList.of()).build(),
+        // Only missing
+        "{\"removed\":null,\"updated\":null,\"missing\":[\"bar\"]}",
+        builder().addMissing(MISSING).build(),
+        "{\"removed\":[],\"updated\":[],\"missing\":[\"bar\"]}",
+        builder().addMissing(MISSING).addUpdated(ImmutableList.of()).addRemoved(ImmutableList.of()).build());

Review comment:
       This is the form I'm planning on using for the valid SerDe tests so the named constants for the JSON can be inlined.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r808551448



##########
File path: core/src/main/java/org/apache/iceberg/rest/RESTUtils.java
##########
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.core.JsonFactory;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class RESTUtils {
+
+  private RESTUtils() {
+  }

Review comment:
       I moved it to `test` for now. We might wind up needing it later, but given that it's not needed presently anywhere outside of tests I think that's not a bad idea to keep it out of any potentially public APIs for now.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r811431987



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/ListNamespacesResponse.java
##########
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Collection;
+import java.util.List;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+
+public class ListNamespacesResponse {
+
+  private List<Namespace> namespaces;
+
+  public ListNamespacesResponse() {
+    // Required for Jackson deserialization
+  }
+
+  private ListNamespacesResponse(List<Namespace> namespaces) {
+    this.namespaces = namespaces;
+    validate();
+  }
+
+  ListNamespacesResponse validate() {
+    Preconditions.checkArgument(namespaces != null,
+        "Cannot create a response to a list namespaces request without a non-null list of namespaces");
+    return this;
+  }
+
+
+  public List<Namespace> namespaces() {
+    return namespaces != null ? namespaces : ImmutableList.of();
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("namespaces", namespaces())
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  static class Builder {
+    private final ImmutableList.Builder<Namespace> namespaces = ImmutableList.builder();
+
+    private Builder() {
+    }
+
+    public Builder add(Namespace toAdd) {
+      Preconditions.checkNotNull(toAdd,
+          "Invalid namespace to list: null");
+      namespaces.add(toAdd);
+      return this;
+    }
+
+    public Builder addAll(Collection<Namespace> toAdd) {
+      Preconditions.checkNotNull(toAdd,
+          "Invalid collection of namespaces to list: null");

Review comment:
       Updated.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r811466082



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/CreateNamespaceRequest.java
##########
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.Maps;
+
+/**
+ * A REST request to create a namespace, with an optional set of properties.
+ * The server might also add properties, such as `last_modified_time` etc.
+ */
+public class CreateNamespaceRequest {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public CreateNamespaceRequest() {
+    // Needed for Jackson Deserialization.
+  }
+
+  private CreateNamespaceRequest(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+    validate();
+  }
+
+  /**
+   * This function needs to be called after reading in JSON from another source, to ensure
+   * that required properties are correctly set.
+   */
+  CreateNamespaceRequest validate() {
+    Preconditions.checkArgument(namespace != null && !namespace.isEmpty(),
+        "Cannot build a request to create a namespace without specifying the namespace");
+    return this;
+  }
+
+  public Namespace namespace() {
+    return namespace;
+  }
+
+  public Map<String, String> properties() {
+    return properties != null ? properties : ImmutableMap.of();
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("namespace", namespace)
+        .add("properties", properties)
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public static class Builder {
+    private Namespace namespace;
+    private final ImmutableMap.Builder<String, String> properties = ImmutableMap.builder();
+
+    private Builder() {
+    }
+
+    public Builder withNamespace(Namespace ns) {
+      Preconditions.checkNotNull(ns, "Invalid namespace to create: null");

Review comment:
       Looks like this error message was missed. Should be "Invalid namespace: null".




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r811477777



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/UpdateNamespacePropertiesRequest.java
##########
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
+import org.apache.iceberg.relocated.com.google.common.collect.Maps;
+
+/**
+ * A REST request to set and/or remove properties on a namespace.
+ */
+public class UpdateNamespacePropertiesRequest {
+
+  private List<String> removals;
+  private Map<String, String> updates;
+
+  public UpdateNamespacePropertiesRequest() {
+    // Required for Jackson deserialization.
+  }
+
+  private UpdateNamespacePropertiesRequest(List<String> removals, Map<String, String> updates) {
+    this.removals = removals;
+    this.updates = updates;
+    validate();
+  }
+
+  UpdateNamespacePropertiesRequest validate() {
+    return this;
+  }
+
+  public List<String> removals() {
+    return removals == null ? ImmutableList.of() : removals;
+  }
+
+  public Map<String, String> updates() {
+    return updates == null ? ImmutableMap.of() : updates;
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("removals", removals)
+        .add("updates", updates)
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public static class Builder {
+    private final ImmutableSet.Builder<String> removalsBuilder = ImmutableSet.builder();
+    private final ImmutableMap.Builder<String, String> updatesBuilder = ImmutableMap.builder();
+
+    private Builder() {
+    }
+
+    public Builder remove(String removal) {
+      Preconditions.checkNotNull(removal,
+          "Invalid property to remove: null");
+      removalsBuilder.add(removal);
+      return this;
+    }
+
+    public Builder removeAll(Collection<String> removals) {

Review comment:
       Yeah. I changed it to have access to `contains` and things. We can revert it to an Iterable in a follow up PR.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r811456072



##########
File path: core/src/test/java/org/apache/iceberg/rest/RESTUtil.java
##########
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.core.JsonFactory;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class RESTUtil {

Review comment:
       Merging it now.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r811459819



##########
File path: core/src/main/java/org/apache/iceberg/util/JsonUtil.java
##########
@@ -129,6 +130,42 @@ public static String getStringOrNull(String property, JsonNode node) {
     return builder.build();
   }
 
+  public static Map<String, String> getStringMapOrNull(String property, JsonNode node) {
+    if (!node.has(property)) {
+      return null;
+    }
+
+    JsonNode pNode = node.get(property);
+    if (pNode == null || pNode.isNull()) {
+      return null;
+    }
+
+    Preconditions.checkArgument(pNode.isObject(),
+        "Cannot parse %s from non-object value: %s", property, pNode);

Review comment:
       After some changes, `getStringMapOrNull` wound up not being needed, and thus this function wasn't needed either.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810294198



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/CreateNamespaceRequest.java
##########
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+
+/**
+ * A REST request to create a namespace, with an optional set of properties.
+ * The server might also add properties, such as `last_modified_time` etc.
+ */
+public class CreateNamespaceRequest {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public CreateNamespaceRequest() {
+    // Required for Jackson deserialization
+  }
+
+  private CreateNamespaceRequest(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public Namespace namespace() {
+    return namespace;
+  }
+
+  public Map<String, String> properties() {
+    return ImmutableMap.copyOf(properties);
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("namespace", namespace)
+        .add("properties", properties)
+        .toString();
+  }
+
+  public static class Builder {
+    private Namespace namespace;
+    private ImmutableMap.Builder<String, String> properties = ImmutableMap.builder();
+
+    private Builder() {
+    }
+
+    public Builder withNamespace(Namespace ns) {
+      this.namespace = ns;
+      return this;
+    }
+
+    public Builder withProperties(Map<String, String> props) {
+      this.properties.putAll(props);
+      return this;
+    }
+
+    public CreateNamespaceRequest build() {
+      Preconditions.checkArgument(
+          namespace != null && !namespace.isEmpty(),
+          "Cannot build a response to create a namespace without specifying the namespace");

Review comment:
       This got moved around, but the assertion message is still tested against (as well as pretty much every precondition path).




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810300606



##########
File path: core/src/test/java/org/apache/iceberg/rest/requests/TestCreateNamespaceRequest.java
##########
@@ -0,0 +1,128 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.util.Map;
+import org.apache.iceberg.AssertHelpers;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.exceptions.ValidationException;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.rest.RESTUtils;
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+
+public class TestCreateNamespaceRequest {
+
+  private static final ObjectMapper MAPPER = RESTUtils.mapper();
+
+  private static final String[] ALL_FIELDS_FROM_SPEC = { "namespace", "properties" };
+
+  /* Values used to fill in request fields */
+  private static final Namespace NAMESPACE = Namespace.of("accounting", "tax");
+  private static final Map<String, String> PROPERTIES = ImmutableMap.of("owner", "Hank");
+  private static final Map<String, String> EMPTY_PROPERTIES = ImmutableMap.of();
+
+  @Test
+  public void testValidSerDe() throws JsonProcessingException {
+    Map<String, CreateNamespaceRequest> toTest = ImmutableMap.of(
+        // Full response
+        "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{\"owner\":\"Hank\"}}",
+        builder().withNamespace(NAMESPACE).setProperties(PROPERTIES).build(),
+        "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":null}",
+        builder().withNamespace(NAMESPACE).build(),
+        "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{}}",
+        builder().withNamespace(NAMESPACE).setProperties(EMPTY_PROPERTIES).build());
+
+    for (Map.Entry<String, CreateNamespaceRequest> testCase : toTest.entrySet()) {
+      String json = testCase.getKey();
+      CreateNamespaceRequest req = testCase.getValue();
+      assertSerializes(req, json);
+      assertDeserializes(json, req);
+    }
+  }
+
+  @Test
+  public void testDeserializeInvalidRequest() {
+    String jsonIncorrectTypeForNamespace = "{\"namespace\":\"accounting%00tax\",\"properties\":null}";
+    AssertHelpers.assertThrows(
+        "A JSON request with incorrect types for fields should fail to deserialize and validate",
+        JsonProcessingException.class,
+        "Namespace must be an array",
+        () -> MAPPER.readValue(jsonIncorrectTypeForNamespace, CreateNamespaceRequest.class).validate()
+    );
+
+    String jsonIncorrectTypeForProperties = "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":[]}";
+    AssertHelpers.assertThrows(
+        "A JSON request with incorrect types for fields should fail to parse and validate",
+        JsonProcessingException.class,
+        () -> MAPPER.readValue(jsonIncorrectTypeForProperties, CreateNamespaceRequest.class).validate()
+    );
+
+    String jsonMisspelledKeys = "{\"namepsace\":[\"accounting\",\"tax\"],\"propertiezzzz\":{\"owner\":\"Hank\"}}";
+    AssertHelpers.assertThrows(
+        "A JSON request with the keys spelled incorrectly should fail to deserialize and validate",
+        JsonProcessingException.class,
+        () -> MAPPER.readValue(jsonMisspelledKeys, CreateNamespaceRequest.class).validate()

Review comment:
       I added an exception message to one of the invalid key tests.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810396401



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/DropNamespaceResponse.java
##########
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Objects;
+import org.apache.iceberg.exceptions.ValidationException;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+
+/**
+ * Represents a REST response to drop a namespace.
+ * <p>
+ * The server may choose to return an error if the namespace is not empty.
+ */
+public class DropNamespaceResponse {
+
+  // For Jackson to properly fail when deserializing, this needs to be boxed.
+  // Otherwise, the boolean is parsed according to "loose" javascript JSON rules.
+  private Boolean dropped;
+
+  public DropNamespaceResponse() {
+    // Required for Jackson deserialization
+  }
+
+  private DropNamespaceResponse(Boolean dropped) {

Review comment:
       I think it has to stay boxed for the time being. At least at the class level.
   
   When I test with the json `{dropped: null}`, there's no failure on deserialization (nor any way to validate the failure because it just sets it to false).
   
   I'll update the builder though.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810545889



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/UpdateNamespacePropertiesRequest.java
##########
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
+import org.apache.iceberg.relocated.com.google.common.collect.Maps;
+
+/**
+ * A REST request to set and/or remove properties on a namespace.
+ */
+public class UpdateNamespacePropertiesRequest {
+
+  private List<String> removals;
+  private Map<String, String> updates;
+
+  public UpdateNamespacePropertiesRequest() {
+    // Required for Jackson deserialization.
+  }
+
+  private UpdateNamespacePropertiesRequest(List<String> removals, Map<String, String> updates) {
+    this.removals = removals;
+    this.updates = updates;
+    validate();
+  }
+
+  UpdateNamespacePropertiesRequest validate() {
+    Preconditions.checkArgument(removals != null || updates != null,
+        "Invalid value for update namespace properties request: at least one of updates and removals must be non-null");
+    return this;
+  }
+
+  public List<String> removals() {
+    return removals == null ? ImmutableList.of() : removals;
+  }
+
+  public Map<String, String> updates() {
+    return updates == null ? ImmutableMap.of() : updates;
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("removals", removals)
+        .add("updates", updates)
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public static class Builder {
+    private final ImmutableSet.Builder<String> removalsBuilder = ImmutableSet.builder();
+    private final ImmutableMap.Builder<String, String> updatesBuilder = ImmutableMap.builder();
+
+    private Builder() {
+    }
+
+    public Builder remove(String removal) {
+      Preconditions.checkNotNull(removal,
+          "Invalid property to remove: null");
+      removalsBuilder.add(removal);
+      return this;
+    }
+
+    public Builder removeAll(Collection<String> removals) {
+      Preconditions.checkNotNull(removals,
+          "Invalid list of properties to remove: null");
+      Preconditions.checkArgument(!removals.contains(null),
+          "Invalid value in list of properties to remove: null");

Review comment:
       I don't think this needs to distinguish between the list case. If an individual removal is null, it should just throw "Invalid property to remove: null" like the `remove(String)` case.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810547312



##########
File path: core/src/main/java/org/apache/iceberg/util/JsonUtil.java
##########
@@ -129,6 +130,42 @@ public static String getStringOrNull(String property, JsonNode node) {
     return builder.build();
   }
 
+  public static Map<String, String> getStringMapOrNull(String property, JsonNode node) {
+    if (!node.has(property)) {
+      return null;
+    }
+
+    JsonNode pNode = node.get(property);
+    if (pNode == null || pNode.isNull()) {
+      return null;
+    }
+
+    Preconditions.checkArgument(pNode.isObject(),
+        "Cannot parse %s from non-object value: %s", property, pNode);

Review comment:
       I would move this check into the `buildStringMap...` method, since that method requires the node is an object.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810547567



##########
File path: core/src/test/java/org/apache/iceberg/rest/RESTUtil.java
##########
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.core.JsonFactory;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class RESTUtil {

Review comment:
       I'd probably merge this into `RequestResponseTestBase`. Not sure if it's useful having a separate class, but up to you.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r809460774



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/UpdateNamespacePropertiesRequest.java
##########
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.List;
+import java.util.Map;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
+
+/**
+ * A REST request to set and/or remove properties on a namespace.
+ * <p>
+ * The request body specifies a list of properties to remove and a map
+ * of key value pairs to update.
+ * <p>
+ * Properties that are not in the request are not modified or removed by this call.
+ * Server implementations are not required to support namespace properties.
+ */
+public class UpdateNamespacePropertiesRequest {
+
+  private List<String> removals;
+  private Map<String, String> updates;
+
+  public UpdateNamespacePropertiesRequest() {
+    // Required for Jackson deserialization.
+  }
+
+  private UpdateNamespacePropertiesRequest(List<String> removals, Map<String, String> updates) {
+    this.removals = removals;
+    this.updates = updates;
+    validate();
+  }
+
+  UpdateNamespacePropertiesRequest validate() {
+    Preconditions.checkArgument((removals != null && !removals.isEmpty()) || (updates != null && !updates.isEmpty()),
+        "Cannot create a request to update a namespace's properties without specifying any props to update or remove");
+    return this;
+  }
+
+  public List<String> removals() {
+    return removals == null ? ImmutableList.of() : removals;
+  }
+
+  public Map<String, String> updates() {
+    return updates == null ? ImmutableMap.of() : updates;
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("removals", removals)
+        .add("updates", updates)
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public static class Builder {
+    private final ImmutableSet.Builder<String> removalsBuilder = ImmutableSet.builder();
+    private final ImmutableMap.Builder<String, String> updatesBuilder = ImmutableMap.builder();
+
+    private Builder() {
+    }
+
+    public Builder remove(String removal) {
+      Preconditions.checkNotNull(removal,
+          "Cannot pass null key to remove to UpdateNamespacePropertiesRequest.Builder");
+      removalsBuilder.add(removal);
+      return this;
+    }
+
+    public Builder removeAll(Iterable<String> removals) {
+      Preconditions.checkNotNull(removals,
+          "Cannot pass null removals to UpdateNamespacePropertiesRequest.Builder");
+      removalsBuilder.addAll(removals);
+      return this;
+    }
+
+    public Builder update(String key, String value) {
+      Preconditions.checkNotNull(key,
+          "Cannot pass null key to update to UpdateNamespacePropertiesRequest.Builder");
+      Preconditions.checkNotNull(value,
+          "Cannot pass null value to update in UpdateNamespacePropertiesRequest.Builder. Use remove instead");

Review comment:
       +1 for "Use remove instead".




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r809455654



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/GetNamespaceResponse.java
##########
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.exceptions.ValidationException;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.util.ImmutablesUtil;
+
+/**
+ * Represents a REST response to fetch namespace metadata.
+ * <p>
+ * The properties returned should include all the user provided properties from the
+ * request, as well as any server-side added properties.
+ */
+public class GetNamespaceResponse {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public GetNamespaceResponse() {
+    // Required for Jackson deserialization
+  }
+
+  private GetNamespaceResponse(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+    validate();
+  }
+
+  GetNamespaceResponse validate() {
+    ValidationException.check(namespace != null && !namespace.isEmpty(),
+        "Cannot build a response to get a namespace without specifying the namespace");

Review comment:
       This isn't correct. You may not be able to create the root namespace, but you can request metadata about it. I think this should remove the `isEmpty` check. Also, it is a bit misleading to say that `[]` falls into "without specifying the namespace".




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r809465279



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/UpdateNamespacePropertiesResponse.java
##########
@@ -0,0 +1,174 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.List;
+import java.util.Objects;
+import org.apache.iceberg.exceptions.ValidationException;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
+import org.apache.iceberg.util.ImmutablesUtil;
+
+/**
+ * A REST response to a request to set and/or remove properties on a namespace.
+ */
+public class UpdateNamespacePropertiesResponse {
+
+  // List of namespace property keys that were removed
+  private List<String> removed;
+  // List of namespace property keys that were added or updated
+  private List<String> updated;
+  // List of properties that were requested for removal that were not found in the namespace's properties
+  private List<String> missing;
+
+  public UpdateNamespacePropertiesResponse() {
+    // Required for Jackson deserialization
+  }
+
+  private UpdateNamespacePropertiesResponse(List<String> removed, List<String> updated, List<String> missing) {
+    this.removed = removed;
+    this.updated = updated;
+    this.missing = missing;
+    validate();
+  }
+
+  UpdateNamespacePropertiesResponse validate() {
+    ValidationException.check((removed != null && !this.removed.isEmpty()) ||
+        (updated != null && !updated.isEmpty()) || (missing != null && !missing.isEmpty()),
+        "Cannot create a response to update namespace properties if all of the fields are missing or empty");

Review comment:
       I'm not sure that I would have this requirement. I think that removed, updated, and missing should all be non-null. But if a service gets a request with removals: [] and updates: {} then all 3 empty here is an appropriate response.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r809453112



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/DropNamespaceResponse.java
##########
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Objects;
+import org.apache.iceberg.exceptions.ValidationException;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+
+/**
+ * Represents a REST response to drop a namespace.
+ * <p>
+ * The server may choose to return an error if the namespace is not empty.
+ */
+public class DropNamespaceResponse {
+
+  // For Jackson to properly fail when deserializing, this needs to be boxed.
+  // Otherwise, the boolean is parsed according to "loose" javascript JSON rules.
+  private Boolean dropped;
+
+  public DropNamespaceResponse() {
+    // Required for Jackson deserialization
+  }
+
+  private DropNamespaceResponse(Boolean dropped) {
+    this.dropped = dropped;
+    validate();
+  }
+
+  DropNamespaceResponse validate() {
+    // Use `checkArguemt` so it will throw IllegalArgumentException, just like the other responses
+    Preconditions.checkArgument(dropped != null,
+        "Cannot instantiate a response to dropping a namespace with missing field(s): `dropped`");
+    return this;
+  }
+
+  public boolean isDropped() {
+    return dropped;
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("dropped", dropped)
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public static class Builder {
+    private Boolean dropped = false;
+
+    private Builder() {
+    }
+
+    public Builder dropped(Boolean isDropped) {
+      this.dropped = isDropped;
+      return this;
+    }
+
+    public DropNamespaceResponse build() {
+      return new DropNamespaceResponse(dropped);

Review comment:
       This should check that `dropped` is not null.

##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/DropNamespaceResponse.java
##########
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Objects;
+import org.apache.iceberg.exceptions.ValidationException;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+
+/**
+ * Represents a REST response to drop a namespace.
+ * <p>
+ * The server may choose to return an error if the namespace is not empty.
+ */
+public class DropNamespaceResponse {
+
+  // For Jackson to properly fail when deserializing, this needs to be boxed.
+  // Otherwise, the boolean is parsed according to "loose" javascript JSON rules.
+  private Boolean dropped;
+
+  public DropNamespaceResponse() {
+    // Required for Jackson deserialization
+  }
+
+  private DropNamespaceResponse(Boolean dropped) {
+    this.dropped = dropped;
+    validate();
+  }
+
+  DropNamespaceResponse validate() {
+    // Use `checkArguemt` so it will throw IllegalArgumentException, just like the other responses
+    Preconditions.checkArgument(dropped != null,
+        "Cannot instantiate a response to dropping a namespace with missing field(s): `dropped`");
+    return this;
+  }
+
+  public boolean isDropped() {
+    return dropped;
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("dropped", dropped)
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public static class Builder {
+    private Boolean dropped = false;
+
+    private Builder() {
+    }
+
+    public Builder dropped(Boolean isDropped) {

Review comment:
       I think this should be `boolean` rather than `Boolean`.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r809452094



##########
File path: core/src/test/java/org/apache/iceberg/rest/responses/TestDropNamespaceResponse.java
##########
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import org.apache.iceberg.AssertHelpers;
+import org.apache.iceberg.rest.RequestResponseTestBase;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestDropNamespaceResponse extends RequestResponseTestBase<DropNamespaceResponse> {
+
+  @Test
+  public void testRoundTripSerDe() throws JsonProcessingException {
+    assertRoundTripSerializesEquallyFrom(
+        "{\"dropped\":true}", DropNamespaceResponse.builder().dropped(true).build());
+
+    assertRoundTripSerializesEquallyFrom(
+        "{\"dropped\":false}", DropNamespaceResponse.builder().dropped(false).build());
+  }
+
+  @Test
+  public void testFailParsingWhenNullOrEmptyJson() {
+    String nullJson = null;
+    AssertHelpers.assertThrows("DropNamespaceResponse should fail to deserialize from a null JSON string",
+        IllegalArgumentException.class,
+        () ->  deserialize(nullJson));

Review comment:
       Exception message validation?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r809463045



##########
File path: core/src/test/java/org/apache/iceberg/rest/requests/TestUpdateNamespacePropertiesRequest.java
##########
@@ -0,0 +1,162 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import java.util.List;
+import java.util.Map;
+import org.apache.iceberg.AssertHelpers;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.rest.RequestResponseTestBase;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestUpdateNamespacePropertiesRequest extends RequestResponseTestBase<UpdateNamespacePropertiesRequest> {
+
+  /* Values used to fill in request fields */
+  private static final Map<String, String> UPDATES = ImmutableMap.of("owner", "Hank");
+  private static final List<String> REMOVALS = ImmutableList.of("foo", "bar");
+  private static final Map<String, String> EMPTY_UPDATES = ImmutableMap.of();
+  private static final List<String> EMPTY_REMOVALS = ImmutableList.of();
+
+
+  @Test
+  public void testRoundTripSerDe() throws JsonProcessingException {
+    // Full request
+    String fullJson = "{\"removals\":[\"foo\",\"bar\"],\"updates\":{\"owner\":\"Hank\"}}";
+    assertRoundTripSerializesEquallyFrom(
+        fullJson, UpdateNamespacePropertiesRequest.builder().updateAll(UPDATES).removeAll(REMOVALS).build());
+
+    // Only updates
+    String emptyRemoval = "{\"removals\":[],\"updates\":{\"owner\":\"Hank\"}}";
+    assertRoundTripSerializesEquallyFrom(
+        emptyRemoval, UpdateNamespacePropertiesRequest.builder().updateAll(UPDATES).removeAll(EMPTY_REMOVALS).build());
+
+    assertRoundTripSerializesEquallyFrom(
+        emptyRemoval, UpdateNamespacePropertiesRequest.builder().update("owner", "Hank").build());
+
+    // Only removals
+    String emptyUpdates = "{\"removals\":[\"foo\",\"bar\"],\"updates\":{}}";
+    assertRoundTripSerializesEquallyFrom(
+        emptyUpdates, UpdateNamespacePropertiesRequest.builder().removeAll(REMOVALS).updateAll(EMPTY_UPDATES).build());
+
+    assertRoundTripSerializesEquallyFrom(
+        emptyUpdates, UpdateNamespacePropertiesRequest.builder().remove("foo").remove("bar").build());
+  }
+
+  @Test
+  // Test cases that can't be constructed with our Builder class e2e but that will parse correctly
+  public void testCanDeserializeWithoutDefaultValues() throws JsonProcessingException {
+    // `removals` is left empty.
+    UpdateNamespacePropertiesRequest noRemovals = UpdateNamespacePropertiesRequest.builder().updateAll(UPDATES).build();
+    String jsonWithNullRemovals = "{\"removals\":null,\"updates\":{\"owner\":\"Hank\"}}";
+    UpdateNamespacePropertiesRequest parsed = deserialize(jsonWithNullRemovals);
+    assertEquals(parsed, noRemovals);
+
+    // `removals` is missing from the JSON.
+    String jsonWithMissingRemovals = "{\"updates\":{\"owner\":\"Hank\"}}";
+    assertEquals(deserialize(jsonWithMissingRemovals), noRemovals);
+
+    UpdateNamespacePropertiesRequest noUpdates = UpdateNamespacePropertiesRequest.builder().removeAll(REMOVALS).build();
+    String jsonWithNullUpdates = "{\"removals\":[\"foo\",\"bar\"],\"updates\":null}";
+    assertEquals(deserialize(jsonWithNullUpdates), noUpdates);
+  }
+
+  @Test
+  public void testParseInvalidJson() {
+    // Invalid top-level types
+    String jsonInvalidTypeOnRemovalField =
+        "{\"removals\":{\"foo\":\"bar\"},\"updates\":{\"owner\":\"Hank\"}}";
+    AssertHelpers.assertThrows(
+        "A JSON request with an invalid type for one of the fields should fail to parse",
+        JsonProcessingException.class,
+        () -> deserialize(jsonInvalidTypeOnRemovalField).validate()
+    );
+
+    String jsonInvalidTypeOnUpdatesField =
+        "{\"removals\":[\"foo\":\"bar\"],\"updates\":[\"owner\"]}";
+    AssertHelpers.assertThrows(
+        "A JSON value with an invalid type for one of the fields should fail to parse",
+        JsonProcessingException.class,
+        () -> deserialize(jsonInvalidTypeOnUpdatesField).validate()
+    );
+
+    // Valid top-level (array) types, but at least one entry in the list is not the expected type
+    // NOTE: non-string values that are integral types will still parse into a string list.
+    //    e.g. { removals: [ "foo", "bar", 1234 ] } will parse correctly.
+    String invalidJsonWrongTypeInRemovalsList =
+        "{\"removals\":[\"foo\",\"bar\", {\"owner\": \"Hank\"}],\"updates\":{\"owner\":\"Hank\"}}";
+    AssertHelpers.assertThrows(
+        "A JSON value with an invalid type inside one of the list fields should fail to parse",
+        JsonProcessingException.class,
+        () -> deserialize(invalidJsonWrongTypeInRemovalsList).validate()
+    );
+
+    // All fields are valid types, but all are empty
+    String jsonWithAllFieldsAsEmptyCollection =
+        "{\"removals\":[],\"updates\":{}}";
+    AssertHelpers.assertThrows(
+        "A JSON value with empty collections for all fields should fail to parse and validate",
+        IllegalArgumentException.class,
+        "Cannot create a request to update a namespace's properties without specifying any props to update or remove",
+        () -> deserialize(jsonWithAllFieldsAsEmptyCollection).validate()
+    );
+
+    String emptyJson = "{}";
+    AssertHelpers.assertThrows(
+        "An empty JSON should fail to parse",
+        IllegalArgumentException.class,
+        "Cannot create a request to update a namespace's properties without specifying any props to update or remove",
+        () -> deserialize(emptyJson).validate()
+    );
+
+    String nullJson = null;
+    AssertHelpers.assertThrows(
+        "A null JSON should fail to parse",
+        IllegalArgumentException.class,
+        () -> deserialize(nullJson).validate()
+    );
+  }
+
+  @Override
+  public String[] allFieldsFromSpec() {
+    return new String[] { "updates", "removals" };
+  }
+
+  @Override
+  public UpdateNamespacePropertiesRequest createExampleInstance() {
+    return UpdateNamespacePropertiesRequest.builder()
+        .updateAll(UPDATES)
+        .removeAll(REMOVALS)
+        .build();
+  }
+
+  @Override
+  public void assertEquals(UpdateNamespacePropertiesRequest actual, UpdateNamespacePropertiesRequest expected) {
+    Assert.assertEquals("Properties to update should be equal", actual.updates(), expected.updates());
+    Assert.assertEquals("Properties to remove should be equal", actual.removals(), expected.removals());

Review comment:
       I think this should build a set from both removals lists. Otherwise, this could be flaky because the builder users a set to accumulate removals and doesn't provide order guarantees.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r809460985



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/UpdateNamespacePropertiesRequest.java
##########
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.List;
+import java.util.Map;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
+
+/**
+ * A REST request to set and/or remove properties on a namespace.
+ * <p>
+ * The request body specifies a list of properties to remove and a map
+ * of key value pairs to update.
+ * <p>
+ * Properties that are not in the request are not modified or removed by this call.
+ * Server implementations are not required to support namespace properties.
+ */
+public class UpdateNamespacePropertiesRequest {
+
+  private List<String> removals;
+  private Map<String, String> updates;
+
+  public UpdateNamespacePropertiesRequest() {
+    // Required for Jackson deserialization.
+  }
+
+  private UpdateNamespacePropertiesRequest(List<String> removals, Map<String, String> updates) {
+    this.removals = removals;
+    this.updates = updates;
+    validate();
+  }
+
+  UpdateNamespacePropertiesRequest validate() {
+    Preconditions.checkArgument((removals != null && !removals.isEmpty()) || (updates != null && !updates.isEmpty()),
+        "Cannot create a request to update a namespace's properties without specifying any props to update or remove");
+    return this;
+  }
+
+  public List<String> removals() {
+    return removals == null ? ImmutableList.of() : removals;
+  }
+
+  public Map<String, String> updates() {
+    return updates == null ? ImmutableMap.of() : updates;
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("removals", removals)
+        .add("updates", updates)
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public static class Builder {
+    private final ImmutableSet.Builder<String> removalsBuilder = ImmutableSet.builder();
+    private final ImmutableMap.Builder<String, String> updatesBuilder = ImmutableMap.builder();
+
+    private Builder() {
+    }
+
+    public Builder remove(String removal) {
+      Preconditions.checkNotNull(removal,
+          "Cannot pass null key to remove to UpdateNamespacePropertiesRequest.Builder");
+      removalsBuilder.add(removal);
+      return this;
+    }
+
+    public Builder removeAll(Iterable<String> removals) {
+      Preconditions.checkNotNull(removals,
+          "Cannot pass null removals to UpdateNamespacePropertiesRequest.Builder");
+      removalsBuilder.addAll(removals);
+      return this;
+    }
+
+    public Builder update(String key, String value) {
+      Preconditions.checkNotNull(key,
+          "Cannot pass null key to update to UpdateNamespacePropertiesRequest.Builder");
+      Preconditions.checkNotNull(value,
+          "Cannot pass null value to update in UpdateNamespacePropertiesRequest.Builder. Use remove instead");
+      updatesBuilder.put(key, value);
+      return this;
+    }
+
+    public Builder updateAll(Map<String, String> updates) {
+      Preconditions.checkNotNull(updates,
+          "Cannot pass null updates to UpdateNamespacePropertiesRequest.Builder");

Review comment:
       This doesn't check the updates for `null` keys or values.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r809489818



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/UpdateNamespacePropertiesRequest.java
##########
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.List;
+import java.util.Map;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
+
+/**
+ * A REST request to set and/or remove properties on a namespace.
+ * <p>
+ * The request body specifies a list of properties to remove and a map
+ * of key value pairs to update.
+ * <p>
+ * Properties that are not in the request are not modified or removed by this call.
+ * Server implementations are not required to support namespace properties.
+ */
+public class UpdateNamespacePropertiesRequest {
+
+  private List<String> removals;
+  private Map<String, String> updates;
+
+  public UpdateNamespacePropertiesRequest() {
+    // Required for Jackson deserialization.
+  }
+
+  private UpdateNamespacePropertiesRequest(List<String> removals, Map<String, String> updates) {
+    this.removals = removals;
+    this.updates = updates;
+    validate();
+  }
+
+  UpdateNamespacePropertiesRequest validate() {
+    Preconditions.checkArgument((removals != null && !removals.isEmpty()) || (updates != null && !updates.isEmpty()),
+        "Cannot create a request to update a namespace's properties without specifying any props to update or remove");
+    return this;
+  }
+
+  public List<String> removals() {
+    return removals == null ? ImmutableList.of() : removals;
+  }
+
+  public Map<String, String> updates() {
+    return updates == null ? ImmutableMap.of() : updates;
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("removals", removals)
+        .add("updates", updates)
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public static class Builder {
+    private final ImmutableSet.Builder<String> removalsBuilder = ImmutableSet.builder();
+    private final ImmutableMap.Builder<String, String> updatesBuilder = ImmutableMap.builder();
+
+    private Builder() {
+    }
+
+    public Builder remove(String removal) {
+      Preconditions.checkNotNull(removal,
+          "Cannot pass null key to remove to UpdateNamespacePropertiesRequest.Builder");
+      removalsBuilder.add(removal);
+      return this;
+    }
+
+    public Builder removeAll(Iterable<String> removals) {
+      Preconditions.checkNotNull(removals,
+          "Cannot pass null removals to UpdateNamespacePropertiesRequest.Builder");

Review comment:
       I like that. i wasn't sure how to phrase it so thanks!




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r809723498



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/GetNamespaceResponse.java
##########
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.exceptions.ValidationException;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.util.ImmutablesUtil;
+
+/**
+ * Represents a REST response to fetch namespace metadata.
+ * <p>
+ * The properties returned should include all the user provided properties from the
+ * request, as well as any server-side added properties.
+ */
+public class GetNamespaceResponse {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public GetNamespaceResponse() {
+    // Required for Jackson deserialization
+  }
+
+  private GetNamespaceResponse(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+    validate();
+  }
+
+  GetNamespaceResponse validate() {
+    ValidationException.check(namespace != null && !namespace.isEmpty(),
+        "Cannot build a response to get a namespace without specifying the namespace");

Review comment:
       That's fair. I hadn't considered the root namespace as possibly being modeled via the empty namespace. We shouldn't disallow that. I will update this.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r809724116



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/GetNamespaceResponse.java
##########
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.Maps;
+
+/**
+ * Represents a REST response to fetch a namespace and its metadata properties
+ */
+public class GetNamespaceResponse {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public GetNamespaceResponse() {
+    // Required for Jackson deserialization
+  }
+
+  private GetNamespaceResponse(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+    validate();
+  }
+
+  GetNamespaceResponse validate() {
+    Preconditions.checkArgument(namespace != null && !namespace.isEmpty(),
+        "Cannot build a response to get a namespace without specifying the namespace");
+    return this;
+  }
+
+  public Namespace namespace() {
+    return namespace;
+  }
+
+  public Map<String, String> properties() {
+    return properties != null ? properties : ImmutableMap.of();
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("namespace", namespace)
+        .add("properties", properties)
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  static class Builder {
+    private Namespace namespace;
+    private final ImmutableMap.Builder<String, String> properties =  ImmutableMap.builder();
+
+    private Builder() {
+    }
+
+    public Builder withNamespace(Namespace ns) {
+      Preconditions.checkNotNull(ns, "Invalid namespace to have requested: null");
+      namespace = ns;
+      return this;
+    }
+
+    public Builder setProperties(Map<String, String> props) {
+      Preconditions.checkNotNull("Invalid collection of properties for a namespace: null");
+      Preconditions.checkArgument(!props.containsKey(null),
+          "Invalid property in collection of namespace properties: null");
+      Preconditions.checkArgument(!props.containsValue(null),
+          "Invalid value for properties %s: null",
+          Maps.filterValues(props, Objects::isNull).keySet());

Review comment:
       The second two `Preconditions` checks are needed, as we can't pass `null` elements to the `ImmutableMap.Builder`.
   
   However, does the first preconditon chck 




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r809448894



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/CreateNamespaceResponse.java
##########
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+
+/**
+ * Represents a REST response for a request to create a namespace / database.
+ * <p>
+ * The properties returned should include all the user provided properties from the
+ * request, as well as any server-side added properties.
+ * <p>
+ * Example server-side added properties can be implementation specific, but might include
+ * such things as `created_at` or `owner`.
+ */
+public class CreateNamespaceResponse {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public CreateNamespaceResponse() {
+    // Required for Jackson deserialization.
+  }
+
+  private CreateNamespaceResponse(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+    validate();
+  }
+
+  // Used to check if the object is valid. This method is necessary
+  // because we let Jackson fill in the values automatically, so precondition

Review comment:
       Style: docs are more direct and usually shorter if you avoid personal pronouns like "we". For example, "this is needed because Jackson deserialization directly sets fields and preconditions are not run"




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r809724116



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/GetNamespaceResponse.java
##########
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.Maps;
+
+/**
+ * Represents a REST response to fetch a namespace and its metadata properties
+ */
+public class GetNamespaceResponse {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public GetNamespaceResponse() {
+    // Required for Jackson deserialization
+  }
+
+  private GetNamespaceResponse(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+    validate();
+  }
+
+  GetNamespaceResponse validate() {
+    Preconditions.checkArgument(namespace != null && !namespace.isEmpty(),
+        "Cannot build a response to get a namespace without specifying the namespace");
+    return this;
+  }
+
+  public Namespace namespace() {
+    return namespace;
+  }
+
+  public Map<String, String> properties() {
+    return properties != null ? properties : ImmutableMap.of();
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("namespace", namespace)
+        .add("properties", properties)
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  static class Builder {
+    private Namespace namespace;
+    private final ImmutableMap.Builder<String, String> properties =  ImmutableMap.builder();
+
+    private Builder() {
+    }
+
+    public Builder withNamespace(Namespace ns) {
+      Preconditions.checkNotNull(ns, "Invalid namespace to have requested: null");
+      namespace = ns;
+      return this;
+    }
+
+    public Builder setProperties(Map<String, String> props) {
+      Preconditions.checkNotNull("Invalid collection of properties for a namespace: null");
+      Preconditions.checkArgument(!props.containsKey(null),
+          "Invalid property in collection of namespace properties: null");
+      Preconditions.checkArgument(!props.containsValue(null),
+          "Invalid value for properties %s: null",
+          Maps.filterValues(props, Objects::isNull).keySet());

Review comment:
       The second two `Preconditions` checks are needed, as we can't pass `null` elements to the `ImmutableMap.Builder`.
   
   However, does the first preconditon chck 




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810546839



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/GetNamespaceResponse.java
##########
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.Maps;
+
+/**
+ * Represents a REST response to fetch a namespace and its metadata properties
+ */
+public class GetNamespaceResponse {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public GetNamespaceResponse() {
+    // Required for Jackson deserialization
+  }
+
+  private GetNamespaceResponse(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+    validate();
+  }
+
+  GetNamespaceResponse validate() {
+    Preconditions.checkArgument(namespace != null,
+        "Cannot build a response to get a null namespace");
+    return this;
+  }
+
+  public Namespace namespace() {
+    return namespace;
+  }
+
+  public Map<String, String> properties() {
+    return properties != null ? properties : ImmutableMap.of();
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("namespace", namespace)
+        .add("properties", properties)
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  static class Builder {
+    private Namespace namespace;
+    private final ImmutableMap.Builder<String, String> properties =  ImmutableMap.builder();
+
+    private Builder() {
+    }
+
+    public Builder withNamespace(Namespace ns) {
+      Preconditions.checkNotNull(ns, "Invalid namespace to have requested: null");

Review comment:
       "to have requested" can be omitted.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r811426116



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/CreateNamespaceResponse.java
##########
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.Maps;
+
+/**
+ * Represents a REST response for a request to create a namespace / database.
+ */
+public class CreateNamespaceResponse {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public CreateNamespaceResponse() {
+    // Required for Jackson deserialization.
+  }
+
+  private CreateNamespaceResponse(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+    validate();
+  }
+
+  CreateNamespaceResponse validate() {
+    Preconditions.checkArgument(
+        namespace != null && !namespace.isEmpty(),
+        "Cannot build a response to create a namespace without specifying the namespace");
+    return this;
+  }
+
+  public Namespace namespace() {
+    return namespace;
+  }
+
+  public Map<String, String> properties() {
+    return properties != null ? properties : ImmutableMap.of();
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("namespace", namespace)
+        .add("properties", properties)
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  static class Builder {
+    private Namespace namespace;
+    private final ImmutableMap.Builder<String, String> properties = ImmutableMap.builder();
+
+    private Builder() {
+    }
+
+    public Builder withNamespace(Namespace ns) {
+      Preconditions.checkNotNull(ns, "Invalid namespace to have created: null");
+      this.namespace = ns;
+      return this;
+    }
+
+    public Builder setProperties(Map<String, String> props) {
+      Preconditions.checkNotNull(props,
+          "Invalid collection of properties to have set: null");
+      Preconditions.checkArgument(!props.containsKey(null),
+          "Invalid property in collection of properties to have set: null");
+      Preconditions.checkArgument(!props.containsValue(null),
+          "Invalid value to have set for properties %s: null", Maps.filterValues(props, Objects::isNull).keySet());

Review comment:
       Ok. I'll leave the explicit check, but you're right the `ImmutableMap` will throw on its own.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r810361714



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/CreateNamespaceRequest.java
##########
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+
+/**
+ * A REST request to create a namespace, with an optional set of properties.

Review comment:
       Ohhh... like you mean `This maps to 'operationId: createNamespace'`? I'd like to avoid something that can drift, so if we can find sommething that we can specifically point to it (even if that's building the OpenAPI doc via code annotation generation in the future), I'd prefer that.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r809452901



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/DropNamespaceResponse.java
##########
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Objects;
+import org.apache.iceberg.exceptions.ValidationException;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+
+/**
+ * Represents a REST response to drop a namespace.
+ * <p>
+ * The server may choose to return an error if the namespace is not empty.
+ */
+public class DropNamespaceResponse {
+
+  // For Jackson to properly fail when deserializing, this needs to be boxed.
+  // Otherwise, the boolean is parsed according to "loose" javascript JSON rules.
+  private Boolean dropped;
+
+  public DropNamespaceResponse() {
+    // Required for Jackson deserialization
+  }
+
+  private DropNamespaceResponse(Boolean dropped) {

Review comment:
       Why is the argument here boxed? I don't think that the builder should ever pass a null value.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r808552878



##########
File path: core/src/test/java/org/apache/iceberg/rest/requests/TestCreateNamespaceRequest.java
##########
@@ -0,0 +1,143 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.util.Map;
+import org.apache.iceberg.AssertHelpers;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.exceptions.ValidationException;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.rest.RESTUtil;
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+
+public class TestCreateNamespaceRequest {
+
+  private static final ObjectMapper MAPPER = RESTUtil.mapper();
+
+  private static final String[] ALL_FIELDS_FROM_SPEC = { "namespace", "properties" };
+
+  /* Values used to fill in request fields */
+  private static final Namespace NAMESPACE = Namespace.of("accounting", "tax");
+  private static final Map<String, String> PROPERTIES = ImmutableMap.of("owner", "Hank");
+  private static final Map<String, String> EMPTY_PROPERTIES = ImmutableMap.of();
+
+  @Test
+  // Test cases that are JSON that can be created via the Builder
+  public void testRoundTripSerDe() throws JsonProcessingException {
+    String fullJson = "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{\"owner\":\"Hank\"}}";
+    CreateNamespaceRequest req = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE).setProperties(PROPERTIES).build();
+    assertRoundTripSerDe(fullJson, req);
+
+    String jsonEmptyProperties = "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{}}";
+    CreateNamespaceRequest reqWithExplicitEmptyProperties = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE).setProperties(EMPTY_PROPERTIES).build();
+    assertRoundTripSerDe(jsonEmptyProperties, reqWithExplicitEmptyProperties);
+
+    CreateNamespaceRequest reqWithImplicitEmptyProperties = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE).build();
+    assertRoundTripSerDe(jsonEmptyProperties, reqWithImplicitEmptyProperties);
+  }
+
+  @Test
+  // Test cases that can't be constructed with our Builder class but that will parse correctly
+  // and can be compared with our builder after calling `validate` to normalize the parsed object.
+  public void testRoundTripSerDeAfterEnsureRequirements() throws JsonProcessingException {
+    String jsonWithNullProperties = "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":null}";
+    CreateNamespaceRequest req = CreateNamespaceRequest.builder().withNamespace(NAMESPACE).build();
+    assertDeserializesEquallyAfterValidation(jsonWithNullProperties, req);
+  }
+
+  @Test
+  public void testDeserializeInvalidRequest() {
+    String jsonIncorrectTypeForNamespace = "{\"namespace\":\"accounting%00tax\",\"properties\":null}";
+    AssertHelpers.assertThrows(
+        "A JSON request with incorrect types for fields should fail to deserialize and validate",
+        JsonProcessingException.class,
+        "Namespace must be an array",
+        () -> MAPPER.readValue(jsonIncorrectTypeForNamespace, CreateNamespaceRequest.class).validate()
+    );
+
+    String jsonIncorrectTypeForProperties = "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":[]}";
+    AssertHelpers.assertThrows(
+        "A JSON request with incorrect types for fields should fail to parse and validate",
+        JsonProcessingException.class,
+        () -> MAPPER.readValue(jsonIncorrectTypeForProperties, CreateNamespaceRequest.class).validate()
+    );
+
+    String jsonMisspelledKeys = "{\"namepsace\":[\"accounting\",\"tax\"],\"propertiezzzz\":{\"owner\":\"Hank\"}}";
+    AssertHelpers.assertThrows(
+        "A JSON request with the keys spelled incorrectly should fail to deserialize and validate",
+        JsonProcessingException.class,
+        () -> MAPPER.readValue(jsonMisspelledKeys, CreateNamespaceRequest.class).validate()
+    );
+
+    String emptyJson = "{}";
+    AssertHelpers.assertThrows(
+        "An empty JSON object should not parse into a CreateNamespaceRequest instance that passes validation",
+        ValidationException.class,
+        () -> MAPPER.readValue(emptyJson, CreateNamespaceRequest.class).validate()
+    );
+
+    AssertHelpers.assertThrows(
+        "An empty JSON request should fail to deserialize",
+        IllegalArgumentException.class,
+        () -> MAPPER.readValue((String) null, CreateNamespaceRequest.class).validate()
+    );
+  }
+
+  @Test
+  public void testHasOnlyKnownFields() {
+    // This test ensures that only the fields that are expected (from the spec) are found on the class.
+    // If new fields are added to the spec, they should be added to the ALL_FIELDS_FROM_SPEC constant.
+    CreateNamespaceRequest req = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .setProperties(PROPERTIES)
+        .build();
+
+    Assertions.assertThat(req)
+        .hasOnlyFields(ALL_FIELDS_FROM_SPEC);
+  }
+
+  // For testing JSON that could be generated by our Builder
+  private void assertRoundTripSerDe(String json, CreateNamespaceRequest expected) throws JsonProcessingException {

Review comment:
       I just used a templated abstract base class instead. That way the code is shareable but we don't have to cast. Let me know if you'd prefer just using `Object`.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r808550991



##########
File path: core/src/main/java/org/apache/iceberg/rest/RESTSerializers.java
##########
@@ -0,0 +1,162 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import java.io.IOException;
+import org.apache.iceberg.PartitionSpec;
+import org.apache.iceberg.PartitionSpecParser;
+import org.apache.iceberg.Schema;
+import org.apache.iceberg.SchemaParser;
+import org.apache.iceberg.SortOrder;
+import org.apache.iceberg.SortOrderParser;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.catalog.TableIdentifier;
+import org.apache.iceberg.catalog.TableIdentifierParser;
+
+public class RESTSerializers {
+
+  private RESTSerializers() {
+  }
+
+  public static void registerAll(ObjectMapper mapper) {
+    SimpleModule module = new SimpleModule();
+    module
+        .addSerializer(TableIdentifier.class, new TableIdentifierSerializer())
+        .addDeserializer(TableIdentifier.class, new TableIdentifierDeserializer())
+        .addSerializer(Namespace.class, new NamespaceSerializer())
+        .addDeserializer(Namespace.class, new NamespaceDeserializer())
+        .addSerializer(Schema.class, new SchemaSerializer())
+        .addDeserializer(Schema.class, new SchemaDeserializer())
+        .addSerializer(PartitionSpec.class, new PartitionSpecSerializer())
+        .addDeserializer(PartitionSpec.class, new PartitionSpecDeserializer())
+        .addSerializer(SortOrder.class, new SortOrderSerializer())
+        .addDeserializer(SortOrder.class, new SortOrderDeserializer());
+    mapper.registerModule(module);
+  }
+
+  public static class NamespaceDeserializer extends JsonDeserializer<Namespace> {
+    @Override
+    public Namespace deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
+      JsonNode jsonNode = p.getCodec().readTree(p);
+      return namespaceFromNode(p, jsonNode);
+    }
+  }
+
+  public static class NamespaceSerializer extends JsonSerializer<Namespace> {
+    @Override
+    public void serialize(Namespace namespace, JsonGenerator gen, SerializerProvider serializers)
+        throws IOException {
+      String[] parts = namespace.levels();
+      gen.writeArray(parts, 0, parts.length);
+    }
+  }
+
+  private static Namespace namespaceFromNode(JsonParser parser, JsonNode jsonNode) throws IOException {
+    if (!jsonNode.isArray()) {
+      throw new JsonParseException(parser, "Namespace must be an array: " + jsonNode);
+    }
+    ArrayNode arrayNode = (ArrayNode) jsonNode;
+    String[] levels = new String[arrayNode.size()];
+    for (int i = 0; i < levels.length; i++) {
+      levels[i] = arrayNode.get(i).asText();
+    }

Review comment:
       Moved.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r809353206



##########
File path: core/src/test/java/org/apache/iceberg/rest/requests/TestCreateNamespaceRequest.java
##########
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import java.util.Map;
+import org.apache.iceberg.AssertHelpers;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.rest.RequestResponseTestBase;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestCreateNamespaceRequest extends RequestResponseTestBase<CreateNamespaceRequest> {
+
+  /* Values used to fill in request fields */
+  private static final Namespace NAMESPACE = Namespace.of("accounting", "tax");
+  private static final Map<String, String> PROPERTIES = ImmutableMap.of("owner", "Hank");
+  private static final Map<String, String> EMPTY_PROPERTIES = ImmutableMap.of();
+
+  @Test
+  // Test cases that are JSON that can be created via the Builder
+  public void testRoundTripSerDe() throws JsonProcessingException {
+    String fullJson = "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{\"owner\":\"Hank\"}}";
+    CreateNamespaceRequest req = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE).setProperties(PROPERTIES).build();
+    assertRoundTripSerializesEquallyFrom(fullJson, req);
+
+    String jsonEmptyProperties = "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{}}";
+    CreateNamespaceRequest reqWithExplicitEmptyProperties = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE).setProperties(EMPTY_PROPERTIES).build();
+    assertRoundTripSerializesEquallyFrom(jsonEmptyProperties, reqWithExplicitEmptyProperties);
+
+    CreateNamespaceRequest reqWithImplicitEmptyProperties = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE).build();
+    assertRoundTripSerializesEquallyFrom(jsonEmptyProperties, reqWithImplicitEmptyProperties);
+  }
+
+  @Test
+  // Test cases that can't be constructed with our Builder class but that will parse correctly
+  public void testCanDeserializeWithoutDefaultValues() throws JsonProcessingException {
+    CreateNamespaceRequest req = CreateNamespaceRequest.builder().withNamespace(NAMESPACE).build();
+    String jsonWithNullProperties = "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":null}";
+    assertEquals(deserialize(jsonWithNullProperties), req);
+
+    String jsonWithMissingProperties = "{\"namespace\":[\"accounting\",\"tax\"]}";
+    assertEquals(deserialize(jsonWithMissingProperties), req);
+  }
+
+  @Test
+  public void testDeserializeInvalidRequest() {
+    String jsonIncorrectTypeForNamespace = "{\"namespace\":\"accounting%00tax\",\"properties\":null}";
+    AssertHelpers.assertThrows(
+        "A JSON request with incorrect types for fields should fail to deserialize and validate",
+        JsonProcessingException.class,
+        "Cannot parse string array from non-array value",
+        () -> deserialize(jsonIncorrectTypeForNamespace).validate()
+    );
+
+    String jsonIncorrectTypeForProperties = "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":[]}";
+    AssertHelpers.assertThrows(
+        "A JSON request with incorrect types for fields should fail to parse and validate",
+        JsonProcessingException.class,
+        () -> deserialize(jsonIncorrectTypeForProperties).validate()
+    );
+
+    String jsonMisspelledKeys = "{\"namepsace\":[\"accounting\",\"tax\"],\"propertiezzzz\":{\"owner\":\"Hank\"}}";
+    AssertHelpers.assertThrows(
+        "A JSON request with the keys spelled incorrectly should fail to deserialize and validate",
+        JsonProcessingException.class,
+        () -> deserialize(jsonMisspelledKeys).validate()

Review comment:
       Will add that in!




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r811431853



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/ListNamespacesResponse.java
##########
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Collection;
+import java.util.List;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+
+public class ListNamespacesResponse {
+
+  private List<Namespace> namespaces;
+
+  public ListNamespacesResponse() {
+    // Required for Jackson deserialization
+  }
+
+  private ListNamespacesResponse(List<Namespace> namespaces) {
+    this.namespaces = namespaces;
+    validate();
+  }
+
+  ListNamespacesResponse validate() {
+    Preconditions.checkArgument(namespaces != null,
+        "Cannot create a response to a list namespaces request without a non-null list of namespaces");
+    return this;
+  }
+
+
+  public List<Namespace> namespaces() {
+    return namespaces != null ? namespaces : ImmutableList.of();
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("namespaces", namespaces())
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  static class Builder {
+    private final ImmutableList.Builder<Namespace> namespaces = ImmutableList.builder();
+
+    private Builder() {
+    }
+
+    public Builder add(Namespace toAdd) {
+      Preconditions.checkNotNull(toAdd,
+          "Invalid namespace to list: null");
+      namespaces.add(toAdd);
+      return this;
+    }
+
+    public Builder addAll(Collection<Namespace> toAdd) {
+      Preconditions.checkNotNull(toAdd,
+          "Invalid collection of namespaces to list: null");
+      Preconditions.checkArgument(!toAdd.contains(null),
+          "Invalid namespace in collection of namespaces to list: null");

Review comment:
       Updated.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r809540515



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/UpdateNamespacePropertiesRequest.java
##########
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.List;
+import java.util.Map;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
+
+/**
+ * A REST request to set and/or remove properties on a namespace.
+ * <p>
+ * The request body specifies a list of properties to remove and a map
+ * of key value pairs to update.
+ * <p>
+ * Properties that are not in the request are not modified or removed by this call.
+ * Server implementations are not required to support namespace properties.
+ */
+public class UpdateNamespacePropertiesRequest {
+
+  private List<String> removals;
+  private Map<String, String> updates;
+
+  public UpdateNamespacePropertiesRequest() {
+    // Required for Jackson deserialization.
+  }
+
+  private UpdateNamespacePropertiesRequest(List<String> removals, Map<String, String> updates) {
+    this.removals = removals;
+    this.updates = updates;
+    validate();
+  }
+
+  UpdateNamespacePropertiesRequest validate() {
+    Preconditions.checkArgument((removals != null && !removals.isEmpty()) || (updates != null && !updates.isEmpty()),
+        "Cannot create a request to update a namespace's properties without specifying any props to update or remove");
+    return this;
+  }
+
+  public List<String> removals() {
+    return removals == null ? ImmutableList.of() : removals;
+  }
+
+  public Map<String, String> updates() {
+    return updates == null ? ImmutableMap.of() : updates;
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("removals", removals)
+        .add("updates", updates)
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public static class Builder {
+    private final ImmutableSet.Builder<String> removalsBuilder = ImmutableSet.builder();
+    private final ImmutableMap.Builder<String, String> updatesBuilder = ImmutableMap.builder();
+
+    private Builder() {
+    }
+
+    public Builder remove(String removal) {
+      Preconditions.checkNotNull(removal,
+          "Cannot pass null key to remove to UpdateNamespacePropertiesRequest.Builder");
+      removalsBuilder.add(removal);
+      return this;
+    }
+
+    public Builder removeAll(Iterable<String> removals) {
+      Preconditions.checkNotNull(removals,
+          "Cannot pass null removals to UpdateNamespacePropertiesRequest.Builder");
+      removalsBuilder.addAll(removals);
+      return this;
+    }
+
+    public Builder update(String key, String value) {
+      Preconditions.checkNotNull(key,
+          "Cannot pass null key to update to UpdateNamespacePropertiesRequest.Builder");
+      Preconditions.checkNotNull(value,
+          "Cannot pass null value to update in UpdateNamespacePropertiesRequest.Builder. Use remove instead");
+      updatesBuilder.put(key, value);
+      return this;
+    }
+
+    public Builder updateAll(Map<String, String> updates) {
+      Preconditions.checkNotNull(updates,
+          "Cannot pass null updates to UpdateNamespacePropertiesRequest.Builder");

Review comment:
       Thrown and tested.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r811460578



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/UpdateNamespacePropertiesRequest.java
##########
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
+import org.apache.iceberg.relocated.com.google.common.collect.Maps;
+
+/**
+ * A REST request to set and/or remove properties on a namespace.
+ */
+public class UpdateNamespacePropertiesRequest {
+
+  private List<String> removals;
+  private Map<String, String> updates;
+
+  public UpdateNamespacePropertiesRequest() {
+    // Required for Jackson deserialization.
+  }
+
+  private UpdateNamespacePropertiesRequest(List<String> removals, Map<String, String> updates) {
+    this.removals = removals;
+    this.updates = updates;
+    validate();
+  }
+
+  UpdateNamespacePropertiesRequest validate() {
+    Preconditions.checkArgument(removals != null || updates != null,
+        "Invalid value for update namespace properties request: at least one of updates and removals must be non-null");
+    return this;
+  }
+
+  public List<String> removals() {
+    return removals == null ? ImmutableList.of() : removals;
+  }
+
+  public Map<String, String> updates() {
+    return updates == null ? ImmutableMap.of() : updates;
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("removals", removals)
+        .add("updates", updates)
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public static class Builder {
+    private final ImmutableSet.Builder<String> removalsBuilder = ImmutableSet.builder();
+    private final ImmutableMap.Builder<String, String> updatesBuilder = ImmutableMap.builder();
+
+    private Builder() {
+    }
+
+    public Builder remove(String removal) {
+      Preconditions.checkNotNull(removal,
+          "Invalid property to remove: null");
+      removalsBuilder.add(removal);
+      return this;
+    }
+
+    public Builder removeAll(Collection<String> removals) {
+      Preconditions.checkNotNull(removals,
+          "Invalid list of properties to remove: null");
+      Preconditions.checkArgument(!removals.contains(null),
+          "Invalid value in list of properties to remove: null");
+      removalsBuilder.addAll(removals);
+      return this;
+    }
+
+    public Builder update(String key, String value) {
+      Preconditions.checkNotNull(key,
+          "Invalid property to update: null");
+      Preconditions.checkNotNull(value,
+          "Invalid value to update for key [%s]: null. Use remove instead", key);
+      updatesBuilder.put(key, value);
+      return this;
+    }
+
+    public Builder updateAll(Map<String, String> updates) {
+      Preconditions.checkNotNull(updates,
+          "Invalid collection of properties to update: null");
+      Preconditions.checkArgument(!updates.containsKey(null),
+          "Invalid property in collection of properties to update: null");
+      Preconditions.checkArgument(!updates.containsValue(null),
+          "Invalid value to update for properties %s: null. Use remove instead",
+          Maps.filterValues(updates, Objects::isNull).keySet());

Review comment:
       Thank you 🙂 




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r811457565



##########
File path: core/src/test/java/org/apache/iceberg/rest/RESTUtil.java
##########
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.core.JsonFactory;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class RESTUtil {

Review comment:
       Merged and removed!




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r809459226



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/UpdateNamespacePropertiesRequest.java
##########
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.List;
+import java.util.Map;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
+
+/**
+ * A REST request to set and/or remove properties on a namespace.
+ * <p>
+ * The request body specifies a list of properties to remove and a map
+ * of key value pairs to update.
+ * <p>
+ * Properties that are not in the request are not modified or removed by this call.
+ * Server implementations are not required to support namespace properties.
+ */
+public class UpdateNamespacePropertiesRequest {
+
+  private List<String> removals;
+  private Map<String, String> updates;
+
+  public UpdateNamespacePropertiesRequest() {
+    // Required for Jackson deserialization.
+  }
+
+  private UpdateNamespacePropertiesRequest(List<String> removals, Map<String, String> updates) {
+    this.removals = removals;
+    this.updates = updates;
+    validate();
+  }
+
+  UpdateNamespacePropertiesRequest validate() {
+    Preconditions.checkArgument((removals != null && !removals.isEmpty()) || (updates != null && !updates.isEmpty()),

Review comment:
       I think this is slightly incorrect. Neither removals nor updates should be null. And one of them should be non-empty. I think that is 3 checks: removals is non-null, updates is non-null, and either one is non-empty.
   
   Separate checks are good because you can have more helpful error messages.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r808427588



##########
File path: core/src/test/java/org/apache/iceberg/rest/requests/TestCreateNamespaceRequest.java
##########
@@ -0,0 +1,128 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.util.Map;
+import org.apache.iceberg.AssertHelpers;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.exceptions.ValidationException;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.rest.RESTUtils;
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+
+public class TestCreateNamespaceRequest {
+
+  private static final ObjectMapper MAPPER = RESTUtils.mapper();
+
+  private static final String[] ALL_FIELDS_FROM_SPEC = { "namespace", "properties" };
+
+  /* Values used to fill in request fields */
+  private static final Namespace NAMESPACE = Namespace.of("accounting", "tax");
+  private static final Map<String, String> PROPERTIES = ImmutableMap.of("owner", "Hank");
+  private static final Map<String, String> EMPTY_PROPERTIES = ImmutableMap.of();
+
+  @Test
+  public void testValidSerDe() throws JsonProcessingException {
+    Map<String, CreateNamespaceRequest> toTest = ImmutableMap.of(
+        // Full response
+        "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{\"owner\":\"Hank\"}}",
+        builder().withNamespace(NAMESPACE).setProperties(PROPERTIES).build(),
+        "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":null}",
+        builder().withNamespace(NAMESPACE).build(),
+        "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{}}",
+        builder().withNamespace(NAMESPACE).setProperties(EMPTY_PROPERTIES).build());
+
+    for (Map.Entry<String, CreateNamespaceRequest> testCase : toTest.entrySet()) {
+      String json = testCase.getKey();
+      CreateNamespaceRequest req = testCase.getValue();
+      assertSerializes(req, json);
+      assertDeserializes(json, req);
+    }
+  }
+
+  @Test
+  public void testDeserializeInvalidRequest() {
+    String jsonIncorrectTypeForNamespace = "{\"namespace\":\"accounting%00tax\",\"properties\":null}";
+    AssertHelpers.assertThrows(
+        "A JSON request with incorrect types for fields should fail to deserialize and validate",
+        JsonProcessingException.class,
+        "Namespace must be an array",
+        () -> MAPPER.readValue(jsonIncorrectTypeForNamespace, CreateNamespaceRequest.class).validate()
+    );
+
+    String jsonIncorrectTypeForProperties = "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":[]}";
+    AssertHelpers.assertThrows(
+        "A JSON request with incorrect types for fields should fail to parse and validate",
+        JsonProcessingException.class,
+        () -> MAPPER.readValue(jsonIncorrectTypeForProperties, CreateNamespaceRequest.class).validate()
+    );
+
+    String jsonMisspelledKeys = "{\"namepsace\":[\"accounting\",\"tax\"],\"propertiezzzz\":{\"owner\":\"Hank\"}}";
+    AssertHelpers.assertThrows(
+        "A JSON request with the keys spelled incorrectly should fail to deserialize and validate",
+        JsonProcessingException.class,
+        () -> MAPPER.readValue(jsonMisspelledKeys, CreateNamespaceRequest.class).validate()

Review comment:
       It fails because there aren't values for what is needed. That's why `validate` is required.
   
   With the way the ObjectMapper is presently configured, it doesn't fail on unknown fields (though other object mappers might).

##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/CreateNamespaceRequest.java
##########
@@ -0,0 +1,128 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.exceptions.ValidationException;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.util.ImmutablesUtil;
+
+/**
+ * A REST request to create a namespace, with an optional set of properties.
+ * The server might also add properties, such as `last_modified_time` etc.
+ */
+public class CreateNamespaceRequest {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public CreateNamespaceRequest() {
+    // Needed for Jackson Deserialization.
+  }
+
+  private CreateNamespaceRequest(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+    validate();
+  }
+
+  CreateNamespaceRequest validate() {
+    ValidationException.check(namespace != null && !namespace.isEmpty(),
+        "Cannot build a request to create a namespace without specifying the namespace");
+    return this;
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }

Review comment:
       Moved.

##########
File path: core/src/main/java/org/apache/iceberg/rest/RESTUtils.java
##########
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.core.JsonFactory;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class RESTUtils {

Review comment:
       Renamed




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r809723498



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/GetNamespaceResponse.java
##########
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.exceptions.ValidationException;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.util.ImmutablesUtil;
+
+/**
+ * Represents a REST response to fetch namespace metadata.
+ * <p>
+ * The properties returned should include all the user provided properties from the
+ * request, as well as any server-side added properties.
+ */
+public class GetNamespaceResponse {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public GetNamespaceResponse() {
+    // Required for Jackson deserialization
+  }
+
+  private GetNamespaceResponse(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+    validate();
+  }
+
+  GetNamespaceResponse validate() {
+    ValidationException.check(namespace != null && !namespace.isEmpty(),
+        "Cannot build a response to get a namespace without specifying the namespace");

Review comment:
       That's fair. I hadn't considered the root namespace or something as possibly being modeled via the empty namespace. We shouldn't disallow that. I will update this.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r799087780



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/UpdateNamespacePropertiesRequest.java
##########
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.List;
+import java.util.Map;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
+
+/**
+ * A REST request to set and/or remove properties on a namespace.
+ * <p/>
+ * The request body specifies a list of properties to remove and a map
+ * of key value pairs to update.
+ * <p/>
+ * Properties that are not in the request are not modified or removed by this call.
+ * Server implementations are not required to support namespace properties.
+ */
+public class UpdateNamespacePropertiesRequest {
+
+  private List<String> removals;
+  private Map<String, String> updates;
+
+  public UpdateNamespacePropertiesRequest() {
+    // Required for Jackson
+  }
+
+  private UpdateNamespacePropertiesRequest(List<String> removals, Map<String, String> updates) {
+    this.removals = removals;
+    this.updates = updates;
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public List<String> removals() {
+    return ImmutableList.copyOf(removals);
+  }
+
+  public Map<String, String> updates() {
+    return ImmutableMap.copyOf(updates);
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("removals", removals())
+        .add("updates", updates())
+        .toString();
+  }
+
+  public static class Builder {
+    private final ImmutableSet.Builder<String> removalsBuilder;
+    private final ImmutableMap.Builder<String, String> updatesBuilder;
+
+    private Builder() {
+      this.removalsBuilder = ImmutableSet.builder();
+      this.updatesBuilder = ImmutableMap.builder();
+    }
+
+    public Builder withRemoval(String removal) {
+      removalsBuilder.add(removal);
+      return this;
+    }
+
+    public Builder withRemovals(Iterable<String> removals) {

Review comment:
       remove / removeAll?

##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/UpdateNamespacePropertiesRequest.java
##########
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.List;
+import java.util.Map;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
+
+/**
+ * A REST request to set and/or remove properties on a namespace.
+ * <p/>
+ * The request body specifies a list of properties to remove and a map
+ * of key value pairs to update.
+ * <p/>
+ * Properties that are not in the request are not modified or removed by this call.
+ * Server implementations are not required to support namespace properties.
+ */
+public class UpdateNamespacePropertiesRequest {
+
+  private List<String> removals;
+  private Map<String, String> updates;
+
+  public UpdateNamespacePropertiesRequest() {
+    // Required for Jackson
+  }
+
+  private UpdateNamespacePropertiesRequest(List<String> removals, Map<String, String> updates) {
+    this.removals = removals;
+    this.updates = updates;
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public List<String> removals() {
+    return ImmutableList.copyOf(removals);
+  }
+
+  public Map<String, String> updates() {
+    return ImmutableMap.copyOf(updates);
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("removals", removals())
+        .add("updates", updates())
+        .toString();
+  }
+
+  public static class Builder {
+    private final ImmutableSet.Builder<String> removalsBuilder;
+    private final ImmutableMap.Builder<String, String> updatesBuilder;
+
+    private Builder() {
+      this.removalsBuilder = ImmutableSet.builder();
+      this.updatesBuilder = ImmutableMap.builder();
+    }
+
+    public Builder withRemoval(String removal) {
+      removalsBuilder.add(removal);
+      return this;
+    }
+
+    public Builder withRemovals(Iterable<String> removals) {
+      removalsBuilder.addAll(removals);
+      return this;
+    }
+
+    public Builder withUpdate(String key, String value) {

Review comment:
       update / updateAll?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r799087029



##########
File path: core/src/test/java/org/apache/iceberg/rest/requests/TestCreateNamespaceRequest.java
##########
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.util.JsonUtil;
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+
+public class TestCreateNamespaceRequest {
+
+  private static final ObjectMapper MAPPER = JsonUtil.withRESTComponents();
+
+  // Non-empty
+  private static final String JSON_REQUEST_STRING =
+      "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{\"owner\":\"Hank\"}}";
+  private static final Namespace NAMESPACE = Namespace.of("accounting", "tax");
+  private static final Map<String, String> PROPERTIES = ImmutableMap.of("owner", "Hank");
+
+  // Empty - The response requires a non-empty namespace
+  private static final String JSON_REQUEST_NO_PROPERTIES =
+      "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{}}";
+
+  @Test
+  public void testDeserialize() throws JsonProcessingException {
+    CreateNamespaceRequest expected = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .withProperties(PROPERTIES)
+        .build();
+
+    CreateNamespaceRequest actual = MAPPER.readValue(JSON_REQUEST_STRING, CreateNamespaceRequest.class);
+
+    assertSame(expected, actual);
+  }
+
+  @Test
+  public void testDeserializeNoProperties() throws JsonProcessingException {
+    CreateNamespaceRequest expected = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .build();
+
+    CreateNamespaceRequest actual = MAPPER.readValue(JSON_REQUEST_NO_PROPERTIES, CreateNamespaceRequest.class);
+
+    assertSame(expected, actual);
+  }
+
+  @Test
+  public void testSerialize() throws JsonProcessingException {
+    CreateNamespaceRequest req = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .withProperties(PROPERTIES)
+        .build();
+
+    Assertions.assertThat(MAPPER.writeValueAsString(req))
+        .isEqualTo(JSON_REQUEST_STRING);
+  }
+
+  @Test
+  public void testSerializeNoProperties() throws JsonProcessingException {
+    CreateNamespaceRequest req = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .build();
+
+    Assertions.assertThat(MAPPER.writeValueAsString(req))
+        .isEqualTo(JSON_REQUEST_NO_PROPERTIES);

Review comment:
       This behavior is fine with me.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r799088242



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/CreateNamespaceResponse.java
##########
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.Maps;
+
+/**
+ * Represents a REST response for a request to create a namespace / database.
+ * <p>
+ * The properties returned should include all the user provided properties from the
+ * request, as well as any server-side added properties.
+ * <p>
+ * Example server-side added properties can be implementation specific, but might include
+ * such things as `created_at` or `owner`.
+ */
+public class CreateNamespaceResponse {
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public CreateNamespaceResponse() {
+    // Required for Jackson
+  }
+
+  private CreateNamespaceResponse(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+  }
+
+  public Namespace namespace() {
+    return namespace;
+  }
+
+  public Map<String, String> properties() {
+    return ImmutableMap.copyOf(properties);
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("namespace", namespace)
+        .add("properties", properties())
+        .toString();
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public static class Builder {

Review comment:
       You can copy this builder for the create request.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r799089415



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/CreateNamespaceResponse.java
##########
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.Maps;
+
+/**
+ * Represents a REST response for a request to create a namespace / database.
+ * <p>
+ * The properties returned should include all the user provided properties from the
+ * request, as well as any server-side added properties.
+ * <p>
+ * Example server-side added properties can be implementation specific, but might include
+ * such things as `created_at` or `owner`.

Review comment:
       The spec needs to be updated to match this. I agree with returning the namespace and actual properties so that the caller doesn't have to immediately send a GET request, but we should make sure the implementation and spec match.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r799086807



##########
File path: core/src/test/java/org/apache/iceberg/rest/requests/TestCreateNamespaceRequest.java
##########
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.util.JsonUtil;
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+
+public class TestCreateNamespaceRequest {
+
+  private static final ObjectMapper MAPPER = JsonUtil.withRESTComponents();
+
+  // Non-empty
+  private static final String JSON_REQUEST_STRING =
+      "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{\"owner\":\"Hank\"}}";
+  private static final Namespace NAMESPACE = Namespace.of("accounting", "tax");
+  private static final Map<String, String> PROPERTIES = ImmutableMap.of("owner", "Hank");
+
+  // Empty - The response requires a non-empty namespace
+  private static final String JSON_REQUEST_NO_PROPERTIES =

Review comment:
       Better name might be "EMPTY_PROPERTIES"




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r799100527



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/UpdateNamespacePropertiesResponse.java
##########
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.List;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
+
+/**
+ * A REST response to a request to set and/or remove properties on a namespace.
+ */
+public class UpdateNamespacePropertiesResponse {
+
+  // List of namespace property keys that were removed
+  private List<String> removed;
+  // List of namesspace property keys that were added or updated
+  private List<String> updated;
+  // List of properties that were requested for removal that were not found in the namespace's properties
+  private List<String> missing;
+
+  public UpdateNamespacePropertiesResponse() {
+    // Required for Jackson
+  }
+
+  private UpdateNamespacePropertiesResponse(List<String> removed, List<String> updated, List<String> missing) {
+    this.removed = removed;
+    this.updated = updated;
+    this.missing = missing;
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public List<String> removed() {
+    return ImmutableList.copyOf(removed);
+  }
+
+  public List<String> updated() {
+    return ImmutableList.copyOf(updated);
+  }
+
+  public List<String> missing() {
+    return ImmutableList.copyOf(missing);
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("removed", removed())
+        .add("updates", updated())
+        .add("missing", missing())

Review comment:
       Fair point. I was using it to use the `toString` method of `ImmutableList` because Jackson can inject a list of some other type, but `ArrayList<String>` prints correctly so the defensive method calls aren't needed.
   
   Removed.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] nastra commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
nastra commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r800066452



##########
File path: core/src/main/java/org/apache/iceberg/rest/RESTJacksonModule.java
##########
@@ -0,0 +1,183 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import java.io.IOException;
+import org.apache.iceberg.PartitionSpec;
+import org.apache.iceberg.PartitionSpecParser;
+import org.apache.iceberg.Schema;
+import org.apache.iceberg.SchemaParser;
+import org.apache.iceberg.SortOrder;
+import org.apache.iceberg.SortOrderParser;
+import org.apache.iceberg.TableMetadata;
+import org.apache.iceberg.TableMetadataParser;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.catalog.TableIdentifier;
+
+public class RESTJacksonModule {
+
+  private RESTJacksonModule() {
+  }
+
+  public static void registerAll(ObjectMapper mapper) {
+    SimpleModule module = new SimpleModule();
+    module
+        .addSerializer(TableIdentifier.class, new TableIdentifierSerializer())
+        .addDeserializer(TableIdentifier.class, new TableIdentifierDeserializer())
+        .addSerializer(Namespace.class, new NamespaceSerializer())
+        .addDeserializer(Namespace.class, new NamespaceDeserializer())
+        .addSerializer(Schema.class, new SchemaSerializer())
+        .addDeserializer(Schema.class, new SchemaDeserializer())
+        .addSerializer(PartitionSpec.class, new PartitionSpecSerializer())
+        .addDeserializer(PartitionSpec.class, new PartitionSpecDeserializer())
+        .addSerializer(SortOrder.class, new SortOrderSerializer())
+        .addDeserializer(SortOrder.class, new SortOrderDeserializer());
+    mapper.registerModule(module);
+
+    mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE);
+    mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);

Review comment:
       would it make sense to add a comment to the code describing this workaround? I think this isn't clear to everyone stumbling across this part of the code why it's being done




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] jackye1995 commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
jackye1995 commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r800917182



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/CreateNamespaceRequest.java
##########
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+
+/**
+ * A REST request to create a namespace, with an optional set of properties.

Review comment:
       I think we can have the javadoc here for every request saying it maps to the XXXX in the OpenAPI spec, for more clarity of the readers who encounter this class. (I don't know if we can link that spec, if so it would be better)




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r801035384



##########
File path: core/src/test/java/org/apache/iceberg/rest/requests/TestCreateNamespaceRequest.java
##########
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.util.JsonUtil;
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+
+public class TestCreateNamespaceRequest {
+
+  private static final ObjectMapper MAPPER = JsonUtil.withRESTComponents();
+
+  // Non-empty
+  private static final String JSON_REQUEST_STRING =
+      "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{\"owner\":\"Hank\"}}";
+  private static final Namespace NAMESPACE = Namespace.of("accounting", "tax");
+  private static final Map<String, String> PROPERTIES = ImmutableMap.of("owner", "Hank");
+
+  // Empty - The response requires a non-empty namespace
+  private static final String JSON_REQUEST_NO_PROPERTIES =
+      "{\"namespace\":[\"accounting\",\"tax\"],\"properties\":{}}";
+
+  @Test
+  public void testDeserialize() throws JsonProcessingException {
+    CreateNamespaceRequest expected = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .withProperties(PROPERTIES)
+        .build();
+
+    CreateNamespaceRequest actual = MAPPER.readValue(JSON_REQUEST_STRING, CreateNamespaceRequest.class);
+
+    assertSame(expected, actual);
+  }
+
+  @Test
+  public void testDeserializeNoProperties() throws JsonProcessingException {
+    CreateNamespaceRequest expected = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .build();
+
+    CreateNamespaceRequest actual = MAPPER.readValue(JSON_REQUEST_NO_PROPERTIES, CreateNamespaceRequest.class);
+
+    assertSame(expected, actual);
+  }
+
+  @Test
+  public void testSerialize() throws JsonProcessingException {
+    CreateNamespaceRequest req = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .withProperties(PROPERTIES)
+        .build();
+
+    Assertions.assertThat(MAPPER.writeValueAsString(req))
+        .isEqualTo(JSON_REQUEST_STRING);
+  }
+
+  @Test
+  public void testSerializeNoProperties() throws JsonProcessingException {
+    CreateNamespaceRequest req = CreateNamespaceRequest.builder()
+        .withNamespace(NAMESPACE)
+        .build();
+
+    Assertions.assertThat(MAPPER.writeValueAsString(req))
+        .isEqualTo(JSON_REQUEST_NO_PROPERTIES);
+  }
+
+  private static void assertSame(CreateNamespaceRequest expected, CreateNamespaceRequest actual) {

Review comment:
       As per a comment from @nastra, I chose to implement `equals` directly on the class and then this method became unnecessary as I can just do the equality check in line in the test.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r799764690



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/CreateNamespaceRequest.java
##########
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.Map;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+
+/**
+ * A REST request to create a namespace, with an optional set of properties.
+ * The server might also add properties, such as `last_modified_time` etc.
+ */
+public class CreateNamespaceRequest {
+
+  private Namespace namespace;
+  private Map<String, String> properties;
+
+  public CreateNamespaceRequest() {
+    // Required for Jackson deserialization
+  }
+
+  private CreateNamespaceRequest(Namespace namespace, Map<String, String> properties) {
+    this.namespace = namespace;
+    this.properties = properties;
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public Namespace namespace() {
+    return namespace;
+  }
+
+  public Map<String, String> properties() {
+    return ImmutableMap.copyOf(properties);
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("namespace", namespace)
+        .add("properties", properties)
+        .toString();
+  }
+
+  public static class Builder {
+    private Namespace namespace;
+    private ImmutableMap.Builder<String, String> properties = ImmutableMap.builder();
+
+    private Builder() {
+    }
+
+    public Builder withNamespace(Namespace ns) {
+      this.namespace = ns;
+      return this;
+    }
+
+    public Builder withProperties(Map<String, String> props) {
+      this.properties.putAll(props);
+      return this;
+    }
+
+    public CreateNamespaceRequest build() {
+      Preconditions.checkArgument(
+          namespace != null && !namespace.isEmpty(),
+          "Cannot build a response to create a namespace without specifying the namespace");

Review comment:
       I'll be adding more unit tests for the non-happy paths. 👍 




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] kbendick commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
kbendick commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r806210962



##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/CreateNamespaceRequest.java
##########
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import com.fasterxml.jackson.annotation.JsonProperty;

Review comment:
       Let me check if Jackson can infer everything. I don't think it can - which is why I added these in."
   
   I would be in favor of the more explicit SerDe as well given what's mentioned above (or using a library to generate the classes for us would be my preferred approach but I know that comes with its own set of issues).

##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/CreateNamespaceRequest.java
##########
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import com.fasterxml.jackson.annotation.JsonProperty;

Review comment:
       Let me check if Jackson can infer everything.
   
   I would be in favor of the more explicit SerDe as well given what's mentioned above (or using a library to generate the classes for us would be my preferred approach but I know that comes with its own set of issues).

##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/CreateNamespaceRequest.java
##########
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import com.fasterxml.jackson.annotation.JsonProperty;

Review comment:
       So I realized the issue. We can't validate the input if we just let Jackson infer things.
   
   For example, if a server sends a `CreateNamespaceResponse` of `{ }`, it will not fail on deserialization and we will get `CreateNamespaceResponse(namespace=null, properties=null)`.
   
   The annotations force it to go through the constructor, which is where we throw if the required / not-null field `namespace` isn't found.

##########
File path: core/src/main/java/org/apache/iceberg/rest/requests/UpdateNamespacePropertiesRequest.java
##########
@@ -0,0 +1,161 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.requests;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import org.apache.iceberg.exceptions.ValidationException;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
+
+/**
+ * A REST request to set and/or remove properties on a namespace.
+ * <p>
+ * The request body specifies a list of properties to remove and a map
+ * of key value pairs to update.
+ * <p>
+ * Properties that are not in the request are not modified or removed by this call.
+ * Server implementations are not required to support namespace properties.
+ */
+public class UpdateNamespacePropertiesRequest {
+
+  private List<String> removals;
+  private Map<String, String> updates;
+
+  public UpdateNamespacePropertiesRequest() {
+    // Required for Jackson deserialization.
+  }
+
+  private UpdateNamespacePropertiesRequest(List<String> removals, Map<String, String> updates) {
+    this.removals = removals;
+    this.updates = updates;
+    validate();
+  }
+
+  UpdateNamespacePropertiesRequest validate() {
+    ValidationException.check((this.removals != null && !this.removals.isEmpty()) ||
+            (this.updates != null && !this.updates.isEmpty()),
+        "Cannot create a request to update a namespace's properties without specifying any props to update or remove");
+    return this;
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public List<String> removals() {
+    return removals != null ? ImmutableList.copyOf(removals) : Collections.emptyList();
+  }
+
+  public Map<String, String> updates() {
+    return updates != null ? ImmutableMap.copyOf(updates) : Collections.emptyMap();
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+
+    UpdateNamespacePropertiesRequest that = (UpdateNamespacePropertiesRequest) o;
+    return Objects.equals(removals, that.removals) && Objects.equals(updates, that.updates);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(removals, updates);
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("removals", removals)
+        .add("updates", updates)
+        .toString();
+  }
+
+  public static class Builder {
+    private ImmutableSet.Builder<String> removalsBuilder;
+    private ImmutableMap.Builder<String, String> updatesBuilder;
+
+    private Builder() {
+    }
+
+    public Builder remove(String removal) {
+      ensureRemovalsInitialized();
+      removalsBuilder.add(removal);
+      return this;
+    }
+
+    public Builder removeAll(Iterable<String> removals) {
+      ensureRemovalsInitialized();
+      removalsBuilder.addAll(removals);
+      return this;
+    }
+
+    public Builder update(String key, String value) {
+      ensureUpdatesInitialized();
+      updatesBuilder.put(key, value);
+      return this;
+    }
+
+    public Builder updateAll(Map<String, String> updates) {
+      ensureUpdatesInitialized();
+      updatesBuilder.putAll(updates);
+      return this;
+    }
+
+    private void ensureRemovalsInitialized() {
+      if (removalsBuilder == null) {
+        removalsBuilder = ImmutableSet.builder();
+      }
+    }

Review comment:
       Lazily instantiated so that we serialize null vs empty in a way that will match what is parsed with equals. Accessor methods return immutable copies, so null values are tolerated.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r807433748



##########
File path: core/src/main/java/org/apache/iceberg/catalog/TableIdentifierParser.java
##########
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.catalog;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.JsonNode;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.UncheckedIOException;
+import java.util.List;
+import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.util.JsonUtil;
+
+/**
+ * Parses TableIdentifiers from a JSON representation, which is the JSON
+ * representation utilized in the REST catalog.
+ * <p>
+ * For TableIdentifier.of("dogs", "owners.and.handlers", "food"), we'd have
+ * the following JSON representation, where the dot character of an
+ * individual level is in the namespace is replaced by the null byte character.
+ * <pre>
+ * {
+ *   "namespace": ["dogs", "owners.and.handlers"],
+ *   "name": "food"
+ * }
+ * </pre>
+ */
+public class TableIdentifierParser {
+
+  private static final String NAMESPACE = "namespace";
+  private static final String NAME = "name";
+
+  private TableIdentifierParser() {
+  }
+
+  public static String toJson(TableIdentifier identifier) {
+    return toJson(identifier, false);
+  }
+
+  public static String toJson(TableIdentifier identifier, boolean pretty) {
+    try {
+      StringWriter writer = new StringWriter();
+      JsonGenerator generator = JsonUtil.factory().createGenerator(writer);
+      if (pretty) {
+        generator.useDefaultPrettyPrinter();
+      }
+      toJson(identifier, generator);
+      generator.flush();
+      return writer.toString();
+    } catch (IOException e) {
+      throw new UncheckedIOException(String.format("Failed to write json for: %s", identifier), e);
+    }
+  }
+
+  public static void toJson(TableIdentifier identifier, JsonGenerator generator) throws IOException {

Review comment:
       Okay, should be fine then. Thanks!




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


[GitHub] [iceberg] rdblue commented on a change in pull request #4037: REST Catalog - Initial request / response objects and Jackson-based SerDe module for some components

Posted by GitBox <gi...@apache.org>.
rdblue commented on a change in pull request #4037:
URL: https://github.com/apache/iceberg/pull/4037#discussion_r799090021



##########
File path: core/src/main/java/org/apache/iceberg/rest/responses/ListNamespacesResponse.java
##########
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.rest.responses;
+
+import java.util.Collection;
+import java.util.List;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
+
+public class ListNamespacesResponse {
+  private List<Namespace> namespaces;
+
+  public ListNamespacesResponse() {
+    // Required for Jackson
+  }
+
+  private ListNamespacesResponse(List<Namespace> namespaces) {
+    this.namespaces = namespaces;
+  }
+
+  public List<Namespace> namespaces() {
+    return ImmutableList.copyOf(namespaces);
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("namespaces", namespaces())
+        .toString();
+  }
+
+  public static class Builder {
+    private final ImmutableList.Builder<Namespace> namespaces = ImmutableList.builder();
+
+    private Builder() {
+    }
+
+    public Builder withNamespaces(Collection<Namespace> toAdd) {

Review comment:
       add / addAll?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org