### Eclipse Workspace Patch 1.0 #P org.eclipse.ecf.provider.xmpp Index: src/org/eclipse/ecf/provider/xmpp/XMPPContainer.java =================================================================== RCS file: /cvsroot/rt/org.eclipse.ecf/providers/bundles/org.eclipse.ecf.provider.xmpp/src/org/eclipse/ecf/provider/xmpp/XMPPContainer.java,v retrieving revision 1.18 diff -u -r1.18 XMPPContainer.java --- src/org/eclipse/ecf/provider/xmpp/XMPPContainer.java 31 Mar 2008 23:35:01 -0000 1.18 +++ src/org/eclipse/ecf/provider/xmpp/XMPPContainer.java 21 Jan 2009 23:42:28 -0000 @@ -41,6 +41,7 @@ import org.eclipse.ecf.internal.provider.xmpp.events.MessageEvent; import org.eclipse.ecf.internal.provider.xmpp.events.PresenceEvent; import org.eclipse.ecf.internal.provider.xmpp.filetransfer.XMPPOutgoingFileTransferHelper; +import org.eclipse.ecf.internal.provider.xmpp.search.XMPPSearchManager; import org.eclipse.ecf.internal.provider.xmpp.smack.ECFConnection; import org.eclipse.ecf.internal.provider.xmpp.smack.ECFConnectionObjectPacketEvent; import org.eclipse.ecf.internal.provider.xmpp.smack.ECFConnectionPacketEvent; @@ -50,6 +51,7 @@ import org.eclipse.ecf.presence.chatroom.IChatRoomManager; import org.eclipse.ecf.presence.im.IChatManager; import org.eclipse.ecf.presence.roster.IRosterManager; +import org.eclipse.ecf.presence.search.IUserSearchManager; import org.eclipse.ecf.presence.service.IPresenceService; import org.eclipse.ecf.provider.comm.AsynchEvent; import org.eclipse.ecf.provider.comm.ConnectionCreateException; @@ -104,6 +106,8 @@ protected XMPPOutgoingFileTransferHelper outgoingFileTransferContainerAdapter = null; protected XMPPContainerPresenceHelper presenceHelper = null; + + protected XMPPSearchManager searchManager = null; protected ID presenceHelperID = null; @@ -112,6 +116,7 @@ this.keepAlive = keepAlive; accountManager = new XMPPContainerAccountManager(); chatRoomManager = new XMPPChatRoomManager(getID()); + searchManager = new XMPPSearchManager(); this.presenceHelperID = IDFactory.getDefault().createStringID(CONTAINER_HELPER_ID); presenceHelper = new XMPPContainerPresenceHelper(this); outgoingFileTransferContainerAdapter = new XMPPOutgoingFileTransferHelper(this); @@ -132,6 +137,10 @@ public IRosterManager getRosterManager() { return presenceHelper.getRosterManager(); } + + public IUserSearchManager getUserSearchManager() { + return searchManager; + } public IAccountManager getAccountManager() { return accountManager; @@ -238,6 +247,8 @@ final ECFConnection conn = getECFConnection(); accountManager.setConnection(conn.getXMPPConnection()); chatRoomManager.setConnection(getConnectNamespace(), originalTarget, conn); + searchManager.setConnection(getConnectNamespace(), originalTarget,conn); + searchManager.setEnabled(!isGoogle(originalTarget)); presenceHelper.setUser(new User(originalTarget)); outgoingFileTransferContainerAdapter.setConnection(conn.getXMPPConnection()); return originalTarget; Index: src/org/eclipse/ecf/internal/provider/xmpp/Messages.java =================================================================== RCS file: /cvsroot/rt/org.eclipse.ecf/providers/bundles/org.eclipse.ecf.provider.xmpp/src/org/eclipse/ecf/internal/provider/xmpp/Messages.java,v retrieving revision 1.5 diff -u -r1.5 Messages.java --- src/org/eclipse/ecf/internal/provider/xmpp/Messages.java 10 Dec 2007 18:58:54 -0000 1.5 +++ src/org/eclipse/ecf/internal/provider/xmpp/Messages.java 21 Jan 2009 23:42:27 -0000 @@ -35,6 +35,7 @@ public static String XMPPContainer_UNEXPECTED_EVENT; public static String XMPPContainer_UNEXPECTED_XMPP_MESSAGE; public static String XMPPContainer_UNRECOGONIZED_CONTAINER_MESSAGE; + public static String XMPPContainer_UNRECOGONIZED_SEARCH_SERVICE; public static String XMPPFileID_EXCEPTION_FILE_IDS_NOT_URLS; public static String XMPPFileNamespace_EXCEPTION_FILEID_FILENAME_NOT_NULL; public static String XMPPFileNamespace_EXCEPTION_FILEID_TARGETID_NOT_NULL; Index: src/org/eclipse/ecf/internal/provider/xmpp/XMPPContainerPresenceHelper.java =================================================================== RCS file: /cvsroot/rt/org.eclipse.ecf/providers/bundles/org.eclipse.ecf.provider.xmpp/src/org/eclipse/ecf/internal/provider/xmpp/XMPPContainerPresenceHelper.java,v retrieving revision 1.39 diff -u -r1.39 XMPPContainerPresenceHelper.java --- src/org/eclipse/ecf/internal/provider/xmpp/XMPPContainerPresenceHelper.java 25 Nov 2008 02:19:20 -0000 1.39 +++ src/org/eclipse/ecf/internal/provider/xmpp/XMPPContainerPresenceHelper.java 21 Jan 2009 23:42:28 -0000 @@ -437,7 +437,8 @@ final IRosterEntry entry = createRosterEntry(newID, item); if (itemType == RosterPacket.ItemType.NONE || itemType == RosterPacket.ItemType.REMOVE) { - removeFromRoster(createIDFromName(item.getUser())); + removeItemFromRoster(roster.getItems(), + createIDFromName(item.getUser())); remove = true; } else { remove = false; @@ -459,24 +460,21 @@ rosterManager.notifyRosterAdd(entry); } - private void removeFromRoster(XMPPID itemIDToRemove) { + private void removeItemFromRoster(Collection rosterItems, + XMPPID itemIDToRemove) { boolean removed = false; - Collection rosterItems = roster.getItems(); synchronized (rosterItems) { for (final Iterator i = rosterItems.iterator(); i.hasNext();) { final IRosterItem item = (IRosterItem) i.next(); if (item instanceof org.eclipse.ecf.presence.roster.RosterGroup) { final org.eclipse.ecf.presence.roster.RosterGroup group = (org.eclipse.ecf.presence.roster.RosterGroup) item; - boolean r = removeItemFromRosterGroup(group, itemIDToRemove); - if (r) - removed = true; + removed = removeItemFromRosterGroup(group, itemIDToRemove); // If group is empty, remove it too if (group.getEntries().size() == 0) i.remove(); } else if (item instanceof org.eclipse.ecf.presence.roster.RosterEntry) { - org.eclipse.ecf.presence.roster.RosterEntry entry = (org.eclipse.ecf.presence.roster.RosterEntry) item; - XMPPID entryID = (XMPPID) entry.getUser().getID(); - if (entryID.equals(itemIDToRemove)) { + if (((org.eclipse.ecf.presence.roster.RosterEntry) item) + .getUser().getID().equals(itemIDToRemove)) { i.remove(); removed = true; } @@ -496,8 +494,7 @@ for (final Iterator i = group.getEntries().iterator(); i.hasNext();) { final org.eclipse.ecf.presence.roster.RosterEntry entry = (org.eclipse.ecf.presence.roster.RosterEntry) i .next(); - XMPPID entryID = (XMPPID) entry.getUser().getID(); - if (entryID.equals(itemIDToRemove)) { + if (entry.getUser().getID().equals(itemIDToRemove)) { i.remove(); return true; } @@ -570,200 +567,93 @@ private void updatePresence(XMPPID fromID, IPresence newPresence) { final Collection rosterItems = roster.getItems(); - AdditionalClient newEntry = null; + List newEntrys = new ArrayList(); synchronized (rosterItems) { for (final Iterator i = roster.getItems().iterator(); i.hasNext();) { final IRosterItem item = (IRosterItem) i.next(); if (item instanceof IRosterGroup) { - AdditionalClient newClient = updatePresenceInGroup( + AdditionalClientRosterEntry[] es = updatePresenceInGroup( (IRosterGroup) item, fromID, newPresence); - if (newClient != null) - newEntry = newClient; + for (int j = 0; j < es.length; j++) { + newEntrys.add(es[j]); + } } else if (item instanceof org.eclipse.ecf.presence.roster.RosterEntry) { - AdditionalClient newClient = updatePresenceForMatchingEntry( + AdditionalClientRosterEntry entry = updatePresenceForMatchingEntry( (org.eclipse.ecf.presence.roster.RosterEntry) item, fromID, newPresence); - if (newClient != null) - newEntry = newClient; + if (entry != null) + newEntrys.add(entry); } } } - if (newEntry != null) { - if (newEntry.add) { - if (!rosterContainsEntry(fromID)) { - IRosterEntry entry = new org.eclipse.ecf.presence.roster.RosterEntry( - newEntry.parent, newEntry.user, newEntry.presence); - rosterManager.notifyRosterUpdate(roster); - fireSetRosterEntry(false, entry); - } - } else { - // remove from roster as it's another client - removeFromRoster(fromID); + AdditionalClientRosterEntry[] entrys = (AdditionalClientRosterEntry[]) newEntrys + .toArray(new AdditionalClientRosterEntry[] {}); + IRosterEntry entry = null; + if (entrys.length > 0) { + for (int i = 0; i < entrys.length; i++) { + entry = new org.eclipse.ecf.presence.roster.RosterEntry(entrys[i].parent,entrys[i].user,entrys[i].presence); + //roster.addItem(entry); } + rosterManager.notifyRosterUpdate(roster); + fireSetRosterEntry(false, entry); } } - class AdditionalClient { - + class AdditionalClientRosterEntry { + IRosterItem parent; IUser user; IPresence presence; - boolean add; - - public AdditionalClient(IRosterItem parent, IUser user, - IPresence presence, boolean add) { + + public AdditionalClientRosterEntry(IRosterItem parent, IUser user, IPresence presence) { this.parent = parent; this.user = user; this.presence = presence; - this.add = add; - } - - public AdditionalClient(IUser user) { - this.user = user; - this.add = false; - } - } - - private int countClientsInRosterGroup( - org.eclipse.ecf.presence.roster.RosterGroup group, XMPPID oldID) { - Collection groupItems = group.getEntries(); - int count = 0; - for (final Iterator i = groupItems.iterator(); i.hasNext();) { - final IRosterItem item = (IRosterItem) i.next(); - if (item instanceof org.eclipse.ecf.presence.roster.RosterEntry) { - org.eclipse.ecf.presence.roster.RosterEntry entry = (org.eclipse.ecf.presence.roster.RosterEntry) item; - XMPPID entryID = (XMPPID) entry.getUser().getID(); - if (entryID.getUsernameAtHost().equals( - oldID.getUsernameAtHost())) - count++; - } } - return count; } - - private int countClientsInRoster(XMPPID oldID) { - Collection rosterItems = roster.getItems(); - int count = 0; - synchronized (rosterItems) { - for (final Iterator i = rosterItems.iterator(); i.hasNext();) { - final IRosterItem item = (IRosterItem) i.next(); - if (item instanceof org.eclipse.ecf.presence.roster.RosterGroup) { - final org.eclipse.ecf.presence.roster.RosterGroup group = (org.eclipse.ecf.presence.roster.RosterGroup) item; - count += countClientsInRosterGroup(group, oldID); - } else if (item instanceof org.eclipse.ecf.presence.roster.RosterEntry) { - org.eclipse.ecf.presence.roster.RosterEntry entry = (org.eclipse.ecf.presence.roster.RosterEntry) item; - XMPPID entryID = (XMPPID) entry.getUser().getID(); - if (entryID.getUsernameAtHost().equals( - oldID.getUsernameAtHost())) { - count++; - } - } - } - } - return count; - } - - private boolean rosterGroupContainsEntry( - org.eclipse.ecf.presence.roster.RosterGroup group, XMPPID oldID) { - Collection groupItems = group.getEntries(); - for (final Iterator i = groupItems.iterator(); i.hasNext();) { - final IRosterItem item = (IRosterItem) i.next(); - if (item instanceof org.eclipse.ecf.presence.roster.RosterEntry) { - org.eclipse.ecf.presence.roster.RosterEntry entry = (org.eclipse.ecf.presence.roster.RosterEntry) item; - XMPPID entryID = (XMPPID) entry.getUser().getID(); - if (entryID.equals(oldID)) - return true; - } - } - return false; - } - - private boolean rosterContainsEntry(XMPPID oldID) { - Collection rosterItems = roster.getItems(); - synchronized (rosterItems) { - for (final Iterator i = rosterItems.iterator(); i.hasNext();) { - final IRosterItem item = (IRosterItem) i.next(); - if (item instanceof org.eclipse.ecf.presence.roster.RosterGroup) { - final org.eclipse.ecf.presence.roster.RosterGroup group = (org.eclipse.ecf.presence.roster.RosterGroup) item; - if (rosterGroupContainsEntry(group, oldID)) - return true; - } else if (item instanceof org.eclipse.ecf.presence.roster.RosterEntry) { - org.eclipse.ecf.presence.roster.RosterEntry entry = (org.eclipse.ecf.presence.roster.RosterEntry) item; - XMPPID entryID = (XMPPID) entry.getUser().getID(); - if (entryID.equals(oldID)) - return true; - } - } - } - return false; - } - - private AdditionalClient removeEntryFromRoster(XMPPID oldID, - org.eclipse.ecf.presence.roster.RosterEntry entry, - IPresence newPresence, IUser user) { - if (countClientsInRoster(oldID) > 1) { - // remove this client from roster - return new AdditionalClient(user); - } else { - // Last one, so we set resource to null and set presence to - // unavailable - oldID.setResourceName(null); - entry.setPresence(newPresence); - rosterManager.notifyRosterUpdate(entry); - return null; - } - } - - private AdditionalClient updatePresenceForMatchingEntry( + + + private AdditionalClientRosterEntry updatePresenceForMatchingEntry( org.eclipse.ecf.presence.roster.RosterEntry entry, XMPPID fromID, IPresence newPresence) { final IUser user = entry.getUser(); XMPPID oldID = (XMPPID) user.getID(); - if (newPresence.getType().equals(IPresence.Type.UNAVAILABLE)) { - // This is an unavailable presence change - if (oldID.equals(fromID)) - return removeEntryFromRoster(oldID, entry, newPresence, user); - } else { - // This is some other presence change - // If the username/host part matches that means we either have to - // update - // the resource, or create a new client - if (oldID.equals(fromID)) { + // If the username/host part matches that means we either have to update + // the resource, or create a new client + if (oldID.equals(fromID)) { + // set the new presence state + entry.setPresence(newPresence); + // and notify with roster update + rosterManager.notifyRosterUpdate(entry); + } else if (oldID.getUsernameAtHost().equals(fromID.getUsernameAtHost())) { + if (oldID.getResourceName() == null) { + oldID.setResourceName(fromID.getResourceName()); // set the new presence state entry.setPresence(newPresence); // and notify with roster update rosterManager.notifyRosterUpdate(entry); - } else if (oldID.getUsernameAtHost().equals( - fromID.getUsernameAtHost())) { - if (oldID.getResourceName() == null) { - oldID.setResourceName(fromID.getResourceName()); - // set the new presence state - entry.setPresence(newPresence); - // and notify with roster update - rosterManager.notifyRosterUpdate(entry); - } else - return new AdditionalClient(entry.getParent(), new User( - fromID, user.getName()), newPresence, true); + } else if (fromID.getResourceName() != null && !newPresence.getType().equals(IPresence.Type.UNAVAILABLE)) { + return new AdditionalClientRosterEntry(entry.getParent(), new User(fromID, user.getName()), newPresence); } } return null; } - private AdditionalClient updatePresenceInGroup(IRosterGroup group, + private AdditionalClientRosterEntry[] updatePresenceInGroup(IRosterGroup group, XMPPID fromID, IPresence newPresence) { + List results = new ArrayList(); final Collection groupEntries = group.getEntries(); - AdditionalClient newEntry = null; synchronized (groupEntries) { for (final Iterator i = group.getEntries().iterator(); i.hasNext();) { - AdditionalClient newClient = updatePresenceForMatchingEntry( + AdditionalClientRosterEntry newEntry = updatePresenceForMatchingEntry( (org.eclipse.ecf.presence.roster.RosterEntry) i.next(), fromID, newPresence); - if (newClient != null) - newEntry = newClient; + if (newEntry != null) + results.add(newEntry); } } - return newEntry; + return (AdditionalClientRosterEntry[]) results.toArray(new AdditionalClientRosterEntry[] {}); } protected void handleRoster(Roster roster) { Index: src/org/eclipse/ecf/internal/provider/xmpp/messages.properties =================================================================== RCS file: /cvsroot/rt/org.eclipse.ecf/providers/bundles/org.eclipse.ecf.provider.xmpp/src/org/eclipse/ecf/internal/provider/xmpp/messages.properties,v retrieving revision 1.5 diff -u -r1.5 messages.properties --- src/org/eclipse/ecf/internal/provider/xmpp/messages.properties 10 Dec 2007 18:58:54 -0000 1.5 +++ src/org/eclipse/ecf/internal/provider/xmpp/messages.properties 21 Jan 2009 23:42:28 -0000 @@ -22,7 +22,8 @@ XMPPContainer_EXCEPTION_INVALID_RESPONSE_FROM_SERVER=invalid connect response from server XMPPIncomingFileTransfer_Status_Transfer_Exception=Transfer Exception XMPPContainer_EXCEPTION_ADDING_SHARED_OBJECT=Exception adding shared object %1 -XMPPContainer_UNRECOGONIZED_CONTAINER_MESSAGE=got unrecognized container message...ignoring message +XMPPContainer_UNRECOGONIZED_CONTAINER_MESSAGE=got unrecognized container message...ignoring message +XMPPContainer_UNRECOGONIZED_SEARCH_SERVICE=Search Service not available on the server XMPPContainer_UNEXPECTED_EVENT=processAsynch got unexpected event %1 XMPPContainer_EXCEPTION_HANDLING_ASYCH_EVENT=processAsynch exception processing event %1 XMPPFileID_EXCEPTION_FILE_IDS_NOT_URLS=XMPPFileIDs cannot be represented as URLs. Index: src/org/eclipse/ecf/internal/provider/xmpp/search/XMPPResultItem.java =================================================================== RCS file: src/org/eclipse/ecf/internal/provider/xmpp/search/XMPPResultItem.java diff -N src/org/eclipse/ecf/internal/provider/xmpp/search/XMPPResultItem.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ecf/internal/provider/xmpp/search/XMPPResultItem.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,60 @@ +/******************************************************************************* + * Copyright (c) 2008 Marcelo Mayworm. All rights reserved. This + * program and the accompanying materials are made available under the terms of + * the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Marcelo Mayworm - initial API and implementation + * + ******************************************************************************/ +package org.eclipse.ecf.internal.provider.xmpp.search; + +import org.eclipse.ecf.core.user.IUser; +import org.eclipse.ecf.presence.search.IResult; + +/** + * Implement a specific result for XMPP + *@since 3.0 + */ +public class XMPPResultItem implements IResult { + + /** contain a IUser */ + protected IUser user; + + /** + * Create a XMPP result with a IUser + * @param user IUser + */ + public XMPPResultItem(IUser user) { + this.user = user; + } + + /* + * (non-Javadoc) + * @see org.eclipse.ecf.presence.search.IResult#getUser() + */ + public IUser getUser() { + return user; + } + + /** + * Verify if there is the same IUser. Compare using ID + */ + public boolean equals(Object o) { + if(o instanceof XMPPResultItem) + return ((XMPPResultItem) o).getUser().getID().toString().equals(user.getID().toString()); + else + return false; + } + + public int hashCode() { + return (user.getID().toString() != null ? user.getID().toString() + .hashCode() : 0); + } + + public Object getAdapter(Class adapter) { + // TODO Auto-generated method stub + return null; + } + +} Index: src/org/eclipse/ecf/internal/provider/xmpp/search/XMPPCriteria.java =================================================================== RCS file: src/org/eclipse/ecf/internal/provider/xmpp/search/XMPPCriteria.java diff -N src/org/eclipse/ecf/internal/provider/xmpp/search/XMPPCriteria.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ecf/internal/provider/xmpp/search/XMPPCriteria.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,73 @@ +/******************************************************************************* + * Copyright (c) 2008 Marcelo Mayworm. All rights reserved. This + * program and the accompanying materials are made available under the terms of + * the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Marcelo Mayworm - initial API and implementation + * + ******************************************************************************/ +package org.eclipse.ecf.internal.provider.xmpp.search; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.ecf.presence.search.ICriteria; +import org.eclipse.ecf.presence.search.ICriterion; + +/** + * Implement a specific criteria control for XMPP + *@since 3.0 + */ +public class XMPPCriteria implements ICriteria { + + /** criteria list */ + protected List criteria; + + /** + * Create a criteria with a sync list + */ + public XMPPCriteria(){ + criteria = Collections.synchronizedList(new ArrayList()); + } + + /* + * (non-Javadoc) + * @see org.eclipse.ecf.presence.search.ICriteria#add(org.eclipse.ecf.presence.search.ICriterion) + */ + public void add(ICriterion criterion) { + criteria.add(criterion); + } + + /* + * (non-Javadoc) + * @see org.eclipse.ecf.presence.search.ICriteria#getCriterions() + */ + public List getCriterions() { + return criteria; + } + + /* + * (non-Javadoc) + * @see org.eclipse.ecf.presence.search.ICriteria#isEmpty() + */ + public boolean isEmpty() { + return criteria.isEmpty(); + } + + public String toString() { + StringBuffer sb = new StringBuffer("XMPPCriteria["); //$NON-NLS-1$ + Iterator it = criteria.iterator(); + while (it.hasNext()) { + sb.append("[");//$NON-NLS-1$ + ICriterion criterion = (ICriterion) it.next(); + sb.append(criterion.toString()); + sb.append("];");//$NON-NLS-1$ + } + sb.append("];");//$NON-NLS-1$ + return sb.toString(); + } + +} Index: src/org/eclipse/ecf/internal/provider/xmpp/search/XMPPSearch.java =================================================================== RCS file: src/org/eclipse/ecf/internal/provider/xmpp/search/XMPPSearch.java diff -N src/org/eclipse/ecf/internal/provider/xmpp/search/XMPPSearch.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ecf/internal/provider/xmpp/search/XMPPSearch.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,52 @@ +/******************************************************************************* + * Copyright (c) 2008 Marcelo Mayworm. All rights reserved. This + * program and the accompanying materials are made available under the terms of + * the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Marcelo Mayworm - initial API and implementation + * + ******************************************************************************/ +package org.eclipse.ecf.internal.provider.xmpp.search; + +import org.eclipse.ecf.presence.search.ICriteria; +import org.eclipse.ecf.presence.search.IResultList; +import org.eclipse.ecf.presence.search.ISearch; +import org.eclipse.ecf.presence.search.ResultList; + +/** + * Implement ISearch for XMPP + *@since 3.0 + */ +public class XMPPSearch implements ISearch { + + protected IResultList resultList; + private ICriteria criteria; + + /* + * (non-Javadoc) + * @see org.eclipse.ecf.presence.search.ISearch#getResultList() + */ + public IResultList getResultList() { + return resultList; + } + + protected XMPPSearch(ICriteria criteria) { + this.criteria = criteria; + } + + public XMPPSearch(ResultList resultList) { + this.resultList = resultList; + } + + public ICriteria getCriteria() { + return this.criteria; + } + + public void setResultList(IResultList resultList) { + this.resultList = resultList; + + } + + +} Index: src/org/eclipse/ecf/internal/provider/xmpp/search/XMPPSelection.java =================================================================== RCS file: src/org/eclipse/ecf/internal/provider/xmpp/search/XMPPSelection.java diff -N src/org/eclipse/ecf/internal/provider/xmpp/search/XMPPSelection.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ecf/internal/provider/xmpp/search/XMPPSelection.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2008 Marcelo Mayworm. All rights reserved. This + * program and the accompanying materials are made available under the terms of + * the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Marcelo Mayworm - initial API and implementation + * + ******************************************************************************/ +package org.eclipse.ecf.internal.provider.xmpp.search; + +import org.eclipse.ecf.presence.search.ICriterion; +import org.eclipse.ecf.presence.search.Restriction; + +/** + * Implement a specific Selection for XMPP + * @since 3.0 + */ +public class XMPPSelection extends Restriction { + + /* + * (non-Javadoc) + * @see org.eclipse.ecf.presence.search.ISelection#eq(java.lang.String, java.lang.String) + */ + public ICriterion eq(String field, String value) { + //the operator is ignored for XMPP + return new XMPPSimpleCriterion(field, value, ""); + } + + /* + * (non-Javadoc) + * @see org.eclipse.ecf.presence.search.ISelection#eq(java.lang.String, java.lang.String) + */ + public ICriterion eq(String field, String value, boolean ignoreCase) { + //the operator is ignored for XMPP + return new XMPPSimpleCriterion(field, value, ""); + } + +} Index: src/org/eclipse/ecf/internal/provider/xmpp/search/XMPPSearchManager.java =================================================================== RCS file: src/org/eclipse/ecf/internal/provider/xmpp/search/XMPPSearchManager.java diff -N src/org/eclipse/ecf/internal/provider/xmpp/search/XMPPSearchManager.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ecf/internal/provider/xmpp/search/XMPPSearchManager.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,270 @@ +/******************************************************************************* + * Copyright (c) 2008 Marcelo Mayworm. All rights reserved. This + * program and the accompanying materials are made available under the terms of + * the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Marcelo Mayworm - initial API and implementation + * + ******************************************************************************/ +package org.eclipse.ecf.internal.provider.xmpp.search; + +import java.net.URISyntaxException; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.ecf.core.ContainerConnectException; +import org.eclipse.ecf.core.identity.ID; +import org.eclipse.ecf.core.identity.Namespace; +import org.eclipse.ecf.core.user.IUser; +import org.eclipse.ecf.core.user.User; +import org.eclipse.ecf.internal.provider.xmpp.Messages; +import org.eclipse.ecf.internal.provider.xmpp.smack.ECFConnection; +import org.eclipse.ecf.presence.search.AbstractUserSearchManager; +import org.eclipse.ecf.presence.search.ICriteria; +import org.eclipse.ecf.presence.search.ICriterion; +import org.eclipse.ecf.presence.search.IResultList; +import org.eclipse.ecf.presence.search.ISearch; +import org.eclipse.ecf.presence.search.IRestriction; +import org.eclipse.ecf.presence.search.IUserSearchListener; +import org.eclipse.ecf.presence.search.IUserSearchManager; +import org.eclipse.ecf.presence.search.ResultList; +import org.eclipse.ecf.presence.search.UserSearchException; +import org.eclipse.ecf.provider.xmpp.identity.XMPPID; +import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smackx.Form; +import org.jivesoftware.smackx.FormField; +import org.jivesoftware.smackx.ReportedData; +import org.jivesoftware.smackx.ReportedData.Row; +import org.jivesoftware.smackx.search.UserSearch; + +/** + * A specific implementation for XMPP provider. XEP-0055: + * http://www.xmpp.org/extensions/xep-0055.html + * + * @see IUserSearchManager + * @since 3.0 + */ +public class XMPPSearchManager extends AbstractUserSearchManager { + + /** Search service name on XMPP server */ + protected static final String SERVICE_SEARCH = "search."; + + /** Wrapper for XMPP connection */ + protected ECFConnection ecfConnection; + + protected Namespace connectNamespace; + + protected ID connectedID; + + protected Form form; + + protected UserSearch manager; + + protected boolean enabled; + + protected static final String FORM_TYPE = "FORM_TYPE"; + + protected static final String NAME = "name"; + + protected static final String JID = "jid"; + + protected static final String SEARCH_ACTION = "search"; + + public XMPPSearchManager() { + manager = new UserSearch(); + } + + /** + * Create a specific {@link ICriteria} for XMPP + */ + public ICriteria createCriteria() { + return new XMPPCriteria(); + } + + /** + * Create a specific {@link IRestriction} for XMPP + */ + public IRestriction createSelection() { + return new XMPPSelection(); + } + + /** + * Specific implementation for XMPP + * + * @see IUserSearchManager#search(ICriteria). + */ + public ISearch search(ICriteria criteria) throws UserSearchException { + + ResultList resultList = new ResultList(); + try { + //initialize the form by chance it is null + if (form == null) + form = manager.getSearchForm(ecfConnection.getXMPPConnection(), + SERVICE_SEARCH + + ecfConnection.getXMPPConnection() + .getServiceName()); + + /* + * For XMPP criterion is considered. The XMPP server will deal with + * the search. + */ + List criterions = criteria.getCriterions(); + // add the fields for the search dynamically + // consider just the fields used on the search + // fields checked by user + + String fields[] = getUserPropertiesFields(); + for (int i = 0; i < fields.length; i++) { + Iterator criterionsIterator = criterions.iterator(); + //for each user properties field check if it + //was added by user for the criteria + //for each field, a search is performed, and + //the partial result is added to the result list + while (criterionsIterator.hasNext()) { + ICriterion criterion = (ICriterion) criterionsIterator.next(); + if(criterion.equals(fields[i])){ + Form answerForm = form.createAnswerForm(); + answerForm.setAnswer(fields[i], true); + answerForm.setAnswer(SEARCH_ACTION, criterion.toExpression()); + ReportedData data = manager.sendSearchForm(ecfConnection + .getXMPPConnection(), answerForm, SERVICE_SEARCH + ecfConnection.getXMPPConnection().getServiceName()); + // create a result list from ReportedData + IResultList partialResultList = createResultList(data); + resultList.addAll(partialResultList.geResults()); + } + } + } + + return new XMPPSearch(resultList); + + } catch (final XMPPException e) { + String message = null; + if (e.getXMPPError() != null && e.getXMPPError().getCode() == 404) { + message = Messages.XMPPContainer_UNRECOGONIZED_SEARCH_SERVICE; + } else{ + message = e.getLocalizedMessage(); + } + throw new UserSearchException(message, e, criteria); + } catch (ContainerConnectException e) { + throw new UserSearchException(e, criteria); + } + + } + + /** + * Create a result list from ReportedData. Identify dynamically columns and + * rows and create users adding it to a {@link IResultList} + * + * @param data ReportedData + * @return {@link IResultList} a list of users + * @throws + */ + protected IResultList createResultList(ReportedData data) { + ResultList result = new ResultList(); + Iterator rows = data.getRows(); + while (rows.hasNext()) { + Row row = (Row) rows.next(); + Iterator jids = row.getValues(JID); + Iterator names = row.getValues(NAME); + String jid = null; + String name = null; + // XMPP server returns the same length for both + while (jids.hasNext() && names.hasNext()) { + try { + jid = (String) jids.next(); + name = (String) names.next(); + IUser user = new User(new XMPPID(connectNamespace, jid), name); + result.add(new XMPPResultItem(user)); + } catch(URISyntaxException e){ + throw new RuntimeException( + "cannot create connect id for client " + jid + + " , name = " + name, e); + } + } + } + return result; + } + + /** + * Specific implementation for XMPP + * + * @see IUserSearchManager#search(ICriteria). + */ + public void search(ICriteria criteria, IUserSearchListener listener) { + this.criteria = criteria; + addListener(listener); + } + + /** + * These parameters must be not null + * + * @param connectNamespace + * @param connectedID + * @param connection + */ + public void setConnection(Namespace connectNamespace, ID connectedID, + ECFConnection connection) { + Assert.isNotNull(connectNamespace); + Assert.isNotNull(connectedID); + Assert.isNotNull(connection); + this.connectNamespace = connectNamespace; + this.connectedID = connectedID; + this.ecfConnection = connection; + } + + /** + * Returns the user properties fields available on the XMPP server + * + * @param form + * @return String[] fields for form + * @throws ContainerConnectException + */ + public String[] getUserPropertiesFields() throws ContainerConnectException { + try{ + if (form == null) + form = manager.getSearchForm(ecfConnection.getXMPPConnection(), + SERVICE_SEARCH + ecfConnection.getXMPPConnection().getServiceName()); + + Set fields = new HashSet(); + Iterator userProperties = form.getFields(); + while (userProperties.hasNext()) { + FormField field = (FormField) userProperties.next(); + String variable = field.getVariable(); + // ignore these fields + if (!variable.equalsIgnoreCase(FORM_TYPE) + && !variable.equalsIgnoreCase(SEARCH_ACTION)) + fields.add(variable); + } + return (String[]) fields.toArray(new String[0]); + } catch (final XMPPException e) { + String message = null; + if (e.getXMPPError() != null && e.getXMPPError().getCode() == 404) { + message = Messages.XMPPContainer_UNRECOGONIZED_SEARCH_SERVICE; + } else{ + message = e.getLocalizedMessage(); + } + throw new ContainerConnectException(message, e); + } + + } + + /** + * Notify that user search for XMPP is enabled + */ + public boolean isEnabled() { + return this.enabled; + } + + /** + * For gtalk it should be not enabled + * @param enabled + */ + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + +} Index: src/org/eclipse/ecf/internal/provider/xmpp/search/XMPPSimpleCriterion.java =================================================================== RCS file: src/org/eclipse/ecf/internal/provider/xmpp/search/XMPPSimpleCriterion.java diff -N src/org/eclipse/ecf/internal/provider/xmpp/search/XMPPSimpleCriterion.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ecf/internal/provider/xmpp/search/XMPPSimpleCriterion.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2008 Marcelo Mayworm. All rights reserved. This + * program and the accompanying materials are made available under the terms of + * the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Marcelo Mayworm - initial API and implementation + * + ******************************************************************************/ +package org.eclipse.ecf.internal.provider.xmpp.search; + +import org.eclipse.ecf.presence.search.SimpleCriterion; + +/** + * Implement specific for ICriterion + * @since 3.0 + */ +public class XMPPSimpleCriterion extends SimpleCriterion { + + public XMPPSimpleCriterion(String field, String value, String operator, + boolean ignoreCase) { + super(field, value, operator, ignoreCase); + + } + + public XMPPSimpleCriterion(String field, String value, String operator) { + super(field, value, operator); + } + + /** + * Provide the expression compose just for the value + */ + public String toExpression() { + return value; + } +} #P org.eclipse.ecf.tests.provider.xmpp Index: .project =================================================================== RCS file: /cvsroot/rt/org.eclipse.ecf/tests/bundles/org.eclipse.ecf.tests.provider.xmpp/.project,v retrieving revision 1.2 diff -u -r1.2 .project --- .project 21 Jan 2009 11:46:02 -0000 1.2 +++ .project 21 Jan 2009 23:42:29 -0000 @@ -20,15 +20,9 @@ - - org.eclipse.pde.api.tools.apiAnalysisBuilder - - - org.eclipse.pde.PluginNature org.eclipse.jdt.core.javanature - org.eclipse.pde.api.tools.apiAnalysisNature Index: src/org/ecllpse/ecf/tests/provider/xmpp/search/XMPPSearchTest.java =================================================================== RCS file: src/org/ecllpse/ecf/tests/provider/xmpp/search/XMPPSearchTest.java diff -N src/org/ecllpse/ecf/tests/provider/xmpp/search/XMPPSearchTest.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/ecllpse/ecf/tests/provider/xmpp/search/XMPPSearchTest.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,248 @@ +/******************************************************************************* + * Copyright (c) 2008 Marcelo Mayworm. All rights reserved. This + * program and the accompanying materials are made available under the terms of + * the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Marcelo Mayworm - initial API and implementation + * + ******************************************************************************/ +package org.ecllpse.ecf.tests.provider.xmpp.search; + +import java.util.Iterator; + +import org.eclipse.ecf.core.ContainerConnectException; +import org.eclipse.ecf.core.IContainer; +import org.eclipse.ecf.core.identity.ID; +import org.eclipse.ecf.presence.search.AbstractUserSearchManager; +import org.eclipse.ecf.presence.search.ICriteria; +import org.eclipse.ecf.presence.search.ICriterion; +import org.eclipse.ecf.presence.search.IResult; +import org.eclipse.ecf.presence.search.IResultList; +import org.eclipse.ecf.presence.search.ISearch; +import org.eclipse.ecf.presence.search.IRestriction; +import org.eclipse.ecf.presence.search.IUserSearchCompleteEvent; +import org.eclipse.ecf.presence.search.IUserSearchEvent; +import org.eclipse.ecf.presence.search.IUserSearchListener; +import org.eclipse.ecf.presence.search.IUserSearchManager; +import org.eclipse.ecf.tests.presence.AbstractSearchTest; +import org.ecllpse.ecf.tests.provider.xmpp.XMPP; + +/** + * + * @since 3.0 + */ +public class XMPPSearchTest extends AbstractSearchTest { + + private static final String USERNAME = "Username"; + private static final String EMAIL = "Email"; + private static final String NAME = "Name"; + IContainer client; + IUserSearchManager searchManager; + ISearch searchResult; + + protected String getClientContainerName() { + return XMPP.CONTAINER_NAME; + } + + public void testRetrieveBuddiesAsync() throws Exception { + assertNotNull(searchManager); + + IRestriction selection = searchManager.createSelection(); + + assertNotNull(selection); + + // fields to consider on XMPP server side search + // search field for XMPP, criterion to match the search + ICriterion name = selection.eq(NAME, "Marcelo*"); + ICriterion email = selection.eq(EMAIL, "zx*"); + ICriterion username = selection.eq(USERNAME, "sl*"); + + // create a specific criteria + ICriteria criteria = searchManager.createCriteria(); + assertNotNull(criteria); + criteria.add(name); + criteria.add(email); + criteria.add(username); + + final IUserSearchEvent event = new IUserSearchEvent(){}; + + IUserSearchListener listenerCompleted = new IUserSearchListener(){ + public void handleUserSearchEvent(IUserSearchEvent event) { + if(event instanceof IUserSearchCompleteEvent){ + searchResult = ((IUserSearchCompleteEvent)event).getSearch(); + } + } + }; + + ((AbstractUserSearchManager) searchManager).addListener(listenerCompleted); + + // call the non-block search + searchManager.search(criteria, ((AbstractUserSearchManager) searchManager).getUserSearchListner()); + + //async operation that fire an event to start a user search + Thread localThread = new Thread(new Runnable() { + public void run() { + ((AbstractUserSearchManager) searchManager).fireUserSearchEvent(event); + } + }); + assertNull(searchResult); + localThread.setDaemon(true); + localThread.start(); + + Thread.sleep(5000); + + //put the completion result on the search handle + assertNotNull(searchResult); + + // check if there is at least one result + assertTrue(0 != searchResult.getResultList().geResults().size()); + } + + /** + * Try to locate buddies on the XMPP server in a call block way + * + * @throws ContainerConnectException + */ + public void testRetrieveBuddiesAllFieldsSync() + throws ContainerConnectException { + + try { + assertNotNull(searchManager); + + IRestriction selection = searchManager.createSelection(); + assertNotNull(selection); + + // fields to consider on XMPP server side search + // search field for XMPP, criterion to match the search + ICriterion name = selection.eq(NAME, "Marcelo*"); + ICriterion email = selection.eq(EMAIL, "zx*"); + ICriterion username = selection.eq(USERNAME, "sl*"); + + // create a specific criteria + ICriteria criteria = searchManager.createCriteria(); + assertNotNull(criteria); + criteria.add(name); + criteria.add(email); + criteria.add(username); + + // call the block search + ISearch search = searchManager.search(criteria); + + // the collection of IResult + IResultList resultList = search.getResultList(); + + // check if there is at least one result + assertTrue(0 != resultList.geResults().size()); + + Iterator it = resultList.geResults().iterator(); + while (it.hasNext()) { + IResult type = (IResult) it.next(); + System.out.println(type.getUser().getName() + " : " + + type.getUser().getID()); + + } + } catch (Exception e) { + e.printStackTrace(); + } + + } + + /** + * Try to locate buddies on the XMPP server in a call block way + * + * @throws ContainerConnectException + */ + public void testRetrieveBuddiesEmailFieldSync() + throws Exception { + + assertNotNull(searchManager); + + IRestriction selection = searchManager.createSelection(); + assertNotNull(selection); + + // search field for XMPP, criterion to match the search + // fields to consider on XMPP server side search + ICriterion email = selection.eq(EMAIL, "mayworm*"); + + // create a specific criteria + ICriteria criteria = searchManager.createCriteria(); + assertNotNull(criteria); + criteria.add(email); + + // call the block search + ISearch search = searchManager.search(criteria); + + // the collection of IResult + IResultList resultList = search.getResultList(); + + // check if there is at least one result + assertTrue(1 == resultList.geResults().size()); + + } + + /** + * Try to locate buddies on the XMPP server in a call block way + * + * @throws ContainerConnectException + */ + public void testRetrieveBuddiesNameFieldSync() + throws Exception { + + assertNotNull(searchManager); + + IRestriction selection = searchManager.createSelection(); + assertNotNull(selection); + + // fields to consider on XMPP server side search + // search field for XMPP, criterion to match the search + ICriterion name = selection.eq(NAME, "marcelo*"); + + // create a specific criteria + ICriteria criteria = searchManager.createCriteria(); + assertNotNull(criteria); + // criteria.add(searchCriterion); + criteria.add(name); + + // call the block search + ISearch search = searchManager.search(criteria); + + // the collection of IResult + IResultList resultList = search.getResultList(); + + // check if there is at least one result + assertTrue(1 == resultList.geResults().size()); + + } + + protected void setUp() throws Exception { + super.setUp(); + final int clientIndex = 0; + client = getClient(clientIndex); + assertNull(client.getConnectedID()); + final ID serverConnectID = getServerConnectID(clientIndex); + assertNotNull(serverConnectID); + + connectClient(client, serverConnectID, getConnectContext(clientIndex)); + assertEquals(serverConnectID, client.getConnectedID()); + + searchManager = getPresenceAdapter(clientIndex).getUserSearchManager(); + + } + + protected void tearDown() throws Exception { + super.tearDown(); + client.disconnect(); + } + + public void testUserProperties() throws ContainerConnectException { + assertNotNull(searchManager); + String userProperties[] = searchManager.getUserPropertiesFields(); + + // check if there is at least one result + assertTrue(0 != userProperties.length); + + } + + +} #P org.eclipse.ecf.presence.ui Index: plugin.properties =================================================================== RCS file: /cvsroot/rt/org.eclipse.ecf/framework/bundles/org.eclipse.ecf.presence.ui/plugin.properties,v retrieving revision 1.8 diff -u -r1.8 plugin.properties --- plugin.properties 22 Mar 2008 17:38:49 -0000 1.8 +++ plugin.properties 21 Jan 2009 23:42:32 -0000 @@ -15,6 +15,7 @@ views.messages = Messages views.multiRosterView = Contacts +views.userSearchView = Search Contacts browse.command.label = Open Contact... browse.command.tooltip = Open Contact Index: plugin.xml =================================================================== RCS file: /cvsroot/rt/org.eclipse.ecf/framework/bundles/org.eclipse.ecf.presence.ui/plugin.xml,v retrieving revision 1.26 diff -u -r1.26 plugin.xml --- plugin.xml 29 Nov 2008 10:34:08 -0000 1.26 +++ plugin.xml 21 Jan 2009 23:42:32 -0000 @@ -78,6 +78,13 @@ name="%views.multiRosterView"> + + 0) + return true; + } + return false; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object) + */ + public Object[] getElements(Object inputElement) { + if (inputElement instanceof List) + return ((List) inputElement).toArray(); + + return null; + + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.viewers.IContentProvider#dispose() + */ + public void dispose() { + // do nothing + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, + * java.lang.Object, java.lang.Object) + */ + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + // do nothing + } + +} #P org.eclipse.ecf.presence Index: src/org/eclipse/ecf/presence/IPresenceContainerAdapter.java =================================================================== RCS file: /cvsroot/rt/org.eclipse.ecf/framework/bundles/org.eclipse.ecf.presence/src/org/eclipse/ecf/presence/IPresenceContainerAdapter.java,v retrieving revision 1.19 diff -u -r1.19 IPresenceContainerAdapter.java --- src/org/eclipse/ecf/presence/IPresenceContainerAdapter.java 31 Dec 2006 07:54:44 -0000 1.19 +++ src/org/eclipse/ecf/presence/IPresenceContainerAdapter.java 21 Jan 2009 23:42:35 -0000 @@ -14,6 +14,7 @@ import org.eclipse.ecf.presence.chatroom.IChatRoomManager; import org.eclipse.ecf.presence.im.IChatManager; import org.eclipse.ecf.presence.roster.IRosterManager; +import org.eclipse.ecf.presence.search.IUserSearchManager; /** * Entry point presence container adapter. For setting up listeners for presence @@ -71,4 +72,14 @@ * available, returns null. */ public IChatRoomManager getChatRoomManager(); + + /** + * Retrieve interface for search on the provide. The returned + * IUserSearchManager (if not null) can be used to search users + * related to the same provider. + * + * @return IUserSearchManager. null if no search + * available for this provider. + */ + public IUserSearchManager getUserSearchManager(); } Index: META-INF/MANIFEST.MF =================================================================== RCS file: /cvsroot/rt/org.eclipse.ecf/framework/bundles/org.eclipse.ecf.presence/META-INF/MANIFEST.MF,v retrieving revision 1.89 diff -u -r1.89 MANIFEST.MF --- META-INF/MANIFEST.MF 8 Sep 2008 23:11:30 -0000 1.89 +++ META-INF/MANIFEST.MF 21 Jan 2009 23:42:35 -0000 @@ -12,6 +12,7 @@ org.eclipse.ecf.presence.history, org.eclipse.ecf.presence.im, org.eclipse.ecf.presence.roster, + org.eclipse.ecf.presence.search, org.eclipse.ecf.presence.service Bundle-ManifestVersion: 2 Bundle-RequiredExecutionEnvironment: CDC-1.0/Foundation-1.0, Index: src/org/eclipse/ecf/presence/search/IUserSearchCompleteEvent.java =================================================================== RCS file: src/org/eclipse/ecf/presence/search/IUserSearchCompleteEvent.java diff -N src/org/eclipse/ecf/presence/search/IUserSearchCompleteEvent.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ecf/presence/search/IUserSearchCompleteEvent.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2008 Marcelo Mayworm. All rights reserved. This + * program and the accompanying materials are made available under the terms of + * the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Marcelo Mayworm - initial API and implementation + * + ******************************************************************************/ +package org.eclipse.ecf.presence.search; + +/** + * This event indicate that a user search was completed + *@since 3.0 + */ +public interface IUserSearchCompleteEvent extends IUserSearchEvent { + + /** + * Provide the result for a non-blocking search + * @return ISearch + */ + public ISearch getSearch(); +} Index: src/org/eclipse/ecf/presence/search/ResultList.java =================================================================== RCS file: src/org/eclipse/ecf/presence/search/ResultList.java diff -N src/org/eclipse/ecf/presence/search/ResultList.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ecf/presence/search/ResultList.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,103 @@ +/******************************************************************************* + * Copyright (c) 2008 Marcelo Mayworm. All rights reserved. This + * program and the accompanying materials are made available under the terms of + * the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Marcelo Mayworm - initial API and implementation + * + ******************************************************************************/ +package org.eclipse.ecf.presence.search; + +import java.util.*; +import org.eclipse.core.runtime.IAdapterManager; +import org.eclipse.ecf.internal.presence.PresencePlugin; + +/** + * This Class implements {@link IResultList}. Subclasses may be created as + * appropriate. + * @since 3.0 + */ +public class ResultList implements IResultList { + + protected Set results; + + /** + * Create a new synchronized result list from a existing one + * @param existingResults + */ + public ResultList(Collection /* */existingResults) { + results = Collections.synchronizedSet(new HashSet()); + if (existingResults != null) + addAll(existingResults); + } + + /** + * Create a new synchronized result list from a existing one + * + */ + public ResultList() { + results = Collections.synchronizedSet(new HashSet()); + } + + /** + * Add an item for the result list + * @param item + * @return boolean + */ + public boolean add(IResult item) { + if (item == null) + return false; + if (results.add(item)) + return true; + return false; + } + + /** + * Add the list for the current result list + * @param existingResults + */ + public void addAll(Collection /* */existingResults) { + if (existingResults == null) + return; + synchronized (results) { + for (Iterator i = existingResults.iterator(); i.hasNext();) { + add((IResult) i.next()); + } + } + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ecf.ui.presence.search.IResultList#getEntries() + */ + public Collection geResults() { + return results; + } + + public boolean remove(IResult item) { + return results.remove(item); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ecf.ui.presence.search.IResultList#getResult + */ + public IResult getResult(String field, String value) { + // TODO + return null; + } + + public Object getAdapter(Class adapter) { + if (adapter.isInstance(this)) { + return this; + } + IAdapterManager adapterManager = PresencePlugin.getDefault().getAdapterManager(); + if (adapterManager == null) + return null; + return adapterManager.loadAdapter(this, adapter.getName()); + } + +} Index: src/org/eclipse/ecf/presence/search/ICriteria.java =================================================================== RCS file: src/org/eclipse/ecf/presence/search/ICriteria.java diff -N src/org/eclipse/ecf/presence/search/ICriteria.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ecf/presence/search/ICriteria.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (c) 2008 Marcelo Mayworm. All rights reserved. This + * program and the accompanying materials are made available under the terms of + * the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Marcelo Mayworm - initial API and implementation + * + ******************************************************************************/ + +package org.eclipse.ecf.presence.search; + +import java.util.List; + +/** + * Criteria helps for retrieving results from the provider search by composing Criterion objects. + * The {@link IUserSearchManager} is a factory for Criteria. Criterion instances are obtained via ISelection methods. + * Criteria can deal with different kind of criterion, as logical or just simple expression. + * + * The typical usage of the Criteria is as + * follows: + * + *
+ *      ISelection selection = ...
+ *		ICriterion name = selection.eq("name", "value");
+ *		ICriterion host = selection.eq("host", "value");
+ *		ICriterion and = selection.and(name, host);
+ *		ICriteria criteria = ...
+ *		criteria.add(and);
+ * 
+ * + * @since 3.0 + */ +public interface ICriteria { + + /** + * Add a criterion that composes the criteria + * @param criterion + */ + public void add(ICriterion criterion); + + /** + * A list of all criterion added to the criteria + * @return List of {@link ICriterion} + */ + public List getCriterions(); + + /** + * Notify if there is or not criterion added for this criteria + * @return indicate if there are or not criterion + */ + public boolean isEmpty(); + +} Index: src/org/eclipse/ecf/presence/search/LogicalCriterion.java =================================================================== RCS file: src/org/eclipse/ecf/presence/search/LogicalCriterion.java diff -N src/org/eclipse/ecf/presence/search/LogicalCriterion.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ecf/presence/search/LogicalCriterion.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2008 Marcelo Mayworm. All rights reserved. This + * program and the accompanying materials are made available under the terms of + * the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Marcelo Mayworm - initial API and implementation + * + ******************************************************************************/ +package org.eclipse.ecf.presence.search; + +/** + * Base class implementation of {@link ICriterion} for logical criterion. + * Subclasses may be created as appropriate. It is just a simple + * implementation that can be considered for some provider or even used + * as base for some implementation. + * @since 3.0 + */ +public class LogicalCriterion implements ICriterion { + + final ICriterion left; + final ICriterion right; + final String operator; + + /** + * Creates a logic operation for compose a {@link ICrteria} + * @param left Criterion on the left side of the expression + * @param right Criterion on the right side of the expression + * @param operator Operator considered on the logical. Ex: And + */ + public LogicalCriterion(ICriterion left, ICriterion right, String operator) { + this.left = left; + this.right = right; + this.operator = operator; + } + + public String toExpression() { + return left.toExpression() + ' ' + operator + ' ' + right.toExpression(); + } + + public String toString() { + StringBuffer sb = new StringBuffer("LogicalCriterion["); //$NON-NLS-1$ + sb.append("left=").append(left).append(";"); //$NON-NLS-1$ //$NON-NLS-2$ + sb.append("right=").append(right).append(";"); //$NON-NLS-1$ //$NON-NLS-2$ + sb.append("operator=").append(operator).append("]"); //$NON-NLS-1$ //$NON-NLS-2$ + return sb.toString(); + } + +} Index: src/org/eclipse/ecf/presence/search/IUserSearchManager.java =================================================================== RCS file: src/org/eclipse/ecf/presence/search/IUserSearchManager.java diff -N src/org/eclipse/ecf/presence/search/IUserSearchManager.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ecf/presence/search/IUserSearchManager.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,73 @@ +/******************************************************************************* + * Copyright (c) 2008 Marcelo Mayworm. All rights reserved. This + * program and the accompanying materials are made available under the terms of + * the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Marcelo Mayworm - initial API and implementation + * + ******************************************************************************/ + +package org.eclipse.ecf.presence.search; + +import org.eclipse.ecf.core.ContainerConnectException; + +/** + * Get a search mechanism for an account. + * @since 3.0 + */ +public interface IUserSearchManager { + + /** + * Execute the search for a specific criteria, blocking until the search returns. + * This method can apply search to math the specific criteria in case if the + * provider is not able to do it completely + * @param criteria + * @return ISearch Contain the search results + * @throws UserSearchException + */ + public ISearch search(ICriteria criteria) throws UserSearchException; + + /** + * Execute the search for a specific criteria, not blocking until the search returns. + * This method can apply search to math the specific criteria in case if the + * provider is not able to do it completely + * @param criteria + * @param listener the listener {@link IUserSearchListener} to search. Must not be null. + */ + public void search(ICriteria criteria, IUserSearchListener listener); + + /** + * Create a specific criteria for the provider. Each provider must + * implement a specific Criteria in a convenient approach for keep, + * organize and deal with the {@link ICriterion}. + * @return {@link ICriteria} + */ + public ICriteria createCriteria(); + + /** + * Create a specific {@link IRestriction} implementation for the provider. + * This implementation will provide the methods to created and organize + * the {@link ICriterion} that composes the search. The {@link Restriction} + * is a simple implementation of this, but subclasses or new implementation + * may be created as appropriate. + * + * @return {@link IRestriction} + */ + public IRestriction createSelection(); + + /** + * Each provider can inform the user properties fields + * to be considered on the user search, allowing the + * dynamically user interface for the search. + * @return String[] user properties provides by server + * @throws ContainerConnectException + */ + public String[] getUserPropertiesFields() throws ContainerConnectException; + + /** + * Whether this handler is capable of executing at this time. + * @return boolean + */ + public boolean isEnabled(); +} Index: src/org/eclipse/ecf/presence/search/ICriterion.java =================================================================== RCS file: src/org/eclipse/ecf/presence/search/ICriterion.java diff -N src/org/eclipse/ecf/presence/search/ICriterion.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ecf/presence/search/ICriterion.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2008 Marcelo Mayworm. All rights reserved. This + * program and the accompanying materials are made available under the terms of + * the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Marcelo Mayworm - initial API and implementation + * + ******************************************************************************/ + +package org.eclipse.ecf.presence.search; + +/** + * A representation of a query criterion for a restriction in a Criteria. + * A Criteria is formed by one or several criterion, + * that together are able to compose an entire expression to project + * a result that match the criteria. The instances of this should be + * created for {@link IRestriction} implementations. + * @since 3.0 + */ +public interface ICriterion { + + /** + * Returns a expression composed for the search. + * The String can be something like 'field' + 'operator' + value, + * that it will be interpreted for each specific provider. + * @return String + */ + public String toExpression(); +} Index: src/org/eclipse/ecf/presence/search/IUserSearchEvent.java =================================================================== RCS file: src/org/eclipse/ecf/presence/search/IUserSearchEvent.java diff -N src/org/eclipse/ecf/presence/search/IUserSearchEvent.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ecf/presence/search/IUserSearchEvent.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,20 @@ +/******************************************************************************* + * Copyright (c) 2008 Marcelo Mayworm. All rights reserved. This + * program and the accompanying materials are made available under the terms of + * the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Marcelo Mayworm - initial API and implementation + * + ******************************************************************************/ +package org.eclipse.ecf.presence.search; + +/** + * An event received by a user search. This interface address the events + * that happens on user search API. There be different sub-interfaces of IUserSearchEvent to + * represent different types of events. + * @since 3.0 + */ +public interface IUserSearchEvent { + // +} Index: src/org/eclipse/ecf/presence/search/UserSearchCompleteEvent.java =================================================================== RCS file: src/org/eclipse/ecf/presence/search/UserSearchCompleteEvent.java diff -N src/org/eclipse/ecf/presence/search/UserSearchCompleteEvent.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ecf/presence/search/UserSearchCompleteEvent.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2008 Marcelo Mayworm. All rights reserved. This + * program and the accompanying materials are made available under the terms of + * the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Marcelo Mayworm - initial API and implementation + * + ******************************************************************************/ +package org.eclipse.ecf.presence.search; + +/** + * + * @since 3.0 + */ +public class UserSearchCompleteEvent implements IUserSearchCompleteEvent { + + private ISearch search; + + public UserSearchCompleteEvent(ISearch search) { + this.search = search; + } + + public ISearch getSearch() { + return search; + } + +} Index: src/org/eclipse/ecf/presence/search/Restriction.java =================================================================== RCS file: src/org/eclipse/ecf/presence/search/Restriction.java diff -N src/org/eclipse/ecf/presence/search/Restriction.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ecf/presence/search/Restriction.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,71 @@ +/******************************************************************************* + * Copyright (c) 2008 Marcelo Mayworm. All rights reserved. This + * program and the accompanying materials are made available under the terms of + * the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Marcelo Mayworm - initial API and implementation + * + ******************************************************************************/ +package org.eclipse.ecf.presence.search; + +/** + * This Class implements {@link IRestriction}. Subclasses may be created as + * appropriate. It is just a simple implementation that can be considered + * for some provider or even used as base for some implementation. + * @since 3.0 + */ +public class Restriction implements IRestriction { + + /** Operator Equal */ + public static final String OPERATOR_EQ = "="; //$NON-NLS-1$ + + /** Operator Not Equal */ + public static final String OPERATOR_NE = "!="; //$NON-NLS-1$ + + /** Operator AND */ + public static final String OPERATOR_AND = "&&"; //$NON-NLS-1$ + + /* + * (non-Javadoc) + * @see org.eclipse.ecf.presence.search.ISelection#and(org.eclipse.ecf.presence.search.ICriterion, org.eclipse.ecf.presence.search.ICriterion) + */ + public ICriterion and(ICriterion left, ICriterion right) { + return new LogicalCriterion(left, right, OPERATOR_AND); + } + + /* + * (non-Javadoc) + * @see org.eclipse.ecf.presence.search.ISelection#eq(java.lang.String, java.lang.String) + */ + public ICriterion eq(String field, String value) { + return new SimpleCriterion(field, value, OPERATOR_EQ); + } + + /* + * (non-Javadoc) + * @see org.eclipse.ecf.presence.search.ISelection#ne(java.lang.String, java.lang.String) + */ + public ICriterion ne(String field, String value) { + return new SimpleCriterion(field, value, OPERATOR_NE); + } + + /* + * (non-Javadoc) + * @see org.eclipse.ecf.presence.search.ISelection#eq(java.lang.String, java.lang.String, boolean) + */ + public ICriterion eq(String field, String value, boolean ignoreCase) { + //TODO implement a criterion that supports ignore case approach + return new SimpleCriterion(field, value, OPERATOR_EQ); + } + + /* + * (non-Javadoc) + * @see org.eclipse.ecf.presence.search.ISelection#ne(java.lang.String, java.lang.String, boolean) + */ + public ICriterion ne(String field, String value, boolean ignoreCase) { + //TODO implement a criterion that supports ignore case approach + return new SimpleCriterion(field, value, OPERATOR_NE); + } + +} Index: src/org/eclipse/ecf/presence/search/UserSearchException.java =================================================================== RCS file: src/org/eclipse/ecf/presence/search/UserSearchException.java diff -N src/org/eclipse/ecf/presence/search/UserSearchException.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ecf/presence/search/UserSearchException.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,72 @@ +/******************************************************************************* + * Copyright (c) 2008 Marcelo Mayworm. All rights reserved. This + * program and the accompanying materials are made available under the terms of + * the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Marcelo Mayworm - initial API and implementation + * + ******************************************************************************/ +package org.eclipse.ecf.presence.search; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.ecf.core.util.ECFException; + +/** + * + * @since 3.0 + */ +public class UserSearchException extends ECFException { + + /** + * + */ + private static final long serialVersionUID = -896845055593390010L; + + private ICriteria criteria = null; + + /** + * + */ + public UserSearchException(ICriteria criteria) { + super(); + this.criteria = criteria; + } + + /** + * @param status + */ + public UserSearchException(IStatus status, ICriteria criteria) { + super(status); + this.criteria = criteria; + } + + /** + * @param message + * @param cause + */ + public UserSearchException(String message, Throwable cause, ICriteria criteria) { + super(message, cause); + this.criteria = criteria; + } + + /** + * @param message + */ + public UserSearchException(String message, ICriteria criteria) { + super(message); + this.criteria = criteria; + } + + /** + * @param cause + */ + public UserSearchException(Throwable cause, ICriteria criteria) { + super(cause); + this.criteria = criteria; + } + + public ICriteria getSearchCriteria() { + return this.criteria; + } +} Index: src/org/eclipse/ecf/presence/search/ISearch.java =================================================================== RCS file: src/org/eclipse/ecf/presence/search/ISearch.java diff -N src/org/eclipse/ecf/presence/search/ISearch.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ecf/presence/search/ISearch.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2008 Marcelo Mayworm. All rights reserved. This + * program and the accompanying materials are made available under the terms of + * the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Marcelo Mayworm - initial API and implementation + * + ******************************************************************************/ + +package org.eclipse.ecf.presence.search; + +/** + * Provide access for the list of matched query results. This interface can be + * extended to supply more features around the result list. + * @since 3.0 + */ +public interface ISearch { + + /** + * Gets a result list. + * Will not return null. + * @return IResultList list of {@link IResult} + */ + IResultList getResultList(); + + /** + * + * @param IResultList + */ + public void setResultList(IResultList resultList); + +} Index: src/org/eclipse/ecf/presence/search/IRestriction.java =================================================================== RCS file: src/org/eclipse/ecf/presence/search/IRestriction.java diff -N src/org/eclipse/ecf/presence/search/IRestriction.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ecf/presence/search/IRestriction.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,61 @@ +/******************************************************************************* + * Copyright (c) 2008 Marcelo Mayworm. All rights reserved. This + * program and the accompanying materials are made available under the terms of + * the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Marcelo Mayworm - initial API and implementation + * + ******************************************************************************/ +package org.eclipse.ecf.presence.search; + +/** + * Instances implementing this interface provide methods to compose the corrects operations for each + * provide + * @since 3.0 + */ +public interface IRestriction { + + /** + * Apply an "add" constraint to the two criterion + * @param left + * @param right + * @return ICriterion + */ + public ICriterion and(ICriterion left, ICriterion right); + + /** + * Apply an "equal" constraint to the field, ignoring case + * @param field + * @param value + * @return ICriterion + */ + public ICriterion eq(String field, String value); + + /** + * Apply an "not equal" constraint to the field ignoring case + * @param field + * @param value + * @return ICriterion + */ + public ICriterion ne(String field, String value); + + /** + * Apply an "equal" constraint to the field, taking into consideration ignore case + * @param field + * @param value + * @param ignoreCase + * @return ICriterion + */ + public ICriterion eq(String field, String value, boolean ignoreCase); + + /** + * Apply an "not equal" constraint to the field, taking into consideration ignore case + * @param field + * @param value + * @param ignoreCase + * @return ICriterion + */ + public ICriterion ne(String field, String value, boolean ignoreCase); + +} Index: src/org/eclipse/ecf/presence/search/IResult.java =================================================================== RCS file: src/org/eclipse/ecf/presence/search/IResult.java diff -N src/org/eclipse/ecf/presence/search/IResult.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ecf/presence/search/IResult.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2008 Marcelo Mayworm. All rights reserved. This + * program and the accompanying materials are made available under the terms of + * the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Marcelo Mayworm - initial API and implementation + * + ******************************************************************************/ +package org.eclipse.ecf.presence.search; + +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.ecf.core.user.IUser; + +/** + * Each result returned for the search will be reach through this interface. + * The result contain the user that match the search. + * @since 3.0 + */ +public interface IResult extends IAdaptable { + + /** + * Get user for the search. This is the user that comes from the search. + * + * @return IUser user associated with the search. + */ + public IUser getUser(); +} Index: src/org/eclipse/ecf/presence/search/IUserSearchListener.java =================================================================== RCS file: src/org/eclipse/ecf/presence/search/IUserSearchListener.java diff -N src/org/eclipse/ecf/presence/search/IUserSearchListener.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ecf/presence/search/IUserSearchListener.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2008 Marcelo Mayworm. All rights reserved. This + * program and the accompanying materials are made available under the terms of + * the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Marcelo Mayworm - initial API and implementation + * + ******************************************************************************/ +package org.eclipse.ecf.presence.search; + +/** + * This Interface allows for implementing classes to execute the search + * for users in a non block way. + * Note these methods will be called asynchronously not blocking a search action. + * The provider is free to call the methods below with an arbitrary thread, so the + * implementation of these methods must be appropriately prepared. + * @since 3.0 + */ +public interface IUserSearchListener { + + /** + * Catch the event fired and proceed to complete the search. + * Handle the search asynchronously. Notify that the search was completed + * for the specific criteria. + * @param event the object that contains the composition of {@link ICriteria} + * and deal with the results in a non-blocking way + */ + public void handleUserSearchEvent(IUserSearchEvent event); + +} Index: src/org/eclipse/ecf/presence/search/SimpleCriterion.java =================================================================== RCS file: src/org/eclipse/ecf/presence/search/SimpleCriterion.java diff -N src/org/eclipse/ecf/presence/search/SimpleCriterion.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ecf/presence/search/SimpleCriterion.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,83 @@ +/******************************************************************************* + * Copyright (c) 2008 Marcelo Mayworm. All rights reserved. This + * program and the accompanying materials are made available under the terms of + * the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Marcelo Mayworm - initial API and implementation + * + ******************************************************************************/ +package org.eclipse.ecf.presence.search; + +/** + * + * Base class implementation of {@link ICriterion} for simple comparisons. Subclasses may be created as + * appropriate. + * @since 3.0 + */ +public class SimpleCriterion implements ICriterion { + + protected final String field; + protected final String value; + protected final String operator; + protected final boolean ignoreCase; + + /** + * Constructor for a instance of {@link ICriterion} + * @param field Name of the field + * @param value Value that match the search + * @param operator Operator opportune for the search + * @param ignoreCase Consider case or not + */ + public SimpleCriterion(String field, String value, String operator, boolean ignoreCase) { + this.field = field; + this.value = value; + this.operator = operator; + this.ignoreCase = ignoreCase; + } + + /** + * Constructor for a instance of {@link ICriterion}. This is + * ignore case + * @param field Name of the field + * @param value Value that match the search + * @param operator Operator opportune for the search + */ + public SimpleCriterion(String field, String value, String operator) { + this.field = field; + this.value = value; + this.operator = operator; + this.ignoreCase = false; + } + + /* + * (non-Javadoc) + * @see org.eclipse.ecf.presence.search.ICriterion#toExpression() + */ + public String toExpression() { + return field + ' ' + operator + ' ' + value; + } + + public String toString() { + StringBuffer sb = new StringBuffer("SimpleCriterion["); //$NON-NLS-1$ + sb.append("field=").append(field).append(";"); //$NON-NLS-1$ //$NON-NLS-2$ + sb.append("value=").append(value).append(";"); //$NON-NLS-1$ //$NON-NLS-2$ + sb.append("operator=").append(operator).append(";"); //$NON-NLS-1$ //$NON-NLS-2$ + sb.append("ignoreCase=").append(ignoreCase).append("]"); //$NON-NLS-1$ //$NON-NLS-2$ + return sb.toString(); + } + + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o instanceof String) { + return o.equals(field); + } + return false; + } + + public int hashCode() { + return (field != null ? field.hashCode() : 0); + } +} Index: src/org/eclipse/ecf/presence/search/AbstractUserSearchManager.java =================================================================== RCS file: src/org/eclipse/ecf/presence/search/AbstractUserSearchManager.java diff -N src/org/eclipse/ecf/presence/search/AbstractUserSearchManager.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ecf/presence/search/AbstractUserSearchManager.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,86 @@ +/******************************************************************************* + * Copyright (c) 2008 Marcelo Mayworm. All rights reserved. This + * program and the accompanying materials are made available under the terms of + * the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Marcelo Mayworm - initial API and implementation + * + ******************************************************************************/ +package org.eclipse.ecf.presence.search; + +import java.util.*; + +/** + * Abstract implementation of IUserSearchManager. Provides implementations of listener + * methods that subsclasses may use to avoid having to implement them + * themselves. This class may be subclassed as needed. + * @since 3.0 + */ +public abstract class AbstractUserSearchManager implements IUserSearchManager { + + private final List userSearchListeners = new ArrayList(5); + protected ICriteria criteria; + + /** + * Add the listener to be notify by events + * @param listener + */ + public void addListener(IUserSearchListener l) { + synchronized (userSearchListeners) { + userSearchListeners.add(l); + } + } + + public void removeListener(IUserSearchListener l) { + synchronized (userSearchListeners) { + userSearchListeners.remove(l); + } + } + + /** + * Fires a user search event + * + * @param event + */ + public void fireUserSearchEvent(IUserSearchEvent event) { + List toNotify = null; + // Copy array + synchronized (userSearchListeners) { + toNotify = new ArrayList(userSearchListeners); + } + // Notify all in toNotify + for (Iterator i = toNotify.iterator(); i.hasNext();) { + IUserSearchListener l = (IUserSearchListener) i.next(); + l.handleUserSearchEvent(event); + } + } + + /** + * Returns a default implementation for IUserSearchListner + * @return IUserSearchListener + */ + public IUserSearchListener getUserSearchListner() { + return new UserListener(); + } + + public class UserListener implements IUserSearchListener { + + public void handleUserSearchEvent(IUserSearchEvent event) { + try { + if (event instanceof IUserSearchCompleteEvent) { + //ISearch searchResult = ((IUserSearchCompleteEvent) event).getSearch(); + } else if (event instanceof IUserSearchEvent) { + ISearch searchResult = search(criteria); + fireUserSearchEvent(new UserSearchCompleteEvent(searchResult)); + } + + } catch (UserSearchException e) { + e.printStackTrace(); + } + + } + + } + +} Index: src/org/eclipse/ecf/presence/search/IResultList.java =================================================================== RCS file: src/org/eclipse/ecf/presence/search/IResultList.java diff -N src/org/eclipse/ecf/presence/search/IResultList.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ecf/presence/search/IResultList.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2008 Marcelo Mayworm. All rights reserved. This + * program and the accompanying materials are made available under the terms of + * the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Marcelo Mayworm - initial API and implementation + * + ******************************************************************************/ + +package org.eclipse.ecf.presence.search; + +import java.util.Collection; +import org.eclipse.core.runtime.IAdaptable; + +/** + * This interface provides methods to handle the result list that match the search. + * @since 3.0 + */ +public interface IResultList extends IAdaptable { + + /** + * Get results that match the search. Instances of list are of type + * {@link IResult} + * + * @return Collection of IResult. Will not return null. + * May return an empty Collection. + */ + public Collection geResults(); + + /** + * Get the result that math the specific field and value + * @param field field's name used as argument to try to match the search + * @param value value for the respective field used as argument to try to match the search + * @return IResult will be null case it doesn't exist + */ + public IResult getResult(String field, String value); +} #P org.eclipse.ecf.provider.msn Index: src/org/eclipse/ecf/internal/provider/msn/MSNContainer.java =================================================================== RCS file: /cvsroot/rt/org.eclipse.ecf/providers/bundles/org.eclipse.ecf.provider.msn/src/org/eclipse/ecf/internal/provider/msn/MSNContainer.java,v retrieving revision 1.31 diff -u -r1.31 MSNContainer.java --- src/org/eclipse/ecf/internal/provider/msn/MSNContainer.java 3 Nov 2007 12:58:41 -0000 1.31 +++ src/org/eclipse/ecf/internal/provider/msn/MSNContainer.java 21 Jan 2009 23:42:37 -0000 @@ -63,6 +63,12 @@ import org.eclipse.ecf.presence.roster.IRosterManager; import org.eclipse.ecf.presence.roster.IRosterSubscriptionListener; import org.eclipse.ecf.presence.roster.IRosterSubscriptionSender; +import org.eclipse.ecf.presence.search.ICriteria; +import org.eclipse.ecf.presence.search.ISearch; +import org.eclipse.ecf.presence.search.IRestriction; +import org.eclipse.ecf.presence.search.IUserSearchListener; +import org.eclipse.ecf.presence.search.IUserSearchManager; +import org.eclipse.ecf.presence.search.UserSearchException; import org.eclipse.ecf.presence.service.IPresenceService; import org.eclipse.ecf.protocol.msn.ChatSession; import org.eclipse.ecf.protocol.msn.Contact; @@ -758,4 +764,48 @@ return null; } + /** + * TODO Implement a User Search Manager for MSN + * for while it just returns a manger + * to inform that user search is not allow + * for this provider see {@link IUserSearchManager#isEnabled()} + */ + public IUserSearchManager getUserSearchManager() { + return new IUserSearchManager(){ + + public ICriteria createCriteria() { + // TODO Auto-generated method stub + return null; + } + + public IRestriction createSelection() { + // TODO Auto-generated method stub + return null; + } + + public String[] getUserPropertiesFields() + throws ContainerConnectException { + // TODO Auto-generated method stub + return null; + } + + public boolean isEnabled() { + // TODO Auto-generated method stub + return false; + } + + public ISearch search(ICriteria criteria) + throws UserSearchException { + // TODO Auto-generated method stub + return null; + } + + public void search(ICriteria criteria, IUserSearchListener listener) { + // TODO Auto-generated method stub + + } + + }; + } + } #P org.eclipse.ecf.tests.presence Index: src/org/eclipse/ecf/tests/presence/AbstractSearchTest.java =================================================================== RCS file: src/org/eclipse/ecf/tests/presence/AbstractSearchTest.java diff -N src/org/eclipse/ecf/tests/presence/AbstractSearchTest.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ecf/tests/presence/AbstractSearchTest.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2008 Marcelo Mayworm. All rights reserved. This + * program and the accompanying materials are made available under the terms of + * the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Marcelo Mayworm - initial API and implementation + * + ******************************************************************************/ +package org.eclipse.ecf.tests.presence; + + +public abstract class AbstractSearchTest extends AbstractPresenceTestCase { + + public static final int CLIENT_COUNT = 1; + public static final int WAITTIME = 3000; + + protected void setUp() throws Exception { + setClientCount(CLIENT_COUNT); + clients = createClients(); + } + +}