package com.sissi.protocol.presence; import java.util.Iterator; import java.util.List; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElements; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlTransient; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.sissi.commons.Trace; import com.sissi.context.JID; import com.sissi.context.StatusClauses; import com.sissi.field.Field; import com.sissi.field.Fields; import com.sissi.field.impl.BeanFields; import com.sissi.io.read.Collector; import com.sissi.io.read.Metadata; import com.sissi.protocol.Protocol; import com.sissi.protocol.error.ServerError; import com.sissi.protocol.muc.Destory; import com.sissi.protocol.muc.Item; import com.sissi.protocol.muc.ItemAffiliation; import com.sissi.protocol.muc.ItemRole; import com.sissi.protocol.muc.XMuc; import com.sissi.protocol.muc.XUser; import com.sissi.protocol.offline.Delay; /** * @author kim 2013-10-28 */ @Metadata(uri = Presence.XMLNS, localName = Presence.NAME) @XmlRootElement public class Presence extends Protocol implements com.sissi.context.Status, Fields, Collector { public final static String XMLNS = "jabber:client"; public final static String NAME = "presence"; private final static XMuc muc = new XMuc(); private final static BeanFields empty = new BeanFields(false); private final static Log log = LogFactory.getLog(Presence.class); private PresenceClauses presenceClauses = new PresenceClauses(); private BeanFields fields; private Delay delay; private PresenceShow show; private PresenceStatus status; private PresencePriority priority; private boolean fields() { return this.fields != null; } private boolean status() { return PresenceType.parse(this.getType()).in(PresenceType.AVAILABLE, PresenceType.UNAVAILABLE); } private Presence show(String show) { this.show = new PresenceShow(show); return this; } private Presence avator(String type) { this.add(new XVCard().add(new XVCardPhoto(type))); return this; } private Presence priority(String priority) { try { this.priority = priority != null ? new PresencePriority(priority) : null; } catch (Exception e) { log.debug(e.toString()); Trace.trace(log, e); } return this; } public boolean valid() { return PresenceType.parse(this.getType()) != PresenceType.NONE; } private XVCard findXVard() { return XVCard.class.cast(this.fields() ? this.fields.findField(XVCard.NAME, XVCard.class) : null); } public Presence type(PresenceType type) { super.setType(type.toString()); if (!this.status()) { this.fields = null; this.priority = null; this.show = null; this.status = null; } return this; } public Presence destory(Destory destory) { return this.type(PresenceType.UNAVAILABLE).add(new XUser().destory(destory).item(new Item().setAffiliation(ItemAffiliation.NONE.toString()).setRole(ItemRole.NONE.toString()))); } public Presence setFrom(JID from) { super.setFrom(from.asString()); return this; } public Presence setTo(JID to) { super.setTo(to); return this; } public Presence delay(Delay delay) { this.delay = delay; return this; } @XmlElement public Delay getDelay() { return this.delay; } public int priority(int def) { return this.priority != null ? this.priority.priority(def) : def; } @XmlElement public Integer getPriority() { return this.priority != null ? this.priority.priority() : null; } @XmlElement(name = PresenceShow.NAME) public String getShowAsText() { return this.show != null ? this.show.getText() : null; } @XmlElement(name = PresenceStatus.NAME) public String getStatusAsText() { return this.status != null ? this.status.getText() : null; } @XmlTransient public String getAvatorAsText() { XVCard x = this.findXVard(); XVCardPhoto xp = x != null ? x.findField(XVCardPhoto.NAME, XVCardPhoto.class) : null; return xp != null ? xp.getValue() : null; } public Presence show(PresenceShow show) { this.show = show; return this; } public Presence status(String status) { this.status = new PresenceStatus(status); return this; } public Presence status(PresenceStatus status) { this.status = status; return this; } @Override public Presence clauses(StatusClauses clauses) { this.fields = this.fields != null ? this.fields.reset() : this.fields; this.show(clauses.find(StatusClauses.KEY_SHOW)).status(clauses.find(StatusClauses.KEY_STATUS)).avator(clauses.find(StatusClauses.KEY_AVATOR)).priority(clauses.find(StatusClauses.KEY_PRIORITY)).setType(clauses.find(StatusClauses.KEY_TYPE)); return this; } @Override public StatusClauses clauses() { return this.presenceClauses; } @XmlElements({ @XmlElement(name = XVCardPhoto.NAME, type = XVCardPhoto.class), @XmlElement(name = XVCard.NAME, type = XVCard.class), @XmlElement(name = XMuc.NAME, type = XMuc.class), @XmlElement(name = XUser.NAME, type = XUser.class) }) public List<Field<?>> getFields() { return this.fields() ? this.fields.getFields() : empty.getFields(); } public Presence reset() { if (this.fields()) { this.fields.reset(); } return this; } public Presence clear() { super.clear(); this.reset(); this.show = null; this.status = null; return this; } @XmlElement public ServerError getError() { return super.getError(); } @Override public Iterator<Field<?>> iterator() { return this.fields() ? this.fields.iterator() : empty.iterator(); } @Override public boolean isEmbed() { return this.fields() ? this.fields.isEmbed() : empty.isEmbed(); } public boolean isEmpty() { return this.fields() ? this.fields.isEmpty() : empty.isEmpty(); } @Override public Presence add(Field<?> field) { if (!this.fields()) { this.fields = new BeanFields(false); } this.fields.add(field); return this; } public Presence clone() { return new Presence().clauses(this.clauses()).setFrom(this.getFrom()).setTo(this.getTo()).setType(this.getType()).cast(Presence.class); } public Fields findFields(String name) { return this.fields() ? this.fields.findFields(name) : empty.findFields(name); } @Override public <T extends Field<?>> T findField(String name, Class<T> clazz) { return this.fields() ? this.fields.findField(name, clazz) : empty.findField(name, clazz); } @Override public void set(String localName, Object ob) { switch (localName) { case X.NAME: this.add(Field.class.cast(ob)); return; case PresenceStatus.NAME: this.status((PresenceStatus) ob); return; case PresenceShow.NAME: this.show((PresenceShow) ob); return; case PresencePriority.NAME: this.priority = PresencePriority.class.cast(ob); return; } } public static Presence muc() { return new Presence().add(Presence.muc); } private class PresenceClauses implements StatusClauses { @Override public String find(String key) { switch (key) { case StatusClauses.KEY_TYPE: return Presence.this.getType(); case StatusClauses.KEY_SHOW: return Presence.this.getShowAsText(); case StatusClauses.KEY_STATUS: return Presence.this.getStatusAsText(); case StatusClauses.KEY_AVATOR: return Presence.this.getAvatorAsText(); case StatusClauses.KEY_PRIORITY: return String.valueOf(Presence.this.getPriority()); } return null; } } }