Adds searching for existing histories and finding recent contacted contacts. Adds tests for parsing ids(folder names) into history IDs.

ice4sip 5106
Damian Minkov 12 years ago
parent 05d5d88104
commit 5377958981

@ -92,7 +92,7 @@ public HistoryServiceImpl(BundleContext bundleContext)
public Iterator<HistoryID> getExistingIDs()
{
List<File> vect = new Vector<File>();
File histDir = null;
File histDir;
try {
String userSetDataDirectory
= System.getProperty("HistoryServiceDirectory");
@ -160,9 +160,12 @@ public History getHistory(HistoryID id)
return retVal;
}
public History createHistory(HistoryID id,
HistoryRecordStructure recordStructure)
throws IllegalArgumentException, IOException {
public History createHistory(
HistoryID id,
HistoryRecordStructure recordStructure)
throws IllegalArgumentException,
IOException
{
History retVal = null;
synchronized (this.histories)
@ -509,4 +512,97 @@ public boolean isHistoryCreated(HistoryID id)
{
return getDirForHistory(id).exists();
}
/**
* Enumerates existing histories.
* @param rawid the start of the HistoryID of all the histories that will be
* returned.
* @return list of histories which HistoryID starts with <tt>rawid</tt>.
* @throws IllegalArgumentException if the <tt>rawid</tt> contains ids
* which are missing in current history.
*/
public List<HistoryID> getExistingHistories(
String[] rawid)
throws IllegalArgumentException
{
File histDir = null;
try
{
histDir = getFileAccessService()
.getPrivatePersistentDirectory(
DATA_DIRECTORY, FileCategory.PROFILE);
}
catch (Exception e)
{
logger.error("Error opening directory", e);
}
if(histDir == null || !histDir.exists())
return new ArrayList<HistoryID>();
StringBuilder folderPath = new StringBuilder();
for(String id : rawid)
folderPath.append(id).append(File.separator);
File srcFolder = new File(histDir, folderPath.toString());
if(!srcFolder.exists())
return new ArrayList<HistoryID>();
TreeMap<File, HistoryID> recentFiles =
new TreeMap<File, HistoryID>(new Comparator<File>()
{
@Override
public int compare(File o1, File o2)
{
return o1.getName().compareTo(o2.getName());
}
});
getExistingFiles(srcFolder, Arrays.asList(rawid), recentFiles);
// return non duplicate
List<HistoryID> result = new ArrayList<HistoryID>();
for(Map.Entry<File, HistoryID> entry : recentFiles.entrySet())
{
HistoryID hid = entry.getValue();
if(result.contains(hid))
continue;
result.add(hid);
}
return result;
}
/**
* Get existing files in <tt>res</tt> and their corresponding historyIDs.
* @param sourceFolder the folder to search into.
* @param rawID the rawID.
* @param res the result map.
*/
private void getExistingFiles(
File sourceFolder, List<String> rawID,
Map<File, HistoryID> res)
{
for(File f : sourceFolder.listFiles())
{
if(f.isDirectory())
{
List<String> newRawID = new ArrayList<String>(rawID);
newRawID.add(f.getName());
getExistingFiles(f, newRawID, res);
}
else
{
if(f.getName().equals(DATA_FILE))
continue;
res.put(f, HistoryID.createFromRawStrings(
rawID.toArray(new String[rawID.size()])));
}
}
}
}

@ -25,6 +25,7 @@
import net.java.sip.communicator.service.protocol.event.*;
import net.java.sip.communicator.util.*;
import net.java.sip.communicator.util.account.*;
import org.jitsi.service.configuration.*;
import org.jitsi.service.resources.*;
import org.osgi.framework.*;
@ -318,8 +319,7 @@ public Collection<EventObject> findLast(MetaContact contact, int count)
while (recs.hasNext())
{
result.add(
convertHistoryRecordToMessageEvent(recs.next(),
item));
convertHistoryRecordToMessageEvent(recs.next(), item));
}
} catch (IOException e)
@ -338,6 +338,114 @@ public Collection<EventObject> findLast(MetaContact contact, int count)
return resultAsList.subList(startIndex, resultAsList.size());
}
/**
* Returns the messages for the recently contacted <tt>count</tt> contacts.
*
* @param count contacts count
* @return Collection of MessageReceivedEvents or MessageDeliveredEvents
* @throws RuntimeException
*/
Collection<EventObject> findRecentMessagesPerContact(int count)
throws RuntimeException
{
TreeSet<EventObject> result
= new TreeSet<EventObject>(
new MessageEventComparator<EventObject>());
List<HistoryID> historyIDs=
this.historyService.getExistingHistories(
new String[]{"messages", "default"});
for(HistoryID id : historyIDs)
{
if(result.size() >= count)
break;
try
{
// find contact for historyID
Contact contact = getContactForHistory(id);
// skip not found contacts, disabled accounts and hidden one
if(contact == null)
continue;
History history;
if (this.historyService.isHistoryExisting(id))
{
history = this.historyService.getHistory(id);
}
else
{
history = this.historyService.createHistory(id,
recordStructure);
}
HistoryReader reader = history.getReader();
Iterator<HistoryRecord> recs = reader.findLast(1);
while (recs.hasNext())
{
result.add(convertHistoryRecordToMessageEvent(
recs.next(), contact));
break;
}
}
catch(IOException ex)
{
logger.error("Could not read history", ex);
}
}
return result;
}
/**
* Founds the contact corresponding this HistoryID. Checks the account and
* then searches for the contact.
* Will skip hidden and disabled accounts.
*
* @param id the history id.
* @return
*/
private Contact getContactForHistory(HistoryID id)
{
// this history id is: "messages", localId, account, remoteId
if(id.getID().length != 4)
return null;
String accountID = id.getID()[2].replace('_', ':');
AccountID account = null;
for(AccountID acc : AccountUtils.getStoredAccounts())
{
if( !acc.isHidden()
&& acc.isEnabled()
&& accountID.startsWith(acc.getAccountUniqueID()))
{
account = acc;
break;
}
}
if(account == null)
return null;
ProtocolProviderService pps =
AccountUtils.getRegisteredProviderForAccount(account);
if(pps == null)
return null;
OperationSetPersistentPresence opSetPresence =
pps.getOperationSet(OperationSetPersistentPresence.class);
if(opSetPresence == null)
return null;
return opSetPresence.findContactByID(id.getID()[3]);
}
/**
* Returns the supplied number of recent messages after the given date
* exchanged by all the contacts in the supplied metacontact

@ -12,8 +12,10 @@ Import-Package: org.osgi.framework,
net.java.sip.communicator.service.history.event,
net.java.sip.communicator.service.msghistory,
net.java.sip.communicator.service.contactlist,
net.java.sip.communicator.service.contactsource,
net.java.sip.communicator.service.history.records,
net.java.sip.communicator.util,
net.java.sip.communicator.util.account,
net.java.sip.communicator.service.protocol,
net.java.sip.communicator.service.protocol.icqconstants,
net.java.sip.communicator.service.protocol.event

@ -55,6 +55,21 @@ public static HistoryID createFromRawID(String[] rawid)
return new HistoryID(id);
}
/**
* Create a HistoryID from a raw Strings. You can pass any kind of strings
* and they will be checked and converted to valid IDs.
*/
public static HistoryID createFromRawStrings(String[] rawStrings)
{
String[] id = new String[rawStrings.length];
for (int i = 0; i < rawStrings.length; i++)
{
id[i] = HistoryID.decodeReadableHash(rawStrings[i]);
}
return new HistoryID(id);
}
/**
* Create a HistoryID from a valid ID. You should pass only valid IDs (ones
* produced from readableHash).
@ -167,6 +182,32 @@ public static String readableHash(String rawString)
return encodedString.toString();
}
/**
* Decodes readable hash.
*
* @param rawString The string to be checked.
* @return The human-readable hash.
*/
public static String decodeReadableHash(String rawString)
{
int replaceCharIx = rawString.indexOf("_");
int hashCharIx = rawString.indexOf("$");
if(replaceCharIx > -1
&& hashCharIx > -1
&& replaceCharIx < hashCharIx)
{
//String rawStrNotHashed = encodedString.substring(0, hashCharIx);
// String hashValue = encodedString.substring(hashCharIx + 1);
// TODO: we can check the string, just to be sure, if we now
// the char to replace, when dealing with accounts it will be :
return rawString;
}
else
return rawString;
}
/**
* Tests if an ID is valid.
*/

@ -53,6 +53,17 @@ public interface HistoryService {
*/
public History getHistory(HistoryID id) throws IllegalArgumentException;
/**
* Enumerates existing histories.
* @param rawid the start of the HistoryID of all the histories that will be
* returned.
* @return list of histories which HistoryID starts with <tt>rawid</tt>.
* @throws IllegalArgumentException if the <tt>rawid</tt> contains ids
* which are missing in current history.
*/
public List<HistoryID> getExistingHistories(String[] rawid)
throws IllegalArgumentException;
/**
* Tests if a history with the given ID exists and is loaded.
*

@ -43,6 +43,7 @@ public static Test suite()
suite.addTest(new TestHistoryService("testWriteRecords"));
suite.addTest(new TestHistoryService("testReadRecords"));
suite.addTest(new TestHistoryService("testPurgeLocallyStoredHistory"));
suite.addTest(new TestHistoryService("testCreatingHistoryIDFromFS"));
return suite;
}
@ -193,4 +194,37 @@ public void testPurgeLocallyStoredHistory()
+ " : " + ex.getMessage());
}
}
/**
* Test of method createFromRawStrings, used when we read history folders
* from FS and from their names want to recreate history.
*/
public void testCreatingHistoryIDFromFS()
{
testHistoryIDCreate(new String[] { "test1", "alltests1" });
//test id which has special chars (accounts)
testHistoryIDCreate(new String[] { "test2", "alltests2",
"Jabber:mincho.penchev@jit.si@jit.si" });
}
private void testHistoryIDCreate(String[] strArr)
{
HistoryID testNoSpecialCharsID = HistoryID.createFromRawID(strArr);
HistoryID testNoSpecialCharsIDFSRead =
HistoryID.createFromRawStrings(testNoSpecialCharsID.getID());
assertEquals("Wrong length", testNoSpecialCharsID.getID().length,
testNoSpecialCharsIDFSRead.getID().length);
for(int i = 0; i < testNoSpecialCharsID.getID().length; i++)
{
/*System.err.println(
testNoSpecialCharsID.getID()[i] +
" ? " +
testNoSpecialCharsIDFSRead.getID()[i]);*/
assertEquals("Wrong id", testNoSpecialCharsID.getID()[i],
testNoSpecialCharsIDFSRead.getID()[i]);
}
}
}

Loading…
Cancel
Save