Package org.zanata.action

Source Code of org.zanata.action.VersionHomeAction

/*
*
* Copyright 2014, Red Hat, Inc. and individual contributors as indicated by the
* @author tags. See the copyright.txt file in the distribution for a full
* listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This software is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this software; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF
* site: http://www.fsf.org.
*/
package org.zanata.action;

import java.io.File;
import java.io.InputStream;
import java.io.Serializable;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.faces.application.FacesMessage;
import javax.validation.ConstraintViolationException;

import org.apache.commons.lang.StringUtils;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.annotations.security.Restrict;
import org.jboss.seam.util.Hex;
import org.zanata.async.handle.CopyVersionTaskHandle;
import org.zanata.common.DocumentType;
import org.zanata.common.EntityStatus;
import org.zanata.common.LocaleId;
import org.zanata.common.MergeType;
import org.zanata.common.ProjectType;
import org.zanata.dao.DocumentDAO;
import org.zanata.dao.LocaleDAO;
import org.zanata.dao.ProjectIterationDAO;
import org.zanata.exception.VirusDetectedException;
import org.zanata.exception.ZanataServiceException;
import org.zanata.file.FilePersistService;
import org.zanata.file.GlobalDocumentId;
import org.zanata.i18n.Messages;
import org.zanata.model.HDocument;
import org.zanata.model.HIterationGroup;
import org.zanata.model.HLocale;
import org.zanata.model.HProjectIteration;
import org.zanata.model.HRawDocument;
import org.zanata.rest.StringSet;
import org.zanata.rest.dto.extensions.ExtensionType;
import org.zanata.rest.dto.resource.Resource;
import org.zanata.rest.dto.resource.TranslationsResource;
import org.zanata.rest.service.VirusScanner;
import org.zanata.seam.scope.ConversationScopeMessages;
import org.zanata.security.ZanataIdentity;
import org.zanata.service.DocumentService;
import org.zanata.service.LocaleService;
import org.zanata.service.TranslationFileService;
import org.zanata.service.TranslationService;
import org.zanata.service.TranslationStateCache;
import org.zanata.service.VersionStateCache;
import org.zanata.ui.AbstractListFilter;
import org.zanata.ui.AbstractSortAction;
import org.zanata.ui.InMemoryListFilter;
import org.zanata.ui.ProgressBar;
import org.zanata.ui.model.statistic.WordStatistic;
import org.zanata.util.DateUtil;
import org.zanata.util.ServiceLocator;
import org.zanata.util.StatisticsUtil;
import org.zanata.util.UrlUtil;
import org.zanata.webtrans.shared.model.DocumentStatus;
import com.google.common.base.Optional;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

@Name("versionHomeAction")
@Scope(ScopeType.PAGE)
@Slf4j
public class VersionHomeAction extends AbstractSortAction implements
        Serializable {
    private static final long serialVersionUID = 1L;

    @In
    private CopyVersionManager copyVersionManager;

    @In
    private ProjectIterationDAO projectIterationDAO;

    @In
    private DocumentDAO documentDAO;

    @In
    private LocaleService localeServiceImpl;

    @In
    private VersionStateCache versionStateCacheImpl;

    @In
    private TranslationStateCache translationStateCacheImpl;

    @In
    private Messages msgs;

    @In
    private DocumentService documentServiceImpl;

    @In
    private ZanataIdentity identity;

    @In
    private TranslationFileService translationFileServiceImpl;

    @In
    private VirusScanner virusScanner;

    @In
    private LocaleDAO localeDAO;

    @In
    private TranslationService translationServiceImpl;

    @Getter
    private String versionSlug;

    @Getter
    private String projectSlug;

    @Getter
    private boolean pageRendered = false;

    @Getter
    private WordStatistic overallStatistic;

    @Getter
    private HLocale selectedLocale;

    @Getter
    private HDocument selectedDocument;

    @In
    private ConversationScopeMessages conversationScopeMessages;

    @In("filePersistService")
    private FilePersistService filePersistService;

    private List<HLocale> supportedLocale;

    private List<HDocument> documents;

    private Map<LocaleId, WordStatistic> localeStatisticMap;

    private Map<DocumentLocaleKey, WordStatistic> documentStatisticMap;

    private List<HIterationGroup> groups;

    private HProjectIteration version;

    @Getter
    private SourceFileUploadHelper sourceFileUpload =
            new SourceFileUploadHelper();

    @Getter
    private TranslationFileUploadHelper translationFileUpload =
            new TranslationFileUploadHelper();

    @Getter
    private SortingType documentSortingList = new SortingType(
            Lists.newArrayList(SortingType.SortOption.ALPHABETICAL,
                    SortingType.SortOption.HOURS,
                    SortingType.SortOption.PERCENTAGE,
                    SortingType.SortOption.WORDS,
                    SortingType.SortOption.LAST_SOURCE_UPDATE,
                    SortingType.SortOption.LAST_TRANSLATED));

    @Getter
    private SortingType sourceDocumentSortingList = new SortingType(
            Lists.newArrayList(SortingType.SortOption.ALPHABETICAL,
                    SortingType.SortOption.HOURS,
                    SortingType.SortOption.PERCENTAGE,
                    SortingType.SortOption.WORDS,
                    SortingType.SortOption.LAST_SOURCE_UPDATE));

    @Getter
    private SortingType settingsDocumentSortingList = new SortingType(
            Lists.newArrayList(SortingType.SortOption.ALPHABETICAL,
                    SortingType.SortOption.LAST_SOURCE_UPDATE));

    private final LanguageComparator languageComparator =
            new LanguageComparator(getLanguageSortingList());

    private final DocumentComparator documentComparator =
            new DocumentComparator(getDocumentSortingList());

    private final DocumentComparator sourceDocumentComparator =
            new DocumentComparator(getSourceDocumentSortingList());

    private final DocumentComparator settingsDocumentComparator =
            new DocumentComparator(getSettingsDocumentSortingList());

    @Getter
    private final SourceDocumentFilter documentsTabDocumentFilter =
            new SourceDocumentFilter();

    @Getter
    private final DocumentFilter settingsTabDocumentFilter =
            new DocumentFilter();

    @Getter
    private final DocumentFilter languageTabDocumentFilter =
            new DocumentFilter();

    @Getter
    private CopyVersionHandler copyVersionHandler = new CopyVersionHandler();

    @Getter
    private final AbstractListFilter<HIterationGroup> groupFilter =
            new InMemoryListFilter<HIterationGroup>() {
                @Override
                protected List<HIterationGroup> fetchAll() {
                    return getGroups();
                }

                @Override
                protected boolean include(HIterationGroup elem, String filter) {
                    return StringUtils.containsIgnoreCase(elem.getName(),
                            filter)
                            || StringUtils.containsIgnoreCase(elem.getSlug(),
                                    filter);
                }
            };

    @Getter
    private final AbstractListFilter<HLocale> languageTabLanguageFilter =
            new InMemoryListFilter<HLocale>() {
                @Override
                protected List<HLocale> fetchAll() {
                    return getSupportedLocale();
                }

                @Override
                protected boolean include(HLocale elem, String filter) {
                    return StringUtils.startsWithIgnoreCase(elem.getLocaleId()
                            .getId(), filter)
                            || StringUtils.containsIgnoreCase(
                                    elem.retrieveDisplayName(), filter);
                }
            };

    @Getter
    private final AbstractListFilter<HLocale> documentsTabLanguageFilter =
            new InMemoryListFilter<HLocale>() {
                @Override
                protected List<HLocale> fetchAll() {
                    return getSupportedLocale();
                }

                @Override
                protected boolean include(HLocale elem, String filter) {
                    return StringUtils.startsWithIgnoreCase(elem.getLocaleId()
                            .getId(), filter)
                            || StringUtils.containsIgnoreCase(
                                    elem.retrieveDisplayName(), filter);
                }
            };

    public void setVersionSlug(String versionSlug) {
        this.versionSlug = versionSlug;
        copyVersionHandler.setVersionSlug(versionSlug);
    }

    public void setProjectSlug(String projectSlug) {
        this.projectSlug = projectSlug;
        copyVersionHandler.setProjectSlug(projectSlug);
    }

    public void onCopyVersionComplete() {
        conversationScopeMessages.setMessage(FacesMessage.SEVERITY_INFO,
                msgs.format("jsf.copyVersion.Completed", versionSlug));
    }

    public void cancelCopyVersion() {
        copyVersionManager.cancelCopyVersion(projectSlug, versionSlug);
        conversationScopeMessages.setMessage(FacesMessage.SEVERITY_INFO,
                msgs.format("jsf.copyVersion.Cancelled", versionSlug));
    }

    @NoArgsConstructor
    public static class CopyVersionHandler implements ProgressBar {

        @Setter
        private String projectSlug;

        @Setter
        private String versionSlug;

        @Override
        public boolean isInProgress() {
            return getCopyVersionManager().isCopyVersionRunning(projectSlug,
                    versionSlug);
        }

        @Override
        public String getCompletedPercentage() {
            CopyVersionTaskHandle handle = getHandle();
            if (handle != null) {
                double completedPercent =
                        (double) handle.getCurrentProgress() / (double) handle
                                .getMaxProgress() * 100;
                return PERCENT_FORMAT.format(completedPercent);
            } else {
                return "0";
            }
        }

        public int getProcessedDocuments() {
            CopyVersionTaskHandle handle = getHandle();
            if (handle != null) {
                return handle.getDocumentCopied();
            }
            return 0;
        }

        public int getTotalDocuments() {
            CopyVersionTaskHandle handle = getHandle();
            if (handle != null) {
                return handle.getTotalDoc();
            }
            return 0;
        }

        private CopyVersionManager getCopyVersionManager() {
            return ServiceLocator.instance().getInstance(
                    CopyVersionManager.class);
        }

        private CopyVersionTaskHandle getHandle() {
            CopyVersionManager copyVersionManager = ServiceLocator
                    .instance().getInstance(CopyVersionManager.class);

            return copyVersionManager.getCopyVersionProcessHandle(projectSlug,
                    versionSlug);
        }
    }

    /**
     * Sort language list based on locale statistic
     */
    public void sortLanguageList() {
        languageComparator.setSelectedDocumentId(null);
        Collections.sort(getSupportedLocale(), languageComparator);
        languageTabLanguageFilter.reset();
    }

    /**
     * Sort language list based on selected document
     */
    public void sortLanguageList(Long documentId) {
        languageComparator.setSelectedDocumentId(documentId);
        Collections.sort(getSupportedLocale(), languageComparator);
        documentsTabLanguageFilter.reset();
    }

    /**
     * Sort document list based on selected locale
     *
     * @param localeId
     */
    public void sortDocumentList(LocaleId localeId) {
        documentComparator.setSelectedLocaleId(localeId);
        Collections.sort(getDocuments(), documentComparator);
        languageTabDocumentFilter.reset();
    }

    public void sortSourceDocumentList() {
        sourceDocumentComparator.setSelectedLocaleId(null);
        Collections.sort(getSourceDocuments(), sourceDocumentComparator);
        documentsTabDocumentFilter.reset();
    }

    public void sortSettingsDocumentList() {
        settingsDocumentComparator.setSelectedLocaleId(null);
        Collections.sort(getDocuments(), settingsDocumentComparator);
        settingsTabDocumentFilter.reset();
    }

    @Override
    public void resetPageData() {
        languageTabDocumentFilter.reset();
        documentsTabDocumentFilter.reset();
        settingsTabDocumentFilter.reset();
        languageTabLanguageFilter.reset();
        documents = null;
        version = null;
        supportedLocale = null;
        loadStatistics();
    }

    @Override
    protected void loadStatistics() {
        localeStatisticMap = Maps.newHashMap();
        for (HLocale locale : getSupportedLocale()) {
            WordStatistic wordStatistic =
                    versionStateCacheImpl.getVersionStatistics(getVersion()
                            .getId(), locale.getLocaleId());
            wordStatistic.setRemainingHours(StatisticsUtil
                    .getRemainingHours(wordStatistic));
            localeStatisticMap.put(locale.getLocaleId(), wordStatistic);
        }

        overallStatistic = new WordStatistic();
        for (Map.Entry<LocaleId, WordStatistic> entry : localeStatisticMap
                .entrySet()) {
            overallStatistic.add(entry.getValue());
        }
        overallStatistic.setRemainingHours(StatisticsUtil
                .getRemainingHours(overallStatistic));

        documentStatisticMap = Maps.newHashMap();
    }

    @Override
    protected String getMessage(String key, Object... args) {
        return msgs.format(key, args);
    }

    public List<HLocale> getSupportedLocale() {
        if (supportedLocale == null) {
            supportedLocale =
                    localeServiceImpl.getSupportedLanguageByProjectIteration(
                            projectSlug, versionSlug);
            Collections.sort(supportedLocale, languageComparator);
        }
        return supportedLocale;
    }

    public int
            getVersionSupportedLocaleCount(String projectSlug,
                    String versionSlug) {
        return localeServiceImpl.getSupportedLanguageByProjectIteration(
                projectSlug, versionSlug).size();
    }

    public List<HDocument> getDocuments() {
        if (documents == null) {
            documents =
                    documentDAO.getByProjectIteration(projectSlug, versionSlug,
                            false);
            Collections.sort(documents, documentComparator);
        }
        return documents;
    }

    public List<HDocument> getDocuments(DocumentDAO documentDAO) {
        if (this.documentDAO == null) {
            this.documentDAO = documentDAO;
        }
        return getDocuments();
    }

    public List<HDocument> getSourceDocuments() {
        if (documents == null) {
            documents =
                    documentDAO.getByProjectIteration(projectSlug, versionSlug,
                            false);
            Collections.sort(documents, sourceDocumentComparator);
        }
        return documents;
    }

    public List<HDocument> getSourceDocuments(DocumentDAO documentDAO) {
        if (this.documentDAO == null) {
            this.documentDAO = documentDAO;
        }
        return getSourceDocuments();
    }

    public List<HIterationGroup> getGroups() {
        if (groups == null) {
            HProjectIteration version = getVersion();
            if (version != null) {
                groups = Lists.newArrayList(version.getGroups());
            }
        }
        return groups;
    }

    public HProjectIteration getVersion() {
        if (version == null) {
            version = projectIterationDAO.getBySlug(projectSlug, versionSlug);
        }
        return version;
    }

    public void setPageRendered(boolean pageRendered) {
        if (pageRendered) {
            loadStatistics();
        }
        this.pageRendered = pageRendered;
    }

    @Getter
    @AllArgsConstructor
    @EqualsAndHashCode
    public class DocumentLocaleKey {
        private Long documentId;
        private LocaleId localeId;
    }

    public WordStatistic getStatisticsForLocale(LocaleId localeId) {
        return localeStatisticMap.get(localeId);
    }

    public WordStatistic getStatisticForDocument(Long documentId,
            LocaleId localeId) {
        DocumentLocaleKey key = new DocumentLocaleKey(documentId, localeId);
        if (!documentStatisticMap.containsKey(key)) {
            WordStatistic wordStatistic =
                    translationStateCacheImpl.getDocumentStatistics(documentId,
                            localeId);
            wordStatistic.setRemainingHours(StatisticsUtil
                    .getRemainingHours(wordStatistic));
            documentStatisticMap.put(key, wordStatistic);
        }
        return documentStatisticMap.get(key);
    }

    public WordStatistic getDocumentStatistic(Long documentId) {
        WordStatistic wordStatistic = new WordStatistic();

        for (HLocale locale : getSupportedLocale()) {
            WordStatistic statistic =
                    getStatisticForDocument(documentId, locale.getLocaleId());
            wordStatistic.add(statistic);
        }

        wordStatistic.setRemainingHours(StatisticsUtil
                .getRemainingHours(wordStatistic));
        return wordStatistic;
    }

    public DisplayUnit getStatisticFigureForDocument(
            SortingType.SortOption sortOption, LocaleId localeId,
            HDocument document) {
        WordStatistic statistic =
                getStatisticForDocument(document.getId(), localeId);

        Date date = null;
        if (sortOption.equals(SortingType.SortOption.LAST_SOURCE_UPDATE)
                || sortOption.equals(SortingType.SortOption.LAST_TRANSLATED)) {
            if (sortOption.equals(SortingType.SortOption.LAST_SOURCE_UPDATE)) {
                date = document.getLastChanged();
            } else {
                DocumentStatus docStat =
                        translationStateCacheImpl.getDocumentStatus(
                                document.getId(), localeId);
                date = docStat.getLastTranslatedDate();
            }
        }

        return getDisplayUnit(sortOption, statistic, date);
    }

    public DisplayUnit getStatisticFigureForDocument(
            SortingType.SortOption sortOption, HDocument document) {
        WordStatistic statistic = getDocumentStatistic(document.getId());
        return getDisplayUnit(sortOption, statistic, document.getLastChanged());
    }

    public DisplayUnit getStatisticFigureForLocale(
            SortingType.SortOption sortOption, LocaleId localeId) {
        WordStatistic statistic = getStatisticsForLocale(localeId);
        return getDisplayUnit(sortOption, statistic, null);
    }

    public boolean isUserAllowedToTranslateOrReview(HLocale hLocale) {
        return isVersionActive()
                && identity != null
                && (identity.hasPermission("add-translation", getVersion()
                        .getProject(), hLocale) || identity.hasPermission(
                        "translation-review", getVersion().getProject(),
                        hLocale));
    }

    private boolean isVersionActive() {
        return getVersion().getProject().getStatus() == EntityStatus.ACTIVE
                || getVersion().getStatus() == EntityStatus.ACTIVE;
    }

    @Restrict("#{versionHomeAction.documentRemovalAllowed}")
    public void deleteDocument(Long docId) {
        HDocument doc = documentDAO.getById(docId);
        documentServiceImpl.makeObsolete(doc);
        resetPageData();
        conversationScopeMessages.setMessage(FacesMessage.SEVERITY_INFO,
                doc.getDocId() + " has been removed.");
    }

    public List<HLocale> getAvailableSourceLocales() {
        return localeDAO.findAllActive();
    }

    public String getLastUpdatedDescription(HDocument document) {
        return DateUtil.getHowLongAgoDescription(document.getLastChanged());
    }

    public String getFormattedDate(HDocument hdoc) {
        return DateUtil.formatShortDate(hdoc.getLastChanged());
    }

    public boolean isDocumentRemovalAllowed() {
        // currently same permissions as uploading a document
        return this.isDocumentUploadAllowed();
    }

    public boolean isDocumentUploadAllowed() {
        return isVersionActive() && identity != null
                && identity.hasPermission("import-template", getVersion());
    }

    public boolean isZipFileDownloadAllowed() {
        return getVersion().getProjectType() != null
                && identity.hasPermission("download-all", getVersion());
    }

    public boolean isPoProject() {
        HProjectIteration projectIteration =
                projectIterationDAO.getBySlug(projectSlug, versionSlug);
        ProjectType type = projectIteration.getProjectType();
        if (type == null) {
            type = projectIteration.getProject().getDefaultProjectType();
        }
        return type == ProjectType.Gettext || type == ProjectType.Podir;
    }

    public String getZipFileDownloadTitle() {
        String message = null;
        if (!isZipFileDownloadAllowed()) {
            if (getVersion().getProjectType() == null) {
                message =
                        msgs.get(
                                "jsf.iteration.files.DownloadAllFiles.ProjectTypeNotSet");
            } else if (getVersion().getProjectType() != ProjectType.Gettext
                    && getVersion().getProjectType() != ProjectType.Podir) {
                message =
                        msgs.get(
                                "jsf.iteration.files.DownloadAllFiles.ProjectTypeNotAllowed");
            }
        } else {
            message =
                    msgs.get("jsf.iteration.files.DownloadAll");
        }
        return message;
    }

    public boolean isKnownProjectType() {
        ProjectType type =
                projectIterationDAO.getBySlug(projectSlug, versionSlug)
                        .getProjectType();
        return type != null;
    }

    public boolean isFileUploadAllowed(HLocale hLocale) {
        return isVersionActive()
                && identity != null
                && identity.hasPermission("modify-translation", getVersion()
                        .getProject(), hLocale);
    }

    public void uploadSourceFile() {
        identity.checkPermission("import-template", getVersion());

        if (sourceFileUpload.getFileName().endsWith(".pot")) {
            uploadPotFile();
        } else {
            DocumentType type =
                    translationFileServiceImpl.getDocumentType(sourceFileUpload
                            .getFileName());
            if (translationFileServiceImpl.hasAdapterFor(type)) {
                uploadAdapterFile();
            } else {
                conversationScopeMessages.setMessage(
                        FacesMessage.SEVERITY_INFO,
                        "Unrecognized file extension for "
                                + sourceFileUpload.getFileName());
            }
        }
        resetPageData();
    }

    public boolean isPoDocument(String docId) {
        return translationFileServiceImpl.isPoDocument(projectSlug,
                versionSlug, docId);
    }

    public String extensionOf(String docPath, String docName) {
        return "."
                + translationFileServiceImpl.getFileExtension(projectSlug,
                        versionSlug, docPath, docName);
    }

    public boolean hasOriginal(String docPath, String docName) {
        GlobalDocumentId id =
                new GlobalDocumentId(projectSlug, versionSlug, docPath
                        + docName);
        return filePersistService.hasPersistedDocument(id);
    }

    private void showUploadSuccessMessage() {
        conversationScopeMessages.setMessage(FacesMessage.SEVERITY_INFO,
                "Document " + sourceFileUpload.getFileName() + " uploaded.");
    }

    /**
     * <p>
     * Upload a pot file. File may be new or overwriting an existing file.
     * </p>
     * <p/>
     * <p>
     * If there is an existing file that is not a pot file, the pot file will be
     * parsed using msgctxt as Zanata id, otherwise id will be generated from a
     * hash of msgctxt and msgid.
     * </p>
     */
    private void uploadPotFile() {
        String docId = sourceFileUpload.getDocId();
        if (docId == null) {
            docId =
                    translationFileServiceImpl.generateDocId(
                            sourceFileUpload.getDocumentPath(),
                            sourceFileUpload.getFileName());
        }
        HDocument existingDoc =
                documentDAO.getByProjectIterationAndDocId(projectSlug,
                        versionSlug, docId);
        boolean docExists = existingDoc != null;
        boolean useOfflinePo = docExists && !isPoDocument(docId);

        try {
            Resource doc =
                    translationFileServiceImpl.parseUpdatedPotFile(
                            sourceFileUpload.getFileContents(), docId,
                            sourceFileUpload.getFileName(), useOfflinePo);

            doc.setLang(new LocaleId(sourceFileUpload.getSourceLang()));

            // TODO Copy Trans values
            documentServiceImpl.saveDocument(projectSlug, versionSlug, doc,
                    new StringSet(ExtensionType.GetText.toString()), false);

            showUploadSuccessMessage();
        } catch (ZanataServiceException e) {
            conversationScopeMessages.setMessage(FacesMessage.SEVERITY_ERROR,
                    e.getMessage() + "-" + sourceFileUpload.getFileName());
        } catch (ConstraintViolationException e) {
            conversationScopeMessages.setMessage(FacesMessage.SEVERITY_ERROR,
                    "Invalid arguments");
        }
    }

    private Optional<String> getOptionalParams() {
        return Optional.fromNullable(Strings.emptyToNull(sourceFileUpload
                .getAdapterParams()));
    }

    public void setSelectedLocaleId(String localeId) {
        this.selectedLocale = localeDAO.findByLocaleId(new LocaleId(localeId));
    }

    public void setSelectedDocumentId(String projectSlug, String versionSlug,
            String docId) {
        docId = UrlUtil.decodeString(docId);
        this.selectedDocument =
                documentDAO.getByProjectIterationAndDocId(projectSlug,
                        versionSlug, docId);
    }

    // TODO add logging for disk writing errors
    // TODO damason: unify this with Source/TranslationDocumentUpload
    private void uploadAdapterFile() {
        String fileName = sourceFileUpload.getFileName();
        String docId = sourceFileUpload.getDocId();
        String documentPath = "";
        if (docId == null) {
            documentPath = sourceFileUpload.getDocumentPath();
        } else if (docId.contains("/")) {
            documentPath = docId.substring(0, docId.lastIndexOf('/'));
        }

        File tempFile = null;
        byte[] md5hash;
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            InputStream fileContents =
                    new DigestInputStream(sourceFileUpload.getFileContents(),
                            md);
            tempFile =
                    translationFileServiceImpl.persistToTempFile(fileContents);
            md5hash = md.digest();
        } catch (ZanataServiceException e) {
            VersionHomeAction.log.error(
                    "Failed writing temp file for document {}", e,
                    sourceFileUpload.getDocId());

            conversationScopeMessages.setMessage(FacesMessage.SEVERITY_ERROR,
                    "Error saving uploaded document " + fileName
                            + " to server.");
            return;
        } catch (NoSuchAlgorithmException e) {
            VersionHomeAction.log.error("MD5 hash algorithm not available", e);
            conversationScopeMessages.setMessage(FacesMessage.SEVERITY_ERROR,
                    "Error generating hash for uploaded document " + fileName
                            + ".");
            return;
        }

        HDocument document = null;
        try {
            Resource doc;
            if (docId == null) {
                doc =
                        translationFileServiceImpl.parseAdapterDocumentFile(
                                tempFile.toURI(), documentPath, fileName,
                                getOptionalParams());
            } else {
                doc =
                        translationFileServiceImpl
                                .parseUpdatedAdapterDocumentFile(
                                        tempFile.toURI(), docId, fileName,
                                        getOptionalParams());
            }
            doc.setLang(new LocaleId(sourceFileUpload.getSourceLang()));
            Set<String> extensions = Collections.<String> emptySet();
            // TODO Copy Trans values
            document =
                    documentServiceImpl.saveDocument(projectSlug, versionSlug,
                            doc, extensions, false);
            showUploadSuccessMessage();
        } catch (SecurityException e) {
            conversationScopeMessages.setMessage(FacesMessage.SEVERITY_ERROR,
                    "Error reading uploaded document " + fileName
                            + " on server.");
        } catch (ZanataServiceException e) {
            conversationScopeMessages.setMessage(FacesMessage.SEVERITY_ERROR,
                    "Invalid document format for " + fileName);
        }

        if (document == null) {
            // error message for failed parse already added.
        } else {
            HRawDocument rawDocument = new HRawDocument();
            rawDocument.setDocument(document);
            rawDocument.setContentHash(new String(Hex.encodeHex(md5hash)));
            rawDocument.setType(DocumentType.typeFor(translationFileServiceImpl
                    .extractExtension(fileName)));
            rawDocument.setUploadedBy(identity.getCredentials().getUsername());

            Optional<String> params = getOptionalParams();
            if (params.isPresent()) {
                rawDocument.setAdapterParameters(params.get());
            }

            try {
                String name = projectSlug + ":" + versionSlug + ":" + docId;
                virusScanner.scan(tempFile, name);
            } catch (VirusDetectedException e) {
                VersionHomeAction.log.warn("File failed virus scan: {}",
                        e.getMessage());
                conversationScopeMessages.setMessage(
                        FacesMessage.SEVERITY_ERROR,
                        "uploaded file did not pass virus scan");
            }
            filePersistService.persistRawDocumentContentFromFile(rawDocument,
                    tempFile);
            documentDAO.addRawDocument(document, rawDocument);
            documentDAO.flush();
        }

        translationFileServiceImpl.removeTempFile(tempFile);
    }

    public String encodeDocId(String docId) {
        return UrlUtil.encodeString(docId);
    }

    public String decodeDocId(String docId) {
        return UrlUtil.decodeString(docId);
    }

    public void uploadTranslationFile(HLocale hLocale) {
        identity.checkPermission("modify-translation", hLocale, getVersion()
                .getProject());
        try {
            // process the file
            TranslationsResource transRes =
                    translationFileServiceImpl.parseTranslationFile(
                            translationFileUpload.getFileContents(),
                            translationFileUpload.getFileName(), hLocale
                                    .getLocaleId().getId(), projectSlug,
                            versionSlug, translationFileUpload.docId);

            // translate it
            Set<String> extensions;
            if (translationFileUpload.getFileName().endsWith(".po")) {
                extensions = new StringSet(ExtensionType.GetText.toString());
            } else {
                extensions = Collections.<String> emptySet();
            }
            List<String> warnings =
                    translationServiceImpl
                            .translateAllInDoc(
                                    projectSlug,
                                    versionSlug,
                                    translationFileUpload.getDocId(),
                                    hLocale.getLocaleId(),
                                    transRes,
                                    extensions,
                                    translationFileUpload.isMergeTranslations() ? MergeType.AUTO
                                            : MergeType.IMPORT);

            StringBuilder infoMsg =
                    new StringBuilder("File ").append(
                            translationFileUpload.getFileName()).append(
                            " uploaded.");

            if (!warnings.isEmpty()) {
                infoMsg.append(" There were some warnings, see below.");
            }
            conversationScopeMessages.setMessage(FacesMessage.SEVERITY_INFO,
                    infoMsg.toString());

            if (!warnings.isEmpty()) {
                List<FacesMessage> warningMessages = Lists.newArrayList();
                for (String warning : warnings) {
                    warningMessages.add(new FacesMessage(
                            FacesMessage.SEVERITY_WARN, warning, null));
                }
                conversationScopeMessages.setMessages(warningMessages);
            }
        } catch (ZanataServiceException e) {
            conversationScopeMessages.setMessage(FacesMessage.SEVERITY_ERROR,
                    translationFileUpload.getFileName() + "-" + e.getMessage());
        }
        resetPageData();
    }

    private class DocumentFilter extends InMemoryListFilter<HDocument> {
        private DocumentDAO documentDAO =
                ServiceLocator.instance().getInstance(DocumentDAO.class);

        @Override
        protected List<HDocument> fetchAll() {
            return getDocuments(documentDAO);
        }

        @Override
        protected boolean include(HDocument elem, String filter) {
            return StringUtils.containsIgnoreCase(elem.getName(), filter)
                    || StringUtils.containsIgnoreCase(elem.getPath(), filter);
        }
    };

    private class SourceDocumentFilter extends InMemoryListFilter<HDocument> {
        private DocumentDAO documentDAO = ServiceLocator.instance()
                .getInstance(DocumentDAO.class);

        @Override
        protected List<HDocument> fetchAll() {
            return getSourceDocuments(documentDAO);
        }

        @Override
        protected boolean include(HDocument elem, String filter) {
            return StringUtils.containsIgnoreCase(elem.getName(), filter)
                    || StringUtils.containsIgnoreCase(elem.getPath(), filter);
        }
    };

    private class DocumentComparator implements Comparator<HDocument> {
        private SortingType sortingType;

        @Setter
        private LocaleId selectedLocaleId;

        public DocumentComparator(SortingType sortingType) {
            this.sortingType = sortingType;
        }

        @Override
        public int compare(HDocument o1, HDocument o2) {
            SortingType.SortOption selectedSortOption =
                    sortingType.getSelectedSortOption();

            if (!selectedSortOption.isAscending()) {
                HDocument temp = o1;
                o1 = o2;
                o2 = temp;
            }

            if (selectedSortOption.equals(SortingType.SortOption.ALPHABETICAL)) {
                return o1.getName().compareToIgnoreCase(o2.getName());
            } else if (selectedSortOption
                    .equals(SortingType.SortOption.LAST_SOURCE_UPDATE)) {
                return DateUtil.compareDate(o1.getLastChanged(),
                        o2.getLastChanged());
            } else if (selectedSortOption
                    .equals(SortingType.SortOption.LAST_TRANSLATED)) {
                if (selectedLocaleId != null) {
                    DocumentStatus docStat1 =
                            translationStateCacheImpl.getDocumentStatus(
                                    o1.getId(), selectedLocaleId);
                    DocumentStatus docStat2 =
                            translationStateCacheImpl.getDocumentStatus(
                                    o2.getId(), selectedLocaleId);

                    return DateUtil.compareDate(
                            docStat1.getLastTranslatedDate(),
                            docStat2.getLastTranslatedDate());
                }
            } else {
                WordStatistic wordStatistic1;
                WordStatistic wordStatistic2;
                if (selectedLocaleId != null) {
                    wordStatistic1 =
                            getStatisticForDocument(o1.getId(),
                                    selectedLocaleId);

                    wordStatistic2 =
                            getStatisticForDocument(o2.getId(),
                                    selectedLocaleId);

                } else {
                    wordStatistic1 = getDocumentStatistic(o1.getId());
                    wordStatistic2 = getDocumentStatistic(o2.getId());
                }
                return compareWordStatistic(wordStatistic1, wordStatistic2,
                        selectedSortOption);
            }
            return 0;
        }
    }

    private class LanguageComparator implements Comparator<HLocale> {
        private SortingType sortingType;

        @Setter
        private Long selectedDocumentId;

        public LanguageComparator(SortingType sortingType) {
            this.sortingType = sortingType;
        }

        @Override
        public int compare(HLocale o1, HLocale o2) {
            SortingType.SortOption selectedSortOption =
                    sortingType.getSelectedSortOption();

            if (!selectedSortOption.isAscending()) {
                HLocale temp = o1;
                o1 = o2;
                o2 = temp;
            }

            // Need to get statistic for comparison
            if (!selectedSortOption.equals(SortingType.SortOption.ALPHABETICAL)) {
                WordStatistic wordStatistic1;
                WordStatistic wordStatistic2;

                if (selectedDocumentId == null) {
                    wordStatistic1 = getStatisticsForLocale(o1.getLocaleId());
                    wordStatistic2 = getStatisticsForLocale(o2.getLocaleId());
                } else {
                    wordStatistic1 =
                            getStatisticForDocument(selectedDocumentId,
                                    o1.getLocaleId());
                    wordStatistic2 =
                            getStatisticForDocument(selectedDocumentId,
                                    o2.getLocaleId());
                }
                return compareWordStatistic(wordStatistic1, wordStatistic2,
                        selectedSortOption);
            } else {
                return o1.retrieveDisplayName().compareTo(
                        o2.retrieveDisplayName());
            }
        }
    }

    /**
     * Helper class to upload documents.
     */
    @Getter
    @Setter
    public static class SourceFileUploadHelper implements Serializable {
        private static final long serialVersionUID = 1L;

        private InputStream fileContents;

        private String docId;

        private String fileName;

        // TODO rename to customDocumentPath (update in EL also)
        private String documentPath;

        private String sourceLang = "en-US"; // en-US by default

        private String adapterParams = "";
    }

    /**
     * Helper class to upload translation files.
     */
    @Getter
    @Setter
    public static class TranslationFileUploadHelper implements Serializable {
        private static final long serialVersionUID = 1L;

        private String docId;

        private InputStream fileContents;

        private String fileName;

        private boolean mergeTranslations = true; // Merge by default
    }
}
TOP

Related Classes of org.zanata.action.VersionHomeAction

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.