com.formkiq.core.service.ArchiveServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.formkiq.core.service.ArchiveServiceImpl.java

Source

/*
 * Copyright (C) 2017 FormKiQ Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.formkiq.core.service;

import static com.formkiq.core.form.dto.WorkflowOutputDocumentType.FORM;
import static com.formkiq.core.util.Strings.CHARSET_UTF8;
import static com.formkiq.core.util.Strings.extractLabelAndValue;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;

import com.formkiq.core.form.JSONService;
import com.formkiq.core.form.dto.ArchiveDTO;
import com.formkiq.core.form.dto.FormJSON;
import com.formkiq.core.form.dto.Workflow;
import com.formkiq.core.form.dto.WorkflowOutput;
import com.formkiq.core.form.dto.WorkflowOutputDocument;
import com.formkiq.core.form.dto.WorkflowOutputForm;
import com.formkiq.core.form.dto.WorkflowOutputFormField;
import com.formkiq.core.form.dto.WorkflowRoute;
import com.formkiq.core.util.Zips;

/**
 * Default Class to handle creating / changing Form Archive format.
 *
 */
public class ArchiveServiceImpl implements ArchiveService {

    /** Logger. */
    private static final Logger LOG = Logger.getLogger(ArchiveServiceImpl.class.getName());

    /** FolderService. */
    @Autowired
    private FolderService folderService;

    /** JSONService. */
    @Autowired
    private JSONService jsonService;

    @Override
    public byte[] createZipFile(final ArchiveDTO archive) throws IOException {

        Map<String, byte[]> map = new HashMap<>();

        Workflow workflow = archive.getWorkflow();

        if (workflow != null) {
            map.put(workflow.getUUID() + ".workflow", this.jsonService.writeValueAsBytes(workflow));
        }

        for (FormJSON form : archive.getForms().values()) {
            byte[] json = this.jsonService.writeValueAsBytes(form);
            map.put(form.getUUID() + ".form", json);
        }

        for (Map.Entry<String, byte[]> e : archive.getPDF().entrySet()) {
            map.put(e.getKey(), e.getValue());
        }

        for (Map.Entry<String, byte[]> e : archive.getSignatures().entrySet()) {
            map.put(e.getKey() + ".signature", e.getValue());
        }

        for (Map.Entry<String, WorkflowRoute> e : archive.getRoutes().entrySet()) {
            map.put(e.getKey() + ".route", this.jsonService.writeValueAsBytes(e.getValue()));
        }

        for (Map.Entry<String, byte[]> e : archive.getObjects().entrySet()) {
            map.put(e.getKey(), e.getValue());
        }

        return Zips.zipFile(map);
    }

    @Override
    public ArchiveDTO extractJSONFromZipFile(final byte[] bytes) {

        ArchiveDTO archive = new ArchiveDTO();

        ByteArrayInputStream is = new ByteArrayInputStream(bytes);
        ZipInputStream zipStream = new ZipInputStream(is);

        try {

            ZipEntry entry = null;
            while ((entry = zipStream.getNextEntry()) != null) {

                String filename = entry.getName();

                if (filename.endsWith(".form")) {

                    String data = IOUtils.toString(zipStream, CHARSET_UTF8);
                    archive.addForm(this.jsonService.readValue(data, FormJSON.class));

                } else if (filename.endsWith(".workflow")) {

                    String data = IOUtils.toString(zipStream, CHARSET_UTF8);
                    archive.setWorkflow(this.jsonService.readValue(data, Workflow.class));

                } else if (filename.endsWith(".pdf")) {

                    byte[] data = IOUtils.toByteArray(zipStream);
                    archive.addPDF(filename, data);

                } else if (filename.endsWith(".signature")) {

                    String s = filename.replaceAll("\\.signature", "");
                    byte[] data = IOUtils.toByteArray(zipStream);
                    archive.addSignature(s, data);

                } else if (filename.endsWith(".route")) {

                    String data = IOUtils.toString(zipStream, CHARSET_UTF8);
                    archive.addRoute(this.jsonService.readValue(data, WorkflowRoute.class));

                } else {

                    byte[] data = IOUtils.toByteArray(zipStream);
                    archive.addObject(filename, data);
                }
            }

            archive.finish();

        } catch (IOException e) {
            LOG.log(Level.WARNING, e.getMessage(), e);
            throw new InvalidRequestBodyException();

        } finally {

            IOUtils.closeQuietly(is);
            IOUtils.closeQuietly(zipStream);
        }

        return archive;
    }

    @Override
    public Pair<ArchiveDTO, String> get(final String folder, final String uuid, final boolean resetUUID)
            throws IOException {

        Pair<byte[], String> p = this.folderService.findFormData(folder, uuid);
        String sha1hash = p.getRight();

        ArchiveDTO archive = extractJSONFromZipFile(p.getLeft());

        // TODO remove..
        for (String formUUID : archive.getWorkflow().getSteps()) {
            if (!archive.getForms().containsKey(formUUID)) {

                byte[] d = this.folderService.findFormData(folder, formUUID).getLeft();

                ArchiveDTO fa = extractJSONFromZipFile(d);
                archive.getForms().putAll(fa.getForms());
            }
        }

        if (resetUUID) {
            resetUUID(archive);
        }

        return Pair.of(archive, sha1hash);
    }

    /**
     * Reset {@link FormJSON} UUID.
     * @param archive {@link ArchiveDTO}
     * @param form {@link FormJSON}
     * @param map {@link Map}
     */
    private void resetFormUUID(final ArchiveDTO archive, final FormJSON form, final Map<String, String> map) {

        String oldUUID = form.getUUID();
        String newUUID = map.get(oldUUID);

        Workflow workflow = archive.getWorkflow();
        archive.removeForm(form);

        form.setSourceFormUUID(oldUUID);
        form.setUUID(newUUID);

        archive.addForm(form);

        form.setParentUUID(workflow.getParentUUID());

        Collections.replaceAll(workflow.getSteps(), oldUUID, newUUID);
        Collections.replaceAll(workflow.getPrintsteps(), oldUUID, newUUID);

        if (!CollectionUtils.isEmpty(workflow.getOutputs())) {
            resetWorkflowOutput(workflow, form, oldUUID, newUUID);
        }
    }

    /**
     * Reset {@link WorkflowOutput} UUIDs.
     * @param workflow {@link Workflow}
     * @param form {@link FormJSON}
     * @param oldUUID {@link String}
     * @param newUUID {@link String}
     */
    private void resetWorkflowOutput(final Workflow workflow, final FormJSON form, final String oldUUID,
            final String newUUID) {

        for (WorkflowOutput wo : workflow.getOutputs()) {

            wo.setUUID(UUID.randomUUID().toString());

            if (FORM.equals(wo.getInputDocumentType())) {

                WorkflowOutputForm wof = (WorkflowOutputForm) wo;
                String uuid = extractLabelAndValue(wof.getForm()).getRight();
                if (uuid.equals(oldUUID)) {
                    wof.setForm(form.getName(), newUUID);
                }

            } else if (wo instanceof WorkflowOutputDocument) {

                WorkflowOutputDocument wd = (WorkflowOutputDocument) wo;
                for (WorkflowOutputFormField f : wd.getFields()) {

                    String uuid = extractLabelAndValue(f.getForm()).getRight();

                    if (uuid.equals(oldUUID)) {
                        f.setForm(form.getName() + "[" + newUUID + "]");
                    }
                }
            }
        }
    }

    @Override
    public Map<String, String> resetUUID(final ArchiveDTO archive) {

        Workflow workflow = archive.getWorkflow();

        workflow.setParentUUID(workflow.getUUID());
        workflow.setUUID(UUID.randomUUID().toString());

        Map<String, String> map = new HashMap<>();
        for (FormJSON form : archive.getForms().values()) {
            map.put(form.getUUID(), UUID.randomUUID().toString());
        }

        for (String step : workflow.getSteps()) {

            FormJSON form = archive.getForm(step);
            resetFormUUID(archive, form, map);
        }

        return map;
    }
}