groupdocs-total/GroupDocs.Total-for-Java-Spring

View on GitHub
src/main/java/com/groupdocs/ui/signature/service/SaveSignatureServiceImpl.java

Summary

Maintainability
A
0 mins
Test Coverage
F
3%
package com.groupdocs.ui.signature.service;

import com.groupdocs.signature.domain.enums.HorizontalAlignment;
import com.groupdocs.signature.domain.enums.VerticalAlignment;
import com.groupdocs.signature.handler.SignatureHandler;
import com.groupdocs.signature.options.OutputType;
import com.groupdocs.signature.options.SignatureOptionsCollection;
import com.groupdocs.signature.options.saveoptions.SaveOptions;
import com.groupdocs.ui.exception.TotalGroupDocsException;
import com.groupdocs.ui.model.response.FileDescriptionEntity;
import com.groupdocs.ui.signature.SignatureConfiguration;
import com.groupdocs.ui.signature.XMLReaderWriter;
import com.groupdocs.ui.signature.model.request.SaveImageRequest;
import com.groupdocs.ui.signature.model.request.SaveOpticalCodeRequest;
import com.groupdocs.ui.signature.model.request.SaveStampRequest;
import com.groupdocs.ui.signature.model.request.SaveTextRequest;
import com.groupdocs.ui.signature.model.web.SignatureDataEntity;
import com.groupdocs.ui.signature.model.xml.*;
import com.groupdocs.ui.signature.signer.BarCodeSigner;
import com.groupdocs.ui.signature.signer.QrCodeSigner;
import com.groupdocs.ui.signature.signer.Signer;
import com.groupdocs.ui.util.directory.SignatureDirectory;
import org.apache.commons.io.FilenameUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.imageio.ImageIO;
import javax.xml.bind.JAXBException;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.Base64;
import java.util.List;

import static com.groupdocs.ui.signature.SignatureType.QR_CODE;
import static com.groupdocs.ui.signature.service.SignatureHandlerFactory.createStreamHandler;
import static com.groupdocs.ui.signature.service.SignatureHandlerFactory.getFullDataPathStr;
import static com.groupdocs.ui.util.Utils.getBufferedImage;
import static com.groupdocs.ui.util.Utils.getFileWithUniqueName;
import static com.groupdocs.ui.util.directory.SignatureDirectory.*;

@Service
public class SaveSignatureServiceImpl implements SaveSignatureService {
    private static final Logger logger = LoggerFactory.getLogger(SaveSignatureServiceImpl.class);

    public static final String PNG = "png";
    public static final String XML = "xml";

    private SignatureHandler signatureHandler;
    @Autowired
    private SignatureConfiguration signatureConfiguration;

    @PostConstruct
    public void init() {
        signatureHandler = SignatureHandlerFactory.createHandler(signatureConfiguration.getFilesDirectory(), signatureConfiguration.getDataDirectory());
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public FileDescriptionEntity saveStamp(SaveStampRequest saveStampRequest) {
        String previewPath = getFullDataPathStr(signatureConfiguration.getDataDirectory(), STAMP_DATA_DIRECTORY.getPreviewPath());
        String xmlPath = getFullDataPathStr(signatureConfiguration.getDataDirectory(), STAMP_DATA_DIRECTORY.getXMLPath());
        try {
            // get/set parameters
            String encodedImage = saveStampRequest.getImage().replace("data:image/png;base64,", "");
            List<StampXmlEntity> stampData = saveStampRequest.getStampData();

            File file = getFileWithUniqueName(previewPath, "", PNG);
            byte[] decodedImg = Base64.getDecoder().decode(encodedImage.getBytes(StandardCharsets.UTF_8));
            Files.write(file.toPath(), decodedImg);
            // stamp data to xml file saving
            StampXmlEntityList stampXmlEntityList = new StampXmlEntityList();
            stampXmlEntityList.setStampXmlEntityList(stampData);
            String xmlFileName = FilenameUtils.removeExtension(file.getName());
            String fileName = String.format("%s%s%s.xml", xmlPath, File.separator, xmlFileName);
            new XMLReaderWriter<StampXmlEntityList>().write(fileName, stampXmlEntityList);

            FileDescriptionEntity savedImage = new FileDescriptionEntity();
            savedImage.setGuid(file.toPath().toString());
            // return loaded page object
            return savedImage;
        } catch (Exception ex) {
            logger.error("Exception occurred while saving stamp", ex);
            throw new TotalGroupDocsException(ex.getMessage(), ex);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public OpticalXmlEntity saveOpticalCode(SaveOpticalCodeRequest saveOpticalCodeRequest) {
        OpticalXmlEntity signatureData = saveOpticalCodeRequest.getProperties();
        // initiate signature data wrapper with default values
        SignatureDataEntity signatureDataEntity = getSignatureDataEntity(270, 200);

        // initiate signature options collection
        SignatureOptionsCollection collection = new SignatureOptionsCollection();

        Signer signer = QR_CODE.equals(saveOpticalCodeRequest.getSignatureType()) ?
                new QrCodeSigner(signatureData, signatureDataEntity) :
                new BarCodeSigner(signatureData, signatureDataEntity);

        collection.add(signer.signImage());

        SignatureDirectory dataDirectory = QR_CODE.equals(saveOpticalCodeRequest.getSignatureType()) ? QRCODE_DATA_DIRECTORY : BARCODE_DATA_DIRECTORY;
        String encodedImage = createAndSaveOpticalCode(signatureData, dataDirectory, collection);
        signatureData.setEncodedImage(encodedImage);
        signatureData.setWidth(signatureDataEntity.getImageWidth());
        signatureData.setHeight(signatureDataEntity.getImageHeight());
        return signatureData;
    }

    /**
     * Create and save image with optical code
     *
     * @param signatureData
     * @param dataDirectory
     * @param collection
     * @return encoded image
     */
    private String createAndSaveOpticalCode(OpticalXmlEntity signatureData, SignatureDirectory dataDirectory, SignatureOptionsCollection collection) {
        // get preview path
        String previewPath = getFullDataPathStr(signatureConfiguration.getDataDirectory(), dataDirectory.getPreviewPath());
        // get xml file path
        String xmlPath = getFullDataPathStr(signatureConfiguration.getDataDirectory(), dataDirectory.getXMLPath());
        try {
            if (signatureData.getTemp()) {
                BufferedImage bufImage = getBufferedImage(200, 200);
                ByteArrayOutputStream os = new ByteArrayOutputStream();
                ImageIO.write(bufImage, PNG, os);
                InputStream is = new ByteArrayInputStream(os.toByteArray());
                return signWithImageToStream(collection, is);
            } else {
                File file = writeImageFile(signatureData.getImageGuid(), previewPath, 200, 200);
                String fileName = FilenameUtils.removeExtension(file.getName());
                // Save data to xml file
                new XMLReaderWriter<OpticalXmlEntity>().write(String.format("%s%s%s.xml", xmlPath, File.separator, fileName), signatureData);
                return signWithImageToFile(previewPath, signatureData, collection, file.toPath().toString());
            }
        } catch (Exception e) {
            logger.error("Exception occurred while saving optical code signature", e);
            throw new TotalGroupDocsException(e.getMessage(), e);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public TextXmlEntity saveText(SaveTextRequest saveTextRequest) {
        String xmlPath = getFullDataPathStr(signatureConfiguration.getDataDirectory(), TEXT_DATA_DIRECTORY.getXMLPath());
        TextXmlEntity signatureData = saveTextRequest.getProperties();
        try {
            File file = getFileWithUniqueName(xmlPath, signatureData.getImageGuid(), XML);
            // Save data to xml file
            String fileName = String.format("%s%s%s.xml", xmlPath, File.separator, FilenameUtils.removeExtension(file.getName()));
            new XMLReaderWriter<TextXmlEntity>().write(fileName, signatureData);
            signatureData.setImageGuid(fileName);
        } catch (JAXBException e) {
            logger.error("Exception occurred while saving text signature", e);
            throw new TotalGroupDocsException(e.getMessage(), e);
        }
        return signatureData;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public FileDescriptionEntity saveImage(SaveImageRequest saveImageRequest) {
        try {
            String dataDirectoryPath = getFullDataPathStr(signatureConfiguration.getDataDirectory(), IMAGE_DATA_DIRECTORY.getPath());
            File file = getFileWithUniqueName(dataDirectoryPath, "", PNG);
            String encodedImage = saveImageRequest.getImage().replace("data:image/png;base64,", "");
            byte[] decodedImg = Base64.getDecoder().decode(encodedImage.getBytes(StandardCharsets.UTF_8));
            Files.write(file.toPath(), decodedImg);

            FileDescriptionEntity savedImage = new FileDescriptionEntity();
            savedImage.setGuid(file.getAbsolutePath());
            // return loaded page object
            return savedImage;
        } catch (Exception ex) {
            logger.error("Exception occurred while saving image signature", ex);
            throw new TotalGroupDocsException(ex.getMessage(), ex);
        }
    }

    /**
     * Write image to file
     *
     * @param imageGuid      image file guid if it exists
     * @param previewPath    path to file
     * @return
     */
    private File writeImageFile(String imageGuid, String previewPath, int width, int height) {
        File file = getFileWithUniqueName(previewPath, imageGuid, PNG);
        try {
            BufferedImage bufImage = getBufferedImage(width, height);
            // save BufferedImage to file
            ImageIO.write(bufImage, PNG, file);
        } catch (Exception ex) {
            logger.error("Exception occurred while saving signatures image", ex);
            throw new TotalGroupDocsException(ex.getMessage(), ex);
        }
        return file;
    }

    /**
     * Sign image with signature data for saving in stream
     *
     * @param collection  signature options
     * @param inputStream stream with image, for temporally sign
     * @return encoded image
     */
    private String signWithImageToStream(SignatureOptionsCollection collection, InputStream inputStream) {
        try {
            final SaveOptions saveOptions = new SaveOptions();
            saveOptions.setOutputType(OutputType.Stream);
            // sign generated image with signature
            SignatureHandler<OutputStream> imgSignatureHandler = createStreamHandler();
            ByteArrayOutputStream bos = (ByteArrayOutputStream) imgSignatureHandler.sign(inputStream, collection, saveOptions);
            byte[] bytes = bos.toByteArray();
            // encode ByteArray into String
            return Base64.getEncoder().encodeToString(bytes);
        } catch (Exception ex) {
            logger.error("Exception occurred while saving optical code signature", ex);
            throw new TotalGroupDocsException(ex.getMessage(), ex);
        }
    }

    /**
     * Sign image with signature data for saving in local storage
     *
     * @param previewPath   local storage path
     * @param signatureData signature
     * @param collection    signature options
     * @param path          path to file
     * @return encoded image
     */
    private String signWithImageToFile(String previewPath, XmlEntityWithImage signatureData, SignatureOptionsCollection collection, String path) {
        try {
            // set signing save options
            final SaveOptions saveOptions = new SaveOptions();
            saveOptions.setOutputType(OutputType.String);
            saveOptions.setOutputFileName(FilenameUtils.getName(path));
            saveOptions.setOverwriteExistingFiles(true);
            // set temporary signed documents path to image previews folder
            signatureHandler.getSignatureConfig().setOutputPath(previewPath);
            // sign generated image with signature
            signatureHandler.sign(path, collection, saveOptions);
            // set data for response
            signatureData.setImageGuid(path);
            // get signature preview as Base64 String
            byte[] bytes = signatureHandler.getPageImage(path, 1, "", null, 100);
            // encode ByteArray into String
            return Base64.getEncoder().encodeToString(bytes);
        } catch (Exception ex) {
            logger.error("Exception occurred while saving optical code signature", ex);
            throw new TotalGroupDocsException(ex.getMessage(), ex);
        }
    }

    /**
     * Get filled signature data
     *
     * @param width
     * @param height
     * @return
     */
    private SignatureDataEntity getSignatureDataEntity(int width, int height) {
        SignatureDataEntity signatureDataEntity = new SignatureDataEntity();
        signatureDataEntity.setHorizontalAlignment(HorizontalAlignment.Center);
        signatureDataEntity.setVerticalAlignment(VerticalAlignment.Center);
        signatureDataEntity.setImageHeight(height);
        signatureDataEntity.setImageWidth(width);
        signatureDataEntity.setLeft(0);
        signatureDataEntity.setTop(0);
        return signatureDataEntity;
    }
}