Skip to content

Commit 43e03d1

Browse files
zimegClaude
andcommitted
refactor(block-kit): share the TableCell cell model across table + data_table
The data_table cells (raw_text / raw_number / rich_text) are the same cell model the table block uses. Rather than ship a parallel DataTableCell family, adopt the shared TableCell interface and its RawTextTableCell / RawNumberTableCell implementations in com.slack.api.model.block.composition, deserialized by a single GsonTableCellFactory: - Remove DataTableCell, RawTextDataTableCell, RawNumberDataTableCell, and GsonDataTableCellFactory. - Add TableCell, RawTextTableCell, RawNumberTableCell (in ...block.composition) and GsonTableCellFactory (in ...util.json). - DataTableBlock.rows is now List<List<TableCell>>; RichTextBlock implements TableCell; the client and model-test GsonFactory register TableCell -> GsonTableCellFactory. This is the same cell model the sibling table-block PR (#1611) introduces, placed in the same package with identical definitions, so whichever of the two lands second drops the now-duplicate files in a trivial merge. Mirrors how node (@slack/types composition objects) and python (slack_sdk basic_components) also share one cell model across both blocks. Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
1 parent 6d8ffce commit 43e03d1

11 files changed

Lines changed: 102 additions & 106 deletions

File tree

‎slack-api-client/src/main/java/com/slack/api/util/json/GsonFactory.java‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
import com.slack.api.model.admin.AppWorkflow;
1111
import com.slack.api.model.block.ContextBlockElement;
1212
import com.slack.api.model.block.ContextActionsBlockElement;
13-
import com.slack.api.model.block.DataTableCell;
1413
import com.slack.api.model.block.LayoutBlock;
14+
import com.slack.api.model.block.composition.TableCell;
1515
import com.slack.api.model.block.composition.TextObject;
1616
import com.slack.api.model.block.element.BlockElement;
1717
import com.slack.api.model.block.element.RichTextElement;
@@ -81,7 +81,7 @@ public static void registerTypeAdapters(GsonBuilder builder, boolean failOnUnkno
8181
.registerTypeAdapter(ContextActionsBlockElement.class, new GsonContextActionsBlockElementFactory(failOnUnknownProps))
8282
.registerTypeAdapter(BlockElement.class, new GsonBlockElementFactory(failOnUnknownProps))
8383
.registerTypeAdapter(RichTextElement.class, new GsonRichTextElementFactory(failOnUnknownProps))
84-
.registerTypeAdapter(DataTableCell.class, new GsonDataTableCellFactory(failOnUnknownProps))
84+
.registerTypeAdapter(TableCell.class, new GsonTableCellFactory(failOnUnknownProps))
8585
.registerTypeAdapter(FunctionExecutedEvent.InputValue.class, new GsonFunctionExecutedEventInputValueFactory())
8686
.registerTypeAdapter(Attachment.VideoHtml.class, new GsonMessageAttachmentVideoHtmlFactory(failOnUnknownProps))
8787
.registerTypeAdapter(MessageChangedEvent.PreviousMessage.class, new GsonMessageChangedEventPreviousMessageFactory(failOnUnknownProps))

‎slack-api-model/src/main/java/com/slack/api/model/block/DataTableBlock.java‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.slack.api.model.block;
22

3+
import com.slack.api.model.block.composition.TableCell;
34
import lombok.AllArgsConstructor;
45
import lombok.Builder;
56
import lombok.Data;
@@ -25,7 +26,7 @@ public class DataTableBlock implements LayoutBlock {
2526
* An array consisting of table rows.
2627
*/
2728
@Builder.Default
28-
private List<List<DataTableCell>> rows = new ArrayList<>();
29+
private List<List<TableCell>> rows = new ArrayList<>();
2930

3031
/**
3132
* A caption for the table; used as the value for the HTML caption element.

‎slack-api-model/src/main/java/com/slack/api/model/block/DataTableCell.java‎

Lines changed: 0 additions & 18 deletions
This file was deleted.

‎slack-api-model/src/main/java/com/slack/api/model/block/RichTextBlock.java‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
@Builder
1717
@NoArgsConstructor
1818
@AllArgsConstructor
19-
public class RichTextBlock implements LayoutBlock, DataTableCell {
19+
public class RichTextBlock implements LayoutBlock, com.slack.api.model.block.composition.TableCell {
2020
public static final String TYPE = "rich_text";
2121
private final String type = TYPE;
2222
@Builder.Default

slack-api-model/src/main/java/com/slack/api/model/block/RawNumberDataTableCell.java renamed to slack-api-model/src/main/java/com/slack/api/model/block/composition/RawNumberTableCell.java

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,24 @@
1-
package com.slack.api.model.block;
1+
package com.slack.api.model.block.composition;
22

33
import lombok.AllArgsConstructor;
44
import lombok.Builder;
55
import lombok.Data;
66
import lombok.NoArgsConstructor;
77

88
/**
9-
* A {@code raw_number} cell within a {@link DataTableBlock}: an object containing a numeric value.
9+
* A {@code raw_number} table cell, holding a numeric value. The optional {@code text}
10+
* field carries the display representation of the value (for example a formatted string).
1011
*
12+
* @see <a href="https://docs.slack.dev/reference/block-kit/blocks/table-block">Table block</a>
1113
* @see <a href="https://docs.slack.dev/reference/block-kit/blocks/data-table-block">Data table block</a>
1214
*/
1315
@Data
1416
@Builder
1517
@NoArgsConstructor
1618
@AllArgsConstructor
17-
public class RawNumberDataTableCell implements DataTableCell {
19+
public class RawNumberTableCell implements TableCell {
1820
public static final String TYPE = "raw_number";
1921
private final String type = TYPE;
20-
21-
/**
22-
* The numeric value.
23-
*/
2422
private Double value;
25-
26-
/**
27-
* The text used to display the value. The minimum length is 1 character.
28-
*/
2923
private String text;
3024
}

slack-api-model/src/main/java/com/slack/api/model/block/RawTextDataTableCell.java renamed to slack-api-model/src/main/java/com/slack/api/model/block/composition/RawTextTableCell.java

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,22 @@
1-
package com.slack.api.model.block;
1+
package com.slack.api.model.block.composition;
22

33
import lombok.AllArgsConstructor;
44
import lombok.Builder;
55
import lombok.Data;
66
import lombok.NoArgsConstructor;
77

88
/**
9-
* A {@code raw_text} cell within a {@link DataTableBlock}: an object containing some text.
9+
* A {@code raw_text} table cell, holding unformatted plain text.
1010
*
11+
* @see <a href="https://docs.slack.dev/reference/block-kit/blocks/table-block">Table block</a>
1112
* @see <a href="https://docs.slack.dev/reference/block-kit/blocks/data-table-block">Data table block</a>
1213
*/
1314
@Data
1415
@Builder
1516
@NoArgsConstructor
1617
@AllArgsConstructor
17-
public class RawTextDataTableCell implements DataTableCell {
18+
public class RawTextTableCell implements TableCell {
1819
public static final String TYPE = "raw_text";
1920
private final String type = TYPE;
20-
21-
/**
22-
* The text for the block. The minimum length is 1 character.
23-
*/
2421
private String text;
2522
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.slack.api.model.block.composition;
2+
3+
/**
4+
* A single cell within a table or data table row. A cell can be one of:
5+
*
6+
* <ul>
7+
* <li>{@link RawTextTableCell} ({@code raw_text})</li>
8+
* <li>{@link RawNumberTableCell} ({@code raw_number})</li>
9+
* <li>{@link com.slack.api.model.block.RichTextBlock RichTextBlock} ({@code rich_text})</li>
10+
* </ul>
11+
*
12+
* @see <a href="https://docs.slack.dev/reference/block-kit/blocks/table-block">Table block</a>
13+
* @see <a href="https://docs.slack.dev/reference/block-kit/blocks/data-table-block">Data table block</a>
14+
*/
15+
public interface TableCell {
16+
17+
String getType();
18+
19+
}

‎slack-api-model/src/main/java/com/slack/api/util/json/GsonDataTableCellFactory.java‎

Lines changed: 0 additions & 56 deletions
This file was deleted.
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package com.slack.api.util.json;
2+
3+
import com.google.gson.*;
4+
import com.slack.api.model.block.RichTextBlock;
5+
import com.slack.api.model.block.composition.RawNumberTableCell;
6+
import com.slack.api.model.block.composition.RawTextTableCell;
7+
import com.slack.api.model.block.composition.TableCell;
8+
9+
import java.lang.reflect.Type;
10+
11+
/**
12+
* Factory for deserializing the cells of a
13+
* {@link com.slack.api.model.block.DataTableBlock data table block}.
14+
*
15+
* @see <a href="https://docs.slack.dev/reference/block-kit/blocks/data-table-block">Data table block</a>
16+
*/
17+
public class GsonTableCellFactory implements JsonDeserializer<TableCell>, JsonSerializer<TableCell> {
18+
19+
private final boolean failOnUnknownProperties;
20+
21+
public GsonTableCellFactory() {
22+
this(false);
23+
}
24+
25+
public GsonTableCellFactory(boolean failOnUnknownProperties) {
26+
this.failOnUnknownProperties = failOnUnknownProperties;
27+
}
28+
29+
@Override
30+
public TableCell deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
31+
throws JsonParseException {
32+
final JsonObject jsonObject = json.getAsJsonObject();
33+
final JsonPrimitive prim = (JsonPrimitive) jsonObject.get("type");
34+
final String typeName = prim.getAsString();
35+
final Class<? extends TableCell> clazz = getTableCellClassInstance(typeName);
36+
return context.deserialize(jsonObject, clazz);
37+
}
38+
39+
@Override
40+
public JsonElement serialize(TableCell src, Type typeOfSrc, JsonSerializationContext context) {
41+
return context.serialize(src);
42+
}
43+
44+
private Class<? extends TableCell> getTableCellClassInstance(String typeName) {
45+
switch (typeName) {
46+
case RawTextTableCell.TYPE:
47+
return RawTextTableCell.class;
48+
case RawNumberTableCell.TYPE:
49+
return RawNumberTableCell.class;
50+
case RichTextBlock.TYPE:
51+
return RichTextBlock.class;
52+
default:
53+
throw new JsonParseException("Unknown table cell type: " + typeName);
54+
}
55+
}
56+
}

‎slack-api-model/src/test/java/test_locally/api/model/block/BlockKitTest.java‎

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
import com.slack.api.model.Message;
66
import com.slack.api.model.block.*;
77
import com.slack.api.model.block.composition.ConfirmationDialogObject;
8+
import com.slack.api.model.block.composition.RawNumberTableCell;
9+
import com.slack.api.model.block.composition.RawTextTableCell;
10+
import com.slack.api.model.block.composition.TableCell;
811
import com.slack.api.model.block.element.*;
912
import com.slack.api.model.view.View;
1013
import org.junit.Test;
@@ -1786,15 +1789,15 @@ public void parseDataTableBlock() {
17861789
assertThat(block.getRowHeaderColumnIndex(), is(0));
17871790
assertThat(block.getRows().size(), is(2));
17881791

1789-
RawTextDataTableCell header = (RawTextDataTableCell) block.getRows().get(0).get(0);
1792+
RawTextTableCell header = (RawTextTableCell) block.getRows().get(0).get(0);
17901793
assertThat(header.getType(), is("raw_text"));
17911794
assertThat(header.getText(), is("Team"));
17921795

1793-
DataTableCell richCell = block.getRows().get(1).get(0);
1796+
TableCell richCell = block.getRows().get(1).get(0);
17941797
assertTrue(richCell instanceof RichTextBlock);
17951798
assertThat(richCell.getType(), is("rich_text"));
17961799

1797-
RawNumberDataTableCell numberCell = (RawNumberDataTableCell) block.getRows().get(1).get(1);
1800+
RawNumberTableCell numberCell = (RawNumberTableCell) block.getRows().get(1).get(1);
17981801
assertThat(numberCell.getType(), is("raw_number"));
17991802
assertThat(numberCell.getValue(), is(1234.5));
18001803
assertThat(numberCell.getText(), is("$1,234.50"));
@@ -1809,12 +1812,12 @@ public void buildDataTableBlock() {
18091812
.rowHeaderColumnIndex(0)
18101813
.rows(Arrays.asList(
18111814
Arrays.asList(
1812-
RawTextDataTableCell.builder().text("Team").build(),
1813-
RawTextDataTableCell.builder().text("Revenue").build()
1815+
RawTextTableCell.builder().text("Team").build(),
1816+
RawTextTableCell.builder().text("Revenue").build()
18141817
),
18151818
Arrays.asList(
1816-
RawTextDataTableCell.builder().text("Platform").build(),
1817-
RawNumberDataTableCell.builder().value(1234.5).text("$1,234.50").build()
1819+
RawTextTableCell.builder().text("Platform").build(),
1820+
RawNumberTableCell.builder().value(1234.5).text("$1,234.50").build()
18181821
)
18191822
)));
18201823
assertThat(block, is(notNullValue()));
@@ -1826,7 +1829,7 @@ public void buildDataTableBlock() {
18261829
assertThat(restored.getCaption(), is("Quarterly results"));
18271830
assertThat(restored.getPageSize(), is(10));
18281831
assertThat(restored.getRows().size(), is(2));
1829-
RawNumberDataTableCell numberCell = (RawNumberDataTableCell) restored.getRows().get(1).get(1);
1832+
RawNumberTableCell numberCell = (RawNumberTableCell) restored.getRows().get(1).get(1);
18301833
assertThat(numberCell.getValue(), is(1234.5));
18311834
}
18321835

0 commit comments

Comments
 (0)