Java tutorial
/** * OpenKM, Open Document Management System (http://www.openkm.com) * Copyright (c) 2006-2015 Paco Avila & Josep Llort * * No bytes were intentionally harmed during the development of this application. * * This program 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 2 of the License, or * (at your option) any later version. * * 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 General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ package com.openkm.module.db.base; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Calendar; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; import org.apache.commons.io.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.openkm.automation.AutomationException; import com.openkm.bean.ContentInfo; import com.openkm.bean.ExtendedAttributes; import com.openkm.bean.Folder; import com.openkm.bean.Note; import com.openkm.bean.Permission; import com.openkm.bean.workflow.ProcessDefinition; import com.openkm.bean.workflow.ProcessInstance; import com.openkm.core.AccessDeniedException; import com.openkm.core.Config; import com.openkm.core.DatabaseException; import com.openkm.core.ItemExistsException; import com.openkm.core.PathNotFoundException; import com.openkm.core.RepositoryException; import com.openkm.core.UserQuotaExceededException; import com.openkm.core.WorkflowException; import com.openkm.dao.NodeBaseDAO; import com.openkm.dao.NodeDocumentDAO; import com.openkm.dao.NodeDocumentVersionDAO; import com.openkm.dao.NodeFolderDAO; import com.openkm.dao.NodeMailDAO; import com.openkm.dao.NodeNoteDAO; import com.openkm.dao.bean.NodeDocument; import com.openkm.dao.bean.NodeDocumentVersion; import com.openkm.dao.bean.NodeFolder; import com.openkm.dao.bean.NodeMail; import com.openkm.dao.bean.NodeNote; import com.openkm.dao.bean.NodeProperty; import com.openkm.frontend.client.widget.ErrorPopup; import com.openkm.module.common.CommonWorkflowModule; import com.openkm.module.db.stuff.DbAccessManager; import com.openkm.module.db.stuff.SecurityHelper; import com.openkm.util.CloneUtils; public class BaseFolderModule { private static Logger log = LoggerFactory.getLogger(BaseFolderModule.class); /** * Create a new folder */ public static NodeFolder create(String user, NodeFolder parentFolder, String name, Calendar created, Set<String> keywords, Set<String> categories, Set<NodeProperty> propertyGroups, List<NodeNote> notes) throws PathNotFoundException, AccessDeniedException, ItemExistsException, DatabaseException { // Create and add a new folder node NodeFolder folderNode = new NodeFolder(); folderNode.setUuid(UUID.randomUUID().toString()); folderNode.setContext(parentFolder.getContext()); folderNode.setParent(parentFolder.getUuid()); folderNode.setAuthor(user); // Modified by Herve AHOUANTCHEDE 15/02/2017 // Check if the folder name entered contains the characters () then // Split the folder name in order to retrieve the keywork if (name.contains("(") && name.contains(")")) { String key = name.substring(name.indexOf("(") + 1, name.indexOf(")")).trim(); name = name.substring(0, name.indexOf("(")); folderNode.setCcmCode(key); folderNode.setName(name); folderNode.setCreated(created != null ? created : Calendar.getInstance()); if (Config.STORE_NODE_PATH) { folderNode.setPath(parentFolder.getPath() + "/" + name); } // Extended Copy Attributes folderNode.setKeywords(CloneUtils.clone(keywords)); folderNode.setCategories(CloneUtils.clone(categories)); for (NodeProperty nProp : CloneUtils.clone(propertyGroups)) { nProp.setNode(folderNode); folderNode.getProperties().add(nProp); } /* Modifi par Mariam SIDIBE * 22/02/2017 * Generation d'erreur si on ne met pas de parenthses a la creation d'un dossier */ } else { ErrorPopup error = null; error.show("Obligation de mettre le code du dossier entre parenthses!"); } // Get parent node auth info Map<String, Integer> userPerms = parentFolder.getUserPermissions(); Map<String, Integer> rolePerms = parentFolder.getRolePermissions(); // Always assign all grants to creator if (Config.USER_ASSIGN_DOCUMENT_CREATION) { int allGrants = Permission.ALL_GRANTS; userPerms.put(user, allGrants); } // Set auth info // NOTICE: Pay attention to the need of cloning folderNode.setUserPermissions(CloneUtils.clone(userPerms)); folderNode.setRolePermissions(CloneUtils.clone(rolePerms)); NodeFolderDAO.getInstance().create(folderNode); // Extended Copy Attributes for (NodeNote nNote : CloneUtils.clone(notes)) { BaseNoteModule.create(folderNode.getUuid(), nNote.getAuthor(), nNote.getText()); } return folderNode; } /* * Add this 23/02/2017 * By Herve AHOUANTCHEDE */ public static NodeFolder createByMigration(String user, NodeFolder parentFolder, String name, Calendar created, Set<String> keywords, Set<String> categories, Set<NodeProperty> propertyGroups, List<NodeNote> notes) throws PathNotFoundException, AccessDeniedException, ItemExistsException, DatabaseException { // Create and add a new folder node NodeFolder folderNode = new NodeFolder(); folderNode.setUuid(UUID.randomUUID().toString()); folderNode.setContext(parentFolder.getContext()); folderNode.setParent(parentFolder.getUuid()); folderNode.setAuthor(user); folderNode.setName(name); folderNode.setCreated(created != null ? created : Calendar.getInstance()); if (Config.STORE_NODE_PATH) { folderNode.setPath(parentFolder.getPath() + "/" + name); } // Extended Copy Attributes folderNode.setKeywords(CloneUtils.clone(keywords)); folderNode.setCategories(CloneUtils.clone(categories)); for (NodeProperty nProp : CloneUtils.clone(propertyGroups)) { nProp.setNode(folderNode); folderNode.getProperties().add(nProp); } // Get parent node auth info Map<String, Integer> userPerms = parentFolder.getUserPermissions(); Map<String, Integer> rolePerms = parentFolder.getRolePermissions(); // Always assign all grants to creator if (Config.USER_ASSIGN_DOCUMENT_CREATION) { int allGrants = Permission.ALL_GRANTS; userPerms.put(user, allGrants); } // Set auth info // NOTICE: Pay attention to the need of cloning folderNode.setUserPermissions(CloneUtils.clone(userPerms)); folderNode.setRolePermissions(CloneUtils.clone(rolePerms)); NodeFolderDAO.getInstance().createByMigration(folderNode); // Extended Copy Attributes for (NodeNote nNote : CloneUtils.clone(notes)) { BaseNoteModule.create(folderNode.getUuid(), nNote.getAuthor(), nNote.getText()); } return folderNode; } /** * Get folder properties */ public static Folder getProperties(String user, NodeFolder nFolder) throws PathNotFoundException, DatabaseException { log.debug("getProperties({}, {})", user, nFolder); long begin = System.currentTimeMillis(); Folder fld = new Folder(); // Properties String fldPath = NodeBaseDAO.getInstance().getPathFromUuid(nFolder.getUuid()); fld.setPath(fldPath); fld.setCreated(nFolder.getCreated()); fld.setAuthor(nFolder.getAuthor()); fld.setUuid(nFolder.getUuid()); fld.setHasChildren(NodeFolderDAO.getInstance().hasChildren(nFolder.getUuid())); // Added 17/02/2017 fld.setCode(nFolder.getCcmCode()); // Get permissions BaseModule.setPermissions(nFolder, fld); // Get user subscription & keywords fld.setSubscriptors(nFolder.getSubscriptors()); fld.setSubscribed(nFolder.getSubscriptors().contains(user)); fld.setKeywords(nFolder.getKeywords()); // Get categories Set<Folder> categories = new HashSet<Folder>(); NodeFolderDAO nFldDao = NodeFolderDAO.getInstance(); Set<NodeFolder> resolvedCategories = nFldDao.resolveCategories(nFolder.getCategories()); for (NodeFolder nfldCat : resolvedCategories) { categories.add(BaseFolderModule.getProperties(user, nfldCat)); } fld.setCategories(categories); if (!Config.ROOT_NODE_UUID.equals(nFolder.getUuid())) { // Get notes List<Note> notes = new ArrayList<Note>(); List<NodeNote> nNoteList = NodeNoteDAO.getInstance().findByParent(nFolder.getUuid()); for (NodeNote nNote : nNoteList) { notes.add(BaseNoteModule.getProperties(nNote, nNote.getUuid())); } fld.setNotes(notes); } log.trace("getProperties.Time: {}", System.currentTimeMillis() - begin); log.debug("getProperties: {}", fld); return fld; } /** * Duplicates a folder into another one */ public static NodeFolder copy(String user, NodeFolder srcFldNode, NodeFolder dstFldNode, ExtendedAttributes extAttr) throws ItemExistsException, UserQuotaExceededException, PathNotFoundException, AccessDeniedException, AutomationException, DatabaseException, IOException { log.debug("copy({}, {}, {}, {})", new Object[] { user, srcFldNode, dstFldNode, extAttr }); InputStream is = null; NodeFolder newFolder = null; try { String name = srcFldNode.getName(); Set<String> keywords = new HashSet<String>(); Set<String> categories = new HashSet<String>(); Set<NodeProperty> propertyGroups = new HashSet<NodeProperty>(); List<NodeNote> notes = new ArrayList<NodeNote>(); if (extAttr != null) { if (extAttr.isKeywords()) { keywords = srcFldNode.getKeywords(); } if (extAttr.isCategories()) { categories = srcFldNode.getCategories(); } if (extAttr.isPropertyGroups()) { propertyGroups = srcFldNode.getProperties(); } if (extAttr.isNotes()) { notes = NodeNoteDAO.getInstance().findByParent(srcFldNode.getUuid()); } } newFolder = BaseFolderModule.create(user, dstFldNode, name, Calendar.getInstance(), keywords, categories, propertyGroups, notes); String newPath = NodeBaseDAO.getInstance().getPathFromUuid(newFolder.getUuid()); for (NodeFolder nFolder : NodeFolderDAO.getInstance().findByParent(srcFldNode.getUuid())) { copy(user, nFolder, newFolder, extAttr); } for (NodeDocument nDocument : NodeDocumentDAO.getInstance().findByParent(srcFldNode.getUuid())) { BaseDocumentModule.copy(user, nDocument, newPath, newFolder, nDocument.getName(), extAttr); } for (NodeMail nMail : NodeMailDAO.getInstance().findByParent(srcFldNode.getUuid())) { BaseMailModule.copy(user, nMail, newPath, newFolder, extAttr); } } finally { IOUtils.closeQuietly(is); } log.debug("copy: {}", newFolder); return newFolder; } /** * Check recursively if the folder contains locked nodes */ public static boolean hasLockedNodes(String fldUuid) throws PathNotFoundException, DatabaseException, RepositoryException { boolean hasLock = false; for (NodeDocument nDoc : NodeDocumentDAO.getInstance().findByParent(fldUuid)) { hasLock |= nDoc.isLocked(); } for (NodeFolder nFld : NodeFolderDAO.getInstance().findByParent(fldUuid)) { hasLock |= hasLockedNodes(nFld.getUuid()); } return hasLock; } /** * Check if a node has removable childs * * TODO: Is this necessary? The access manager should prevent this and make the core thrown an exception. */ public static boolean hasWriteAccess(String fldUuid) throws PathNotFoundException, DatabaseException, RepositoryException { log.debug("hasWriteAccess({})", fldUuid); DbAccessManager am = SecurityHelper.getAccessManager(); boolean canWrite = true; for (NodeDocument nDoc : NodeDocumentDAO.getInstance().findByParent(fldUuid)) { canWrite &= am.isGranted(nDoc, Permission.WRITE); } for (NodeMail nMail : NodeMailDAO.getInstance().findByParent(fldUuid)) { canWrite &= am.isGranted(nMail, Permission.WRITE); } for (NodeFolder nFld : NodeFolderDAO.getInstance().findByParent(fldUuid)) { canWrite &= am.isGranted(nFld, Permission.WRITE); canWrite &= hasWriteAccess(nFld.getUuid()); } log.debug("hasWriteAccess: {}", canWrite); return canWrite; } /** * Check if a node is being used in a running workflow */ public static boolean hasWorkflowNodes(String fldUuid) throws WorkflowException, PathNotFoundException, DatabaseException { Set<String> workflowNodes = new HashSet<String>(); for (ProcessDefinition procDef : CommonWorkflowModule.findAllProcessDefinitions()) { for (ProcessInstance procIns : CommonWorkflowModule.findProcessInstances(procDef.getId())) { if (procIns.getEnd() == null) { String uuid = (String) procIns.getVariables() .get(Config.WORKFLOW_PROCESS_INSTANCE_VARIABLE_UUID); workflowNodes.add(uuid); } } } return hasWorkflowNodesInDepth(fldUuid, workflowNodes); } /** * Check if a node is being used in a running workflow (Helper) */ private static boolean hasWorkflowNodesInDepth(String fldUuid, Set<String> workflowNodes) throws WorkflowException, PathNotFoundException, DatabaseException { for (NodeDocument nDoc : NodeDocumentDAO.getInstance().findByParent(fldUuid)) { if (workflowNodes.contains(nDoc.getUuid())) { return true; } } for (NodeFolder nFld : NodeFolderDAO.getInstance().findByParent(fldUuid)) { return hasWorkflowNodesInDepth(nFld.getUuid(), workflowNodes); } return false; } /** * Check if a folder is used as category in other nodes. */ public static boolean isCategoryInUse(String fldUuid) throws PathNotFoundException, DatabaseException, RepositoryException { boolean inUse = NodeBaseDAO.getInstance().isCategoryInUse(fldUuid); for (NodeFolder nFld : NodeFolderDAO.getInstance().findByParent(fldUuid)) { inUse |= isCategoryInUse(nFld.getUuid()); } return inUse; } /** * Get content info recursively */ public static ContentInfo getContentInfo(String folderUuid) throws PathNotFoundException, DatabaseException { log.debug("getContentInfo({})", folderUuid); ContentInfo contentInfo = new ContentInfo(); for (NodeFolder nFld : NodeFolderDAO.getInstance().findByParent(folderUuid)) { ContentInfo ci = getContentInfo(nFld.getUuid()); contentInfo.setFolders(contentInfo.getFolders() + ci.getFolders() + 1); contentInfo.setDocuments(contentInfo.getDocuments() + ci.getDocuments()); contentInfo.setSize(contentInfo.getSize() + ci.getSize()); } for (NodeDocument nDoc : NodeDocumentDAO.getInstance().findByParent(folderUuid)) { NodeDocumentVersion nDocVer = NodeDocumentVersionDAO.getInstance().findCurrentVersion(nDoc.getUuid()); long size = nDocVer.getSize(); contentInfo.setDocuments(contentInfo.getDocuments() + 1); contentInfo.setSize(contentInfo.getSize() + size); } for (NodeMail nMail : NodeMailDAO.getInstance().findByParent(folderUuid)) { long size = nMail.getSize(); contentInfo.setDocuments(contentInfo.getDocuments() + 1); contentInfo.setSize(contentInfo.getSize() + size); } log.debug("getContentInfo: {}", contentInfo); return contentInfo; } /** * Get content info by user recursively */ public static Map<String, ContentInfo> getUserContentInfo(String folderUuid) throws PathNotFoundException, DatabaseException { log.debug("getUserContentInfo({})", folderUuid); Map<String, ContentInfo> userContentInfo = new HashMap<String, ContentInfo>(); for (NodeFolder nFld : NodeFolderDAO.getInstance().findByParent(folderUuid)) { Map<String, ContentInfo> usrContInfoRt = getUserContentInfo(nFld.getUuid()); for (String user : usrContInfoRt.keySet()) { ContentInfo ciRt = usrContInfoRt.get(user); ContentInfo ci = getOrCreate(userContentInfo, user); ci.setDocuments(ci.getDocuments() + ciRt.getDocuments()); ci.setSize(ci.getSize() + ciRt.getSize()); userContentInfo.put(user, ci); } ContentInfo ci = getOrCreate(userContentInfo, nFld.getAuthor()); ci.setFolders(ci.getFolders() + ci.getFolders() + 1); userContentInfo.put(nFld.getAuthor(), ci); } for (NodeDocument nDoc : NodeDocumentDAO.getInstance().findByParent(folderUuid)) { for (NodeDocumentVersion nDocVer : NodeDocumentVersionDAO.getInstance().findByParent(nDoc.getUuid())) { ContentInfo ci = getOrCreate(userContentInfo, nDocVer.getAuthor()); ci.setSize(ci.getSize() + nDocVer.getSize()); userContentInfo.put(nDocVer.getAuthor(), ci); } ContentInfo ci = getOrCreate(userContentInfo, nDoc.getAuthor()); ci.setDocuments(ci.getDocuments() + 1); userContentInfo.put(nDoc.getAuthor(), ci); } for (NodeMail nMail : NodeMailDAO.getInstance().findByParent(folderUuid)) { ContentInfo ci = getOrCreate(userContentInfo, nMail.getAuthor()); ci.setDocuments(ci.getDocuments() + 1); ci.setSize(ci.getSize() + nMail.getSize()); userContentInfo.put(nMail.getAuthor(), ci); } log.debug("getUserContentInfo: {}", userContentInfo); return userContentInfo; } /** * Helper method */ private static ContentInfo getOrCreate(Map<String, ContentInfo> userContentInfo, String user) { ContentInfo ci = userContentInfo.get(user); if (ci == null) { ci = new ContentInfo(); } return ci; } }