[ 
https://issues.apache.org/jira/browse/BEAM-9331?focusedWorklogId=389357&page=com.atlassian.jira.plugin.system.issuetabpanels:worklog-tabpanel#worklog-389357
 ]

ASF GitHub Bot logged work on BEAM-9331:
----------------------------------------

                Author: ASF GitHub Bot
            Created on: 19/Feb/20 09:07
            Start Date: 19/Feb/20 09:07
    Worklog Time Spent: 10m 
      Work Description: alexvanboxel commented on pull request #10883: 
[BEAM-9331] Add better Row builders
URL: https://github.com/apache/beam/pull/10883#discussion_r381152948
 
 

 ##########
 File path: sdks/java/core/src/main/java/org/apache/beam/sdk/values/Row.java
 ##########
 @@ -539,37 +568,118 @@ public String toString() {
   }
 
   /**
-   * Creates a record builder with specified {@link #getSchema()}. {@link 
Builder#build()} will
-   * throw an {@link IllegalArgumentException} if number of fields in {@link 
#getSchema()} does not
-   * match the number of fields specified.
+   * Creates a row builder with specified {@link #getSchema()}. {@link 
Builder#build()} will throw
+   * an {@link IllegalArgumentException} if number of fields in {@link 
#getSchema()} does not match
+   * the number of fields specified. If any of the arguments don't match the 
expected types for the
+   * schema fields, {@link Builder#build()} will throw a {@link 
ClassCastException}.
    */
   public static Builder withSchema(Schema schema) {
     return new Builder(schema);
   }
 
+  /**
+   * Creates a row builder based on the specified row. Field values in the new 
row can be explicitly
+   * set using {@link ModifyingBuilder#withFieldValue}. Any values not so 
overridden will be the
+   * same as the values in the original row.
+   */
+  public static ModifyingBuilder fromRow(Row row) {
+    return new ModifyingBuilder(row);
+  }
+
+  /** Builder for {@link Row} that bases a row on another row. */
+  public static class ModifyingBuilder {
+    private final Row sourceRow;
+    private final Map<FieldAccessDescriptor, FieldOverride> fieldValues = 
Maps.newHashMap();
+
+    private ModifyingBuilder(Row sourceRow) {
+      this.sourceRow = sourceRow;
+    }
+
+    public Schema getSchema() {
+      return sourceRow.getSchema();
+    }
+
+    public ModifyingBuilder withFieldValue(String fieldName, Object value) {
+      FieldAccessDescriptor fieldAccessDescriptor =
+          FieldAccessDescriptor.withFieldNames(fieldName).resolve(getSchema());
+      checkArgument(fieldAccessDescriptor.referencesSingleField(), "");
+      fieldValues.put(fieldAccessDescriptor, new FieldOverride(value));
+      return this;
+    }
+
+    public ModifyingBuilder withFieldValues(Map<String, Object> values) {
+      fieldValues.putAll(
+          values.entrySet().stream()
+              .collect(
+                  Collectors.toMap(
+                      e -> FieldAccessDescriptor.withFieldNames(e.getKey()),
+                      e -> new FieldOverride(e.getValue()))));
+      return this;
+    }
+
+    public Row build() {
+      Row row =
+          (Row)
+              new RowFieldMatcher()
+                  .match(
+                      new CapturingRowCases(getSchema(), this.fieldValues, 
false),
+                      FieldType.row(getSchema()),
+                      FieldAccessDescriptor.create(),
+                      sourceRow);
+      return row;
+    }
+  }
+
   /** Builder for {@link Row}. */
   public static class Builder {
+    private final Map<FieldAccessDescriptor, FieldOverride> fieldValues = 
Maps.newHashMap();
     private List<Object> values = Lists.newArrayList();
     private boolean attached = false;
     @Nullable private Factory<List<FieldValueGetter>> fieldValueGetterFactory;
     @Nullable private Object getterTarget;
-    private Schema schema;
+    private final Schema schema;
 
     Builder(Schema schema) {
       this.schema = schema;
     }
 
-    public int nextFieldId() {
-      if (fieldValueGetterFactory != null) {
-        throw new RuntimeException("Not supported");
-      }
-      return values.size();
-    }
-
+    /** Return the schema for the row being built. */
     public Schema getSchema() {
       return schema;
     }
 
+    /**
+     * Set a field value using the field name. Nested values can be set using 
the field selection
+     * syntax.
+     */
+    public Builder withFieldValue(String fieldName, Object value) {
 
 Review comment:
   Maybe this one can return the ModifyingBuilder so that no other methods can 
used (no attachValues, no add's).
 
----------------------------------------------------------------
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.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


Issue Time Tracking
-------------------

    Worklog Id:     (was: 389357)

> The Row object needs better builders
> ------------------------------------
>
>                 Key: BEAM-9331
>                 URL: https://issues.apache.org/jira/browse/BEAM-9331
>             Project: Beam
>          Issue Type: Sub-task
>          Components: sdk-java-core
>            Reporter: Reuven Lax
>            Priority: Major
>          Time Spent: 1h
>  Remaining Estimate: 0h
>
> Users should be able to build a Row object by specifying field names. Desired 
> syntax:
>  
> Row.withSchema(schema)
>    .withFieldName("field1", "value)
>   .withFieldName("field2.field3", value)
>   .build()
>  
> Users should also have a builder that allows taking an existing row and 
> changing specific fields.



--
This message was sent by Atlassian Jira
(v8.3.4#803005)

Reply via email to