This is an automated email from the git hooks/post-receive script. New commit to branch develop in repository coselmar. See http://git.codelutin.com/coselmar.git commit fbea68405a181f596388b98595791a540c166d62 Author: Yannick Martel <martel@©odelutin.com> Date: Thu Jan 8 14:50:19 2015 +0100 integrate index search for question --- .../fr/ifremer/coselmar/persistence/DaoUtils.java | 15 ++++ .../persistence/entity/QuestionTopiaDao.java | 83 ++++++++++++++++++-- .../coselmar/services/v1/QuestionsWebService.java | 88 +++++++++++----------- .../coselmar/services/QuestionsWebServiceTest.java | 4 +- 4 files changed, 136 insertions(+), 54 deletions(-) diff --git a/coselmar-persistence/src/main/java/fr/ifremer/coselmar/persistence/DaoUtils.java b/coselmar-persistence/src/main/java/fr/ifremer/coselmar/persistence/DaoUtils.java index 2435ab7..b6fa567 100644 --- a/coselmar-persistence/src/main/java/fr/ifremer/coselmar/persistence/DaoUtils.java +++ b/coselmar-persistence/src/main/java/fr/ifremer/coselmar/persistence/DaoUtils.java @@ -128,11 +128,26 @@ public class DaoUtils { return result; } + protected static String getQueryForAttributeIn(String entityAlias, String entityAttributeName, Map<String, Object> args, Object value, String operator) { + String result = ""; + + String alias = StringUtils.isBlank(entityAlias) ? "" : entityAlias + "."; + String queryAttributeName = addQueryAttribute(args, entityAttributeName, value); + result += String.format(" %s %s in ( :%s )", operator, alias + entityAttributeName, queryAttributeName); + + return result; + } + public static String andAttributeContains(String entityAlias, String entityAttributeName, Map<String, Object> args, Object value) { String result = getQueryForAttributeContains(entityAlias, entityAttributeName, args, value, "AND"); return result; } + public static String andAttributeIn(String entityAlias, String entityAttributeName, Map<String, Object> args, Object value) { + String result = getQueryForAttributeIn(entityAlias, entityAttributeName, args, value, "AND"); + return result; + } + public static String orAttributeContains(String entityAlias, String entityAttributeName, Map<String, Object> args, Object value) { String result = getQueryForAttributeContains(entityAlias, entityAttributeName, args, value, "OR"); return result; diff --git a/coselmar-persistence/src/main/java/fr/ifremer/coselmar/persistence/entity/QuestionTopiaDao.java b/coselmar-persistence/src/main/java/fr/ifremer/coselmar/persistence/entity/QuestionTopiaDao.java index d1d1e71..389bfc9 100644 --- a/coselmar-persistence/src/main/java/fr/ifremer/coselmar/persistence/entity/QuestionTopiaDao.java +++ b/coselmar-persistence/src/main/java/fr/ifremer/coselmar/persistence/entity/QuestionTopiaDao.java @@ -31,6 +31,7 @@ import java.util.Map; import fr.ifremer.coselmar.beans.QuestionSearchBean; import fr.ifremer.coselmar.persistence.DaoUtils; import org.apache.commons.lang3.StringUtils; +import org.nuiton.topia.persistence.TopiaQueryBuilderAddCriteriaOrRunQueryStep; public class QuestionTopiaDao extends AbstractQuestionTopiaDao<Question> { @@ -49,15 +50,73 @@ public class QuestionTopiaDao extends AbstractQuestionTopiaDao<Question> { hqlBuilder.append(" OR (" + privateCondition); - String userCondition = DaoUtils.andAttributeContains("CUG", CoselmarUserGroup.PROPERTY_MEMBERS, args, expert); + String participantCondition = DaoUtils.andAttributeContains("CUG", CoselmarUserGroup.PROPERTY_MEMBERS, args, expert); + hqlBuilder.append(participantCondition); - hqlBuilder.append(userCondition + ") )"); + String clientCondition = DaoUtils.andAttributeContains("Q", Question.PROPERTY_CLIENTS, args, expert); - if (searchBean != null) { - String finerHql = refineSearch(searchBean, "Q", args); - hqlBuilder.append(" AND (" + finerHql + ")" ); - } + hqlBuilder.append(clientCondition + ") )"); + + String finerHql = refineSearch(searchBean, "Q", args); + hqlBuilder.append(" AND (" + finerHql + ")" ); + + + List<Question> questions = forHql(hqlBuilder.toString(), args).findAll(); + + return questions; + } + + public List<Question> findForExpert(CoselmarUser expert) { + + StringBuilder hqlBuilder = new StringBuilder("SELECT Q FROM " + Question.class.getName() + " Q " + + " INNER JOIN Q." + Question.PROPERTY_PARTICIPANTS + " CUG "); + + Map<String, Object> args = new HashMap<>(); + + String publicCondition = DaoUtils.getQueryForAttributeEquals("Q", Question.PROPERTY_PRIVACY, args, Privacy.PUBLIC, ""); + + hqlBuilder.append(" WHERE ( (" + publicCondition + " ) "); + + String privateCondition = DaoUtils.getQueryForAttributeEquals("Q", Question.PROPERTY_PRIVACY, args, Privacy.PRIVATE, ""); + + hqlBuilder.append(" OR (" + privateCondition); + + String participantCondition = DaoUtils.andAttributeContains("CUG", CoselmarUserGroup.PROPERTY_MEMBERS, args, expert); + hqlBuilder.append(participantCondition); + + String clientCondition = DaoUtils.andAttributeContains("Q", Question.PROPERTY_CLIENTS, args, expert); + + hqlBuilder.append(clientCondition + ") )"); + List<Question> questions = forHql(hqlBuilder.toString(), args).findAll(); + + return questions; + } + + public List<Question> findForExpert(CoselmarUser expert, List<String> topiaIds) { + + StringBuilder hqlBuilder = new StringBuilder("SELECT Q FROM " + Question.class.getName() + " Q " + + " INNER JOIN Q." + Question.PROPERTY_PARTICIPANTS + " CUG "); + + Map<String, Object> args = new HashMap<>(); + + String publicCondition = DaoUtils.getQueryForAttributeEquals("Q", Question.PROPERTY_PRIVACY, args, Privacy.PUBLIC, ""); + + hqlBuilder.append(" WHERE ( (" + publicCondition + " ) "); + + String privateCondition = DaoUtils.getQueryForAttributeEquals("Q", Question.PROPERTY_PRIVACY, args, Privacy.PRIVATE, ""); + + hqlBuilder.append(" OR (" + privateCondition); + + String participantCondition = DaoUtils.andAttributeContains("CUG", CoselmarUserGroup.PROPERTY_MEMBERS, args, expert); + hqlBuilder.append(participantCondition); + + String clientCondition = DaoUtils.andAttributeContains("Q", Question.PROPERTY_CLIENTS, args, topiaIds); + + hqlBuilder.append(clientCondition + ") )"); + + String topiaIdsCondition = DaoUtils.andAttributeIn("Q", Question.PROPERTY_TOPIA_ID, args, topiaIds); + hqlBuilder.append(topiaIdsCondition); List<Question> questions = forHql(hqlBuilder.toString(), args).findAll(); @@ -70,7 +129,7 @@ public class QuestionTopiaDao extends AbstractQuestionTopiaDao<Question> { Map<String, Object> args = new HashMap<>(); - String clientCondition = DaoUtils.andAttributeContains("Q", Question.PROPERTY_PRIVACY, args, Privacy.PUBLIC); + String clientCondition = DaoUtils.andAttributeContains("Q", Question.PROPERTY_CLIENTS, args, client); hqlBuilder.append(" WHERE 1=1 AND (" + clientCondition + " ) "); @@ -84,6 +143,16 @@ public class QuestionTopiaDao extends AbstractQuestionTopiaDao<Question> { return questions; } + public List<Question> findForClient(CoselmarUser client, List<String> topiaIds) { + + TopiaQueryBuilderAddCriteriaOrRunQueryStep<Question> queryBuilder = forTopiaIdIn(topiaIds); + queryBuilder.addContains(Question.PROPERTY_CLIENTS, client); + + List<Question> questions = queryBuilder.findAll(); + + return questions; + } + public List<Question> findWithSearchBean(QuestionSearchBean searchBean) { StringBuilder hqlBuilder = new StringBuilder("SELECT Q FROM " + Question.class.getName() + " Q "); diff --git a/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/v1/QuestionsWebService.java b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/v1/QuestionsWebService.java index 05ce72e..5092a89 100644 --- a/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/v1/QuestionsWebService.java +++ b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/v1/QuestionsWebService.java @@ -58,7 +58,6 @@ import org.apache.commons.logging.LogFactory; import org.apache.lucene.queryparser.classic.ParseException; import org.nuiton.topia.persistence.TopiaIdFactory; import org.nuiton.topia.persistence.TopiaNoResultException; -import org.nuiton.topia.persistence.TopiaQueryBuilderAddCriteriaOrRunQueryStep; /** * @author ymartel <martel@codelutin.com> @@ -840,7 +839,7 @@ public class QuestionsWebService extends CoselmarWebServiceSupport { questionList = getQuestionDao().forPrivacyEquals(Privacy.PUBLIC).findAll(); } else if (StringUtils.equalsIgnoreCase(CoselmarUserRole.EXPERT.name(), currentUserRole)) { - questionList = getQuestionDao().findForExpert(currentUser, null); + questionList = getQuestionDao().findForExpert(currentUser); } else if (StringUtils.equalsIgnoreCase(CoselmarUserRole.CLIENT.name(), currentUserRole)) { questionList = getQuestionDao().forClientsContains(currentUser).findAll(); @@ -874,30 +873,30 @@ public class QuestionsWebService extends CoselmarWebServiceSupport { String currentUserRole = currentUser.getRole().name(); QuestionsIndexationService questionsIndexationService = getServicesContext().newService(QuestionsIndexationService.class); + //Try to retrieve corresponding questionIds from the index if searchBean given + List<String> fromIndexQuestionIds = null; + if (searchBean != null) { + try { + List<String> questionIds = questionsIndexationService.searchQuestion(searchBean); + fromIndexQuestionIds = getQuestionsFullId(questionIds); + + } catch (IOException |ParseException e) { + if (log.isErrorEnabled()) { + log.error("Unable to search by lucene, make search directly in database", e); + } + } + + // classical search with DAO + } + List<Question> questionList; + + // Supervisor or Admin : access to all questions, no restriction if (StringUtils.equalsIgnoreCase(CoselmarUserRole.ADMIN.name(), currentUserRole) || StringUtils.equalsIgnoreCase(CoselmarUserRole.SUPERVISOR.name(), currentUserRole)) { - if (searchBean != null && searchBean.getKeywords() != null && !searchBean.getKeywords().isEmpty()) { - try { - //TODO martel 20150106 : maybe its should be better if privacy and status are indexed too ? - List<String> questionIds = questionsIndexationService.searchQuestion(searchBean); - List<String> questionFullIds = getQuestionsFullId(questionIds); - TopiaQueryBuilderAddCriteriaOrRunQueryStep<Question> queryBuilder = getQuestionDao().forTopiaIdIn(questionFullIds); - if (StringUtils.isNotBlank(searchBean.getPrivacy())) { - queryBuilder.addEquals(Question.PROPERTY_PRIVACY, Privacy.valueOf(searchBean.getPrivacy().toUpperCase())); - } - if (StringUtils.isNotBlank(searchBean.getStatus())) { - queryBuilder.addEquals(Question.PROPERTY_STATUS, Privacy.valueOf(searchBean.getStatus().toUpperCase())); - } - questionList = queryBuilder.findAll(); - - } catch (IOException |ParseException e) { - if (log.isErrorEnabled()) { - log.error("Unable to search by lucene, make search directly in database", e); - } - questionList = getQuestionDao().findWithSearchBean(searchBean); - } + if (fromIndexQuestionIds != null && !fromIndexQuestionIds.isEmpty()) { + questionList = getQuestionDao().forTopiaIdIn(fromIndexQuestionIds).findAll(); // classical search with DAO } else { @@ -905,43 +904,42 @@ public class QuestionsWebService extends CoselmarWebServiceSupport { } + // Member : access to public question only } else if (StringUtils.equalsIgnoreCase(CoselmarUserRole.MEMBER.name(), currentUserRole)) { + if (StringUtils.equals(searchBean.getPrivacy(), Privacy.PRIVATE.name())) { + // Asking for private question ? directly no result ! questionList = new ArrayList<>(0); + } else { - if (searchBean != null && searchBean.getKeywords() != null && !searchBean.getKeywords().isEmpty()) { - try { - //TODO martel 20150106 : maybe its should be better if privacy and status are indexed too ? - List<String> questionIds = questionsIndexationService.searchQuestion(searchBean); - List<String> questionFullIds = getQuestionsFullId(questionIds); - TopiaQueryBuilderAddCriteriaOrRunQueryStep<Question> queryBuilder = getQuestionDao().forTopiaIdIn(questionFullIds); - if (StringUtils.isNotBlank(searchBean.getPrivacy())) { - queryBuilder.addEquals(Question.PROPERTY_PRIVACY, Privacy.valueOf(searchBean.getPrivacy().toUpperCase())); - } - if (StringUtils.isNotBlank(searchBean.getStatus())) { - queryBuilder.addEquals(Question.PROPERTY_STATUS, Privacy.valueOf(searchBean.getStatus().toUpperCase())); - } - questionList = queryBuilder.findAll(); - - } catch (IOException |ParseException e) { - if (log.isErrorEnabled()) { - log.error("Unable to search by lucene, make search directly in database", e); - } - questionList = getQuestionDao().findWithSearchBean(searchBean); - } + if (fromIndexQuestionIds != null && !fromIndexQuestionIds.isEmpty()) { + questionList = getQuestionDao().forTopiaIdIn(fromIndexQuestionIds).findAll(); - // classical search with DAO + // classical search with DAO } else { questionList = getQuestionDao().findWithSearchBean(searchBean); } } + // Expert : access to all public question and private question if he is participant or client } else if (StringUtils.equalsIgnoreCase(CoselmarUserRole.EXPERT.name(), currentUserRole)) { - questionList = getQuestionDao().findForExpert(currentUser, searchBean); + if (fromIndexQuestionIds != null && !fromIndexQuestionIds.isEmpty()) { + questionList = getQuestionDao().findForExpert(currentUser, fromIndexQuestionIds); + + } else { + questionList = getQuestionDao().findForExpert(currentUser, searchBean); + } + // Client : access to question he is client } else if (StringUtils.equalsIgnoreCase(CoselmarUserRole.CLIENT.name(), currentUserRole)) { - questionList = getQuestionDao().findForClient(currentUser, searchBean); + if (fromIndexQuestionIds != null && !fromIndexQuestionIds.isEmpty()) { + questionList = getQuestionDao().findForClient(currentUser, fromIndexQuestionIds); + + } else { + questionList = getQuestionDao().findForClient(currentUser, searchBean); + } + } else { String message = "Not allowed to access this page"; if (log.isWarnEnabled()) { diff --git a/coselmar-rest/src/test/java/fr/ifremer/coselmar/services/QuestionsWebServiceTest.java b/coselmar-rest/src/test/java/fr/ifremer/coselmar/services/QuestionsWebServiceTest.java index f315b76..f47edc7 100644 --- a/coselmar-rest/src/test/java/fr/ifremer/coselmar/services/QuestionsWebServiceTest.java +++ b/coselmar-rest/src/test/java/fr/ifremer/coselmar/services/QuestionsWebServiceTest.java @@ -112,7 +112,7 @@ public class QuestionsWebServiceTest extends AbstractCoselmarWebServiceTest { "{title: '" + documentThreeTitle + "'," + " summary: 'This question is private, zero access for others'," + " submissionDate: '" + (new Date()).getTime() + "'," - + " themes: ['Universe', 'test'], type: 'question'," + + " themes: ['Universe', 'test', 'zero'], type: 'question'," + " privacy : 'PRIVATE' }") .Post() .addHeader("Authorization", "Bearer " + supervisorToken); @@ -286,7 +286,7 @@ public class QuestionsWebServiceTest extends AbstractCoselmarWebServiceTest { // Eleventh search : as expert, searchBean with pandorica keyword : retrieve nothing (documentThree is private) searchRequest = createRequest("/v1/questions") - .addParameter("searchBean", "{keywords : ['pandorica']}") + .addParameter("searchBean", "{keywords : ['zero']}") .Get() .addHeader("Authorization", "Bearer " + expertToken); -- To stop receiving notification emails like this one, please contact codelutin.com SCM administrator <admin+scm@codelutin.com>.