class TableMetadata implements Serializable {

  public TableMetadata updateSortOrder(SortOrder newOrder) {
    SortOrder.checkCompatibility(newOrder, schema);

    // determine the next order id
    int newOrderId = INITIAL_SORT_ORDER_ID;
    for (SortOrder order : sortOrders) {
      if (order.sameOrder(newOrder)) {
        newOrderId = order.orderId();
        break;
      } else if (newOrderId <= order.orderId()) {
        newOrderId = order.orderId() + 1;
      }
    }

    if (newOrderId == defaultSortOrderId) {
      return this;
    }

    ImmutableList.Builder<SortOrder> builder = ImmutableList.builder();
    builder.addAll(sortOrders);

    if (!sortOrdersById.containsKey(newOrderId)) {
      if (newOrder.isUnsorted()) {
        newOrderId = SortOrder.unsorted().orderId();
        builder.add(SortOrder.unsorted());
      } else {
        // rebuild the sort order using new column ids
        builder.add(freshSortOrder(newOrderId, schema, newOrder));
      }
    }

    return new TableMetadata(null, formatVersion, uuid, location,
        lastSequenceNumber, System.currentTimeMillis(), lastColumnId, schema, defaultSpecId, specs,
        newOrderId, builder.build(), properties, currentSnapshotId, snapshots, snapshotLog,
        addPreviousFile(file, lastUpdatedMillis));
  }

  @SuppressWarnings("checkstyle:CyclomaticComplexity")  TableMetadata(InputFile file,
                int formatVersion,
                String uuid,
                String location,
                long lastSequenceNumber,
                long lastUpdatedMillis,
                int lastColumnId,
                Schema schema,
                int defaultSpecId,
                List<PartitionSpec> specs,
                int defaultSortOrderId,
                List<SortOrder> sortOrders,
                Map<String, String> properties,
                long currentSnapshotId,
                List<Snapshot> snapshots,
                List<HistoryEntry> snapshotLog,
                List<MetadataLogEntry> previousFiles);

}