//@include lib_Class.js /** * @private * Creates a signed PDF file * Combines a given file with a signature image. * The signature image is retrieved as base64 content from a "properties" property of a data node or form a form blob field * * @author MW, ELO Digital Office GmbH * * @eloas * @requires sol.common.as.FunctionBase * @requires sol.common.JsonUtils * @requires sol.common.RepoUtils * @requires sol.common.WfUtils * * Sample node configuration: * * { * "$directRule": "sol.common.CreateSignedPdf" , * "field": { * "type": "FORMBLOB", * "key": "WO_SIGNATURE" * }, * "signatureBasePath": "ARCPATH[(E10E1000-E100-E100-E100-E10E10E10E00)]:/Business Solutions/visitor/Configuration/Reports/Signature", * "signatureType": "Default" * } * * { * "$function": "sol.common.as.functions.CreateSignedPdf" , * "dataNodeName": "[data] signature", * "templateId": "ARCPATH:/Administration/Business Solutions/visitor/Configuration/Reports/Signature/Signature", * "name": "signed" * } */ sol.define("sol.common.as.functions.CreateSignedPdf", { extend: "sol.common.as.FunctionBase", requiredProperty: ["objId", "flowId", "dataNodeName"], /** * @cfg {String} objId (required) * Object ID of the PDF file that should be signed */ /** * @cfg {String} flowId (required) * Workflow ID */ /** * @cfg {String} dataNodeName * Name which holds the base64 string with the signature */ /** * @cfg {String} field * Field that contains the signature data */ /** * @cfg {String} name (optional) * Name of the created document, default will be the name of the original element */ /** * @cfg {String} templateId (optional) * Object ID of the FOP template. Either this, or `signatureBasePath` and `signatureType` has to be set. If a `templateId` is defined, it has priority. */ /** * @cfg {String} signatureBasePath (optional) * ARCPATH with the signatur types. If not set, `templateId` has to be defined. If a `templateId` is defined, it has priority. */ /** * @cfg {String} signatureType (optional) * The template name for the signature (in the `signatureBasePath`). If not set, `templateId` has to be defined. If a `templateId` is defined, it has priority. */ /** * @cfg {String} dstFolderId (optional) * Folder ID of the destination folder */ initialize: function (config) { var me = this; me.$super("sol.common.as.FunctionBase", "initialize", [config]); }, getName: function () { return "SignPdf"; }, process: function () { var me = this, wfDiagram, dataNode, blobValue, blobData, imageData, imageDataParts, fopRenderer, sord, srcObjUrl, srcTempFilePath, data, signatureFopResult, srcDocInputStream, signatureInputStream, mergedOutputStream, signatureTypeFromDocument, connectionLanguage, documentLanguage; if (!me.templateId && !me.signatureBasePath) { throw "IllegalArgumentException: either a 'templateId' or 'signatureBasePath' has to be defined"; } me.signatureType = me.signatureType || me.signaturType; // Correct spelling mistake sord = ixConnect.ix().checkoutSord(me.objId, SordC.mbAllIndex, LockC.NO); connectionLanguage = ixConnect.loginResult.clientInfo.language; documentLanguage = sol.common.SordUtils.getValue(sord, { type: "MAP", key: "SIGNATURE_LANGUAGE" }); ixConnect.loginResult.clientInfo.language = documentLanguage; if (me.signatureBasePath) { signatureTypeFromDocument = sol.common.SordUtils.getValue(sord, { type: "MAP", key: "SIGNATURE_FO_TEMPLATE" }); me.signatureType = signatureTypeFromDocument || me.signatureType; if (!me.signatureType) { throw "IllegalArgumentException: if a 'signatureBasePath' is defined, a 'signatureType' is mandatory"; } me.logger.debug(["signatureBasePath={0}, signatureType={1}", me.signatureBasePath, me.signatureType]); } if (me.dataNodeName) { wfDiagram = sol.common.WfUtils.getWorkflow(me.flowId); dataNode = sol.common.WfUtils.getNodeByName(wfDiagram, me.dataNodeName); if (!dataNode) { throw "Data node '" + me.dataNodeName + "' not found."; } imageData = dataNode.properties + ""; } if (me.field) { blobValue = sol.common.SordUtils.getValue(sord, me.field); blobData = JSON.parse(blobValue); imageData = blobData.signature; } if (!imageData) { throw "Image data is empty"; } imageDataParts = imageData.split(";base64,"); if (imageDataParts && (imageDataParts.length == 2)) { imageData = imageDataParts[1]; } me.dstFolderId = me.dstFolderId || sord.parentId; me.name = me.name || sord.name; me.templateId = me.getTemplateId(); data = { srcTempFilePath: srcTempFilePath, srcObjUrl: srcObjUrl, imageData: imageData, sord: sol.common.SordUtils.getTemplateSord(sord).sord }; me.logger.debug(["Create signature PDF: imageData={0}" + imageData]); fopRenderer = sol.create("sol.common.as.renderer.Fop", { templateId: me.templateId, toStream: true }); signatureFopResult = fopRenderer.render(me.name, data); signatureInputStream = me.convertOutputStreamToInputStream(signatureFopResult.outputStream); srcDocInputStream = sol.common.RepoUtils.downloadToStream(me.objId); mergedOutputStream = new ByteArrayOutputStream(); sol.common.as.PdfUtils.mergePdfStreams([srcDocInputStream, signatureInputStream], mergedOutputStream); sol.common.RepoUtils.saveToRepo({ objId: me.objId, name: me.name, outputStream: mergedOutputStream, extension: "pdf", versionIncrement: 1 }); if (connectionLanguage) { ixConnect.loginResult.clientInfo.language = connectionLanguage; } return { passOn: true }; }, /** * @private * Converts an output stream to an input stream * @param {java.io.OutputStream} outputStream * @return {java.io.InputStream} */ convertOutputStreamToInputStream: function (outputStream) { if (!outputStream) { throw "Output stream is empty"; } var inputStream = new ByteArrayInputStream(outputStream.toByteArray()); outputStream.close(); return inputStream; }, /** * @private * @return {String} */ getTemplateId: function () { var me = this; return me.templateId || sol.common.RepoUtils.getObjIdFromRelativePath(me.signatureBasePath, "/" + me.signatureType); } });