/*******************************************************************************
* Australian National University Data Commons
* Copyright (C) 2013 The Australian National University
*
* This file is part of Australian National University Data Commons.
*
* Australian National University Data Commons 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 3 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, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package au.edu.anu.datacommons.data.db.dao;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import au.edu.anu.datacommons.collectionrequest.Question;
import au.edu.anu.datacommons.collectionrequest.QuestionMap;
import au.edu.anu.datacommons.data.db.PersistenceManager;
import au.edu.anu.datacommons.data.db.model.AclObjectIdentity;
import au.edu.anu.datacommons.data.db.model.FedoraObject;
/**
* QuestionDAOImpl
*
* Australian National University Data Commons
*
* An implementation for QuestionDAO
*
* JUnit Coverage:
* None
*
* <pre>
* Version Date Developer Description
* 0.1 29/06/2012 Genevieve Turner (GT) Initial
* 0.2 04/04/2013 Genevieve Turner (GT) Updated to allow for questions also potentially having a group or domain
* </pre>
*
*/
public class QuestionDAOImpl extends GenericDAOImpl<Question, Long> implements
QuestionDAO {
static final Logger LOGGER = LoggerFactory.getLogger(QuestionDAOImpl.class);
private static final String fedoraObjectStr = "SELECT q, qm FROM Question q, QuestionMap qm WHERE qm.pid=:pid AND q=qm.question";
private static final String groupQueryStr = "SELECT q, qm FROM Question q, QuestionMap qm WHERE qm.group.id = :groupId AND q=qm.question";
private static final String domainQueryStr = "SELECT q, qm FROM Question q, QuestionMap qm WHERE qm.domain.id = :domainId AND q=qm.question";
private static final String aclQueryStr = "FROM AclObjectIdentity WHERE object_id_class = :idClass and object_id_identity = :id";
/**
* Constructor
*
* Constructor class that includes the type
*
* <pre>
* Version Date Developer Description
* 0.1 29/06/2012 Genevieve Turner(GT) Initial
* </pre>
*/
public QuestionDAOImpl() {
super(Question.class);
}
/**
* getQuestionsByPid
*
* Retrieves a list of questions associated with the pid
*
* <pre>
* Version Date Developer Description
* 0.1 29/06/2012 Genevieve Turner(GT) Initial
* 0.2 04/04/2013 Genevieve Turner (GT) Updated to find questions up the hierarchy if there are no questions so far
* </pre>
*
* @param pid The pid of the fedora object to retireve questions for
* @return A list of questions associated with the pid
* @see au.edu.anu.datacommons.data.db.dao.QuestionDAO#getQuestionsByPid(java.lang.String)
*/
@Override
public List<Question> getQuestionsByPid(String pid, Boolean required) {
EntityManager entityManager = PersistenceManager.getEntityManagerFactory().createEntityManager();
List<Question> questions = null;
try {
Query query = entityManager.createQuery(fedoraObjectStr);
query.setParameter("pid", pid);
List<Object[]> results = query.getResultList();
LOGGER.info("Number of results: {}", results.size());
//if (questions == null || questions.size() == 0) {
if (results == null || results.size() == 0) {
FedoraObjectDAO fedoraObjectDAO = new FedoraObjectDAOImpl();
FedoraObject fedoraObject = fedoraObjectDAO.getSingleByName(pid);
questions = getParentQuestions(entityManager, new Long(3), fedoraObject.getId(), required);
}
else {
questions = filterQuestionRequirement(results, required);
}
}
finally {
entityManager.close();
}
return questions;
}
/**
* getQuestionsByGroup
*
* Retrieves a list of questions associated with the group id
*
* <pre>
* Version Date Developer Description
* 0.2 04/04/2013 Genevieve Turner(GT) Initial
* </pre>
*
* @param groupId The group id
* @return The list of associated questions
* @see au.edu.anu.datacommons.data.db.dao.QuestionDAO#getQuestionsByGroup(java.lang.Long)
*/
public List<Question> getQuestionsByGroup(Long groupId, Boolean required) {
EntityManager entityManager = PersistenceManager.getEntityManagerFactory().createEntityManager();
List<Question> questions = null;
try {
Query groupQuery = entityManager.createQuery(groupQueryStr);
groupQuery.setParameter("groupId", groupId);
List<Object[]> results = groupQuery.getResultList();
if (results == null || results.size() == 0) {
questions = getParentQuestions(entityManager, new Long(2), groupId, required);
}
else {
questions = filterQuestionRequirement(results, required);
}
}
finally {
entityManager.close();
}
return questions;
}
/**
* getQuestionsByDomain
*
* Retrieves a list of questions associated with the domain
*
* <pre>
* Version Date Developer Description
* 0.2 04/04/2013 Genevieve Turner(GT) Initial
* </pre>
*
* @param domainId The domain id
* @return The list of associated questions
*/
public List<Question> getQuestionsByDomain(Long domainId, Boolean required) {
EntityManager entityManager = PersistenceManager.getEntityManagerFactory().createEntityManager();
List<Question> questions = null;
try {
Query domainQuery = entityManager.createQuery(domainQueryStr);
domainQuery.setParameter("domainId", domainId);
List<Object[]> results = domainQuery.getResultList();
if (results == null || results.size() == 0) {
questions = getParentQuestions(entityManager, new Long(1), domainId, required);
}
else {
questions = filterQuestionRequirement(results, required);
}
}
finally {
entityManager.close();
}
return questions;
}
/**
* getParentQuestions
*
* Traverses up the acl object tree to find questions
*
* <pre>
* Version Date Developer Description
* 0.2 04/04/2013 Genevieve Turner(GT) Initial
* </pre>
*
* @param entityManager The entity manager to retrieve questions for
* @param objectClassId The id of the object_id_class for the acl_object_identity
* @param id The id of the object to retrieve
* @return A list of questions
*/
private List<Question> getParentQuestions(EntityManager entityManager, Long objectClassId, Long id, Boolean required) {
Query groupQuery = entityManager.createQuery(groupQueryStr);
Query domainQuery = entityManager.createQuery(domainQueryStr);
List<Question> questions = null;
LOGGER.debug("Retrieving parent questions for Class Id: {}, Identity: {}", objectClassId, id);
//Find the acl object for the item
Query aclQuery = entityManager.createQuery(aclQueryStr, AclObjectIdentity.class);
aclQuery.setParameter("idClass", objectClassId);
aclQuery.setParameter("id", id);
AclObjectIdentity aclObject = (AclObjectIdentity) aclQuery.getSingleResult();
//Keep looping through until either questions are found or there is no parent object
while ((questions == null || questions.size() == 0) &&aclObject.getParent_object() != null) {
aclObject = entityManager.find(AclObjectIdentity.class, aclObject.getParent_object());
if (aclObject.getObject_id_class().longValue() == 2) {
groupQuery.setParameter("groupId", aclObject.getObject_id_identity());
List<Object[]> results = groupQuery.getResultList();
questions = filterQuestionRequirement(results, required);
}
else if (aclObject.getObject_id_class().longValue() == 1) {
domainQuery.setParameter("domainId", aclObject.getObject_id_identity());
List<Object[]> results = domainQuery.getResultList();
questions = filterQuestionRequirement(results, required);
}
}
return questions;
}
/**
* getQuestionsForObject
*
* Retrieves a list of questions with the given pid, group or domain
*
* <pre>
* Version Date Developer Description
* 0.2 04/04/2013 Genevieve Turner(GT) Initial
* </pre>
*
* @param pid The pid
* @param groupId The group id
* @param domainId The domain id
* @return A list of associated questions
*/
public List<Question> getQuestionsForObject(String pid, Long groupId, Long domainId, Boolean required) {
EntityManager entityManager = PersistenceManager.getEntityManagerFactory().createEntityManager();
List<Question> questions = null;
try {
if (pid != null && pid.trim().length() > 0) {
Query query = entityManager.createQuery(fedoraObjectStr);
query.setParameter("pid", pid);
List<Object[]> results = query.getResultList();
questions = filterQuestionRequirement(results, required);
}
else if (groupId != null) {
Query query = entityManager.createQuery(groupQueryStr);
query.setParameter("groupId", groupId);
List<Object[]> results = query.getResultList();
questions = filterQuestionRequirement(results, required);
}
else if (domainId != null) {
Query query = entityManager.createQuery(domainQueryStr);
query.setParameter("domainId", domainId);
List<Object[]> results = query.getResultList();
questions = filterQuestionRequirement(results, required);
}
}
finally {
entityManager.close();
}
return questions;
}
/**
* filterQuestionRequirement
*
* Filters the list of questions by whether they are required or not
*
* <pre>
* Version Date Developer Description
* 0.2 08/04/2013 Genevieve Turner(GT) Initial
* </pre>
*
* @param results The list of results to filter
* @param required Indicates whether to return required or optional questions
* @return The list of filtered questions
*/
public List<Question> filterQuestionRequirement(List<Object[]> results, Boolean required) {
List<Question> questions = new ArrayList<Question>();
QuestionMap questionMap = null;
Question question = null;
for (Object[] result : results) {
questionMap = (QuestionMap) result[1];
if (questionMap.getRequired().equals(required)) {
question = (Question) result[0];
questions.add(question);
}
}
return questions;
}
}