/**
* \package com.bluevia.messagery.mt.sms This package contains the classes in order to semd SMS using Bluevia API.
* \package com.bluevia.messagery.mt.sms.client This package contains REST client to send SMS using Bluevia API.
*/
package com.bluevia.messagery.mt.sms.client;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import org.apache.log4j.Logger;
import com.bluevia.commons.Encoding;
import com.bluevia.commons.Entity;
import com.bluevia.commons.GsdpConstants;
import com.bluevia.commons.Utils;
import com.bluevia.commons.connector.GenericResponse;
import com.bluevia.commons.data.JaxbEntity;
import com.bluevia.commons.data.UserId;
import com.bluevia.commons.exception.BlueviaException;
import com.bluevia.commons.exception.ConnectorException;
import com.bluevia.commons.parser.SerializeException;
import com.bluevia.commons.parser.xml.XmlConstants;
import com.bluevia.commons.parser.xml.XmlParser;
import com.bluevia.commons.parser.xml.XmlSerializer;
import com.bluevia.messagery.mt.client.BVMtClient;
import com.bluevia.messagery.mt.data.DeliveryInfo;
import com.bluevia.messagery.mt.data.DeliveryInfoList;
import com.telefonica.schemas.unica.rest.common.v1.SimpleReferenceType;
import com.telefonica.schemas.unica.rest.common.v1.UserIdType;
import com.telefonica.schemas.unica.rest.sms.v1.SMSDeliveryStatusType;
import com.telefonica.schemas.unica.rest.sms.v1.SMSTextType;
/**
*
* Abstract client interface for the REST binding of the Bluevia SMS MT Service.
*
* @author Telefonica R&D
*
*/
public abstract class BVMtSmsClient extends BVMtClient {
private static Logger log = Logger.getLogger(BVMtSmsClient.class.getName());
/**
* Initializer for common attributes
*/
protected void init(){
// TODO Revisar mBaseUri ()
//mBaseUri += buildUri(mMode, FEED_SMS_BASE_URI) + FEED_OUTBOUND_REQUESTS;
mEncoding = Encoding.APPLICATION_XML;
mParser = new XmlParser();
mSerializer = new XmlSerializer();
}
/**
*
* Allows to send and SMS to the gSDP. Sent SMS notifications will be received in the endpoint.
* The SMSID of the sent SMS is returned in order to ask later for the status of the message as well.
* The max length of the message must be less than 160 characters.
* @param destination the addresses of the recipients of the message
* @param text the text of the message
* @param originAddress the origingAdress
* @param senderName the name of sender
* @param payer the payer
* @param endpoint the endpoint to receive notifications of sent SMSs
* @param correlator the correlator
*
* @return the sent SMS ID
* @throws BlueviaException
* @throws IOException
*/
protected String send(ArrayList<String> destination, String text, UserId originAddress, String senderName, String payer, String endpoint, String correlator) throws BlueviaException, IOException {
SMSTextType message = new SMSTextType();
if (!Utils.isEmpty(endpoint)) {
SimpleReferenceType srt= new SimpleReferenceType();
srt.setCorrelator(correlator);
srt.setEndpoint(endpoint);
message.setReceiptRequest(srt);
}
message.setMessage(text);
message.setOriginAddress(originAddress.toUserIdType());
if (!Utils.isEmpty(senderName)) {
message.setSenderName(senderName);
}
ArrayList<UserIdType> destinations= new ArrayList<UserIdType>();
for (String number: destination) {
UserIdType destinationList= new UserIdType();
destinationList.setPhoneNumber(number);
destinations.add(destinationList);
}
message.setAddress(destinations);
return sendSmsMessage(message, payer);
}
/**
* Allows to send and SMS to the gSDP. It returns a String containing the SMSID of the sent SMS,
* in order to ask later for the status of the message.
* The max length of the message must be less than 160 characters.
*
* @param message the message to send via SMS. Message includes both message and message properties like senders, etc
* @return the sent SMS ID
* @throws BlueviaException
* @throws SerializeException
* @throws IOException
*/
protected String sendSmsMessage(SMSTextType message, String payer) throws BlueviaException, SerializeException, IOException {
String result = null;
// TODO: Check Message?
//checkMessage(message);
GenericResponse response = null;
InputStream is = null;
try {
HashMap<String, String> params = new HashMap<String, String>();
params.put(XmlConstants.PARAM_VERSION_KEY, XmlConstants.VERSION_1);
JaxbEntity messageEntity= new JaxbEntity();
messageEntity.setJcInstance(XmlConstants.XSD_SMS_API_INSTANCE);
messageEntity.setNamespace(XmlConstants.NS_SMS_API_URI);
messageEntity.setQname(XmlConstants.XSD_SMSTEXTTYPE_SMSTEXT);
messageEntity.setObject(message);
byte[] bytes = serializeEntity(messageEntity);
String uri = mBaseUri;
HashMap<String, String> headers = new HashMap<String, String>();
headers.put(GsdpConstants.HEADER_CONTENT_TYPE, getEncoding(mEncoding));
if (!Utils.isEmpty(payer)) {
headers.put(HEADER_X_CHARGED_ID, payer);
}
response = mConnector.create(uri, params, bytes, headers);
is = response.getAdditionalData().getBody();
result = getMesageIdFromResponse(response.getAdditionalData().getHeaders(), uri);
} catch (ConnectorException e){
if (e.getAdditionalData().getBody() == null)
throw e;
else {
is = e.getAdditionalData().getBody();
String error = parseError(is);
throw new ConnectorException(error, e.getCode());
}
} finally {
//Close the stream
if (is != null)
try {
is.close();
} catch (IOException e) {
log.info(e.getMessage(), e);
}
}
return result;
}
/**
*
* Allows to know the delivery status of a previous sent message using Bluevia API
*
* @param messageId the id of the message previously sent using this API
* @return an arrayList containing the DeliveryInfo for each destination address from the sent message.
* @throws BlueviaException
* @throws IOException
*
*/
public ArrayList<DeliveryInfo> getDeliveryStatus(String messageId) throws BlueviaException, IOException {
ArrayList<DeliveryInfo> status = null;
if (Utils.isEmpty(messageId))
throw new BlueviaException("Bad request: messageId is either null or empty", BlueviaException.BAD_REQUEST_EXCEPTION);
//Build the status feed uri
String feedUri = "/" + messageId + DELIVERY_STATUS_PATH;
HashMap<String, String> parameters = new HashMap<String, String>();
parameters.put(XmlConstants.PARAM_VERSION_KEY, XmlConstants.VERSION_1);
((XmlParser) mParser).setParseClass(SMSDeliveryStatusType.class);
Entity response = retrieve(feedUri, parameters);
//Check if response is instance of JaxbEntity
if ((response == null) || (! (response instanceof JaxbEntity)))
throw new BlueviaException("Error during request. Response received does not correspond to an DeliveryInfo",
BlueviaException.INTERNAL_CLIENT_ERROR);
JaxbEntity parseEntity= (JaxbEntity) response;
//Check if parseEntity is instance of SMSDeliveryStatusType
SMSDeliveryStatusType deliveryStatusType= new SMSDeliveryStatusType();
if ((parseEntity.getObject() == null) || (! (parseEntity.getObject() instanceof SMSDeliveryStatusType)))
throw new BlueviaException("Error during request. Response received does not correspond to an DeliveryInfo",
BlueviaException.INTERNAL_CLIENT_ERROR);
deliveryStatusType = (SMSDeliveryStatusType) parseEntity.getObject();
log.debug("Creating response List of DeliveryInfo");
Entity retEntity = new DeliveryInfoList(deliveryStatusType);
//Check if response is instance of DeliveryInfo
if ((retEntity == null) || (! (retEntity instanceof DeliveryInfoList)))
throw new BlueviaException("Error during request. Response received does not correspond to an DeliveryInfo",
BlueviaException.INTERNAL_CLIENT_ERROR);
//Set the response
status = ((DeliveryInfoList) retEntity).getDeliveryStatusList();
if (status.isEmpty())
throw new BlueviaException("The DeliveryInfo received is empty",
BlueviaException.INTERNAL_CLIENT_ERROR);
return status;
}
}