io.lavagna.service.LavagnaExporter.java Source code

Java tutorial

Introduction

Here is the source code for io.lavagna.service.LavagnaExporter.java

Source

/**
 * This file is part of lavagna.
 *
 * lavagna is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * lavagna 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with lavagna.  If not, see <http://www.gnu.org/licenses/>.
 */
package io.lavagna.service;

import io.lavagna.common.Json;
import io.lavagna.model.Board;
import io.lavagna.model.BoardInfo;
import io.lavagna.model.Card;
import io.lavagna.model.CardData;
import io.lavagna.model.CardDataUploadContentInfo;
import io.lavagna.model.CardLabel;
import io.lavagna.model.CardType;
import io.lavagna.model.Event;
import io.lavagna.model.EventFull;
import io.lavagna.model.LabelListValueWithMetadata;
import io.lavagna.model.Pair;
import io.lavagna.model.Project;
import io.lavagna.model.User;
import io.lavagna.query.StatisticsQuery;

import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import org.apache.commons.lang3.tuple.ImmutablePair;
import org.springframework.stereotype.Component;

@Component
class LavagnaExporter {

    private final ConfigurationRepository configurationRepository;
    private final UserRepository userRepository;
    private final PermissionService permissionService;
    private final ProjectService projectService;
    private final CardLabelRepository cardLabelRepository;
    private final BoardRepository boardRepository;
    private final BoardColumnRepository boardColumnRepository;
    private final EventRepository eventRepository;
    private final CardRepository cardRepository;
    private final CardDataRepository cardDataRepository;
    private final StatisticsQuery statisticsQuery;

    public LavagnaExporter(ConfigurationRepository configurationRepository, UserRepository userRepository,
            PermissionService permissionService, ProjectService projectService,
            CardLabelRepository cardLabelRepository, BoardRepository boardRepository,
            BoardColumnRepository boardColumnRepository, EventRepository eventRepository,
            CardRepository cardRepository, CardDataRepository cardDataRepository, StatisticsQuery statisticsQuery) {
        this.configurationRepository = configurationRepository;
        this.userRepository = userRepository;
        this.permissionService = permissionService;
        this.projectService = projectService;
        this.cardLabelRepository = cardLabelRepository;
        this.boardRepository = boardRepository;
        this.boardColumnRepository = boardColumnRepository;
        this.eventRepository = eventRepository;
        this.cardRepository = cardRepository;
        this.cardDataRepository = cardDataRepository;
        this.statisticsQuery = statisticsQuery;
    }

    public void exportData(OutputStream os) throws IOException {
        try (ZipOutputStream zf = new ZipOutputStream(os);
                OutputStreamWriter osw = new OutputStreamWriter(zf, StandardCharsets.UTF_8)) {
            writeEntry("config.json", configurationRepository.findAll(), zf, osw);
            writeEntry("users.json", userRepository.findAll(), zf, osw);
            writeEntry("permissions.json", permissionService.findAllRolesAndRelatedPermissionWithUsers(), zf, osw);

            exportFiles(zf, osw);

            for (Project p : projectService.findAll()) {
                exportProject(zf, osw, p);
            }

            //
            final int amountPerPage = 100;
            int pages = (eventRepository.count() + amountPerPage - 1) / amountPerPage;

            writeEntry("events-page-count.json", pages, zf, osw);
            for (int i = 0; i < pages; i++) {
                writeEntry("events-" + i + ".json", toEventFull(eventRepository.find(i * 100, 100)), zf, osw);
            }
            //
            writeEntry("card-data-types-order.json",
                    cardDataRepository.findAllByTypes(
                            EnumSet.of(CardType.ACTION_LIST, CardType.ACTION_CHECKED, CardType.ACTION_UNCHECKED)),
                    zf, osw);
        }
    }

    private void exportFiles(ZipOutputStream zf, OutputStreamWriter osw) throws IOException {
        osw.flush();
        for (CardDataUploadContentInfo fileData : cardDataRepository.findAllDataUploadContentInfo()) {
            zf.putNextEntry(new ZipEntry("files/" + fileData.getDigest()));
            cardDataRepository.outputFileContent(fileData.getDigest(), zf);
            writeEntry("files/" + fileData.getDigest() + ".json", fileData, zf, osw);
        }
    }

    private List<EventFull> toEventFull(List<Event> events) {
        List<EventFull> res = new ArrayList<>(events.size());
        for (Event e : events) {
            // TODO not optimal

            User u = userRepository.findById(e.getUserId());
            ImmutablePair<Board, Card> bc = findByCardId(e.getCardId());
            //
            String content = handleContent(e);

            User labelUser = e.getValueUser() != null ? userRepository.findById(e.getValueUser()) : null;
            ImmutablePair<Board, Card> labelCard = e.getValueCard() != null ? findByCardId(e.getValueCard()) : null;

            //
            res.add(new EventFull(e, u, bc, content, labelCard, labelUser));
        }
        return res;
    }

    private ImmutablePair<Board, Card> findByCardId(int id) {
        Card c = cardRepository.findBy(id);
        Board b = boardRepository.findBoardById(boardColumnRepository.findById(c.getColumnId()).getBoardId());
        return ImmutablePair.of(b, c);
    }

    // TODO CLEANUP
    private String handleContent(Event e) {
        if (e.getDataId() == null) {
            return null;
        }

        switch (e.getEvent()) {
        case COMMENT_CREATE:
            return extractFirstContent(e, CardType.COMMENT_HISTORY);
        case DESCRIPTION_CREATE:
            return extractFirstContent(e, CardType.DESCRIPTION_HISTORY);
        case DESCRIPTION_UPDATE:
        case COMMENT_UPDATE:
            List<Event> nextEvent = eventRepository.findNextEventFor(e);
            return cardDataRepository
                    .getDataLightById(nextEvent.isEmpty() ? e.getDataId() : nextEvent.get(0).getPreviousDataId())
                    .getContent();
        case ACTION_ITEM_CREATE:
        case ACTION_LIST_CREATE:
            return cardDataRepository.getDataLightById(e.getDataId()).getContent();
        case FILE_UPLOAD:
        case FILE_DELETE:
            return cardDataRepository.getDataLightById(e.getDataId()).getContent();
        default:
            return null;
        }

    }

    private String extractFirstContent(Event e, CardType type) {
        CardData cd = cardDataRepository.getDataLightById(e.getDataId());
        List<CardData> history = cardDataRepository.findAllDataLightByReferenceIdAndType(cd.getId(), type);
        return (history.isEmpty() ? cd : history.get(0)).getContent();
    }

    private static void writeEntry(String entryName, Object toSerialize, ZipOutputStream zf,
            OutputStreamWriter osw) {
        try {
            zf.putNextEntry(new ZipEntry(entryName));
            Json.GSON.toJson(toSerialize, osw);
            osw.flush();
            zf.flush();
            zf.closeEntry();
        } catch (IOException ioe) {
            throw new IllegalStateException("error while serializing entry " + entryName, ioe);
        }
    }

    private void exportProject(ZipOutputStream zf, OutputStreamWriter osw, Project p) {

        String projectNameDir = "projects/" + p.getShortName();
        writeEntry(projectNameDir + ".json", p, zf, osw);
        writeEntry(projectNameDir + "/permissions.json",
                permissionService.findAllRolesAndRelatedPermissionWithUsersInProjectId(p.getId()), zf, osw);

        List<Pair<CardLabel, List<LabelListValueWithMetadata>>> labels = new ArrayList<>();
        for (CardLabel cl : cardLabelRepository.findLabelsByProject(p.getId())) {
            labels.add(Pair.of(cl, cardLabelRepository.findListValuesByLabelId(cl.getId())));
        }
        writeEntry(projectNameDir + "/labels.json", labels, zf, osw);
        writeEntry(projectNameDir + "/column-definitions.json",
                projectService.findMappedColumnDefinitionsByProjectId(p.getId()), zf, osw);

        for (BoardInfo boardInfo : boardRepository.findBoardInfo(p.getId())) {
            exportBoard(boardInfo, p, zf, osw);
        }
    }

    private void exportBoard(BoardInfo boardInfo, Project p, ZipOutputStream zf, OutputStreamWriter osw) {
        String boardNameDir = "boards/" + boardInfo.getShortName();
        writeEntry(boardNameDir + ".json", Pair.of(p.getShortName(), boardInfo), zf, osw);
        int boardId = boardRepository.findBoardIdByShortName(boardInfo.getShortName());

        writeEntry(boardNameDir + "/columns.json", boardColumnRepository.findAllColumnsFor(boardId), zf, osw);
        writeEntry(boardNameDir + "/cards.json", cardRepository.findAllByBoardShortName(boardInfo.getShortName()),
                zf, osw);
        writeEntry(boardNameDir + "/statistics.json", statisticsQuery.findForBoard(boardId), zf, osw);
    }
}