/*******************************************************************************
* Open Behavioral Health Information Technology Architecture (OBHITA.org)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the <organization> nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
******************************************************************************/
package gov.samhsa.consent2share.infrastructure;
import java.util.Arrays;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import echosign.api.clientv20.dto.ArrayOfFileInfo;
import echosign.api.clientv20.dto.CallbackInfo;
import echosign.api.clientv20.dto.DocumentCreationInfo;
import echosign.api.clientv20.dto.FileInfo;
import echosign.api.clientv20.dto.Pong;
import echosign.api.clientv20.dto.SignatureFlow;
import echosign.api.clientv20.dto.SignatureType;
import echosign.api.clientv20.dto14.ArrayOfRecipientInfo;
import echosign.api.clientv20.dto14.GetDocumentsOptions;
import echosign.api.clientv20.dto14.RecipientInfo;
import echosign.api.clientv20.dto14.RecipientRole;
import echosign.api.clientv20.dto16.ArrayOfDocumentKey;
import echosign.api.clientv20.dto16.EmbeddedWidgetCreationResult;
import echosign.api.clientv20.dto16.GetDocumentsResult;
import echosign.api.clientv20.dto20.DocumentInfo;
import echosign.api.clientv20.dto8.GetFormDataResult;
import echosign.api.clientv20.dto8.WidgetCreationInfo;
import echosign.api.clientv20.dto8.WidgetPersonalizationInfo;
import echosign.api.clientv20.service.EchoSignDocumentService20Client;
import echosign.api.clientv20.service.EchoSignDocumentService20PortType;
/**
* The Class EchoSignSignatureServiceImpl.
*/
public class EchoSignSignatureServiceImpl implements EchoSignSignatureService {
/** The echo sign service url. */
private String echoSignServiceUrl;
/** The echo sign api key. */
private String echoSignApiKey;
/** The cached service. */
private EchoSignDocumentService20PortType cachedService;
/** The logger. */
private final Logger logger = LoggerFactory.getLogger(this.getClass());
/**
* Instantiates a new echo sign signature service impl.
*
* @param echoSignServiceUrl
* the echo sign service url
* @param echoSignApiKey
* the echo sign api key
*/
public EchoSignSignatureServiceImpl(String echoSignServiceUrl,
String echoSignApiKey) {
Assert.hasText(echoSignServiceUrl);
Assert.hasText(echoSignApiKey);
this.echoSignServiceUrl = echoSignServiceUrl;
this.echoSignApiKey = echoSignApiKey;
}
/**
* Gets the cached service.
*
* @return the cached service
*/
EchoSignDocumentService20PortType getCachedService() {
if (cachedService == null) {
EchoSignDocumentService20Client client = new EchoSignDocumentService20Client();
cachedService = client
.getEchoSignDocumentService20HttpPort(echoSignServiceUrl);
}
return cachedService;
}
/*
* (non-Javadoc)
*
* @see
* gov.samhsa.consent2share.domain.commondomainservices.SignatureService
* #sendDocumentToSign(byte[], java.lang.String, java.lang.String,
* java.lang.String, java.lang.String)
*/
@Override
public String sendDocumentToSign(byte[] documentBytes,
String documentFileName, String documentName,
String recipientEmail, String messageToRecipient) {
String documentKey = sendDocumentToSign(documentBytes,
documentFileName, documentName, recipientEmail,
messageToRecipient, null);
return documentKey;
}
/*
* (non-Javadoc)
*
* @see
* gov.samhsa.consent2share.domain.commondomainservices.SignatureService
* #sendDocumentToSign(byte[], java.lang.String, java.lang.String,
* java.lang.String, java.lang.String, java.lang.String)
*/
@Override
public String sendDocumentToSign(byte[] documentBytes,
String documentFileName, String documentName,
String recipientEmail, String messageToRecipient,
String signedDocumentUrl) {
Assert.notNull(documentBytes, "Document bytes must not be null.");
Assert.hasText(documentFileName,
"Document file name must not be null or empty.");
Assert.notNull(recipientEmail,
"Recipient email address must not be null.");
RecipientInfo recipientInfo = new RecipientInfo();
// email is required
recipientInfo.setEmail(recipientEmail);
// role is required
recipientInfo.setRole(RecipientRole.SIGNER);
ArrayOfRecipientInfo arrayOfRecipientInfo = new ArrayOfRecipientInfo();
arrayOfRecipientInfo.getRecipientInfo().add(recipientInfo);
FileInfo fileInfo = new FileInfo();
// fileName is required
fileInfo.setFileName(documentFileName);
// The raw file content, encoded using base64.
fileInfo.setFile(documentBytes);
ArrayOfFileInfo fileInfos = new ArrayOfFileInfo();
fileInfos.getFileInfo().add(fileInfo);
DocumentCreationInfo documentInfo = new DocumentCreationInfo();
// recipients is required
documentInfo.setRecipients(arrayOfRecipientInfo);
if (!StringUtils.hasText(documentName)) {
documentName = documentFileName;
}
// The name of the agreement, which will be used to identify it in the
// emails and on the website.
// name is required
documentInfo.setName(documentName);
if (StringUtils.hasText(messageToRecipient)) {
// An optional message to the recipient(s) describing to them what
// is being sent and/or why their signature is required.
documentInfo.setMessage(messageToRecipient);
}
// Optional parameter which sets how often you'd like the recipient(s)
// to be reminded to sign this document.
// reminderFrequency is not required
// documentInfo.setReminderFrequency(value);
if (StringUtils.hasText(signedDocumentUrl)) {
// Sets the callback properties that allows EchoSign to notify you
// when the agreement has been signed and avoid polling.
// callbackInfo is not required
CallbackInfo callbackInfo = new CallbackInfo();
callbackInfo.setSignedDocumentUrl(signedDocumentUrl);
documentInfo.setCallbackInfo(callbackInfo);
}
// The locale associated with this agreement - specifies the language
// for the signing page and emails, for example en_US or fr_FR. If none
// specified, defaults to the language configured for the widget's
// sender.
// locale is not required
// documentInfo.setLocale(value);
// Optional default values for fields to merge into the document. The
// values will be presented to the signers for editable fields; for
// read-only fields the provided values will not be editable during the
// signing process.
// mergeFieldInfo is not required
// documentInfo.setMergeFieldInfo(value);
documentInfo.setFileInfos(fileInfos);
documentInfo.setSignatureType(SignatureType.ESIGN);
documentInfo
.setSignatureFlow(SignatureFlow.SENDER_SIGNATURE_NOT_REQUIRED);
ArrayOfDocumentKey documentKeys = getCachedService().sendDocument(
echoSignApiKey, null, documentInfo);
String documentKey = documentKeys.getDocumentKey().get(0)
.getDocumentKey();
return documentKey;
}
/*
* (non-Javadoc)
*
* @see gov.samhsa.consent2share.infrastructure.EchoSignSignatureService#
* getDocumentInfo(java.lang.String)
*/
@Override
public DocumentInfo getDocumentInfo(String documentKey) {
Assert.hasText(documentKey, "Document key must not be null or empty.");
DocumentInfo info = getCachedService().getDocumentInfo(echoSignApiKey,
documentKey);
return info;
}
/*
* (non-Javadoc)
*
* @see gov.samhsa.consent2share.infrastructure.EchoSignSignatureService#
* getLatestDocument(java.lang.String)
*/
@Override
public byte[] getLatestDocument(String documentKey) {
Assert.hasText(documentKey, "Document key must not be null or empty.");
GetDocumentsOptions documentOptions = new GetDocumentsOptions();
GetDocumentsResult documentResult = getCachedService().getDocuments(
echoSignApiKey, documentKey, documentOptions);
return documentResult.getDocuments().getDocumentContent().get(0)
.getBytes();
}
/*
* (non-Javadoc)
*
* @see gov.samhsa.consent2share.infrastructure.EchoSignSignatureService#
* getChildDocumentKey(java.lang.String)
*/
@Override
public String getChildDocumentKey(String documentKey) {
GetFormDataResult getFormDataResult = getCachedService().getFormData(
echoSignApiKey, documentKey);
String formDataCsv = getFormDataResult.getFormDataCsv();
String childDocumentKey = null;
/* example of formdatacsv for signed consent from adobe
"completed","email","role","first","last","title","company","Document Key","Transaction Number"
"2015-04-16 13:34:48","sadhana.chandravanka@feisystems.com","SIGNER","check","Share","","","XM733SIL7K5R7GW","XM733SIXL4E5DXT"
example of formdatacsv for unsigned consent from adobe
"completed","email","role","first","last","title","company","Transaction Number"*/
if (formDataCsv != null) {
logger.info(formDataCsv);
String[] splittedFormDataCsv = formDataCsv.split("\\r?\\n");
String[] keys = splittedFormDataCsv[0].replace("\"", "").split(",");
int documentKeyIndex = Arrays.asList(keys).indexOf("Document Key");
if( documentKeyIndex != -1) {
String[] values = splittedFormDataCsv[1].replace("\"", "").split(",");
childDocumentKey = values[documentKeyIndex];
}
}
return childDocumentKey;
}
/**
* Test ping.
*
* @return the pong
*/
public Pong testPing() {
Pong pong = getCachedService().testPing(echoSignApiKey);
return pong;
}
/**
* Test echo file.
*
* @param input
* the input
* @return the byte[]
*/
public byte[] testEchoFile(byte[] input) {
byte[] output = getCachedService().testEchoFile(echoSignApiKey, input);
return output;
}
/*
* (non-Javadoc)
*
* @see
* gov.samhsa.consent2share.domain.commondomainservices.SignatureService
* #createEmbeddedWidget(byte[], java.lang.String, java.lang.String,
* java.lang.String, java.lang.String)
*/
@Override
public EmbeddedWidgetCreationResult createEmbeddedWidget(
byte[] documentBytes, String documentFileName, String documentName,
String signedDocumentUrl, String email) {
Assert.notNull(documentBytes, "Document bytes must not be null.");
Assert.hasText(documentFileName,
"Document file name must not be null or empty.");
FileInfo fileInfo = new FileInfo();
// fileName is required
fileInfo.setFileName(documentFileName);
// The raw file content, encoded using base64.
fileInfo.setFile(documentBytes);
ArrayOfFileInfo fileInfos = new ArrayOfFileInfo();
fileInfos.getFileInfo().add(fileInfo);
WidgetCreationInfo widgetInfo = new WidgetCreationInfo();
if (!StringUtils.hasText(documentName)) {
documentName = documentFileName;
}
// The name of the agreement, which will be used to identify it in the
// emails and on the website.
// name is required
widgetInfo.setName(documentName);
// Optional parameter which sets how often you'd like the recipient(s)
// to be reminded to sign this document.
// reminderFrequency is not required
// documentInfo.setReminderFrequency(value);
if (StringUtils.hasText(signedDocumentUrl)) {
// Sets the callback properties that allows EchoSign to notify you
// when the agreement has been signed and avoid polling.
// callbackInfo is not required
CallbackInfo callbackInfo = new CallbackInfo();
widgetInfo.setCallbackInfo(callbackInfo);
}
// The locale associated with this agreement - specifies the language
// for the signing page and emails, for example en_US or fr_FR. If none
// specified, defaults to the language configured for the widget's
// sender.
// locale is not required
// documentInfo.setLocale(value);
// Optional default values for fields to merge into the document. The
// values will be presented to the signers for editable fields; for
// read-only fields the provided values will not be editable during the
// signing process.
// mergeFieldInfo is not required
// documentInfo.setMergeFieldInfo(value);
widgetInfo.setFileInfos(fileInfos);
widgetInfo
.setSignatureFlow(SignatureFlow.SENDER_SIGNATURE_NOT_REQUIRED);
WidgetPersonalizationInfo personalizationInfo = new WidgetPersonalizationInfo();
personalizationInfo.setReusable(false);
personalizationInfo.setEmail(email);
EmbeddedWidgetCreationResult embeddedWidgetCreationResult = getCachedService()
.createPersonalEmbeddedWidget(echoSignApiKey, null, widgetInfo,
personalizationInfo);
return embeddedWidgetCreationResult;
}
}