1010import io .ably .lib .types .AsyncPaginatedResult ;
1111import io .ably .lib .types .Callback ;
1212import io .ably .lib .types .ChannelOptions ;
13+ import io .ably .lib .types .ErrorInfo ;
1314import io .ably .lib .types .Message ;
15+ import io .ably .lib .types .MessageAction ;
16+ import io .ably .lib .types .MessageDecodeException ;
1417import io .ably .lib .types .MessageSerializer ;
1518import io .ably .lib .types .PaginatedResult ;
1619import io .ably .lib .types .Param ;
1720import io .ably .lib .types .PresenceMessage ;
1821import io .ably .lib .types .PresenceSerializer ;
1922import io .ably .lib .util .Crypto ;
23+ import io .ably .lib .util .Serialisation ;
2024
2125/**
2226 * A class representing a Channel in the Ably REST API.
@@ -45,13 +49,15 @@ public class ChannelBase {
4549 public final RestAnnotations annotations ;
4650
4751
52+ private final MessageEditsMixin messageEditsMixin ;
53+
54+
4855 /**
4956 * Publish a message on this channel using the REST API.
5057 * Since the REST API is stateless, this request is made independently
5158 * of any other request on this or any other channel.
5259 * @param name the event name
53- * @param data the message payload; see {@link io.ably.types.Data} for
54- * details of supported data types.
60+ * @param data the message payload;
5561 * @throws AblyException
5662 */
5763 public void publish (String name , Object data ) throws AblyException {
@@ -68,7 +74,7 @@ void publish(Http http, String name, Object data) throws AblyException {
6874 * of any other request on this or any other channel.
6975 *
7076 * @param name the event name
71- * @param data the message payload; see {@link io.ably.types.Data} for
77+ * @param data the message payload;
7278 * @param listener a listener to be notified of the outcome of this message.
7379 * <p>
7480 * This listener is invoked on a background thread.
@@ -311,6 +317,117 @@ private BasePaginatedQuery.ResultRequest<PresenceMessage> historyImpl(Http http,
311317
312318 }
313319
320+ /**
321+ * Retrieves the latest version of a specific message by its serial identifier.
322+ * <p>
323+ * This method allows you to fetch the current state of a message, including any updates
324+ * or deletions that have been applied since its creation.
325+ *
326+ * @param serial The unique serial identifier of the message to retrieve.
327+ * @return A {@link Message} object representing the latest version of the message.
328+ * @throws AblyException If the message cannot be retrieved or does not exist.
329+ */
330+ public Message getMessage (String serial ) throws AblyException {
331+ return messageEditsMixin .getMessage (ably .http , serial );
332+ }
333+
334+ /**
335+ * Asynchronously retrieves the latest version of a specific message by its serial identifier.
336+ *
337+ * @param serial The unique serial identifier of the message to retrieve.
338+ * @param callback A callback to handle the result asynchronously.
339+ * <p>
340+ * This callback is invoked on a background thread.
341+ */
342+ public void getMessageAsync (String serial , Callback <Message > callback ) {
343+ messageEditsMixin .getMessageAsync (ably .http , serial , callback );
344+ }
345+
346+ /**
347+ * Updates an existing message by its serial identifier using patch semantics.
348+ * <p>
349+ * Non-null fields in the provided message (name, data, extras) will replace the corresponding
350+ * fields in the existing message, while null fields will be left unchanged.
351+ *
352+ * @param serial The unique serial identifier of the message to update.
353+ * @param message A {@link Message} object containing the fields to update.
354+ * Only non-null fields will be applied to the existing message.
355+ * @throws AblyException If the update operation fails.
356+ */
357+ public void updateMessage (String serial , Message message ) throws AblyException {
358+ messageEditsMixin .updateMessage (ably .http , serial , message );
359+ }
360+
361+ /**
362+ * Asynchronously updates an existing message by its serial identifier.
363+ *
364+ * @param serial The unique serial identifier of the message to update.
365+ * @param message A {@link Message} object containing the fields to update.
366+ * @param listener A listener to be notified of the outcome of this operation.
367+ * <p>
368+ * This listener is invoked on a background thread.
369+ */
370+ public void updateMessageAsync (String serial , Message message , CompletionListener listener ) {
371+ messageEditsMixin .updateMessageAsync (ably .http , serial , message , listener );
372+ }
373+
374+ /**
375+ * Marks a message as deleted by its serial identifier.
376+ * <p>
377+ * This operation does not remove the message from history; it marks it as deleted
378+ * while preserving the full message history. The deleted message can still be
379+ * retrieved and will have its action set to MESSAGE_DELETE.
380+ *
381+ * @param serial The unique serial identifier of the message to delete.
382+ * @param message A {@link Message} object that may contain operation metadata such as
383+ * clientId, description, or metadata in the version field.
384+ * @throws AblyException If the delete operation fails.
385+ */
386+ public void deleteMessage (String serial , Message message ) throws AblyException {
387+ messageEditsMixin .deleteMessage (ably .http , serial , message );
388+ }
389+
390+ /**
391+ * Asynchronously marks a message as deleted by its serial identifier.
392+ *
393+ * @param serial The unique serial identifier of the message to delete.
394+ * @param message A {@link Message} object for operation metadata.
395+ * @param listener A listener to be notified of the outcome of this operation.
396+ * <p>
397+ * This listener is invoked on a background thread.
398+ */
399+ public void deleteMessageAsync (String serial , Message message , CompletionListener listener ) {
400+ messageEditsMixin .deleteMessageAsync (ably .http , serial , message , listener );
401+ }
402+
403+ /**
404+ * Retrieves all historical versions of a specific message.
405+ * <p>
406+ * This method returns a paginated result containing all versions of the message,
407+ * ordered chronologically. Each version includes metadata about when and by whom
408+ * the message was modified.
409+ *
410+ * @param serial The unique serial identifier of the message.
411+ * @param params Query parameters for filtering or pagination (e.g., limit, start, end).
412+ * @return A {@link PaginatedResult} containing an array of {@link Message} objects
413+ * representing all versions of the message.
414+ * @throws AblyException If the versions cannot be retrieved.
415+ */
416+ public PaginatedResult <Message > getMessageVersions (String serial , Param [] params ) throws AblyException {
417+ return messageEditsMixin .getMessageVersions (ably .http , serial , params );
418+ }
419+
420+ /**
421+ * Asynchronously retrieves all historical versions of a specific message.
422+ *
423+ * @param serial The unique serial identifier of the message.
424+ * @param params Query parameters for filtering or pagination.
425+ * @param callback A callback to handle the result asynchronously.
426+ */
427+ public void getMessageVersionsAsync (String serial , Param [] params , Callback <AsyncPaginatedResult <Message >> callback ) throws AblyException {
428+ messageEditsMixin .getMessageVersionsAsync (ably .http , serial , params , callback );
429+ }
430+
314431 /******************
315432 * internal
316433 * @throws AblyException
@@ -323,6 +440,7 @@ private BasePaginatedQuery.ResultRequest<PresenceMessage> historyImpl(Http http,
323440 this .basePath = "/channels/" + HttpUtils .encodeURIComponent (name );
324441 this .presence = new Presence ();
325442 this .annotations = new RestAnnotations (name , ably .http , ably .options , options );
443+ this .messageEditsMixin = new MessageEditsMixin (basePath , ably .options , options , ably .auth );
326444 }
327445
328446 private final AblyBase ably ;
0 commit comments