/**
* 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.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import org.apache.log4j.Logger;
import au.org.intersect.exsite9.dao.GroupDAO;
import au.org.intersect.exsite9.dao.MetadataAssociationDAO;
import au.org.intersect.exsite9.dao.ResearchFileDAO;
import au.org.intersect.exsite9.dao.factory.GroupDAOFactory;
import au.org.intersect.exsite9.dao.factory.MetadataAssociationDAOFactory;
import au.org.intersect.exsite9.dao.factory.ResearchFileDAOFactory;
import au.org.intersect.exsite9.domain.ExcludedFilesGroup;
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.NewFilesGroup;
import au.org.intersect.exsite9.domain.Project;
import au.org.intersect.exsite9.domain.ResearchFile;
import au.org.intersect.exsite9.domain.ResearchFileSortField;
import au.org.intersect.exsite9.domain.SortFieldDirection;
import au.org.intersect.exsite9.dto.HierarchyMoveDTO;
/**
* Allows the manipulation of {@link Group}s.
*/
public final class GroupService implements IGroupService
{
private static final String NEW_LINE = System.getProperty("line.separator");
private static final Logger LOG = Logger.getLogger(GroupService.class);
private final EntityManagerFactory entityManagerFactory;
private final GroupDAOFactory groupDAOFactory;
private final MetadataAssociationDAOFactory metadataAssociationDAOFactory;
private final ResearchFileDAOFactory researchFileDAOFactory;
public GroupService(final EntityManagerFactory entityManagerFactory,
final GroupDAOFactory groupDAOFactory,
final MetadataAssociationDAOFactory metadataAssociationDAOFactory,
final ResearchFileDAOFactory researchFileDAOFactory)
{
this.entityManagerFactory = entityManagerFactory;
this.groupDAOFactory = groupDAOFactory;
this.metadataAssociationDAOFactory = metadataAssociationDAOFactory;
this.researchFileDAOFactory = researchFileDAOFactory;
}
/**
* @{inheritDoc}
*/
@Override
public Group createNewGroup(final String groupName, final Project project)
{
EntityManager em = entityManagerFactory.createEntityManager();
try
{
final GroupDAO groupDAO = groupDAOFactory.createInstance(em);
final Group group = new Group(groupName);
group.setProject(project);
groupDAO.createGroup(group);
return group;
}
finally
{
em.close();
}
}
/**
* @{inheritDoc}
*/
@Override
public String deleteGroupCheck(final Group groupToDelete)
{
final Group parent = groupToDelete.getParentGroup();
final List<Group> siblingGroups = parent.getGroups();
final List<ResearchFile> parentResearchFiles = parent.getResearchFiles();
final StringBuilder sb = new StringBuilder();
// All children of the group to be deleted will become children of the parent. Ensure the deletion will not cause duplicate group names.
for (final Group group : groupToDelete.getGroups())
{
final String groupName = group.getName();
for (final Group sibling : siblingGroups)
{
if (sibling.getName().equalsIgnoreCase(groupName))
{
sb.append(NEW_LINE + "Duplicate group " + groupName + " under " + parent.getName());
}
}
}
// All research files of the group to be deleted will become children of the parent. Ensure the deletion will not cause duplicate file names.
for (final ResearchFile researchFile : groupToDelete.getResearchFiles())
{
final String researchFileName = researchFile.getFile().getName();
for (final ResearchFile parentResearchFile : parentResearchFiles)
{
if (parentResearchFile.getFile().getName().equalsIgnoreCase(researchFileName))
{
sb.append(NEW_LINE + "Duplicate file named " + researchFileName + " under group " + parent.getName());
}
}
}
if (sb.length() > 0)
{
return "Unable to delete group " + groupToDelete.getName() + "." + sb.toString();
}
return null;
}
/**
* @{inheritDoc}
*/
@Override
public void deleteGroup(final Group groupToDelete)
{
final EntityManager em = entityManagerFactory.createEntityManager();
try
{
final GroupDAO groupDAO = groupDAOFactory.createInstance(em);
final MetadataAssociationDAO metadataDAO = metadataAssociationDAOFactory.createInstance(em);
final ResearchFileDAO researchFileDAO = researchFileDAOFactory.createInstance(em);
final Group parentGroup = groupToDelete.getParentGroup();
parentGroup.getGroups().remove(groupToDelete);
final List<Group> childGroups = groupToDelete.getGroups();
for (final Group childGroup : childGroups)
{
childGroup.setParentGroup(parentGroup);
groupDAO.updateGroup(childGroup);
}
parentGroup.getGroups().addAll(childGroups);
final List<ResearchFile> childResearchFiles = groupToDelete.getResearchFiles();
for (final ResearchFile childResearchFile : childResearchFiles)
{
childResearchFile.setParentGroup(parentGroup);
researchFileDAO.updateResearchFile(childResearchFile);
}
parentGroup.getResearchFiles().addAll(childResearchFiles);
groupToDelete.getGroups().clear();
groupToDelete.setParentGroup(null);
childResearchFiles.clear();
groupDAO.updateGroup(parentGroup);
groupDAO.deleteGroup(groupToDelete);
// Remove metadata associations
for (final MetadataAssociation metadataAssociation : groupToDelete.getMetadataAssociations())
{
metadataDAO.removeMetadataAssociation(metadataAssociation);
}
}
finally
{
em.close();
}
}
/**
* @{inheritDoc}
*/
@Override
public void addChildGroup(final Group parentGroup, final Group childGroup)
{
EntityManager em = entityManagerFactory.createEntityManager();
try
{
GroupDAO groupDAO = groupDAOFactory.createInstance(em);
parentGroup.getGroups().add(childGroup);
childGroup.setParentGroup(parentGroup);
childGroup.setResearchFileSortField(parentGroup.getResearchFileSortField());
childGroup.setResearchFileSortDirection(parentGroup.getResearchFileSortDirection());
groupDAO.updateGroup(childGroup);
groupDAO.updateGroup(parentGroup);
}
finally
{
em.close();
}
}
/**
* {@inheritDoc}
*/
@Override
public String performHierarchyMove(final List<HierarchyMoveDTO> moveList)
{
final EntityManager em = entityManagerFactory.createEntityManager();
final GroupDAO groupDAO = groupDAOFactory.createInstance(em);
final ResearchFileDAO researchFileDAO = researchFileDAOFactory.createInstance(em);
final StringBuilder sb = new StringBuilder();
try
{
for (final HierarchyMoveDTO moveDTO : moveList)
{
final Group oldParent;
if (moveDTO.getOldParent() instanceof Project)
{
oldParent = ((Project)moveDTO.getOldParent()).getRootNode();
}
else
{
oldParent = (Group) moveDTO.getOldParent();
}
final Group newParent;
if(moveDTO.getNewParent() instanceof Project)
{
newParent = ((Project)moveDTO.getNewParent()).getRootNode();
}
else
{
newParent = (Group) moveDTO.getNewParent();
}
final Object childObj = moveDTO.getChild();
boolean movedOK = false;
if (childObj instanceof Group)
{
final Group group = (Group) childObj;
boolean toContinue = false;
// Ensure there are no groups with the same name as the one being dropped into the destination.
for (final Group siblingGroup : newParent.getGroups())
{
if (siblingGroup.getName().equalsIgnoreCase(group.getName()))
{
sb.append("A group named " + group.getName() + " already exists in the destination group.").append(NEW_LINE);
toContinue = true;
break;
}
}
if (toContinue)
{
continue;
}
movedOK = moveGroupToNewGroup((Group) childObj,oldParent,newParent);
groupDAO.updateGroup(group);
}
else if (childObj instanceof ResearchFile)
{
final ResearchFile researchFile = (ResearchFile) childObj;
boolean toContinue = false;
// Ensure there are no research files with the same name as the one being dropped into the destination.
// It is OK to have research files with the same name in the NewFilesGroup or the ExcludedFilesGroup - since they never make it into SIPs.
if (!(newParent instanceof NewFilesGroup || newParent instanceof ExcludedFilesGroup))
{
for (final ResearchFile siblingResearchFile : newParent.getResearchFiles())
{
if (siblingResearchFile.getFile().getName().equalsIgnoreCase(researchFile.getFile().getName()))
{
sb.append("A file named " + researchFile.getFile().getName() + " already exists in the destination group.").append(NEW_LINE);
toContinue = true;
break;
}
}
}
if (toContinue)
{
continue;
}
movedOK = moveFileToNewGroup(researchFile, oldParent, newParent);
researchFileDAO.updateResearchFile(researchFile);
}
else
{
// TODO: Log this?
continue;
}
if (movedOK)
{
em.getTransaction().begin();
groupDAO.updateGroup(oldParent);
groupDAO.updateGroup(newParent);
em.getTransaction().commit();
}
}
}
finally
{
em.close();
}
if (sb.length() == 0)
{
return null;
}
return sb.toString();
}
@Override
public void associateMetadata(final Group group, final MetadataCategory metadataCategory, final MetadataValue metadataValue, final MetadataAttributeValue metadataAttributeValue)
{
LOG.info("Assosciating metadata with group. " + group + " " + metadataCategory + " " + metadataValue);
final EntityManager em = this.entityManagerFactory.createEntityManager();
try
{
final List<MetadataAssociation> existingAssociations = group.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;
}
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);
group.getMetadataAssociations().add(metadataAssociation);
}
final GroupDAO groupDAO = this.groupDAOFactory.createInstance(em);
groupDAO.updateGroup(group);
}
finally
{
em.close();
}
}
@Override
public void disassociateMetadata(final Group group, final MetadataCategory metadataCategory, final MetadataValue metadataValue)
{
LOG.info("Disassosciating metadata from group. " + group + " " + metadataCategory + " " + metadataValue);
final List<MetadataAssociation> existingAssociations = group.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 GroupDAO groupDAO = this.groupDAOFactory.createInstance(em);
groupDAO.updateGroup(group);
metadataAssociationDAO.removeMetadataAssociation(existingAssociation);
}
return;
}
finally
{
em.close();
}
}
}
}
}
@Override
public void disassociateMetadataAttributeValue(final MetadataCategory metadataCategory, final MetadataAttributeValue metadataAttributeValue)
{
final List<Group> groups = getGroupsWithAssociatedMetadataAttribute(metadataCategory, metadataAttributeValue);
for (final Group group : groups)
{
final List<MetadataAssociation> associations = group.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();
}
}
}
}
}
private boolean moveGroupToNewGroup(Group child, Group oldParent, Group newParent)
{
if(oldParent.getGroups().remove(child))
{
if(newParent.getGroups().add(child))
{
child.setParentGroup(newParent);
return true;
}
}
return false;
}
private boolean moveFileToNewGroup(ResearchFile child, Group oldParent, Group newParent)
{
if(oldParent.getResearchFiles().remove(child))
{
if(newParent.getResearchFiles().add(child))
{
child.setParentGroup(newParent);
return true;
}
}
return false;
}
@Override
public void renameGroup(final Group groupToBeRenamed, final String newName)
{
final EntityManager em = entityManagerFactory.createEntityManager();
try
{
final GroupDAO groupDAO = groupDAOFactory.createInstance(em);
groupToBeRenamed.setName(newName);
groupDAO.updateGroup(groupToBeRenamed);
}
finally
{
em.close();
}
}
@Override
public List<Group> getGroupsWithAssociatedMetadata(final MetadataCategory metadataCategory, final MetadataValue metadataValue)
{
final EntityManager em = entityManagerFactory.createEntityManager();
try
{
final GroupDAO groupDAO = groupDAOFactory.createInstance(em);
return groupDAO.getGroupsWithAssociatedMetadata(metadataCategory, metadataValue);
}
finally
{
em.close();
}
}
@Override
public List<Group> getGroupsWithAssociatedMetadataAttribute(final MetadataCategory metadataCategory, final MetadataAttributeValue metadataAttributeValue)
{
final EntityManager em = entityManagerFactory.createEntityManager();
try
{
final GroupDAO groupDAO = groupDAOFactory.createInstance(em);
return groupDAO.getGroupsWithAssociatedMetadataAttribute(metadataCategory, metadataAttributeValue);
}
finally
{
em.close();
}
}
@Override
public Group findGroupByID(final Long groupID)
{
final EntityManager em = entityManagerFactory.createEntityManager();
try
{
final GroupDAO gropDAO = groupDAOFactory.createInstance(em);
return gropDAO.findById(groupID);
}
finally
{
em.close();
}
}
@Override
public void disassociateMultipleMetadataValues(Group group, MetadataCategory metadataCategory, List<MetadataValue> metadataValues)
{
for(MetadataValue metadataValue : metadataValues)
{
disassociateMetadata(group, metadataCategory, metadataValue);
}
}
@Override
public void sortResearchFilesInGroup(final Group group, final ResearchFileSortField sortField, final SortFieldDirection sortDirection)
{
final EntityManager em = entityManagerFactory.createEntityManager();
final GroupDAO groupDAO = new GroupDAO(em);
try
{
configureReserachFileSortParams(groupDAO, group, sortField, sortDirection);
}
finally
{
em.close();
}
}
private static void configureReserachFileSortParams(final GroupDAO groupDAO, final Group group, final ResearchFileSortField sortField, final SortFieldDirection sortDirection)
{
group.setResearchFileSortDirection(sortDirection);
group.setResearchFileSortField(sortField);
for (final Group childGroup : group.getGroups())
{
// Recursion
configureReserachFileSortParams(groupDAO, childGroup, sortField, sortDirection);
}
groupDAO.updateGroup(group);
}
}