Status: Jot-down
Type: Standards Track
Number: xxxx
Version: 0.0
Last Updated: 2005-12-14
JIG: Standards JIG
Approving Body: —
Supersedes: None
Superseded By: None
Short Name: updt
Schema:
Wiki Page:
Email: campey@informationlogistics.co.za
JID: campey@informationlogistics.co.za
Often in instant-messaging conversations, participants wish to make changes to already transmitted messages. This JEP proposes a mechanism that can be used to transmit requests for updates to previous messages.
There are three types of update identified in this JEP:
This JEP describes mechanisms for handling three types of updates as described below.
Changes the body of a previously transmitted message. Used to correct for typographical and any other type of errors or simply to rephrase. This will relieve conversers of the hassle of trying to decipher a jumble of find & replace notations (e.g. s/foo/bar/, -foo+bar or foo-->bar).
A little less obvious; allows for concatenating to other messages. This can be used to transmit phrases of a long composition, to deliver portions of a message with timing, or to add afterthoughts. Particularly useful for achieveing dramatic effect, either while reading scripts, telling jokes, or simply engaging in witty discourse.
Removes the body of a previous message from the output window. "Oops, wrong window." et al.
All messages sent MUST be identified using the 'id' attribute of the <message/> element.
Update directives are conveyed by adding to subsequent <message/> elements an <x/> child element qualified by the 'jabber:x:update' namespace. This information is added by the originating client based on interactions with the user.
The following attributes MUST be set on the <x/> element:
On receipt of an update message of 'type' "correction", the client MUST replace the body of the target message with that of the update message. The client MAY provide a mechanism for the display of the previous states for a message.
The client SHOULD highlight the message for a short period of time after display and provide any incoming message notifications. The client could potentially check the target body against the update body and only highlight differences for additional clarity.
Subsequent references (by <message/> 'id' attribute) to either the target or correction update message MUST achieve the same result.
On receipt of an update message of 'type' "continuation", the client MUST replace the body of the target message with the concatenation of the target message body and the update message body. The client MAY provide a mechanism for the display of the previous states for a message.
Message Update directives targeted at the components of a composite continuation message MUST only apply to those parts of the message corresponding to the target 'id'. Continuation directives targeted at non-ultimate messages in composite messages should result in insertion of the new <body /> element after the target body.
On receipt of an update message of 'type' "retraction", the client MUST remove the body of the target message from the display. The client MAY provide a mechanism for displaying retracted messages.
The <body/> element of a retraction SHOULD contain a message which will be displayed by clients not supporting Message Updates. e.g. 'Please ignore that last message.' or 'Please ignore message: "$message-body$".'.
Messages SHOULD be displayed in the order of the timestamp of the first <message/> element in a composite message.
If a timestamp is displayed, it SHOULD be that of the most recent <message/> in a composite message.
If messages from a Contact do not have 'id' attributes, it can be assumed that the client does not support Message Update and message updates SHOULD NOT be sent.
[maybe support should be explicitly established using Chat Session Negotiation or ServiceDisco or EntCap]Note: clients that don't support Message Updates will simply ignore the <x/> element and the messages will still be displayed in a sensible fashion.
<message from='juliet@capulet.com/balcony' to='romeo@montague.net' id='0000'> <body>O Romeo</body> </message> Juliet: O Romeo <message from='juliet@capulet.com/balcony' to='romeo@montague.net' id='0001'> <body>, Romeo!</body> <x target='0000' type='continuation'/> </message> Juliet: O Romeo, Romeo! <message from='juliet@capulet.com/balcony' to='romeo@montague.net' id='0002'> <body> wherefore art htou Romeo?</body> <x target='0000' type='continuation'/> </message> Juliet: O Romeo, Romeo! wherefore art htou Romeo? <message from='juliet@capulet.com/balcony' to='romeo@montague.net' id='0003'> <body> wherefore art thou Romeo?</body> <x target='0002' type='correction'/> </message> Juliet: O Romeo, Romeo! wherefore art thou Romeo? <message from='juliet@capulet.com/balcony' to='romeo@montague.net' id='0004'> <body>Deny thy dad, and refuse thy name;</body> </message> Juliet: O Romeo, Romeo! wherefore art thou Romeo? Juliet: Deny thy dad, and refuse thy name; <message from='juliet@capulet.com/balcony' to='romeo@montague.net' id='0005'> <body>Deny thy father, and refuse thy name</body> <x target='0004' type='correction'> Adjustment for meter — (Ed) </x> </message> Juliet: O Romeo, Romeo! wherefore art thou Romeo? Juliet: Deny thy father, and refuse thy name; <message from='juliet@capulet.com/balcony' to='romeo@montague.net' id='0006'> <body>Or if htou wilt not, be but shorn by love</body> </message> Juliet: O Romeo, Romeo! wherefore art thou Romeo? Juliet: Deny thy father, and refuse thy name; Juliet: Or if htou wilt not, be but shorn by love <message from='juliet@capulet.com/balcony' to='romeo@montague.net' id='0007'> <body>, And I'll no longer be a Capulet.</body> <x target='0006' type='continuation'/> </message> Juliet: O Romeo, Romeo! wherefore art thou Romeo? Juliet: Deny thy father, and refuse thy name; Juliet: Or if htou wilt not, be but shorn by love, And I'll no longer be a Capulet. <message from='juliet@capulet.com/balcony' to='romeo@montague.net' id='0008'> <body>Or if thou wilt not, be but sworn by love</body> <x target='0006' type='correction'/> </message> Juliet: O Romeo, Romeo! wherefore art thou Romeo? Juliet: Deny thy father, and refuse thy name; Juliet: Or if thou wilt not, be but sworn by love, And I'll no longer be a Capulet. <message from='romeo@montague.net/orchard' to='juliet@capulet.com' id='rrr1'> <body>Shall I hear more, or shall I spak at this?</body> </message> Juliet: O Romeo, Romeo! wherefore art thou Romeo? Juliet: Deny thy father, and refuse thy name; Juliet: Or if thou wilt not, be but sworn by love, And I'll no longer be a Capulet. Romeo: Shall I hear more, or shall I speak at this? <message from='romeo@montague.net/orchard' to='juliet@capulet.com' id='rrr2'> <body>Please ignore that last message.</body> <x target='rrr1' type='retraction'> Not for your ears, bright angel. </x> </message> Juliet: O Romeo, Romeo! wherefore art thou Romeo? Juliet: Deny thy father, and refuse thy name; Juliet: Or if thou wilt not, be but sworn by love, And I'll no longer be a Capulet.
Rendering a message log would generate a series of strings (one for each message node) of the form: [node.last_change] node.sender node.body, ordered by node.start.
Changes to the message log SHOULD cause incremental changes in the output buffer. This would integrate nicely with a dynamic XHTML-IM DOM implementation using 'id' attributes on elements.
Diagram 1: Messages, Correction Stacks, Message Nodes, and the Message Log
+---MessageLog-----------------------------------------------+ |+---MessageNode-----------+ +---MN----+ +-----------------+ | || +--CS-+ +--CS-+ +--CS-+ | | +--CS-+ | | +--CS-+ +--CS-+ | | || |m0000| |m0001| |m0003| | | |m0005| | | |m0008| |m0007| | | || +-----+ +-----+ |m0002| | | |m0004| | | |m0006| +-----+ | | || +-----+ | | +-----+ | | +-----+ | | |+-------------------------+ +---------+ +-----------------+ | +------------------------------------------------------------+ CS: Correction Stack MN: Message Node mxxxx: Message with 'id' of "xxxx".
The Message Log in Diagram 1 corresponds to Juliet's messages from the Act 2:Scene 2 example used in the previous section.
class Message {
DateTime timestamp;
string id;
string body;
}
class CorrectionStack {
Message[] messages;
DateTime start; DateTime last_change;
string body;
CorrectionStack(Message m) {
start, last_change, body = m.timestamp, m.timestamp, m.body;
add m to messages
}
Contains(string id) {
foreach Message m in messages if (m.id == id) return true;
return false;
}
AddMessage(Message m) {
if (m.timestamp > this.lastchange) {
this.lastchange = m.timestamp; this.body = m.body;
}
add m to messages
}
}
class MessageNode : IComparable {
CorrectionStack[] stacks; // must ensure order of this list is preserved
MessageNode(Message m) {
insert new CorrectionStack(m) into parts;
}
Contains(string id) {
foreach CorrectionStack stack in stacks
if(stacks.Contains(id))
return true;
return false;
}
InsertAfter(string id, Message m) {
locate target_stack that Contains(id)
insert new CorrectionStack(m) into parts after target_stack
}
DateTime start ( get { return parts[0].start; } }
DateTime last_change { get { return max last_change from stacks; } }
string body {
foreach stack in stacks
rstring += stack.body;
return rstring;
}
int CompareTo(object other) { // order by start
return this.start.CompareTo(((MessageNode)other).start);
}
}
A message log 'log' is a set of message nodes.
foreach node in log.Sort() outputstrings.Add(node.last_change.ToString() + node.sender + node.body);
log.GetNodeWhichContains(id).GetStackWhichContains(id).AddMessage(m)
log.GetNodeWhichContains(id).InsertAfter(id, m)
Retraction would be treated as a special case of correction with an empty string as the new message body.
These suggestions relate to UI behaviours that would allow the transmitting user to access message update functionality.
s/htou/thou/ (vi notation) after the <message/> with 'id' of "0002" had been sent would result in an update message like the one in the example with 'id' "0003" being sent.
Note: The client should check if the attempted correction is really a continuation (i.e. the update message body starts with the full target message body) and in such cases transmit as a continuation. This will serve to both improve the experience for users with clients not supporting Message Updates and reduce bandwidth requirements.
Similar mechanism to continuation.