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

View on GitHub
src/main/java/com/groupdocs/ui/viewer/service/ViewerServiceImpl.java

Summary

Maintainability
A
2 hrs
Test Coverage
F
16%
package com.groupdocs.ui.viewer.service;

import com.groupdocs.ui.config.GlobalConfiguration;
import com.groupdocs.ui.exception.TotalGroupDocsException;
import com.groupdocs.ui.model.response.PageDescriptionEntity;
import com.groupdocs.ui.util.Utils;
import com.groupdocs.ui.viewer.config.ViewerConfiguration;
import com.groupdocs.ui.viewer.exception.ReadWriteException;
import com.groupdocs.ui.viewer.model.request.LoadDocumentPageRequest;
import com.groupdocs.ui.viewer.model.request.LoadDocumentRequest;
import com.groupdocs.ui.viewer.model.request.RotateDocumentPagesRequest;
import com.groupdocs.ui.viewer.model.response.FileDescriptionEntity;
import com.groupdocs.ui.viewer.model.response.LoadDocumentEntity;
import com.groupdocs.ui.viewer.util.PagesInfoStorage;
import com.groupdocs.ui.viewer.util.ViewerUtils;
import com.groupdocs.ui.viewer.viewer.CustomViewer;
import com.groupdocs.ui.viewer.viewer.HtmlViewer;
import com.groupdocs.ui.viewer.viewer.PngViewer;
import com.groupdocs.viewer.License;
import com.groupdocs.viewer.exception.IncorrectPasswordException;
import com.groupdocs.viewer.exception.PasswordRequiredException;
import com.groupdocs.viewer.fonts.FolderFontSource;
import com.groupdocs.viewer.fonts.FontSettings;
import com.groupdocs.viewer.fonts.FontSource;
import com.groupdocs.viewer.fonts.SearchOption;
import com.groupdocs.viewer.results.Page;
import com.groupdocs.viewer.results.ViewInfo;
import com.groupdocs.viewer.utils.PathUtils;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ContentDisposition;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

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

    @Autowired
    private GlobalConfiguration globalConfiguration;
    @Autowired
    private ViewerConfiguration viewerConfiguration;

    /**
     * Initializing fields after creating configuration objects
     */
    @PostConstruct
    public void init() {
        setLicense();
        // Register custom fonts
        if (!StringUtils.isEmpty(viewerConfiguration.getFontsDirectory())) {
            FontSource fontSource = new FolderFontSource(viewerConfiguration.getFontsDirectory(), SearchOption.TOP_FOLDER_ONLY);
            FontSettings.setFontSources(fontSource);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List<FileDescriptionEntity> getFileList(String path) {
        final File filesDirectory = new File(PathUtils.combine(viewerConfiguration.getFilesDirectory(), path));

        try {
            final File[] files = filesDirectory.listFiles();
            if (files == null) {
                throw new TotalGroupDocsException("Can't list files");
            }

            List<FileDescriptionEntity> filesList = createListOfFileDescriptionEntities(files);

            // Sort by name and to make directories to be before files
            Collections.sort(filesList, new Comparator<FileDescriptionEntity>() {
                @Override
                public int compare(FileDescriptionEntity o1, FileDescriptionEntity o2) {
                    if (o1.isIsDirectory() && !o2.isIsDirectory()) {
                        return -1;
                    }
                    if (!o1.isIsDirectory() && o2.isIsDirectory()) {
                        return 1;
                    }
                    return o1.getName().compareTo(o2.getName());
                }
            });
            return filesList;
        } catch (IOException e) {
            logger.error("Exception in getting file list", e);
            throw new TotalGroupDocsException(e.getMessage(), e);
        }
    }

    private List<FileDescriptionEntity> createListOfFileDescriptionEntities(File[] files) throws IOException {
        List<FileDescriptionEntity> filesList = new ArrayList<>();
        for (File file : files) {
            // check if current file/folder is not hidden
            if (
                    !(file.getName().equals(viewerConfiguration.getCacheFolderName()))
                            && !(file.getName().equals(viewerConfiguration.getResourcesFolderName()))
                            && !file.getName().startsWith(".")
                            && !file.isHidden()) {
                FileDescriptionEntity fileDescription = new FileDescriptionEntity();
                fileDescription.setGuid(file.getCanonicalFile().getAbsolutePath());
                fileDescription.setName(file.getName());
                // set is directory true/false
                fileDescription.setIsDirectory(file.isDirectory());

                // set file size
                if (!fileDescription.isIsDirectory()) {
                    fileDescription.setSize(file.length());
                }

                // add object to array list
                filesList.add(fileDescription);
            }
        }
        return filesList;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public LoadDocumentEntity loadDocument(LoadDocumentRequest loadDocumentRequest, boolean loadAllPages) {
        // set request parameters
        String documentGuid = loadDocumentRequest.getGuid();
        String password = loadDocumentRequest.getPassword();
        password = org.apache.commons.lang3.StringUtils.isEmpty(password) ? null : password;
        LoadDocumentEntity loadDocumentEntity;
        try (CustomViewer<?> customViewer = createCustomViewer(documentGuid, password)) {

            loadDocumentEntity = getLoadDocumentEntity(loadAllPages, documentGuid, customViewer);
            loadDocumentEntity.setShowGridLines(viewerConfiguration.getShowGridLines());
            loadDocumentEntity.setPrintAllowed(viewerConfiguration.getPrintAllowed());
        } catch (IncorrectPasswordException | PasswordRequiredException ex) {
            logger.error("Exception that is connected to password", ex);
            throw new TotalGroupDocsException(Utils.getExceptionMessage(password), ex);
        } catch (Exception ex) {
            logger.error("Exception in loading document", ex);
            throw new TotalGroupDocsException("Exception in loading document", ex);
        }
        return loadDocumentEntity;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public PageDescriptionEntity loadDocumentPage(LoadDocumentPageRequest loadDocumentPageRequest) {
        String documentGuid = loadDocumentPageRequest.getGuid();
        Integer pageNumber = loadDocumentPageRequest.getPage();
        String password = loadDocumentPageRequest.getPassword();
        password = org.apache.commons.lang3.StringUtils.isEmpty(password) ? null : password;

        try (CustomViewer<?> customViewer = createCustomViewer(documentGuid, password)) {
            return getPageDescriptionEntity(customViewer, documentGuid, pageNumber);
        } catch (Exception ex) {
            logger.error("Exception in loading document page", ex);
            throw new TotalGroupDocsException(ex.getMessage(), ex);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public PageDescriptionEntity rotateDocumentPages(RotateDocumentPagesRequest rotateDocumentPagesRequest) {
        // set request parameters
        String documentGuid = rotateDocumentPagesRequest.getGuid();
        List<Integer> pages = rotateDocumentPagesRequest.getPages();
        String password = rotateDocumentPagesRequest.getPassword();
        Integer angle = rotateDocumentPagesRequest.getAngle();
        int pageNumber = pages.get(0);

        try {
            final Path resourcesDir = ViewerUtils.makeResourcesDir(viewerConfiguration);
            // Getting new rotation angle value.
            int currentAngle = PagesInfoStorage.loadPageAngle(resourcesDir, documentGuid, pageNumber);
            int newAngle = mergeAngles(currentAngle, angle);
            PagesInfoStorage.savePageAngle(resourcesDir, documentGuid, pageNumber, newAngle);

            try (CustomViewer<?> customViewer = createCustomViewer(documentGuid, password, pageNumber, newAngle)) {
                if (viewerConfiguration.isCache()) {
                    // Delete cache files connected to the page
                    customViewer.clearCache(pageNumber);
                }

                return getPageDescriptionEntity(customViewer, documentGuid, pageNumber);
            }
        } catch (Exception ex) {
            logger.error("Exception in rotating document page", ex);
            throw new TotalGroupDocsException(ex.getMessage(), ex);
        }
    }

    @Override
    public ResponseEntity<byte[]> getResource(String guid, String resourceName) {
        try {
            if (!org.apache.commons.lang3.StringUtils.isEmpty(guid)) {
                final Path resourceFile = ViewerUtils.makeResourcesDir(viewerConfiguration).resolve(guid).resolve(resourceName);

                HttpHeaders responseHeaders = new HttpHeaders();
                responseHeaders.setContentType(ViewerUtils.detectMediaType(resourceFile.getFileName().toString()));
                responseHeaders.setContentDisposition(
                        ContentDisposition.builder("inline")
                                .filename(resourceFile.toAbsolutePath().toString())
                                .build()
                );

                return ResponseEntity.ok()
                        .headers(responseHeaders)
                        .body(FileUtils.readFileToByteArray(resourceFile.toFile()));
            }
        } catch (IOException e) {
            logger.error("Exception in loading resource", e);
            throw new TotalGroupDocsException(e.getMessage(), e);
        }
        return ResponseEntity.badRequest().build();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ViewerConfiguration getViewerConfiguration() {
        return viewerConfiguration;
    }

    private PageDescriptionEntity getPageDescriptionEntity(CustomViewer<?> customViewer, String documentGuid, int pageNumber) {
        ViewInfo viewInfo = customViewer.getViewInfo();
        final Path resourcesDir = ViewerUtils.makeResourcesDir(viewerConfiguration);
        PageDescriptionEntity page = getPageInfo(documentGuid, viewInfo.getPages().get(pageNumber - 1), resourcesDir);
        page.setData(customViewer.getPageContent(pageNumber));

        return page;
    }

    private LoadDocumentEntity getLoadDocumentEntity(boolean loadAllPages, String documentGuid, CustomViewer<?> customViewer) {
        try {
            ViewInfo viewInfo = customViewer.getViewInfo();

            LoadDocumentEntity loadDocumentEntity = new LoadDocumentEntity();

            final Path resourcesDir = ViewerUtils.makeResourcesDir(viewerConfiguration);
            PagesInfoStorage.createPagesInfo(resourcesDir, documentGuid, viewInfo);

            for (Page page : viewInfo.getPages()) {
                PageDescriptionEntity pageData = getPageInfo(documentGuid, page, resourcesDir);
                if (loadAllPages) {
                    pageData.setData(customViewer.getPageContent(page.getNumber()));
                }

                loadDocumentEntity.getPages().add(pageData);
            }

            loadDocumentEntity.setGuid(documentGuid);
            return loadDocumentEntity;
        } catch (Exception e) {
            throw new ReadWriteException(e);
        }
    }

    private static int mergeAngles(int currentAngle, int angle) {
        switch (currentAngle) {
            case 0:
                return (angle == 90 ? 90 : 270);
            case 90:
                return (angle == 90 ? 180 : 0);
            case 180:
                return (angle == 90 ? 270 : 90);
            case 270:
                return (angle == 90 ? 0 : 180);
        }
        return 0;
    }

    private void setLicense() {
        try {
            // set GroupDocs license
            License license = new License();
            license.setLicense(globalConfiguration.getApplication().getLicensePath());
        } catch (Throwable throwable) {
            logger.error("Can not verify Viewer license!");
        }
    }


    private static PageDescriptionEntity getPageInfo(String documentGuid, Page page, Path resourcesFolder) {

        int currentAngle = PagesInfoStorage.loadPageAngle(resourcesFolder, documentGuid, page.getNumber());

        PageDescriptionEntity pageDescriptionEntity = new PageDescriptionEntity();

        pageDescriptionEntity.setNumber(page.getNumber());

        // we intentionally use the 0 here because we plan to rotate only the page background using height/width
        pageDescriptionEntity.setAngle(0);
        pageDescriptionEntity.setHeight(currentAngle == 0 || currentAngle == 180 ? page.getHeight() : page.getWidth());
        pageDescriptionEntity.setWidth(currentAngle == 0 || currentAngle == 180 ? page.getWidth() : page.getHeight());

        return pageDescriptionEntity;
    }


    private CustomViewer<?> createCustomViewer(String documentGuid, String password) {
        return createCustomViewer(documentGuid, password, -1, 0);
    }

    private CustomViewer<?> createCustomViewer(String documentGuid, String password, int pageNumber, int newAngle) {

        CustomViewer<?> customViewer;
        if (viewerConfiguration.isHtmlMode()) {
            customViewer = new HtmlViewer(documentGuid, password, viewerConfiguration, pageNumber, newAngle);
        } else {
            customViewer = new PngViewer(documentGuid, password, viewerConfiguration, pageNumber, newAngle);
        }
        return customViewer;
    }
}