package com.sissi.protocol;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlElements;
import javax.xml.bind.annotation.XmlRootElement;
import com.sissi.io.read.Metadata;
import com.sissi.io.write.WriterFragement;
import com.sissi.io.write.WriterPart;
import com.sissi.protocol.error.ServerError;
import com.sissi.protocol.feature.Bind;
import com.sissi.protocol.feature.Mechanisms;
import com.sissi.protocol.feature.Register;
import com.sissi.protocol.feature.Session;
import com.sissi.protocol.feature.Starttls;
/**
* @author Kim.shen 2013-10-16
*/
@Metadata(uri = Stream.XMLNS, localName = Stream.NAME)
@XmlRootElement(namespace = Stream.XMLNS)
@WriterFragement(part = WriterPart.WITHOUT_LAST)
public class Stream extends Protocol {
public final static String XMLNS = "http://etherx.jabber.org/streams";
public final static String NAME = "stream";
private final String xmlns = "jabber:client";
private final AtomicBoolean isUsing = new AtomicBoolean();
private List<Feature> features;
private String version;
private String stream;
/**
* XMPP流是否已开启
*
* @return
*/
public Stream consume() {
this.isUsing.set(true);
return this;
}
public boolean consumed() {
return this.isUsing.get();
}
/*
* 已有ID则使用否则使用UUID创建
*
* @see com.sissi.protocol.Protocol#getId()
*/
public String getId() {
return super.getId() != null ? super.getId() : UUID.randomUUID().toString();
}
/**
* Xmlns校验
*
* @return
*/
public boolean xmlns() {
return this.stream != null && this.stream.equals(Stream.XMLNS);
}
@XmlAttribute
public String getXmlns() {
return this.xmlns;
}
/**
* Version校验
*
* @param version
* @return
*/
public boolean version(String version) {
return version.compareTo(this.version) >= 0;
}
@XmlAttribute
public String getVersion() {
return this.version;
}
public Stream setVersion(String version) {
this.version = version;
return this;
}
public Stream setStream(String stream) {
this.stream = stream;
return this;
}
public Stream addFeature(Feature... features) {
if (this.features == null) {
this.features = new ArrayList<Feature>();
}
for (Feature feature : features) {
this.features.add(feature);
}
return this;
}
@XmlElementWrapper(namespace = Stream.XMLNS, name = "features")
@XmlElements({ @XmlElement(name = Starttls.NAME, type = Starttls.class), @XmlElement(name = Mechanisms.NAME, type = Mechanisms.class), @XmlElement(name = Bind.NAME, type = Bind.class), @XmlElement(name = Session.NAME, type = Session.class), @XmlElement(name = Register.NAME, type = Register.class) })
public List<Feature> getFeatures() {
return this.features;
}
@XmlElement(namespace = Stream.XMLNS, name = ServerError.NAME)
public ServerError getError() {
return super.getError();
}
/**
* 安全关闭
*
* @return
*/
public static Stream closeGraceFully() {
return CloseGracefully.close;
}
/**
* XMPP流初始化失败后关闭
*
* @param error
* @return
*/
public static Stream closeWhenOpening(Error error) {
return new CloseWhenOpening(error);
}
/**
* XMPP流交互时失败后关闭
*
* @param error
* @return
*/
public static Stream closeWhenRunning(Error error) {
return new CloseWhenRunning(error);
}
@WriterFragement(part = WriterPart.WITH_LAST)
public static class CloseGracefully extends Stream {
private final static CloseGracefully close = new CloseGracefully();
private final List<Feature> empty = new ArrayList<Feature>();
private CloseGracefully() {
}
public List<Feature> getFeatures() {
return empty;
}
}
public static class CloseWhenOpening extends Stream {
private CloseWhenOpening() {
}
private CloseWhenOpening(Error error) {
super.setError(error);
}
}
@WriterFragement(part = WriterPart.WITHOUT_FIRST)
public static class CloseWhenRunning extends Stream {
private CloseWhenRunning() {
}
private CloseWhenRunning(Error error) {
super.setError(error);
}
}
}