/*
* Tigase Jabber/XMPP Server
* Copyright (C) 2004-2012 "Artur Hefczyc" <artur.hefczyc@tigase.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. Look for COPYING file in the top folder.
* If not, see http://www.gnu.org/licenses/.
*
* $Rev$
* Last modified by $Author$
* $Date$
*/
package tigase.xmpp.impl.roster;
//~--- non-JDK imports --------------------------------------------------------
import tigase.util.TigaseStringprepException;
import tigase.util.XMPPStringPrepFactory;
import tigase.xml.Element;
import tigase.xml.XMLUtils;
import tigase.xmpp.JID;
import tigase.xmpp.XMPPResourceConnection;
import static tigase.xmpp.impl.roster.RosterAbstract.SubscriptionType;
//~--- JDK imports ------------------------------------------------------------
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;
//~--- classes ----------------------------------------------------------------
/**
* Describe class RosterElement here.
*
*
* Created: Wed Oct 29 14:21:16 2008
*
* @author <a href="mailto:artur.hefczyc@tigase.org">Artur Hefczyc</a>
* @version $Rev$
*/
public class RosterElement implements RosterElementIfc {
private static final Logger log = Logger.getLogger(RosterElement.class.getName());
private static final String ELEM_NAME = "contact";
private static final String JID_ATT = "jid";
private static final String NAME_ATT = "name";
private static final String SUBS_ATT = "subs";
private static final String GRP_ATT = "groups";
private static final String OTHER_ATT = "other";
private static final String STRINGPREP_ATT = "preped";
private static final String ACTIVITY_ATT = "activity";
private static final String WEIGHT_ATT = "weight";
private static final String LAST_SEEN_ATT = "last-seen";
private static final double INITIAL_ACTIVITY_VAL = 1d;
private static final double INITIAL_WEIGHT_VAL = 1d;
protected static final long INITIAL_LAST_SEEN_VAL = 1000l;
// ~--- fields ---------------------------------------------------------------
private String[] groups = null;
private JID jid = null;
private String name = null;
private String otherData = null;
private long lastSeen = INITIAL_LAST_SEEN_VAL;
private double activity = INITIAL_ACTIVITY_VAL;
private double weight = INITIAL_WEIGHT_VAL;
private XMPPResourceConnection session = null;
private String stringpreped = null;
private SubscriptionType subscription = null;
private boolean presence_sent = false;
private Map<String, Boolean> onlineMap = new HashMap<String, Boolean>();
// private Element item = null;
// private boolean online = false;
private boolean modified = false;
private boolean persistent = true;
// ~--- constructors ---------------------------------------------------------
/**
* Creates a new <code>RosterElement</code> instance.
*
*
* @param roster_el
* @param session
* @throws TigaseStringprepException
*/
public RosterElement(Element roster_el, XMPPResourceConnection session)
throws TigaseStringprepException {
this.session = session;
if (roster_el.getName() == ELEM_NAME) {
this.stringpreped = roster_el.getAttribute(STRINGPREP_ATT);
setJid(roster_el.getAttribute(JID_ATT));
setName(roster_el.getAttribute(NAME_ATT));
if (roster_el.getAttribute(SUBS_ATT) == null) {
subscription = SubscriptionType.none;
} else {
subscription = SubscriptionType.valueOf(roster_el.getAttribute(SUBS_ATT));
}
String grps = roster_el.getAttribute(GRP_ATT);
if ((grps != null) && !grps.trim().isEmpty()) {
groups = grps.split(",");
}
String other_data = roster_el.getAttribute(OTHER_ATT);
if ((other_data != null) && !other_data.trim().isEmpty()) {
otherData = other_data;
}
String num_str = roster_el.getAttribute(ACTIVITY_ATT);
if (num_str != null) {
try {
activity = Double.parseDouble(num_str);
} catch (NumberFormatException nfe) {
log.warning("Incorrect activity field: " + num_str);
activity = INITIAL_ACTIVITY_VAL;
}
}
num_str = roster_el.getAttribute(WEIGHT_ATT);
if (num_str != null) {
try {
weight = Double.parseDouble(num_str);
} catch (NumberFormatException nfe) {
log.warning("Incorrect weight field: " + num_str);
weight = INITIAL_WEIGHT_VAL;
}
}
num_str = roster_el.getAttribute(LAST_SEEN_ATT);
if (num_str != null) {
try {
lastSeen = Long.parseLong(num_str);
} catch (NumberFormatException nfe) {
log.warning("Incorrect last seen field: " + num_str);
lastSeen = INITIAL_LAST_SEEN_VAL;
}
}
} else {
log.warning("Incorrect roster data: " + roster_el.toString());
}
}
/**
* Constructs ...
*
*
* @param jid
* @param name
* @param groups
* @param session
*/
public RosterElement(JID jid, String name, String[] groups,
XMPPResourceConnection session) {
this.stringpreped = XMPPStringPrepFactory.STRINGPREP_PROCESSOR;
this.session = session;
setJid(jid);
setName(name);
this.groups = groups;
this.subscription = SubscriptionType.none;
}
// ~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @param groups
*/
public void addGroups(String[] groups) {
if (groups != null) {
if (this.groups == null) {
this.groups = groups;
} else {
// Groups names must be unique
Set<String> groupsSet = new HashSet<String>();
for (String group : this.groups) {
groupsSet.add(group);
}
for (String group : groups) {
groupsSet.add(group);
}
this.groups = groupsSet.toArray(new String[groupsSet.size()]);
}
}
// item = null;
}
// ~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @return
*/
public String[] getGroups() {
return groups;
}
/**
* Method description
*
*
* @return
*/
public JID getJid() {
return jid;
}
/**
* Method description
*
*
* @return
*/
public String getName() {
return name;
}
/**
* Method description
*
*
* @return
*/
public String getOtherData() {
return otherData;
}
/**
* Method description
*
*
* @return
*/
public Element getRosterElement() {
Element elem =
new Element(ELEM_NAME,
new String[] { JID_ATT, SUBS_ATT, NAME_ATT, STRINGPREP_ATT }, new String[] {
jid.toString(), subscription.toString(), name, "" + stringpreped });
if ((groups != null) && (groups.length > 0)) {
String grps = "";
for (String group : groups) {
grps += group + ",";
}
grps = grps.substring(0, grps.length() - 1);
elem.setAttribute(GRP_ATT, grps);
}
if (otherData != null) {
elem.setAttribute(OTHER_ATT, otherData);
}
elem.setAttribute(ACTIVITY_ATT, Double.toString(activity));
elem.setAttribute(WEIGHT_ATT, Double.toString(weight));
elem.setAttribute(LAST_SEEN_ATT, Long.toString(lastSeen));
modified = false;
return elem;
}
/**
* Method description
*
*
* @return
*/
public Element getRosterItem() {
// This is actually not a good idea to cache the item element.
// This causes a huge memory consumption and usually the item
// is needed only once at the roster retrieving time.
// if (item == null) {
Element item = new Element("item");
item.setAttribute("jid", jid.toString());
item.addAttributes(subscription.getSubscriptionAttr());
if (name != null) {
item.setAttribute("name", XMLUtils.escape(name));
}
if (groups != null) {
for (String gr : groups) {
Element group = new Element("group");
group.setCData(XMLUtils.escape(gr));
item.addChild(group);
} // end of for ()
} // end of if-else
// }
return item;
}
public String toString() {
return getRosterItem().toString();
}
/**
* Method description
*
*
* @return
*/
public SubscriptionType getSubscription() {
return subscription;
}
/**
* Method description
*
*
* @return
*/
public boolean isModified() {
return modified;
}
/**
* Method description
*
*
* @return
*/
public boolean isOnline() {
return onlineMap.size() > 0;
}
/**
* Method description
*
*
* @return
*/
public boolean isPresence_sent() {
return presence_sent;
}
// ~--- set methods ----------------------------------------------------------
/**
* Method description
*
*
* @param groups
*/
public void setGroups(String[] groups) {
this.groups = groups;
modified = true;
// item = null;
}
/**
* Method description
*
*
* @param name
*/
public void setName(String name) {
if (name == null) {
this.name = this.jid.getLocalpart();
if ((this.name == null) || this.name.trim().isEmpty()) {
this.name = this.jid.getBareJID().toString();
}
modified = true;
} else {
this.name = name;
}
}
/**
* Method description
*
*
* @param online
*/
public void setOnline(String resource, boolean online) {
if (onlineMap != null) {
if (online) {
onlineMap.put(resource, Boolean.TRUE);
} else {
onlineMap.remove(resource);
}
}
}
/**
* Method description
*
*
* @param other_data
*/
public void setOtherData(String other_data) {
otherData = other_data;
}
/**
* Method description
*
*
* @param presence_sent
*/
public void setPresence_sent(boolean presence_sent) {
this.presence_sent = presence_sent;
}
/**
* Method description
*
*
* @param subscription
*/
public void setSubscription(SubscriptionType subscription) {
if (subscription == null) {
this.subscription = SubscriptionType.none;
} else {
this.subscription = subscription;
}
modified = true;
// item = null;
}
private void setJid(JID jid) {
this.jid = jid;
modified = true;
}
private void setJid(String jid) throws TigaseStringprepException {
if (XMPPStringPrepFactory.STRINGPREP_PROCESSOR.equals(stringpreped)) {
this.jid = JID.jidInstanceNS(jid);
} else {
this.jid = JID.jidInstance(jid);
modified = true;
}
stringpreped = XMPPStringPrepFactory.STRINGPREP_PROCESSOR;
}
/**
* @return
*/
public boolean isPersistent() {
return persistent;
}
public void setPersistent(boolean persistent) {
this.persistent = persistent;
}
/**
* @return the activity
*/
public double getActivity() {
return activity;
}
/**
* @param activity
* the activity to set
*/
public void setActivity(double activity) {
this.activity = activity;
if (activity != 0) {
weight = 1 / activity;
}
modified = true;
}
/**
* @return the weight
*/
public double getWeight() {
return weight;
}
/**
* @param weight
* the weight to set
*/
public void setWeight(double weight) {
this.weight = weight;
modified = true;
}
/**
* @return the lastSeen
*/
public long getLastSeen() {
return lastSeen;
}
/**
* @param lastSeen the lastSeen to set
*/
public void setLastSeen(long lastSeen) {
this.lastSeen = lastSeen;
modified = true;
}
}