Adds advanced msg history service, to allow plugins to insert messages into the history, and tests for the implementation.

cefexperiments
Damian Minkov 12 years ago
parent 12d551f7a1
commit d47cbb28e3

@ -145,54 +145,8 @@ private void addRecord(String[] propertyNames,
removeFirstRecord(root);
}
Element elem = this.currentDoc.createElement("record");
SimpleDateFormat sdf
= new SimpleDateFormat(DATE_FORMAT);
elem.setAttribute("timestamp", sdf.format(date));
for (int i = 0; i < propertyNames.length; i++)
{
String propertyName = propertyNames[i];
if(propertyName.endsWith(CDATA_SUFFIX))
{
if (propertyValues[i] != null)
{
propertyName =
propertyName.replaceFirst(CDATA_SUFFIX, "");
Element propertyElement = this.currentDoc
.createElement(propertyName);
Text value = this.currentDoc
.createCDATASection(
XmlEscapers.xmlContentEscaper().escape(
propertyValues[i].replaceAll("\0", " ")
));
propertyElement.appendChild(value);
elem.appendChild(propertyElement);
}
}
else
{
if (propertyValues[i] != null)
{
Element propertyElement = this.currentDoc
.createElement(propertyName);
Text value = this.currentDoc
.createTextNode(
XmlEscapers.xmlContentEscaper().escape(
propertyValues[i].replaceAll("\0", " ")
));
propertyElement.appendChild(value);
elem.appendChild(propertyElement);
}
}
}
Element elem = createRecord(
this.currentDoc, propertyNames, propertyValues, date);
root.appendChild(elem);
this.currentDocElements++;
}
@ -208,6 +162,66 @@ private void addRecord(String[] propertyNames,
}
}
/**
* Creates an element.
* @param doc the parent of the element.
* @param propertyNames property names for the element
* @param propertyValues values for the properties
* @param date the of creation of the record
* @return the newly created element.
*/
private Element createRecord(Document doc,
String[] propertyNames,
String[] propertyValues,
Date date)
{
Element elem = doc.createElement("record");
SimpleDateFormat sdf
= new SimpleDateFormat(DATE_FORMAT);
elem.setAttribute("timestamp", sdf.format(date));
for (int i = 0; i < propertyNames.length; i++)
{
String propertyName = propertyNames[i];
if(propertyName.endsWith(CDATA_SUFFIX))
{
if (propertyValues[i] != null)
{
propertyName =
propertyName.replaceFirst(CDATA_SUFFIX, "");
Element propertyElement = doc.createElement(propertyName);
Text value = doc.createCDATASection(
XmlEscapers.xmlContentEscaper().escape(
propertyValues[i].replaceAll("\0", " ")
));
propertyElement.appendChild(value);
elem.appendChild(propertyElement);
}
}
else
{
if (propertyValues[i] != null)
{
Element propertyElement = doc.createElement(propertyName);
Text value = doc.createTextNode(
XmlEscapers.xmlContentEscaper().escape(
propertyValues[i].replaceAll("\0", " ")
));
propertyElement.appendChild(value);
elem.appendChild(propertyElement);
}
}
}
return elem;
}
/**
* Finds the oldest node by timestamp in current root and deletes it.
* @param root where to search for records
@ -252,6 +266,99 @@ private void removeFirstRecord(Node root)
root.removeChild(oldestNode);
}
/**
* Stores the passed propertyValues complying with the
* historyRecordStructure.
*
* @param propertyValues
* The values of the record.
* @param timestamp
* The timestamp of the record.
*
* @throws IOException
*/
public void insertRecord(
String[] propertyValues, Date timestamp, String timestampProperty)
throws IOException
{
SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
Iterator<String> fileIterator
= HistoryReaderImpl.filterFilesByDate(
this.historyImpl.getFileList(), timestamp, null)
.iterator();
String filename = null;
while (fileIterator.hasNext())
{
filename = fileIterator.next();
Document doc = this.historyImpl.getDocumentForFile(filename);
if(doc == null)
continue;
NodeList nodes = doc.getElementsByTagName("record");
boolean changed = false;
Node node;
for (int i = 0; i < nodes.getLength(); i++)
{
node = nodes.item(i);
Element idNode = XMLUtils.findChild(
(Element)node, timestampProperty);
if(idNode == null)
continue;
Node nestedNode = idNode.getFirstChild();
if(nestedNode == null)
continue;
// Get nested TEXT node's value
String nodeValue = nestedNode.getNodeValue();
Date nodeTimeStamp;
try
{
nodeTimeStamp = sdf.parse(nodeValue);
}
catch (ParseException e)
{
nodeTimeStamp = new Date(Long.parseLong(nodeValue));
}
if(nodeTimeStamp.before(timestamp))
continue;
Element newElem = createRecord(
doc, structPropertyNames, propertyValues, timestamp);
doc.getFirstChild().insertBefore(newElem, node);
changed = true;
break;
}
if(changed)
{
// write changes
synchronized (this.docWriteLock)
{
this.historyImpl.writeFile(filename, doc);
}
// this prevents that the current writer, which holds
// instance for the last document he is editing will not
// override our last changes to the document
if(filename.equals(this.currentFile))
{
this.currentDoc = doc;
}
break;
}
}
}
/**
* If no file is currently loaded loads the last opened file. If it does not

@ -43,6 +43,7 @@
*/
public class MessageHistoryServiceImpl
implements MessageHistoryService,
MessageHistoryAdvancedService,
MessageListener,
ChatRoomMessageListener,
AdHocChatRoomMessageListener,
@ -1485,6 +1486,58 @@ private void writeMessage(History history, String direction,
}
}
/**
* Inserts message to the history. Allows to update the laready saved
* history.
* @param direction String direction of the message in or out.
* @param source The source Contact
* @param destination The destination Contact
* @param message Message message to be written
* @param messageTimestamp Date this is the timestamp when was message
* received that came from the protocol provider
* @param isSmsSubtype whether message to write is an sms
*/
public void insertMessage(
String direction,
Contact source,
Contact destination,
Message message,
Date messageTimestamp,
boolean isSmsSubtype)
{
try
{
MetaContact metaContact = MessageHistoryActivator
.getContactListService().findMetaContactByContact(destination);
if(metaContact != null
&& !isHistoryLoggingEnabled(
metaContact.getMetaUID()))
{
// logging is switched off for this particular contact
return;
}
History history = this.getHistory(source, destination);
HistoryWriter historyWriter = history.getWriter();
SimpleDateFormat sdf
= new SimpleDateFormat(HistoryService.DATE_FORMAT);
historyWriter.insertRecord(new String[]{direction,
message.getContent(), message.getContentType(),
message.getEncoding(), message.getMessageUID(),
message.getSubject(), sdf.format(messageTimestamp),
isSmsSubtype ? MSG_SUBTYPE_SMS : null},
messageTimestamp,
STRUCTURE_NAMES[6]);
// this date is when the history record to be written
// as we are inserting
} catch (IOException e)
{
logger.error("Could not add message to history", e);
}
}
// //////////////////////////////////////////////////////////////////////////
/**

@ -69,6 +69,21 @@ public void addRecord(String[] propertyValues,
public void addRecord(String[] propertyValues, Date timestamp)
throws IOException;
/**
* Stores the passed propertyValues complying with the
* historyRecordStructure.
*
* @param propertyValues
* The values of the record.
* @param timestamp
* The timestamp of the record.
*
* @throws IOException
*/
public void insertRecord(
String[] propertyValues, Date timestamp, String timestampProperty)
throws IOException;
/**
* Updates a record by searching for record with idProperty which have idValue
* and updating/creating the property with newValue.

@ -0,0 +1,39 @@
/*
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.service.msghistory;
import net.java.sip.communicator.service.protocol.*;
import java.util.*;
/**
* Adds advanced operation to the message service like inserting/editing
* messages. Can be used to insert messages when synchronizing history with
* external source.
* @author Damian Minkov
*/
public interface MessageHistoryAdvancedService
{
/**
* Inserts message to the history. Allows to update the already saved
* history.
* @param direction String direction of the message in or out.
* @param source The source Contact
* @param destination The destination Contact
* @param message Message message to be written
* @param messageTimestamp Date this is the timestamp when was message
* received that came from the protocol provider
* @param isSmsSubtype whether message to write is an sms
*/
public void insertMessage(
String direction,
Contact source,
Contact destination,
Message message,
Date messageTimestamp,
boolean isSmsSubtype);
}

@ -93,6 +93,8 @@ public static Test suite()
new TestMsgHistoryService("readRecords"));
suite.addTest(
new TestMsgHistoryService("specialChars"));
suite.addTest(
new TestMsgHistoryService("insertRecords"));
suite.addTest(
new TestMsgHistoryService("writeRecordsToMultiChat"));
suite.addTest(
@ -436,6 +438,26 @@ public void specialChars()
msgs.contains(messagesToSend[6].getContent()));
}
/**
* Inserts a message between the control dates and queries to check
* of the expected number of messages.
*/
public void insertRecords()
{
if(!(msgHistoryService instanceof MessageHistoryAdvancedService))
return;
((MessageHistoryAdvancedService)msgHistoryService).insertMessage(
"out", null, testContact, messagesToSend[1],
new Date(controlDate1.getTime() + 50), false);
Collection<EventObject> rs
= msgHistoryService.findByPeriod(
testMetaContact, controlDate1, controlDate2);
List<String> msgs = getMessages(rs);
assertEquals("Messages must be 3", 3, msgs.size());
}
private static void waitWrite(long timeout)
{
synchronized (lock)

Loading…
Cancel
Save