Java tutorial
/* * 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; } }