/** * Copyright (C) Intersect 2012. * * This module contains Proprietary Information of Intersect, * and should be treated as Confidential. */ package au.org.intersect.exsite9.service; import java.io.File; import java.util.ArrayList; import java.util.List; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.TypedQuery; import org.apache.log4j.Logger; import au.org.intersect.exsite9.dao.FolderDAO; import au.org.intersect.exsite9.dao.GroupDAO; import au.org.intersect.exsite9.dao.MetadataAssociationDAO; import au.org.intersect.exsite9.dao.ProjectDAO; import au.org.intersect.exsite9.dao.ResearchFileDAO; import au.org.intersect.exsite9.dao.factory.FolderDAOFactory; import au.org.intersect.exsite9.dao.factory.GroupDAOFactory; import au.org.intersect.exsite9.dao.factory.MetadataAssociationDAOFactory; import au.org.intersect.exsite9.dao.factory.ProjectDAOFactory; import au.org.intersect.exsite9.dao.factory.ResearchFileDAOFactory; import au.org.intersect.exsite9.domain.Folder; import au.org.intersect.exsite9.domain.Group; import au.org.intersect.exsite9.domain.MetadataAssociation; import au.org.intersect.exsite9.domain.MetadataAttributeValue; import au.org.intersect.exsite9.domain.MetadataCategory; import au.org.intersect.exsite9.domain.MetadataCategoryType; import au.org.intersect.exsite9.domain.MetadataValue; import au.org.intersect.exsite9.domain.Project; import au.org.intersect.exsite9.domain.ResearchFile; import au.org.intersect.exsite9.util.FolderUtils; /** * A service for manipulating {@link ResearchFile}s */ public class ResearchFileService implements IResearchFileService { private static final Logger LOG = Logger.getLogger(ResearchFileService.class); private final EntityManagerFactory entityManagerFactory; private final ResearchFileDAOFactory researchFileDAOFactory; private final ProjectDAOFactory projectDAOFactory; private final MetadataAssociationDAOFactory metadataAssociationDAOFactory; private final FolderDAOFactory folderDAOFactory; private final GroupDAOFactory groupDAOFactory; public ResearchFileService(final EntityManagerFactory entityManagerFactory, final ProjectDAOFactory projectDAOFactory, final ResearchFileDAOFactory researchFileDAOFactory, final MetadataAssociationDAOFactory metadataAssociationDAOFactory, final FolderDAOFactory folderDAOFactory, final GroupDAOFactory groupDAOFactory) { this.entityManagerFactory = entityManagerFactory; this.researchFileDAOFactory = researchFileDAOFactory; this.projectDAOFactory = projectDAOFactory; this.metadataAssociationDAOFactory = metadataAssociationDAOFactory; this.folderDAOFactory = folderDAOFactory; this.groupDAOFactory = groupDAOFactory; } @Override public void identifyNewFilesForProject(Project project) { for(Folder folder : project.getFolders()) { addFilesFromFolder(project, folder); } } @Override public void identifyNewFilesForFolder(Project project, Folder folder) { addFilesFromFolder(project, folder); } private void addFilesFromFolder(Project project, Folder folder) { EntityManager em = entityManagerFactory.createEntityManager(); try { if (!folder.getFolder().exists()) { LOG.info("Cannot identify new files in folder '" + folder.getFolder().getAbsolutePath() + "'. It does not exist."); return; } final List<File> newFileList = FolderUtils.getAllFilesInFolder(folder); final ProjectDAO projectDAO = projectDAOFactory.createInstance(em); final ResearchFileDAO researchFileDAO = researchFileDAOFactory.createInstance(em); final FolderDAO folderDAO = folderDAOFactory.createInstance(em); for (final File file : newFileList) { // If there is already a research file in the database, do not insert another. if(researchFileDAO.findByPath(project, file) == null) { final ResearchFile researchFile = new ResearchFile(file); researchFile.setProject(project); researchFile.setParentGroup(project.getNewFilesNode()); researchFileDAO.createResearchFile(researchFile); folder.getFiles().add(researchFile); folderDAO.updateFolder(folder); project.getNewFilesNode().getResearchFiles().add(researchFile); } } projectDAO.updateProject(project); } finally { em.close(); } } @Override public void associateMetadata(final ResearchFile file, final MetadataCategory metadataCategory, final MetadataValue metadataValue, final MetadataAttributeValue metadataAttributeValue) { LOG.info("Assosciating metadata with file. " + file + " " + metadataCategory + " " + metadataValue); final EntityManager em = this.entityManagerFactory.createEntityManager(); try { final List<MetadataAssociation> existingAssociations = file.getMetadataAssociations(); final MetadataAssociationDAO metadataAssociationDAO = this.metadataAssociationDAOFactory.createInstance(em); boolean addedAssociation = false; if (metadataCategory.getType() == MetadataCategoryType.CONTROLLED_VOCABULARY) { for (final MetadataAssociation existingAssociation : existingAssociations) { if (existingAssociation.getMetadataCategory().equals(metadataCategory)) { if (existingAssociation.getMetadataValues().contains(metadataValue)) { // nothing to do! return; } if (metadataCategory.getType() == MetadataCategoryType.FREETEXT) { existingAssociation.getMetadataValues().clear(); } existingAssociation.getMetadataValues().add(metadataValue); existingAssociation.setMetadataAttributeValue(metadataAttributeValue); metadataAssociationDAO.updateMetadataAssociation(existingAssociation); addedAssociation = true; } } } if (metadataCategory.getType() == MetadataCategoryType.FREETEXT || !addedAssociation) { final MetadataAssociation metadataAssociation = new MetadataAssociation(metadataCategory); metadataAssociation.getMetadataValues().add(metadataValue); metadataAssociation.setMetadataAttributeValue(metadataAttributeValue); metadataAssociationDAO.createMetadataAssociation(metadataAssociation); file.getMetadataAssociations().add(metadataAssociation); } final ResearchFileDAO researchFileDAO = this.researchFileDAOFactory.createInstance(em); researchFileDAO.updateResearchFile(file); } finally { em.close(); } } @Override public void disassociateMetadata(final ResearchFile file, final MetadataCategory metadataCategory, final MetadataValue metadataValue) { LOG.info("Disassosciating metadata from file. " + file + " " + metadataCategory + " " + metadataValue); final List<MetadataAssociation> existingAssociations = file.getMetadataAssociations(); for (final MetadataAssociation existingAssociation : existingAssociations) { if (existingAssociation.getMetadataCategory().equals(metadataCategory)) { if (existingAssociation.getMetadataValues().remove(metadataValue)) { final EntityManager em = this.entityManagerFactory.createEntityManager(); try { final MetadataAssociationDAO metadataAssociationDAO = this.metadataAssociationDAOFactory.createInstance(em); metadataAssociationDAO.updateMetadataAssociation(existingAssociation); if (existingAssociation.getMetadataValues().isEmpty()) { existingAssociations.remove(existingAssociation); final ResearchFileDAO researchFileDAO = this.researchFileDAOFactory.createInstance(em); researchFileDAO.updateResearchFile(file); metadataAssociationDAO.removeMetadataAssociation(existingAssociation); } return; } finally { em.close(); } } } } } @Override public void disassociateMetadataAttributeValue(final MetadataCategory metadataCategory, final MetadataAttributeValue metadataAttributeValue) { final List<ResearchFile> files = getResearchFilesWithAssociatedMetadataAttribute(metadataCategory, metadataAttributeValue); for (final ResearchFile file : files) { final List<MetadataAssociation> associations = file.getMetadataAssociations(); for (final MetadataAssociation association : associations) { final MetadataAttributeValue currentMetadataAttributeValue = association.getMetadataAttributeValue(); if (currentMetadataAttributeValue == null) { continue; } if (association.getMetadataCategory().equals(metadataCategory) && currentMetadataAttributeValue.equals(metadataAttributeValue)) { association.setMetadataAttributeValue(null); final EntityManager em = this.entityManagerFactory.createEntityManager(); try { final MetadataAssociationDAO metadataAssociationDAO = this.metadataAssociationDAOFactory.createInstance(em); metadataAssociationDAO.updateMetadataAssociation(association); } finally { em.close(); } } } } } @Override public List<ResearchFile> getResearchFilesWithAssociatedMetadata(MetadataCategory metadataCategory, MetadataValue metadataValue) { final EntityManager em = entityManagerFactory.createEntityManager(); try { final String queryJQL = "SELECT f FROM ResearchFile f JOIN f.metadataAssociations a WHERE a.metadataCategory = :category AND :value MEMBER OF a.metadataValues"; final TypedQuery<ResearchFile> query = em.createQuery(queryJQL, ResearchFile.class); query.setParameter("category", metadataCategory); query.setParameter("value", metadataValue); return query.getResultList(); } finally { em.close(); } } @Override public List<ResearchFile> getResearchFilesWithAssociatedMetadataAttribute(final MetadataCategory metadataCategory, final MetadataAttributeValue metadataAttributeValue) { final EntityManager em = entityManagerFactory.createEntityManager(); try { final String queryJQL = "SELECT f FROM ResearchFile f JOIN f.metadataAssociations a WHERE a.metadataCategory = :category AND a.metadataAttributeValue = :value"; final TypedQuery<ResearchFile> query = em.createQuery(queryJQL, ResearchFile.class); query.setParameter("category", metadataCategory); query.setParameter("value", metadataAttributeValue); return query.getResultList(); } finally { em.close(); } } @Override public ResearchFile findResearchFileByID(final Long id) { final EntityManager em = entityManagerFactory.createEntityManager(); try { final ResearchFileDAO researchFileDAO = researchFileDAOFactory.createInstance(em); return researchFileDAO.findById(id); } finally { em.close(); } } @Override public void disassociateMultipleMetadataValues(ResearchFile file, MetadataCategory metadataCategory, List<MetadataValue> metadataValues) { for (MetadataValue metadataValue : metadataValues) { disassociateMetadata(file, metadataCategory, metadataValue); } } @Override public void updateResearchFile(ResearchFile selectionObject) { final EntityManager em = entityManagerFactory.createEntityManager(); try { final ResearchFileDAO researchFileDAO = researchFileDAOFactory.createInstance(em); researchFileDAO.updateResearchFile(selectionObject); } finally { em.close(); } } @Override public void consolidateSubFolderIntoParentFolder(final Project project, final Folder parentFolder, final Folder subFolder) { final EntityManager em = entityManagerFactory.createEntityManager(); try { final ProjectDAO projectDAO = projectDAOFactory.createInstance(em); final FolderDAO folderDAO = folderDAOFactory.createInstance(em); parentFolder.getFiles().addAll(subFolder.getFiles()); subFolder.getFiles().clear(); folderDAO.updateFolder(parentFolder); folderDAO.updateFolder(subFolder); project.getFolders().remove(subFolder); projectDAO.updateProject(project); folderDAO.removeFolder(subFolder); } finally { em.close(); } } @Override public void importFolderStructureForProject(Project project, Folder folder) { final EntityManager em = entityManagerFactory.createEntityManager(); try { final ProjectDAO projectDAO = projectDAOFactory.createInstance(em); final FolderDAO folderDAO = folderDAOFactory.createInstance(em); em.getTransaction().begin(); List<ResearchFile> folderResearchFiles = new ArrayList<ResearchFile>(); importFolder(em, project, folderResearchFiles, project.getRootNode(), folder.getFolder()); folder.getFiles().addAll(folderResearchFiles); folderDAO.createFolder(folder); project.getFolders().add(folder); projectDAO.updateProject(project); em.getTransaction().commit(); } catch(Exception e) { em.getTransaction().rollback(); } finally { em.close(); } } private void importFolder(EntityManager em, Project project, List<ResearchFile> folderResearchFiles, Group parentGroup, File folder) { LOG.debug("Import Folder: " + folder.getName()); final ResearchFileDAO researchFileDAO = researchFileDAOFactory.createInstance(em); final GroupDAO groupDAO = groupDAOFactory.createInstance(em); // Create group for folder Group newGroup = null; for(Group group : parentGroup.getGroups()) { if(group.getName().equalsIgnoreCase(folder.getName())) { newGroup = groupDAO.findById(group.getId()); break; } } if(newGroup == null) { newGroup = new Group(folder.getName()); newGroup.setParentGroup(parentGroup); newGroup.setProject(project); newGroup.setResearchFileSortDirection(parentGroup.getResearchFileSortDirection()); newGroup.setResearchFileSortField(parentGroup.getResearchFileSortField()); parentGroup.getGroups().add(newGroup); groupDAO.createGroup(newGroup); groupDAO.updateGroup(parentGroup); } // Create Research files for files List<File> folderList = new ArrayList<File>(0); for(File file : folder.listFiles()) { if(file.isDirectory()) { folderList.add(file); } else { boolean createFile = false; if(researchFileDAO.findByPath(project, file) == null){ createFile = true; } if (createFile) { ResearchFile researchFile = new ResearchFile(file); researchFile.setProject(project); researchFile.setParentGroup(newGroup); researchFileDAO.createResearchFile(researchFile); folderResearchFiles.add(researchFile); newGroup.getResearchFiles().add(researchFile); } } } // Recurse through the folders if(! folderList.isEmpty()) { for(File newFolder : folderList) { importFolder(em, project, folderResearchFiles, newGroup, newFolder); } } groupDAO.updateGroup(newGroup); } @Override public void changeAFilesParentFolder(ResearchFile researchFile, long newFolderId) { EntityManager em = entityManagerFactory.createEntityManager(); try { final ResearchFileDAO researchFileDAO = this.researchFileDAOFactory.createInstance(em); final FolderDAO folderDAO = this.folderDAOFactory.createInstance(em); Folder folder = researchFileDAO.getParentFolder(researchFile); folder.getFiles().remove(researchFile); Folder newFolder = folderDAO.findById(newFolderId); newFolder.getFiles().add(researchFile); folderDAO.updateFolder(folder); folderDAO.updateFolder(newFolder); } finally { em.close(); } } }