1
0
Fork 0
mirror of https://github.com/vanitasvitae/Smack.git synced 2025-12-08 12:01:09 +01:00

Adding workgroup API (SMACK-185).

git-svn-id: http://svn.igniterealtime.org/svn/repos/smack/trunk@7400 b35dd754-fafc-0310-a699-88a17e54d16e
This commit is contained in:
Matt Tucker 2007-03-07 23:38:36 +00:00 committed by matt
parent 939feb9017
commit fe545abeae
64 changed files with 9744 additions and 0 deletions

View file

@ -0,0 +1,126 @@
/**
* $RCSfile$
* $Revision: 19406 $
* $Date: 2005-07-28 18:12:09 -0700 (Thu, 28 Jul 2005) $
*
* Copyright (C) 2003-2005 Jive Software. All rights reserved.
*
* This software is the proprietary information of Jive Software.
* Use is subject to license terms.
*/
package org.jivesoftware.smackx.workgroup.util;
import java.lang.reflect.Method;
import java.util.*;
/**
* This class is a very flexible event dispatcher which implements Runnable so that it can
* dispatch easily from a newly created thread. The usage of this in code is more or less:
* create a new instance of this class, use addListenerTriplet to add as many listeners
* as desired to be messaged, create a new Thread using the instance of this class created
* as the argument to the constructor, start the new Thread instance.<p>
*
* Also, this is intended to be used to message methods that either return void, or have
* a return which the developer using this class is uninterested in receiving.
*
* @author loki der quaeler
*/
public class ListenerEventDispatcher
implements Runnable {
protected transient ArrayList triplets;
protected transient boolean hasFinishedDispatching;
protected transient boolean isRunning;
public ListenerEventDispatcher () {
super();
this.triplets = new ArrayList();
this.hasFinishedDispatching = false;
this.isRunning = false;
}
/**
* Add a listener triplet - the instance of the listener to be messaged, the Method on which
* the listener should be messaged, and the Object array of arguments to be supplied to the
* Method. No attempts are made to determine whether this triplet was already added.<br>
*
* Messages are dispatched in the order in which they're added via this method; so if triplet
* X is added after triplet Z, then triplet Z will undergo messaging prior to triplet X.<br>
*
* This method should not be called once the owning Thread instance has been started; if it
* is called, the triplet will not be added to the messaging queue.<br>
*
* @param listenerInstance the instance of the listener to receive the associated notification
* @param listenerMethod the Method instance representing the method through which notification
* will occur
* @param methodArguments the arguments supplied to the notification method
*/
public void addListenerTriplet(Object listenerInstance, Method listenerMethod,
Object[] methodArguments)
{
if (!this.isRunning) {
this.triplets.add(new TripletContainer(listenerInstance, listenerMethod,
methodArguments));
}
}
/**
* @return whether this instance has finished dispatching its messages
*/
public boolean hasFinished() {
return this.hasFinishedDispatching;
}
public void run() {
ListIterator li = null;
this.isRunning = true;
li = this.triplets.listIterator();
while (li.hasNext()) {
TripletContainer tc = (TripletContainer)li.next();
try {
tc.getListenerMethod().invoke(tc.getListenerInstance(), tc.getMethodArguments());
} catch (Exception e) {
System.err.println("Exception dispatching an event: " + e);
e.printStackTrace();
}
}
this.hasFinishedDispatching = true;
}
protected class TripletContainer {
protected Object listenerInstance;
protected Method listenerMethod;
protected Object[] methodArguments;
protected TripletContainer (Object inst, Method meth, Object[] args) {
super();
this.listenerInstance = inst;
this.listenerMethod = meth;
this.methodArguments = args;
}
protected Object getListenerInstance() {
return this.listenerInstance;
}
protected Method getListenerMethod() {
return this.listenerMethod;
}
protected Object[] getMethodArguments() {
return this.methodArguments;
}
}
}

View file

@ -0,0 +1,106 @@
/**
* $RCSfile$
* $Revision: 38648 $
* $Date: 2006-12-27 01:46:18 -0800 (Wed, 27 Dec 2006) $
*
* Copyright (C) 2003-2005 Jive Software. All rights reserved.
*
* This software is the proprietary information of Jive Software.
* Use is subject to license terms.
*/
package org.jivesoftware.smackx.workgroup.util;
import org.jivesoftware.smackx.workgroup.MetaData;
import org.jivesoftware.smack.util.StringUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.util.*;
/**
* Utility class for meta-data parsing and writing.
*
* @author Matt Tucker
*/
public class MetaDataUtils {
/**
* Parses any available meta-data and returns it as a Map of String name/value pairs. The
* parser must be positioned at an opening meta-data tag, or the an empty map will be returned.
*
* @param parser the XML parser positioned at an opening meta-data tag.
* @return the meta-data.
* @throws XmlPullParserException if an error occurs while parsing the XML.
* @throws IOException if an error occurs while parsing the XML.
*/
public static Map parseMetaData(XmlPullParser parser) throws XmlPullParserException, IOException {
int eventType = parser.getEventType();
// If correctly positioned on an opening meta-data tag, parse meta-data.
if ((eventType == XmlPullParser.START_TAG)
&& parser.getName().equals(MetaData.ELEMENT_NAME)
&& parser.getNamespace().equals(MetaData.NAMESPACE)) {
Map metaData = new Hashtable();
eventType = parser.nextTag();
// Keep parsing until we've gotten to end of meta-data.
while ((eventType != XmlPullParser.END_TAG)
|| (!parser.getName().equals(MetaData.ELEMENT_NAME))) {
String name = parser.getAttributeValue(0);
String value = parser.nextText();
if (metaData.containsKey(name)) {
List values = (List)metaData.get(name);
values.add(value);
}
else {
List values = new ArrayList();
values.add(value);
metaData.put(name, values);
}
eventType = parser.nextTag();
}
return metaData;
}
return Collections.EMPTY_MAP;
}
/**
* Serializes a Map of String name/value pairs into the meta-data XML format.
*
* @param metaData the Map of meta-data.
* @return the meta-data values in XML form.
*/
public static String serializeMetaData(Map metaData) {
StringBuilder buf = new StringBuilder();
if (metaData != null && metaData.size() > 0) {
buf.append("<metadata xmlns=\"http://jivesoftware.com/protocol/workgroup\">");
for (Iterator i = metaData.keySet().iterator(); i.hasNext();) {
Object key = i.next();
Object value = metaData.get(key);
if (value instanceof List) {
List values = (List)metaData.get(key);
for (Iterator it = values.iterator(); it.hasNext();) {
String v = (String)it.next();
buf.append("<value name=\"").append(key).append("\">");
buf.append(StringUtils.escapeForXML(v));
buf.append("</value>");
}
}
else if (value instanceof String) {
buf.append("<value name=\"").append(key).append("\">");
buf.append(StringUtils.escapeForXML((String)value));
buf.append("</value>");
}
}
buf.append("</metadata>");
}
return buf.toString();
}
}

View file

@ -0,0 +1,318 @@
/**
* $RCSfile$
* $Revision: 38648 $
* $Date: 2006-12-27 01:46:18 -0800 (Wed, 27 Dec 2006) $
*
* Copyright (C) 2004-2005 Jive Software. All rights reserved.
*
* This software is the proprietary information of Jive Software.
* Use is subject to license terms.
*/
package org.jivesoftware.smackx.workgroup.util;
import java.util.*;
/**
* Utility methods frequently used by data classes and design-time
* classes.
*/
public final class ModelUtil {
private ModelUtil() {
// Prevents instantiation.
}
/**
* This is a utility method that compares two objects when one or
* both of the objects might be <CODE>null</CODE> The result of
* this method is determined as follows:
* <OL>
* <LI>If <CODE>o1</CODE> and <CODE>o2</CODE> are the same object
* according to the <CODE>==</CODE> operator, return
* <CODE>true</CODE>.
* <LI>Otherwise, if either <CODE>o1</CODE> or <CODE>o2</CODE> is
* <CODE>null</CODE>, return <CODE>false</CODE>.
* <LI>Otherwise, return <CODE>o1.equals(o2)</CODE>.
* </OL>
* <p/>
* This method produces the exact logically inverted result as the
* {@link #areDifferent(Object, Object)} method.<P>
* <p/>
* For array types, one of the <CODE>equals</CODE> methods in
* {@link java.util.Arrays} should be used instead of this method.
* Note that arrays with more than one dimension will require some
* custom code in order to implement <CODE>equals</CODE> properly.
*/
public static final boolean areEqual(Object o1, Object o2) {
if (o1 == o2) {
return true;
}
else if (o1 == null || o2 == null) {
return false;
}
else {
return o1.equals(o2);
}
}
/**
* This is a utility method that compares two Booleans when one or
* both of the objects might be <CODE>null</CODE> The result of
* this method is determined as follows:
* <OL>
* <LI>If <CODE>b1</CODE> and <CODE>b2</CODE> are both TRUE or
* neither <CODE>b1</CODE> nor <CODE>b2</CODE> is TRUE,
* return <CODE>true</CODE>.
* <LI>Otherwise, return <CODE>false</CODE>.
* </OL>
* <p/>
*/
public static final boolean areBooleansEqual(Boolean b1, Boolean b2) {
// !jwetherb treat NULL the same as Boolean.FALSE
return (b1 == Boolean.TRUE && b2 == Boolean.TRUE) ||
(b1 != Boolean.TRUE && b2 != Boolean.TRUE);
}
/**
* This is a utility method that compares two objects when one or
* both of the objects might be <CODE>null</CODE>. The result
* returned by this method is determined as follows:
* <OL>
* <LI>If <CODE>o1</CODE> and <CODE>o2</CODE> are the same object
* according to the <CODE>==</CODE> operator, return
* <CODE>false</CODE>.
* <LI>Otherwise, if either <CODE>o1</CODE> or <CODE>o2</CODE> is
* <CODE>null</CODE>, return <CODE>true</CODE>.
* <LI>Otherwise, return <CODE>!o1.equals(o2)</CODE>.
* </OL>
* <p/>
* This method produces the exact logically inverted result as the
* {@link #areEqual(Object, Object)} method.<P>
* <p/>
* For array types, one of the <CODE>equals</CODE> methods in
* {@link java.util.Arrays} should be used instead of this method.
* Note that arrays with more than one dimension will require some
* custom code in order to implement <CODE>equals</CODE> properly.
*/
public static final boolean areDifferent(Object o1, Object o2) {
return !areEqual(o1, o2);
}
/**
* This is a utility method that compares two Booleans when one or
* both of the objects might be <CODE>null</CODE> The result of
* this method is determined as follows:
* <OL>
* <LI>If <CODE>b1</CODE> and <CODE>b2</CODE> are both TRUE or
* neither <CODE>b1</CODE> nor <CODE>b2</CODE> is TRUE,
* return <CODE>false</CODE>.
* <LI>Otherwise, return <CODE>true</CODE>.
* </OL>
* <p/>
* This method produces the exact logically inverted result as the
* {@link #areBooleansEqual(Boolean, Boolean)} method.<P>
*/
public static final boolean areBooleansDifferent(Boolean b1, Boolean b2) {
return !areBooleansEqual(b1, b2);
}
/**
* Returns <CODE>true</CODE> if the specified array is not null
* and contains a non-null element. Returns <CODE>false</CODE>
* if the array is null or if all the array elements are null.
*/
public static final boolean hasNonNullElement(Object[] array) {
if (array != null) {
final int n = array.length;
for (int i = 0; i < n; i++) {
if (array[i] != null) {
return true;
}
}
}
return false;
}
/**
* Returns a single string that is the concatenation of all the
* strings in the specified string array. A single space is
* put between each string array element. Null array elements
* are skipped. If the array itself is null, the empty string
* is returned. This method is guaranteed to return a non-null
* value, if no expections are thrown.
*/
public static final String concat(String[] strs) {
return concat(strs, " "); //NOTRANS
}
/**
* Returns a single string that is the concatenation of all the
* strings in the specified string array. The strings are separated
* by the specified delimiter. Null array elements are skipped. If
* the array itself is null, the empty string is returned. This
* method is guaranteed to return a non-null value, if no expections
* are thrown.
*/
public static final String concat(String[] strs, String delim) {
if (strs != null) {
final StringBuilder buf = new StringBuilder();
final int n = strs.length;
for (int i = 0; i < n; i++) {
final String str = strs[i];
if (str != null) {
buf.append(str).append(delim);
}
}
final int length = buf.length();
if (length > 0) {
// Trim trailing space.
buf.setLength(length - 1);
}
return buf.toString();
}
else {
return ""; // NOTRANS
}
}
/**
* Returns <CODE>true</CODE> if the specified {@link String} is not
* <CODE>null</CODE> and has a length greater than zero. This is
* a very frequently occurring check.
*/
public static final boolean hasLength(String s) {
return (s != null && s.length() > 0);
}
/**
* Returns <CODE>null</CODE> if the specified string is empty or
* <CODE>null</CODE>. Otherwise the string itself is returned.
*/
public static final String nullifyIfEmpty(String s) {
return ModelUtil.hasLength(s) ? s : null;
}
/**
* Returns <CODE>null</CODE> if the specified object is null
* or if its <CODE>toString()</CODE> representation is empty.
* Otherwise, the <CODE>toString()</CODE> representation of the
* object itself is returned.
*/
public static final String nullifyingToString(Object o) {
return o != null ? nullifyIfEmpty(o.toString()) : null;
}
/**
* Determines if a string has been changed.
*
* @param oldString is the initial value of the String
* @param newString is the new value of the String
* @return true If both oldString and newString are null or if they are
* both not null and equal to each other. Otherwise returns false.
*/
public static boolean hasStringChanged(String oldString, String newString) {
if (oldString == null && newString == null) {
return false;
}
else if ((oldString == null && newString != null)
|| (oldString != null && newString == null)) {
return true;
}
else {
return !oldString.equals(newString);
}
}
public static String getTimeFromLong(long diff) {
final String HOURS = "h";
final String MINUTES = "min";
final String SECONDS = "sec";
final long MS_IN_A_DAY = 1000 * 60 * 60 * 24;
final long MS_IN_AN_HOUR = 1000 * 60 * 60;
final long MS_IN_A_MINUTE = 1000 * 60;
final long MS_IN_A_SECOND = 1000;
Date currentTime = new Date();
long numDays = diff / MS_IN_A_DAY;
diff = diff % MS_IN_A_DAY;
long numHours = diff / MS_IN_AN_HOUR;
diff = diff % MS_IN_AN_HOUR;
long numMinutes = diff / MS_IN_A_MINUTE;
diff = diff % MS_IN_A_MINUTE;
long numSeconds = diff / MS_IN_A_SECOND;
diff = diff % MS_IN_A_SECOND;
long numMilliseconds = diff;
StringBuilder buf = new StringBuilder();
if (numHours > 0) {
buf.append(numHours + " " + HOURS + ", ");
}
if (numMinutes > 0) {
buf.append(numMinutes + " " + MINUTES + ", ");
}
buf.append(numSeconds + " " + SECONDS);
String result = buf.toString();
return result;
}
/**
* Build a List of all elements in an Iterator.
*/
public static List iteratorAsList(Iterator i) {
ArrayList list = new ArrayList(10);
while (i.hasNext()) {
list.add(i.next());
}
return list;
}
/**
* Creates an Iterator that is the reverse of a ListIterator.
*/
public static Iterator reverseListIterator(ListIterator i) {
return new ReverseListIterator(i);
}
}
/**
* An Iterator that is the reverse of a ListIterator.
*/
class ReverseListIterator implements Iterator {
private ListIterator _i;
ReverseListIterator(ListIterator i) {
_i = i;
while (_i.hasNext())
_i.next();
}
public boolean hasNext() {
return _i.hasPrevious();
}
public Object next() {
return _i.previous();
}
public void remove() {
_i.remove();
}
}