package esmska.data;
import esmska.transfer.GatewayExecutor.Problem;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.ImageIcon;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.Validate;
/** SMS entity class
*
* @author ripper
*/
public class SMS {
private static final Logger logger = Logger.getLogger(SMS.class.getName());
private String number; //recipient number
private String name; //recipient name
private String text; //message text
private ImageIcon image; //security image
private String imageCode = ""; //security image code
private String imageHint; //hint from gateway where to find security image (eg. sent to cell)
private String gateway;
private Status status = Status.NEW; //sms status
private String supplMsg = ""; //supplemental message from gateway about remaining credit, etc
private Tuple<Problem, String> problem; //problem enum, string param
private String id; //message ID, useful when splitting/joining message parts
/** Status of SMS */
public static enum Status {
/** newly created, still not in the queue */
NEW,
/** waiting in the queue, but still not ready (waiting for delay, etc) */
WAITING,
/** waiting in the queue, ready to be sent */
READY,
/** currently being sent */
SENDING,
/** successfully sent */
SENT;
}
/** Shortcut for SMS(number, text, gateway, null, null). */
public SMS(String number, String text, String gateway) {
this(number, text, gateway, null, null);
}
/** Constructs new SMS. For detailed parameters restrictions see individual setter methods.
* @param number not null nor empty
* @param text not null
* @param gateway not null nor empty
* @param name
* @param id
*/
public SMS(String number, String text, String gateway, String name, String id) {
setNumber(number);
setText(text);
setGateway(gateway);
setName(name);
setId(id);
}
/** Generate a new random message ID and return it. */
public static String generateID() {
String newId = Long.toString(System.currentTimeMillis());
newId += "#" + RandomStringUtils.randomAlphanumeric(4);
return newId;
}
/** Get signature matching current gateway or null if no such found. */
private Signature getSignature() {
Gateway gw = Gateways.getInstance().get(gateway);
if (gw == null) {
return null;
}
String sigName = gw.getConfig().getSignature();
Signature signature = Signatures.getInstance().get(sigName);
return signature;
}
/** Return whether some error occured during sending.
* SMS is problematic if there is some problem stored.
*/
public boolean isProblematic() {
return problem != null;
}
/** Return name of the recipient, or if that's empty, his number
*/
public String getRecipient() {
return StringUtils.defaultIfEmpty(name, number);
}
// <editor-fold defaultstate="collapsed" desc="Get Methods">
/** Recepient number in international format (starting with "+").
Never null nor empty. */
public String getNumber() {
return number;
}
/** Text of the message. Never null. */
public String getText() {
return text;
}
/** Sender number. Never null. */
public String getSenderNumber() {
return getSignature() == null ? "" : getSignature().getUserNumber();
}
/** Sender name. Never null. */
public String getSenderName() {
return getSignature() == null ? "" : getSignature().getUserName();
}
/** Security image. May be null. */
public ImageIcon getImage() {
return image;
}
/** Security image code. Never null. */
public String getImageCode() {
return imageCode;
}
/** Hint from gateway where to find security image. May be null. */
public String getImageHint() {
return imageHint;
}
/** Gateway of the message. Never null nor empty. */
public String getGateway() {
return gateway;
}
/** Status of the message. Never null. */
public Status getStatus() {
return status;
}
/** Name of the recepient. Never null. */
public String getName() {
return name;
}
/** Get the message ID. Never empty. This ID is used to mark different
* parts (fragments) of the same message - they share its ID.
*/
public String getId() {
return id;
}
/** Supplemental message from gateway. Never null. */
public String getSupplMsg() {
return supplMsg;
}
/** Get the current problem this SMS has. May be null. */
public Tuple<Problem, String> getProblem() {
return problem;
}
// </editor-fold>
// <editor-fold defaultstate="collapsed" desc="Set Methods">
/** Recepient number in international format (starting with "+").
May not be null nor empty. */
public void setNumber(String number) {
Validate.notEmpty(number);
if (!number.startsWith("+")) {
throw new IllegalArgumentException("Number does not start with '+': " + number);
}
this.number = number;
}
/** Text of the message. Not null. */
public void setText(String text) {
Validate.notNull(text);
this.text = text;
}
/** Security image. May be null. */
public void setImage(ImageIcon image) {
this.image = image;
}
/** Security image code. Null value is changed to empty string. */
public void setImageCode(String imageCode) {
this.imageCode = StringUtils.defaultString(imageCode);
}
/** Hint from gateway where to find security image. May be null. */
public void setImageHint(String imageHint) {
this.imageHint = imageHint;
}
/** Gateway of the message. May not be null nor empty. */
public void setGateway(String gateway) {
Validate.notEmpty(gateway);
this.gateway = gateway;
}
/** Status of the message. May not be null. */
void setStatus(Status status) {
Validate.notNull(status);
if (this.status != status) {
logger.log(Level.FINER, "SMS {0} has a new status: {1}",
new Object[]{this, status});
}
this.status = status;
}
/** Name of the recipient. Null value is changed to empty string. */
public void setName(String name) {
this.name = StringUtils.defaultString(name);
}
/** Message from gateway. Null value is changed to empty string. */
public void setSupplMsg(String supplMsg) {
supplMsg = StringUtils.defaultString(supplMsg);
if (!StringUtils.equals(supplMsg, this.supplMsg)) {
logger.log(Level.FINER, "SMS {0} has a new supplemental message: {1}",
new Object[]{this, supplMsg});
}
this.supplMsg = supplMsg;
}
/** Set the current problem this SMS has. */
public void setProblem(Tuple<Problem, String> problem) {
if (!ObjectUtils.equals(problem, this.problem) && problem != null) {
logger.log(Level.FINER, "SMS {0} has a new problem: {1}",
new Object[]{this, problem});
}
this.problem = problem;
}
/** Set the message ID. If empty or null, a random ID is generated. This ID
* is used to mark different parts (fragments) of the same message - they
* share its ID.
*/
public void setId(String id) {
if (StringUtils.isEmpty(id)) {
this.id = generateID();
} else {
this.id = id;
}
}
// </editor-fold>
@Override
public String toString() {
return "[recipient=" + StringUtils.defaultIfEmpty(name, Contact.anonymizeNumber(number)) +
", gateway=" + gateway + "]";
}
/** Return very detailed description of the instance, used mainly for
* debugging purposes.
*/
public String toDebugString() {
return "[name=" + name + ", number=" + Contact.anonymizeNumber(number) +
", gateway=" + gateway + ", status=" + status + ", supplMsg=" +
supplMsg + ", problem=" + problem + "]";
}
}