Java tutorial
/* * Copyright (C) 2000 - 2015 Silverpeas * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * As a special exception to the terms and conditions of version 3.0 of * the GPL, you may redistribute this Program in connection with Free/Libre * Open Source Software ("FLOSS") applications as described in Silverpeas's * FLOSS exception. You should have received a copy of the text describing * the FLOSS exception, and it is also available here: * "https://www.silverpeas.org/legal/floss_exception.html" * * This program 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.silverpeas.components.kmelia.workflowextensions; import com.lowagie.text.Element; import com.lowagie.text.Font; import com.lowagie.text.Phrase; import com.lowagie.text.pdf.PdfPCell; import com.lowagie.text.pdf.PdfPTable; import com.lowagie.text.pdf.PdfWriter; import org.silverpeas.core.contribution.content.form.DataRecord; import org.silverpeas.core.contribution.content.form.DataRecordUtil; import org.silverpeas.core.contribution.content.form.Field; import org.silverpeas.core.contribution.content.form.FieldTemplate; import org.silverpeas.core.contribution.content.form.Form; import org.silverpeas.core.contribution.content.form.FormException; import org.silverpeas.core.contribution.content.form.displayers.WysiwygFCKFieldDisplayer; import org.silverpeas.core.contribution.content.form.field.ExplorerField; import org.silverpeas.core.contribution.content.form.field.FileField; import org.silverpeas.core.contribution.content.form.form.XmlForm; import org.silverpeas.core.contribution.content.form.record.GenericFieldTemplate; import org.silverpeas.core.contribution.template.publication.PublicationTemplateException; import org.silverpeas.core.contribution.template.publication.PublicationTemplateImpl; import org.silverpeas.core.contribution.template.publication.PublicationTemplateManager; import org.silverpeas.core.workflow.api.WorkflowException; import org.silverpeas.core.workflow.api.instance.HistoryStep; import org.silverpeas.core.workflow.api.instance.ProcessInstance; import org.silverpeas.core.workflow.api.instance.UpdatableProcessInstance; import org.silverpeas.core.workflow.api.model.Action; import org.silverpeas.core.workflow.api.model.Parameter; import org.silverpeas.core.workflow.api.model.State; import org.silverpeas.core.workflow.external.impl.ExternalActionImpl; import org.silverpeas.core.admin.user.model.UserDetail; import org.silverpeas.components.kmelia.service.KmeliaService; import org.silverpeas.components.kmelia.model.KmeliaRuntimeException; import org.silverpeas.core.node.service.NodeService; import org.silverpeas.core.node.model.NodeDetail; import org.silverpeas.core.node.model.NodePK; import org.silverpeas.core.contribution.publication.model.PublicationDetail; import org.silverpeas.core.contribution.publication.model.PublicationPK; import net.htmlparser.jericho.Source; import org.silverpeas.core.contribution.attachment.AttachmentException; import org.silverpeas.core.contribution.attachment.AttachmentService; import org.silverpeas.core.contribution.attachment.AttachmentServiceProvider; import org.silverpeas.core.contribution.attachment.model.DocumentType; import org.silverpeas.core.contribution.attachment.model.SimpleDocument; import org.silverpeas.core.contribution.attachment.model.SimpleDocumentPK; import org.silverpeas.core.admin.service.OrganizationController; import org.silverpeas.core.admin.service.OrganizationControllerProvider; import org.silverpeas.core.util.DateUtil; import org.silverpeas.core.ForeignPK; import org.silverpeas.core.util.ServiceProvider; import org.silverpeas.core.util.StringUtil; import org.silverpeas.core.exception.SilverpeasRuntimeException; import org.silverpeas.core.util.logging.SilverLogger; import java.awt.*; import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; public class SendInKmelia extends ExternalActionImpl { private String targetId = "unknown"; private String topicId = "unknown"; private String pubDesc = null; private String role = "unknown"; private String xmlFormName = null; private boolean addPDFHistory = true; // Add pdf history before instance attachments private boolean addPDFHistoryFirst = true; private String pdfHistoryName = null; private String userId = null; private static final String ADMIN_ID = "0"; public SendInKmelia() { } @Override public void execute() { setRole(getEvent().getUserRoleName()); Parameter parameter = getTriggerParameter("explorerFieldName"); if (parameter != null && StringUtil.isDefined(parameter.getValue())) { String explorerFieldName = parameter.getValue(); // getting place to create publication from explorer field try { ExplorerField explorer = (ExplorerField) getProcessInstance().getField(explorerFieldName); ForeignPK pk = (ForeignPK) explorer.getObjectValue(); targetId = pk.getInstanceId(); topicId = pk.getId(); } catch (WorkflowException e) { SilverLogger.getLogger(this).error(e.getMessage(), e); } } else { targetId = getTriggerParameter("targetComponentId").getValue(); Parameter paramTopicPath = getTriggerParameter("targetFolderPath"); if (paramTopicPath != null && StringUtil.isDefined(paramTopicPath.getValue())) { try { String path = DataRecordUtil.applySubstitution(paramTopicPath.getValue(), getProcessInstance().getAllDataRecord(role, "fr"), "fr"); topicId = getNodeId(path); } catch (WorkflowException e) { SilverLogger.getLogger(this).error(e.getMessage(), e); topicId = "0"; } } else { topicId = getTriggerParameter("targetTopicId").getValue(); } } final String pubTitle = getTriggerParameter("pubTitle").getValue(); Parameter paramDescription = getTriggerParameter("pubDescription"); if (paramDescription != null && StringUtil.isDefined(paramDescription.getValue())) { pubDesc = paramDescription.getValue(); } if (getTriggerParameter("xmlFormName") != null) { xmlFormName = getTriggerParameter("xmlFormName").getValue(); if (StringUtil.isDefined(xmlFormName) && xmlFormName.lastIndexOf(".xml") != -1) { xmlFormName = xmlFormName.substring(0, xmlFormName.lastIndexOf(".xml")); } } boolean formIsUsed = StringUtil.isDefined(xmlFormName); if (getTriggerParameter("addPDFHistory") != null) { addPDFHistory = StringUtil.getBooleanValue(getTriggerParameter("addPDFHistory").getValue()); if (getTriggerParameter("addPDFHistoryFirst") != null) { addPDFHistoryFirst = StringUtil .getBooleanValue(getTriggerParameter("addPDFHistoryFirst").getValue()); } Parameter paramPDFName = getTriggerParameter("pdfHistoryName"); if (paramPDFName != null) { pdfHistoryName = getTriggerParameter("pdfHistoryName").getValue(); } } // 1 - Create publication PublicationPK pubPK = new PublicationPK("0", getTargetId()); Date now = new Date(); String pubName = getProcessInstance().getTitle(getRole(), getLanguage()); if (StringUtil.isDefined(pubTitle)) { try { pubName = DataRecordUtil.applySubstitution(pubTitle, getProcessInstance().getAllDataRecord(role, "fr"), "fr"); } catch (WorkflowException e) { SilverLogger.getLogger(this).error(e.getMessage(), e); } } String desc = ""; if (StringUtil.isDefined(pubDesc)) { try { desc = DataRecordUtil.applySubstitution(pubDesc, getProcessInstance().getAllDataRecord(role, "fr"), "fr"); } catch (WorkflowException e) { SilverLogger.getLogger(this).error(e.getMessage(), e); } } userId = getBestUserDetail().getId(); PublicationDetail pubDetail = new PublicationDetail(pubPK, pubName, desc, now, now, null, userId, 1, null, null, null); if (formIsUsed) { pubDetail.setInfoId(xmlFormName); } KmeliaService kmelia = getKmeliaBm(); String pubId = kmelia.createPublicationIntoTopic(pubDetail, new NodePK(getTopicId(), getTargetId())); pubPK.setId(pubId); // 2 - Attach history as pdf file if (addPDFHistory && addPDFHistoryFirst) { addPdfHistory(pubPK, userId); } // 3 - Copy all instance regular files to publication ForeignPK fromPK = new ForeignPK(getProcessInstance().getInstanceId(), getProcessInstance().getModelId()); ForeignPK toPK = new ForeignPK(pubPK); copyFiles(fromPK, toPK, DocumentType.attachment, DocumentType.attachment); if (addPDFHistory && !addPDFHistoryFirst) { addPdfHistory(pubPK, userId); } // force the update PublicationDetail newPubli = getKmeliaBm().getPublicationDetail(pubPK); newPubli.setStatusMustBeChecked(false); getKmeliaBm().updatePublication(newPubli); // process form content if (formIsUsed) { // target app use form : populate form fields populateFields(pubId, fromPK, toPK); } else { // target app do not use form : copy files of worflow folder copyFiles(fromPK, toPK, DocumentType.form, DocumentType.attachment); } } public void populateFields(String pubId, ForeignPK fromPK, ForeignPK toPK) { // Get the current instance UpdatableProcessInstance currentProcessInstance = (UpdatableProcessInstance) getProcessInstance(); try { // register xmlForm of publication PublicationTemplateManager.getInstance().addDynamicPublicationTemplate(targetId + ":" + xmlFormName, xmlFormName + ".xml"); PublicationTemplateImpl pubTemplate = (PublicationTemplateImpl) PublicationTemplateManager.getInstance() .getPublicationTemplate(targetId + ":" + xmlFormName); DataRecord record = pubTemplate.getRecordSet().getEmptyRecord(); record.setId(pubId); for (String fieldName : record.getFieldNames()) { Object fieldValue = null; try { Field fieldOfFolder = currentProcessInstance.getField(fieldName); fieldValue = fieldOfFolder.getObjectValue(); // Check file attachment in order to put them inside form if (fieldOfFolder instanceof FileField) { fieldValue = copyFormFile(fromPK, toPK, ((FileField) fieldOfFolder).getAttachmentId()); } } catch (WorkflowException e) { } record.getField(fieldName).setObjectValue(fieldValue); } // Update pubTemplate.getRecordSet().save(record); } catch (PublicationTemplateException | FormException e) { SilverLogger.getLogger(this).error(e.getMessage(), e); } } private String copyFormFile(ForeignPK fromPK, ForeignPK toPK, String attachmentId) { SimpleDocument attachment; if (StringUtil.isDefined(attachmentId)) { AttachmentService service = AttachmentServiceProvider.getAttachmentService(); // Retrieve attachment detail to copy attachment = service.searchDocumentById(new SimpleDocumentPK(attachmentId, fromPK.getInstanceId()), null); if (attachment != null) { SimpleDocumentPK copyPK = copyFileWithoutDocumentTypeChange(attachment, toPK); return copyPK.getId(); } } return null; } private Map<String, String> copyFiles(ForeignPK fromPK, ForeignPK toPK, DocumentType fromType, DocumentType toType) { Map<String, String> fileIds = new HashMap<>(); try { List<SimpleDocument> origins = AttachmentServiceProvider.getAttachmentService() .listDocumentsByForeignKeyAndType(fromPK, fromType, getLanguage()); for (SimpleDocument origin : origins) { SimpleDocumentPK copyPk = copyFile(origin, toPK, toType); fileIds.put(origin.getId(), copyPk.getId()); } } catch (AttachmentException e) { SilverLogger.getLogger(this).error(e.getMessage(), e); } return fileIds; } private SimpleDocumentPK copyFileWithoutDocumentTypeChange(SimpleDocument file, ForeignPK toPK) { return copyFile(file, toPK, null); } private SimpleDocumentPK copyFile(SimpleDocument file, ForeignPK toPK, DocumentType type) { if (type != null) { file.setDocumentType(type); } return AttachmentServiceProvider.getAttachmentService().copyDocument(file, toPK); } private byte[] generatePDF(ProcessInstance instance) { com.lowagie.text.Document document = new com.lowagie.text.Document(); try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); PdfWriter.getInstance(document, baos); document.open(); HistoryStep[] steps = instance.getHistorySteps(); for (HistoryStep historyStep : steps) { generatePDFStep(historyStep, document); } document.close(); return baos.toByteArray(); } catch (Exception e) { SilverLogger.getLogger(this).error(e.getMessage(), e); } return null; } private void generatePDFStep(HistoryStep step, com.lowagie.text.Document document) { if (step != null) { generatePDFStepHeader(step, document); generatePDFStepContent(step, document); } } private void generatePDFStepHeader(HistoryStep step, com.lowagie.text.Document document) { try { String activity = ""; if (step.getResolvedState() != null) { State resolvedState = step.getProcessInstance().getProcessModel().getState(step.getResolvedState()); activity = resolvedState.getLabel(getRole(), getLanguage()); } String sAction; try { if ("#question#".equals(step.getAction())) { sAction = getString("processManager.question"); } else if ("#response#".equals(step.getAction())) { sAction = getString("processManager.response"); } else if ("#reAssign#".equals(step.getAction())) { sAction = getString("processManager.reAffectation"); } else { Action action = step.getProcessInstance().getProcessModel().getAction(step.getAction()); sAction = action.getLabel(getRole(), getLanguage()); } } catch (WorkflowException we) { sAction = "##"; } String actor = step.getUser().getFullName(); String date = DateUtil.getOutputDateAndHour(step.getActionDate(), getLanguage()); String header = ""; if (StringUtil.isDefined(activity)) { header += activity + " - "; } header += sAction + " (" + actor + " - " + date + ")"; Font fontHeader = new Font(Font.HELVETICA, 12, Font.NORMAL); PdfPCell pCell = new PdfPCell(new Phrase(header, fontHeader)); pCell.setFixedHeight(28); pCell.setBackgroundColor(new Color(239, 239, 239)); pCell.setVerticalAlignment(Element.ALIGN_MIDDLE); PdfPTable pTable = new PdfPTable(1); pTable.setWidthPercentage(100); pTable.addCell(pCell); document.add(pTable); } catch (Exception e) { SilverLogger.getLogger(this).error(e.getMessage(), e); } } private void generatePDFStepContent(HistoryStep step, com.lowagie.text.Document document) { try { Form form; if ("#question#".equals(step.getAction()) || "#response#".equals(step.getAction())) { // TODO form = null; } else { form = getProcessInstance().getProcessModel().getPresentationForm(step.getAction(), getRole(), getLanguage()); } XmlForm xmlForm = (XmlForm) form; if (xmlForm != null && step.getActionRecord() != null) { DataRecord data = step.getActionRecord(); // Force simpletext displayers because itext cannot display HTML Form fields (select, // radio...) float[] colsWidth = { 25, 75 }; PdfPTable tableContent = new PdfPTable(colsWidth); tableContent.setWidthPercentage(100); String fieldValue = ""; Font fontLabel = new Font(Font.HELVETICA, 10, Font.BOLD); Font fontValue = new Font(Font.HELVETICA, 10, Font.NORMAL); List<FieldTemplate> fieldTemplates = xmlForm.getFieldTemplates(); for (FieldTemplate fieldTemplate1 : fieldTemplates) { try { GenericFieldTemplate fieldTemplate = (GenericFieldTemplate) fieldTemplate1; String fieldLabel = fieldTemplate.getLabel("fr"); Field field = data.getField(fieldTemplate.getFieldName()); String componentId = step.getProcessInstance().getProcessModel().getModelId(); // wysiwyg field if ("wysiwyg".equals(fieldTemplate.getDisplayerName())) { String file = WysiwygFCKFieldDisplayer.getFile(componentId, getProcessInstance().getInstanceId(), fieldTemplate.getFieldName(), getLanguage()); // Extract the text content of the html code Source source = new Source(new FileInputStream(file)); fieldValue = source.getTextExtractor().toString(); } // Field file type else if (FileField.TYPE.equals(fieldTemplate.getDisplayerName()) && StringUtil.isDefined(field.getValue())) { SimpleDocument doc = AttachmentServiceProvider.getAttachmentService() .searchDocumentById(new SimpleDocumentPK(field.getValue(), componentId), null); if (doc != null) { fieldValue = doc.getFilename(); } } // Field date type else if ("date".equals(fieldTemplate.getTypeName())) { fieldValue = DateUtil.getOutputDate(field.getValue(), "fr"); } // Others fields type else { fieldTemplate.setDisplayerName("simpletext"); fieldValue = field.getValue(getLanguage()); } PdfPCell cell = new PdfPCell(new Phrase(fieldLabel, fontLabel)); cell.setBorderWidth(0); cell.setPaddingBottom(5); tableContent.addCell(cell); cell = new PdfPCell(new Phrase(fieldValue, fontValue)); cell.setBorderWidth(0); cell.setPaddingBottom(5); tableContent.addCell(cell); } catch (Exception e) { SilverLogger.getLogger(this).error(e.getMessage(), e); } } document.add(tableContent); } } catch (Exception e) { SilverLogger.getLogger(this).error(e.getMessage(), e); } } private OrganizationController getOrganizationController() { return OrganizationControllerProvider.getOrganisationController(); } private String getString(String key) { return key; } private String getTargetId() { return targetId; } private String getTopicId() { return topicId; } private String getLanguage() { return "fr"; } public String getRole() { return role; } public void setRole(String role) { this.role = role; } private KmeliaService getKmeliaBm() { try { return ServiceProvider.getService(KmeliaService.class); } catch (Exception e) { throw new KmeliaRuntimeException("SendInKmelia.getKmeliaService()", SilverpeasRuntimeException.ERROR, "root.EX_CANT_GET_REMOTE_OBJECT", e); } } /** * Get actor if exist, admin otherwise * @return UserDetail */ private UserDetail getBestUserDetail() { String currentUserId = ADMIN_ID; // For a manual action (event) if (getEvent().getUser() != null) { currentUserId = getEvent().getUser().getUserId(); } return getOrganizationController().getUserDetail(currentUserId); } private void addPdfHistory(PublicationPK pubPK, String userId) { String fileName = "processHistory_" + getProcessInstance().getInstanceId() + ".pdf"; if (StringUtil.isDefined(pdfHistoryName)) { fileName = pdfHistoryName; if (!fileName.endsWith(".pdf")) { fileName += ".pdf"; } } byte[] pdf = generatePDF(getProcessInstance()); getKmeliaBm().addAttachmentToPublication(pubPK, userId, fileName, "", pdf); } private String getNodeId(String explicitPath) { String[] path = explicitPath.substring(1).split("/"); NodePK nodePK = new NodePK("unknown", targetId); String parentId = NodePK.ROOT_NODE_ID; for (String name : path) { NodeDetail existingNode = null; try { existingNode = getNodeBm().getDetailByNameAndFatherId(nodePK, name, Integer.parseInt(parentId)); } catch (Exception e) { SilverLogger.getLogger(this).warn("Node named {0} in path {1} doesn't exist", name, explicitPath); } if (existingNode != null) { // topic exists parentId = existingNode.getNodePK().getId(); } else { // topic does not exists, creating it NodeDetail newNode = new NodeDetail(); newNode.setName(name); newNode.setNodePK(new NodePK("unknown", targetId)); newNode.setFatherPK(new NodePK(parentId, targetId)); newNode.setCreatorId(userId); NodePK newNodePK; try { newNodePK = getNodeBm().createNode(newNode); } catch (Exception e) { SilverLogger.getLogger(this).error("Cannot create node {0} in path {1}", new String[] { name, explicitPath }, e); return "-1"; } parentId = newNodePK.getId(); } } return parentId; } protected NodeService getNodeBm() { return ServiceProvider.getService(NodeService.class); } }