From 1d4b73174d241a2eea3f59625aa724bbde98afa9 Mon Sep 17 00:00:00 2001 From: rkv Date: Thu, 7 Mar 2013 08:54:18 +0000 Subject: [PATCH] Search knowledge is implemented. Unit tests are improved. Lucene index is not used now for study and knowledge adding, updating and searching. --- .../service/KnowledgeElementServiceImpl.java | 14 +- .../splat/service/ScenarioServiceImpl.java | 16 +- .../src/org/splat/service/SearchService.java | 17 +- .../org/splat/service/SearchServiceImpl.java | 248 +++++++++++-- .../org/splat/service/StepServiceImpl.java | 102 +++-- .../org/splat/service/StudyServiceImpl.java | 100 +++-- .../service/technical/IndexServiceImpl.java | 110 ++++-- .../src/spring/businessServiceContext.xml | 2 + .../src/test/splat/common/BaseTest.java | 2 +- .../splat/common/TestListingAndOrder.java | 2 +- .../splat/dao/TestKnowledgeElementDAO.java | 2 +- .../test/splat/service/TestSearchService.java | 347 +++++++++++++++++- .../splat/util/TestEntitiesGenerator.java | 97 +++-- .../splat/simer/SearchKnowledgeAction.java | 38 +- 14 files changed, 843 insertions(+), 254 deletions(-) diff --git a/Workspace/Siman-Common/src/org/splat/service/KnowledgeElementServiceImpl.java b/Workspace/Siman-Common/src/org/splat/service/KnowledgeElementServiceImpl.java index 2171ff9..43f1517 100644 --- a/Workspace/Siman-Common/src/org/splat/service/KnowledgeElementServiceImpl.java +++ b/Workspace/Siman-Common/src/org/splat/service/KnowledgeElementServiceImpl.java @@ -91,15 +91,15 @@ public class KnowledgeElementServiceImpl implements KnowledgeElementService { * @return true if updating succeeded */ protected boolean update(final KnowledgeElement knowledgeElement) { - try { +// try { getKnowledgeElementDAO().update(knowledgeElement); - getIndexService().update(knowledgeElement); +// getIndexService().update(knowledgeElement); return true; - } catch (Exception error) { - LOG.error("Unable to re-index the knowledge '" - + knowledgeElement.getIndex() + "', reason:", error); - return false; - } +// } catch (Exception error) { +// LOG.error("Unable to re-index the knowledge '" +// + knowledgeElement.getIndex() + "', reason:", error); +// return false; +// } } /** diff --git a/Workspace/Siman-Common/src/org/splat/service/ScenarioServiceImpl.java b/Workspace/Siman-Common/src/org/splat/service/ScenarioServiceImpl.java index 4562f64..5ecf611 100644 --- a/Workspace/Siman-Common/src/org/splat/service/ScenarioServiceImpl.java +++ b/Workspace/Siman-Common/src/org/splat/service/ScenarioServiceImpl.java @@ -324,7 +324,7 @@ public class ScenarioServiceImpl implements ScenarioService { throws MissedPropertyException, InvalidPropertyException, MultiplyDefinedException { KnowledgeElement kelm = null; - try { +// try { long aScenarioId = aScenarioDTO.getIndex(); if (LOG.isDebugEnabled()) { LOG.debug("Add a knowledge element to the scenario #" @@ -351,17 +351,17 @@ public class ScenarioServiceImpl implements ScenarioService { // all study actors durng reindexing. getStudyService().loadWorkflow(aScenario.getOwnerStudy()); - // Update the lucene index of knowledge elements. - getIndexService().add(kelm); +// // Update the lucene index of knowledge elements. +// getIndexService().add(kelm); if (LOG.isDebugEnabled()) { LOG.debug("A knowledge element #" + kelm.getIndex() + " is added to the scenario #" + aScenario.getIndex()); } - } catch (IOException error) { - LOG.error("Unable to index the knowedge element '" - + kelm.getIndex() + "', reason:", error); - kelm = null; - } +// } catch (IOException error) { +// LOG.error("Unable to index the knowedge element '" +// + kelm.getIndex() + "', reason:", error); +// kelm = null; +// } return kelm; } diff --git a/Workspace/Siman-Common/src/org/splat/service/SearchService.java b/Workspace/Siman-Common/src/org/splat/service/SearchService.java index 28dae50..3bd9edc 100644 --- a/Workspace/Siman-Common/src/org/splat/service/SearchService.java +++ b/Workspace/Siman-Common/src/org/splat/service/SearchService.java @@ -14,6 +14,7 @@ import java.util.List; import org.splat.dal.bo.som.KnowledgeElement; import org.splat.dal.bo.som.Study; import org.splat.service.dto.ImportedStudyDTO; +import org.splat.service.dto.KnowledgeSearchFilterDTO; import org.splat.service.dto.Proxy; import org.splat.service.dto.StudySearchFilterDTO; @@ -39,6 +40,16 @@ public interface SearchService { */ void reindexStudies(String[] ridlist); + /** + * Find knowledge elements with given properties. + * + * @param filter + * search filter parameters + * @return the list of found knowledge elements as proxiy results of lucene search + */ + List selectKnowledgeElementsWhere( + final KnowledgeSearchFilterDTO filter); + /** * Find knowledge elements with given properties. * @@ -52,11 +63,7 @@ public interface SearchService { /** * Find studies with given properties. * - * @param allCriteria - * if true then search for all criteria (AND), otherwise search for any criteria - * @param allContexts - * if true then search for all simulation contexts (AND), otherwise search for any simulation contexts - * @param sprop + * @param filter * search filter parameters * @return the list of found studies as proxy results */ diff --git a/Workspace/Siman-Common/src/org/splat/service/SearchServiceImpl.java b/Workspace/Siman-Common/src/org/splat/service/SearchServiceImpl.java index 7e62fd6..3405356 100644 --- a/Workspace/Siman-Common/src/org/splat/service/SearchServiceImpl.java +++ b/Workspace/Siman-Common/src/org/splat/service/SearchServiceImpl.java @@ -16,6 +16,7 @@ import java.util.Iterator; import java.util.List; import org.apache.log4j.Logger; +import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.Term; import org.apache.lucene.search.BooleanClause; import org.apache.lucene.search.BooleanFilter; @@ -46,9 +47,12 @@ import org.splat.dal.bo.som.Scenario; import org.splat.dal.bo.som.SimulationContext; import org.splat.dal.bo.som.Study; import org.splat.dal.bo.som.Visibility; +import org.splat.dal.dao.som.KnowledgeElementDAO; import org.splat.dal.dao.som.StudyDAO; import org.splat.service.dto.ImportedStudyDTO; +import org.splat.service.dto.KnowledgeSearchFilterDTO; import org.splat.service.dto.Proxy; +import org.splat.service.dto.SearchFilterDTO; import org.splat.service.dto.StudyDTO; import org.splat.service.dto.StudySearchFilterDTO; import org.splat.service.technical.IndexService; @@ -86,6 +90,10 @@ public class SearchServiceImpl implements SearchService { * Injected study DAO. */ private StudyDAO _studyDAO; + /** + * Injected knowledge element DAO. + */ + private KnowledgeElementDAO _knowledgeElementDAO; /** * Get a list of studies which are currently not presented in the lucene index. @@ -133,11 +141,104 @@ public class SearchServiceImpl implements SearchService { } } + /** + * {@inheritDoc} + * + * @see org.splat.service.SearchService#selectKnowledgeElementsWhere(org.splat.service.dto.KnowledgeSearchFilterDTO) + */ + public List selectKnowledgeElementsWhere( + final KnowledgeSearchFilterDTO filter) { + List result = new ArrayList(); + + // Search matching all criteria + DetachedCriteria query = DetachedCriteria.forClass( + KnowledgeElement.class, "kelm"); + query.createAlias("kelm.owner", "scen", Criteria.INNER_JOIN) + .createCriteria("scen.owner", "study", Criteria.INNER_JOIN) + .add(visibleStudyFilter(filter)); + + // Creation of the query + Junction topJunction = initQuery(filter); + + addByWordsCriteria(topJunction, filter); + + List context = filter.getSimContexts(); + if (context != null && (!context.isEmpty())) { + // Get only studies which have given contexts + query.createAlias("study.contex", "ctx", Criteria.INNER_JOIN); + Junction critctx; + if (filter.isMatchAllContexts()) { // AND + critctx = Restrictions.conjunction(); + } else { // OR + critctx = Restrictions.disjunction(); + } + for (SimulationContext seltext : context) { + // (simctxType = seltext.getType() AND simctxValue = seltext.getValue()) + critctx.add(Restrictions.and(Restrictions.eq("ctx.value", + seltext.getValue()), Restrictions.eq("ctx.type", + seltext.getType()))); + + } + topJunction.add(critctx); + } + + query.add(topJunction); + // Group by study + query.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); + // Creation of the sort criteria + query.addOrder(Order.asc("title")); + + if (LOG.isInfoEnabled()) { + LOG.info("Searching knowledge elements: \"" + query.toString()); + } + + // Search + List found = getKnowledgeElementDAO() + .getFilteredList(query); + + // Construction of the result list + for (KnowledgeElement kelm : found) { + result.add(new StudyDTO(kelm.getIndex(), kelm.getReference(), kelm + .getProgressState(), kelm.getTitle(), kelm.getAuthor() + .getDisplayName())); + } + return result; + } + + /** + * Add search criteria for filtering by title contents. + * + * @param topJunction + * the search condition to be appended + * @param filter + * the criteria + */ + private void addByWordsCriteria(final Junction topJunction, + final SearchFilterDTO filter) { + String title = filter.getWords(); // Title + if (title != null && (!title.isEmpty())) { + // Look for given words in titles + Junction critext; + if (filter.isMatchAllCriteria()) { // AND + critext = Restrictions.conjunction(); + } else { // OR + critext = Restrictions.disjunction(); + } + + String[] word = title.split(" "); + for (int j = 0; j < word.length; j++) { + critext.add(Restrictions.like("title", "%" + word[j] + "%")); + } + topJunction.add(critext); + } + } + /** * {@inheritDoc} * * @see org.splat.service.SearchService#selectKnowledgeElementsWhere(org.splat.dal.bo.som.KnowledgeElement.Properties[]) */ + @Deprecated public List selectKnowledgeElementsWhere( final KnowledgeElement.Properties... kprop) { List result = new ArrayList(); @@ -227,7 +328,7 @@ public class SearchServiceImpl implements SearchService { } if (LOG.isInfoEnabled()) { LOG.info("Searching knowledges by Lucene query \"" - + fulquery.toString() + "\"."); + + fulquery.toString()); } // Creation of the knowledge filter BooleanFilter filter = new BooleanFilter(); @@ -263,33 +364,18 @@ public class SearchServiceImpl implements SearchService { /** * {@inheritDoc} * - * @see org.splat.service.SearchService#selectStudiesWhere(org.splat.dal.bo.som.Study.Properties[]) + * @see org.splat.service.SearchService#selectStudiesWhere(org.splat.service.dto.StudySearchFilterDTO) */ public List selectStudiesWhere(final StudySearchFilterDTO filter) { List result = new ArrayList(); DetachedCriteria query = DetachedCriteria - .forClass(Study.class, "study"); + .forClass(Study.class, "study").add(visibleStudyFilter(filter)); // Creation of the query Junction topJunction = initQuery(filter); - String title = filter.getWords(); // Title - if (title != null && (!title.isEmpty())) { - // Look for given words in study titles - Junction critext; - if (filter.isMatchAllCriteria()) { // AND - critext = Restrictions.conjunction(); - } else { // OR - critext = Restrictions.disjunction(); - } - - String[] word = title.split(" "); - for (int j = 0; j < word.length; j++) { - critext.add(Restrictions.like("title", "%" + word[j] + "%")); - } - topJunction.add(critext); - } + addByWordsCriteria(topJunction, filter); List context = filter.getSimContexts(); if (context != null && (!context.isEmpty())) { @@ -318,7 +404,7 @@ public class SearchServiceImpl implements SearchService { query.addOrder(Order.asc("title")); if (LOG.isInfoEnabled()) { - LOG.info("Searching studies: \"" + query.toString() + "\"."); + LOG.info("Searching studies: \"" + query.toString()); } // Search @@ -360,11 +446,71 @@ public class SearchServiceImpl implements SearchService { addDatesCriteria(topJunction, filter); + // Filter by study author long authorId = Long.valueOf(filter.getAuthor()); - if (authorId > 0) { // Author + if (authorId > 0) { topJunction.add(Restrictions.eq("manager.rid", authorId)); } + return topJunction; + } + + /** + * Initialize query with base criteria. + * + * @param filter + * the criteria + * @return top junction of the search filter + */ + private Junction initQuery(final KnowledgeSearchFilterDTO filter) { + Junction topJunction; + if (filter.isMatchAllCriteria()) { // AND + topJunction = Restrictions.conjunction(); + } else { // OR + topJunction = Restrictions.disjunction(); + } + + // Filter by knowledge type + long ktypeId = Long.valueOf(filter.getKtype()); + if (ktypeId > 0) { + topJunction.add(Restrictions.eq("kelm.type.rid", ktypeId)); + } + + String refid = filter.getReference(); // Reference + if (refid != null && !refid.isEmpty()) { + long id = Long.valueOf(refid.replaceAll("^KE(0)*", "")); + if (id > 0) { + topJunction.add(Restrictions.eq("kelm.rid", id)); + } + } + + addCreationDateCriteria(topJunction, filter, "date"); + + // Filter by knowledge author + long authorId = Long.valueOf(filter.getAuthor()); + if (authorId > 0) { + topJunction.add(Restrictions.eq("kelm.author.rid", authorId)); + } + + return topJunction; + } + + /** + * Filter for visible studies. + * + * @param filter + * search criteria + * @return search condition for studies to get only visible studies + */ + private Junction visibleStudyFilter(final SearchFilterDTO filter) { + Junction topJunction; + if (filter.isMatchAllCriteria()) { // AND + topJunction = Restrictions.conjunction(); + } else { // OR + topJunction = Restrictions.disjunction(); + } + + // Filter by connected user long actorId = filter.getConnectedUserId(); // Contributor, Reviewer or Approver if (actorId > 0) { // User is loggen in - show public studies and studies where he is participating @@ -398,7 +544,8 @@ public class SearchServiceImpl implements SearchService { Visibility.PUBLIC))); } else { // User is not logged in - show only public studies - topJunction.add(Restrictions.eq("visibility", Visibility.PUBLIC)); + topJunction.add(Restrictions.eq("study.visibility", + Visibility.PUBLIC)); } return topJunction; } @@ -414,14 +561,7 @@ public class SearchServiceImpl implements SearchService { private void addDatesCriteria(final Junction topJunction, final StudySearchFilterDTO filter) { // Filter by creation date - if (filter.getCreatedAfter() != null) { - topJunction.add(Restrictions - .gt("credate", filter.getCreatedAfter())); - } - if (filter.getCreatedBefore() != null) { - topJunction.add(Restrictions.lt("credate", filter - .getCreatedBefore())); - } + addCreationDateCriteria(topJunction, filter, "credate"); // Filter by modification date if (filter.getUpdatedAfter() != null) { topJunction.add(Restrictions @@ -434,6 +574,27 @@ public class SearchServiceImpl implements SearchService { } + /** + * Add search criteria by dates to the junction filter condition. + * + * @param topJunction + * the junction filter condition + * @param filter + * search criteria + */ + private void addCreationDateCriteria(final Junction topJunction, + final SearchFilterDTO filter, final String propName) { + // Filter by creation date + if (filter.getCreatedAfter() != null) { + topJunction.add(Restrictions + .gt(propName, filter.getCreatedAfter())); + } + if (filter.getCreatedBefore() != null) { + topJunction.add(Restrictions.lt(propName, filter + .getCreatedBefore())); + } + } + /** * {@inheritDoc} * @@ -534,7 +695,7 @@ public class SearchServiceImpl implements SearchService { } if (LOG.isInfoEnabled()) { LOG.info("Searching studies by Lucene query \"" - + fulquery.toString() + "\"."); + + fulquery.toString()); } // Creation of the studies filter BooleanFilter filter = new BooleanFilter(); @@ -618,6 +779,11 @@ public class SearchServiceImpl implements SearchService { */ private IndexService getIndex() throws IOException { IndexService lucin = getIndexService(); + if (IndexWriter.isLocked(FSDirectory.open(getRepositoryService() + .getRepositoryIndexDirectory()))) { + IndexWriter.unlock(FSDirectory.open(getRepositoryService() + .getRepositoryIndexDirectory())); + } if (!lucin.exists()) { lucin.create(); // Happens when re-indexing all studies } @@ -699,4 +865,24 @@ public class SearchServiceImpl implements SearchService { public void setStudyDAO(final StudyDAO studyDAO) { _studyDAO = studyDAO; } + + /** + * Get the knowledgeElementDAO. + * + * @return the knowledgeElementDAO + */ + public KnowledgeElementDAO getKnowledgeElementDAO() { + return _knowledgeElementDAO; + } + + /** + * Set the knowledgeElementDAO. + * + * @param knowledgeElementDAO + * the knowledgeElementDAO to set + */ + public void setKnowledgeElementDAO( + final KnowledgeElementDAO knowledgeElementDAO) { + _knowledgeElementDAO = knowledgeElementDAO; + } } diff --git a/Workspace/Siman-Common/src/org/splat/service/StepServiceImpl.java b/Workspace/Siman-Common/src/org/splat/service/StepServiceImpl.java index 9e94849..7b23bc5 100644 --- a/Workspace/Siman-Common/src/org/splat/service/StepServiceImpl.java +++ b/Workspace/Siman-Common/src/org/splat/service/StepServiceImpl.java @@ -58,7 +58,7 @@ import org.springframework.transaction.annotation.Transactional; /** * Step service implementation. - * + * * @author Roman Kozlov (RKV) */ public class StepServiceImpl implements StepService { @@ -126,11 +126,11 @@ public class StepServiceImpl implements StepService { * Injected user DAO. */ private UserDAO _userDAO; - - + + /** * {@inheritDoc} - * + * * @see org.splat.service.StepService#addSimulationContext(org.splat.som.Step, org.splat.dal.bo.som.SimulationContext.Properties) */ @Override @@ -145,7 +145,7 @@ public class StepServiceImpl implements StepService { /** * {@inheritDoc} - * + * * @see org.splat.service.StepService#addSimulationContext(org.splat.som.Step, org.splat.dal.bo.som.SimulationContext) */ @Override @@ -178,7 +178,7 @@ public class StepServiceImpl implements StepService { /** * Update lucene index of knowledge elements of a scenario or a study which the given step is related to. - * + * * @param aStep * the step (activity) */ @@ -190,31 +190,31 @@ public class StepServiceImpl implements StepService { } else { scenarii = aStep.getOwnerStudy().getScenarii(); } - try { +// try { for (int i = 0; i < scenarii.length; i++) { Scenario scene = scenarii[i]; List knelm = scene.getAllKnowledgeElements(); for (Iterator j = knelm.iterator(); j .hasNext();) { KnowledgeElement kelm = j.next(); - getIndexService().update(kelm); +// getIndexService().update(kelm); } updateScenarioIndex(scene); } - } catch (Exception error) { - LOG.error("Unable to re-index Knowledge Elements, reason:", error); - } +// } catch (Exception error) { +// LOG.error("Unable to re-index Knowledge Elements, reason:", error); +// } } /** * Update lucene index for knowledge elements of the scenario. - * + * * @param scene * the scenario * @throws IOException * if can't update lucene index */ - private void updateScenarioIndex(final Scenario scene) throws IOException { + private void updateScenarioIndex(final Scenario scene) /*throws IOException*/ { if (scene.getUcase() == null) { for (Iterator i = scene.getKnowledgeElements() .iterator(); i.hasNext();) { @@ -226,12 +226,12 @@ public class StepServiceImpl implements StepService { break; } } - getIndexService().update(scene.getUcase()); +// getIndexService().update(scene.getUcase()); } /** * {@inheritDoc} - * + * * @see org.splat.service.StepService#removeSimulationContext(org.splat.som.Step, org.splat.dal.bo.som.SimulationContext) */ @Override @@ -258,7 +258,7 @@ public class StepServiceImpl implements StepService { /** * {@inheritDoc} - * + * * @see org.splat.service.StepService#createDocument(org.splat.som.Step, org.splat.dal.bo.som.Document.Properties) */ @Override @@ -294,7 +294,7 @@ public class StepServiceImpl implements StepService { /** * {@inheritDoc} - * + * * @see org.splat.service.StepService#assignDocument(org.splat.som.Step, org.splat.dal.bo.som.Document.Properties) */ @Override @@ -317,7 +317,7 @@ public class StepServiceImpl implements StepService { /** * Create a new version of a document in the given study step. - * + * * @param aStep * the study step * @param base @@ -342,7 +342,7 @@ public class StepServiceImpl implements StepService { /** * Create a new version of a document in the given study step. - * + * * @param aStep * the study step * @param base @@ -371,7 +371,7 @@ public class StepServiceImpl implements StepService { /** * Create a new version of a document in the given study step. - * + * * @param aStep * the study step * @param base @@ -445,7 +445,7 @@ public class StepServiceImpl implements StepService { /** * Get document types which are applicable for the given study step (activity). - * + * * @param aStep * the study step * @return the list of document types @@ -457,7 +457,7 @@ public class StepServiceImpl implements StepService { /** * Add a document publication to the given step. - * + * * @param aStep * the target study step * @param newdoc @@ -478,7 +478,7 @@ public class StepServiceImpl implements StepService { /** * Remove a document publication from the given step. - * + * * @param aStep * the study step * @param oldoc @@ -558,10 +558,8 @@ public class StepServiceImpl implements StepService { } } return res; - - } - + /** * {@inheritDoc} * @@ -605,7 +603,7 @@ public class StepServiceImpl implements StepService { comment.setId(resultKey); } - /** + /** * {@inheritDoc} * @see org.splat.service.StepService#getStepComments(org.splat.som.Step) */ @@ -630,8 +628,8 @@ public class StepServiceImpl implements StepService { } return commentDTOs; } - - /** + + /** * {@inheritDoc} * @see org.splat.service.StepService#removeStepComment(long) */ @@ -683,7 +681,7 @@ public class StepServiceImpl implements StepService { /** * Get the documentService. - * + * * @return the documentService */ public DocumentService getDocumentService() { @@ -692,7 +690,7 @@ public class StepServiceImpl implements StepService { /** * Set the documentService. - * + * * @param documentService * the documentService to set */ @@ -702,7 +700,7 @@ public class StepServiceImpl implements StepService { /** * Get the simulationContextService. - * + * * @return the simulationContextService */ public SimulationContextService getSimulationContextService() { @@ -711,7 +709,7 @@ public class StepServiceImpl implements StepService { /** * Set the simulationContextService. - * + * * @param simulationContextService * the simulationContextService to set */ @@ -722,7 +720,7 @@ public class StepServiceImpl implements StepService { /** * Get the documentDAO. - * + * * @return the documentDAO */ public DocumentDAO getDocumentDAO() { @@ -731,7 +729,7 @@ public class StepServiceImpl implements StepService { /** * Set the documentDAO. - * + * * @param documentDAO * the documentDAO to set */ @@ -741,7 +739,7 @@ public class StepServiceImpl implements StepService { /** * Get the simulationContextDAO. - * + * * @return the simulationContextDAO */ public SimulationContextDAO getSimulationContextDAO() { @@ -750,7 +748,7 @@ public class StepServiceImpl implements StepService { /** * Set the simulationContextDAO. - * + * * @param simulationContextDAO * the simulationContextDAO to set */ @@ -761,7 +759,7 @@ public class StepServiceImpl implements StepService { /** * Get the projectElementDAO. - * + * * @return the projectElementDAO */ public ProjectElementDAO getProjectElementDAO() { @@ -770,7 +768,7 @@ public class StepServiceImpl implements StepService { /** * Set the projectElementDAO. - * + * * @param projectElementDAO * the projectElementDAO to set */ @@ -780,7 +778,7 @@ public class StepServiceImpl implements StepService { /** * Get the indexService. - * + * * @return the indexService */ public IndexService getIndexService() { @@ -789,7 +787,7 @@ public class StepServiceImpl implements StepService { /** * Set the indexService. - * + * * @param indexService * the indexService to set */ @@ -799,7 +797,7 @@ public class StepServiceImpl implements StepService { /** * Get the fileDAO. - * + * * @return the fileDAO */ public FileDAO getFileDAO() { @@ -808,7 +806,7 @@ public class StepServiceImpl implements StepService { /** * Set the fileDAO. - * + * * @param fileDAO * the fileDAO to set */ @@ -818,7 +816,7 @@ public class StepServiceImpl implements StepService { /** * Get the documentTypeService. - * + * * @return the documentTypeService */ public DocumentTypeService getDocumentTypeService() { @@ -827,7 +825,7 @@ public class StepServiceImpl implements StepService { /** * Set the documentTypeService. - * + * * @param documentTypeService * the documentTypeService to set */ @@ -838,7 +836,7 @@ public class StepServiceImpl implements StepService { /** * Get the versionsRelationDAO. - * + * * @return the versionsRelationDAO */ public VersionsRelationDAO getVersionsRelationDAO() { @@ -847,7 +845,7 @@ public class StepServiceImpl implements StepService { /** * Set the versionsRelationDAO. - * + * * @param versionsRelationDAO * the versionsRelationDAO to set */ @@ -858,16 +856,16 @@ public class StepServiceImpl implements StepService { /** * Get project settings. - * + * * @return Project settings service */ private ProjectSettingsService getProjectSettings() { return _projectSettings; } - + /** * Set project settings service. - * + * * @param projectSettingsService * project settings service */ @@ -875,7 +873,7 @@ public class StepServiceImpl implements StepService { final ProjectSettingsService projectSettingsService) { _projectSettings = projectSettingsService; } - + /** * Get the stepCommentAttributeDAO. * @return the stepCommentAttributeDAO @@ -907,7 +905,7 @@ public class StepServiceImpl implements StepService { public void setUserDAO(final UserDAO userDAO) { _userDAO = userDAO; } - + /** * Get the publicationDAO. * diff --git a/Workspace/Siman-Common/src/org/splat/service/StudyServiceImpl.java b/Workspace/Siman-Common/src/org/splat/service/StudyServiceImpl.java index 211f2d9..4749a98 100644 --- a/Workspace/Siman-Common/src/org/splat/service/StudyServiceImpl.java +++ b/Workspace/Siman-Common/src/org/splat/service/StudyServiceImpl.java @@ -25,6 +25,8 @@ import java.util.Map; import java.util.Scanner; import java.util.Set; +import org.apache.lucene.index.IndexWriter; +import org.apache.lucene.store.FSDirectory; import org.hibernate.criterion.Restrictions; import org.jfree.chart.ChartFactory; import org.jfree.chart.JFreeChart; @@ -39,18 +41,16 @@ import org.splat.dal.bo.som.ContributorRelation; import org.splat.dal.bo.som.DescriptionAttribute; import org.splat.dal.bo.som.DocumentType; import org.splat.dal.bo.som.IDBuilder; -import org.splat.dal.bo.som.KnowledgeElement; import org.splat.dal.bo.som.ProgressState; import org.splat.dal.bo.som.Publication; -import org.splat.dal.bo.som.Scenario; import org.splat.dal.bo.som.SimulationContext; import org.splat.dal.bo.som.Study; -import org.splat.dal.bo.som.Study.Properties; import org.splat.dal.bo.som.ValidationCycle; -import org.splat.dal.bo.som.ValidationCycle.Actor; import org.splat.dal.bo.som.ValidationCycleRelation; import org.splat.dal.bo.som.ValidationStep; import org.splat.dal.bo.som.Visibility; +import org.splat.dal.bo.som.Study.Properties; +import org.splat.dal.bo.som.ValidationCycle.Actor; import org.splat.dal.dao.som.DescriptionAttributeDAO; import org.splat.dal.dao.som.DocumentDAO; import org.splat.dal.dao.som.IDBuilderDAO; @@ -144,7 +144,7 @@ public class StudyServiceImpl implements StudyService { * Injected user service. */ private UserService _userService; - + /** * Injected publication DAO. */ @@ -170,7 +170,6 @@ public class StudyServiceImpl implements StudyService { * * @see org.splat.service.StudyService#selectStudy(long) */ - @Override @Transactional public Study selectStudy(final long index) { Study result = getStudyDAO().get(index); @@ -198,7 +197,6 @@ public class StudyServiceImpl implements StudyService { * * @see org.splat.service.StudyService#createStudy(org.splat.dal.bo.som.Study.Properties) */ - @Override @Transactional public Study createStudy(final Study.Properties sprop) throws MissedPropertyException, InvalidPropertyException, @@ -208,14 +206,14 @@ public class StudyServiceImpl implements StudyService { buildReference(study); getStudyDAO().create(study); - try { - IndexService lucin = getIndex(); - lucin.add(study); - } catch (IOException error) { - LOG.error("Unable to index the study '" + study.getIndex() - + "', reason:", error); - // Continue and try to index later - } +// try { +// IndexService lucin = getIndex(); +// lucin.add(study); +// } catch (IOException error) { +// LOG.error("Unable to index the study '" + study.getIndex() +// + "', reason:", error); +// // Continue and try to index later +// } return study; } @@ -224,7 +222,6 @@ public class StudyServiceImpl implements StudyService { * * @see org.splat.service.StudyService#addProjectContext(org.splat.dal.bo.som.Study, org.splat.dal.bo.som.SimulationContext.Properties) */ - @Override @Transactional public SimulationContext addProjectContext(final Study aStudy, final SimulationContext.Properties cprop) @@ -241,7 +238,6 @@ public class StudyServiceImpl implements StudyService { * * @see org.splat.service.StudyService#addProjectContext(org.splat.dal.bo.som.Study, org.splat.dal.bo.som.SimulationContext) */ - @Override @Transactional public SimulationContext addProjectContext(final Study aStudy, final SimulationContext context) { @@ -256,7 +252,6 @@ public class StudyServiceImpl implements StudyService { * * @see org.splat.service.StudyService#addContributor(org.splat.dal.bo.som.Study, org.splat.dal.bo.kernel.User) */ - @Override public boolean addContributor(final Study aStudy, final User user) { List contributor = getModifiableContributors(aStudy); // Initializes contributor for (Iterator i = contributor.iterator(); i.hasNext();) { @@ -286,7 +281,6 @@ public class StudyServiceImpl implements StudyService { * @see #isPublic() * @see Publication#approve(Date) */ - @Override public boolean moveToReference(final Study aStudy) { if (aStudy.getProgressState() != ProgressState.APPROVED) { return false; @@ -307,7 +301,6 @@ public class StudyServiceImpl implements StudyService { * * @see org.splat.service.StudyService#update(org.splat.dal.bo.som.Study, org.splat.dal.bo.som.Study.Properties) */ - @Override public boolean update(final Study aStudy, final Properties sprop) throws InvalidPropertyException { if (sprop.getTitle() != null) { @@ -347,7 +340,6 @@ public class StudyServiceImpl implements StudyService { * * @see org.splat.service.StudyService#removeContributor(org.splat.dal.bo.som.Study, org.splat.dal.bo.kernel.User[]) */ - @Override public boolean removeContributor(final Study aStudy, final User... users) { List contributor = getModifiableContributors(aStudy); // Initializes contributor Boolean done = false; @@ -376,7 +368,6 @@ public class StudyServiceImpl implements StudyService { * * @see org.splat.service.StudyService#removeProjectContext(org.splat.dal.bo.som.Study, org.splat.dal.bo.som.SimulationContext) */ - @Override public boolean removeProjectContext(final Study aStudy, final SimulationContext context) { boolean done = getStepService().removeSimulationContext( @@ -391,7 +382,6 @@ public class StudyServiceImpl implements StudyService { * @see org.splat.service.StudyService#setValidationCycle(org.splat.dal.bo.som.Study, org.splat.dal.bo.som.DocumentType, * org.splat.dal.bo.som.ValidationCycle.Properties) */ - @Override @Transactional public void setValidationCycle(final Study aStudyDTO, final DocumentType type, final ValidationCycle.Properties vprop) { @@ -436,7 +426,6 @@ public class StudyServiceImpl implements StudyService { * a study to demote * @return true if the demotion succeeded. */ - @Override public boolean demote(final Study aStudy) { if (aStudy.getProgressState() == ProgressState.inCHECK) { aStudy.setProgressState(ProgressState.inDRAFT); @@ -453,7 +442,6 @@ public class StudyServiceImpl implements StudyService { * * @see org.splat.service.StudyService#generateLocalIndex(org.splat.dal.bo.som.Study) */ - @Override @Transactional public int generateLocalIndex(final Study aStudy) { aStudy.setLastLocalIndex(aStudy.getLastLocalIndex() + 1); @@ -468,7 +456,6 @@ public class StudyServiceImpl implements StudyService { * a study to promote * @return true if the demotion succeeded. */ - @Override @Transactional public boolean promote(final Study aStudy) { if (aStudy.getProgressState() == ProgressState.inWORK) { @@ -497,7 +484,6 @@ public class StudyServiceImpl implements StudyService { * @return true if the move succeeded. * @see #isPublic() */ - @Override @Transactional public boolean moveToPublic(final Study aStudy) { boolean isOk = false; @@ -517,7 +503,6 @@ public class StudyServiceImpl implements StudyService { * a study to move * @return true if the move succeeded. */ - @Override @Transactional public boolean moveToPrivate(final Study aStudy) { boolean isOk = false; @@ -543,7 +528,7 @@ public class StudyServiceImpl implements StudyService { try { getStudyDAO().merge(aStudy); // Update of relational base setShortCuts(aStudy); // RKV: initialize transient actors set - getIndex().update(aStudy); // Update of Lucene index + //RKV: getIndex().update(aStudy); // Update of Lucene index isOk = true; } catch (Exception e) { LOG.error("STD-000001", e, aStudy.getIndex(), e.getMessage()); @@ -691,25 +676,26 @@ public class StudyServiceImpl implements StudyService { * @return true if reindexing succeeded */ private boolean updateKnowledgeElementsIndex(final Study aStudy) { - boolean isOk = false; - try { - IndexService lucin = getIndex(); - - for (Iterator i = aStudy.getScenariiList().iterator(); i - .hasNext();) { - Scenario scene = i.next(); - for (Iterator j = scene - .getAllKnowledgeElements().iterator(); j.hasNext();) { - KnowledgeElement kelm = j.next(); - lucin.update(kelm); - } - } - isOk = true; - } catch (Exception error) { - LOG.error("Unable to re-index Knowledge Elements, reason:", - error); - } - return isOk; +// boolean isOk = false; +// try { +// IndexService lucin = getIndex(); +// +// for (Iterator i = aStudy.getScenariiList().iterator(); i +// .hasNext();) { +// Scenario scene = i.next(); +// for (Iterator j = scene +// .getAllKnowledgeElements().iterator(); j.hasNext();) { +// KnowledgeElement kelm = j.next(); +// lucin.update(kelm); +// } +// } +// isOk = true; +// } catch (Exception error) { +// LOG.error("Unable to re-index Knowledge Elements, reason:", +// error); +// } +// return isOk; + return true; } /** @@ -721,6 +707,11 @@ public class StudyServiceImpl implements StudyService { */ private IndexService getIndex() throws IOException { IndexService lucin = getIndexService(); + if (IndexWriter.isLocked(FSDirectory.open(getRepositoryService() + .getRepositoryIndexDirectory()))) { + IndexWriter.unlock(FSDirectory.open(getRepositoryService() + .getRepositoryIndexDirectory())); + } if (!lucin.exists()) { lucin.create(); // Happens when re-indexing all studies } @@ -893,7 +884,6 @@ public class StudyServiceImpl implements StudyService { * the study * @return the unmodifiable not null transient list of contributors of this study */ - @Override public List getContributors(final Study aStudy) { if (aStudy.getContributor() == null) { setShortCuts(aStudy); @@ -924,7 +914,6 @@ public class StudyServiceImpl implements StudyService { * the document type being subject of validation * @return the validation cycle of the document, or null if not defined. */ - @Override public ValidationCycle getValidationCycleOf(final Study aStudy, final DocumentType type) { if (aStudy.getValidationCycles() == null || aStudy.getValidationCycles().isEmpty()) { @@ -953,7 +942,6 @@ public class StudyServiceImpl implements StudyService { * @return true if the given user is actor of this study. * @see #getActors() */ - @Override public boolean hasActor(final Study aStudy, final User user) { if (user == null) { return false; @@ -977,7 +965,6 @@ public class StudyServiceImpl implements StudyService { * @return true if the given user is actor of this study. * @see #getContributors() */ - @Override public boolean isStaffedBy(final Study aStudy, final User user) { if (user == null) { return false; @@ -1005,7 +992,6 @@ public class StudyServiceImpl implements StudyService { * @param aStudy * the study */ - @Override public void loadWorkflow(final Study aStudy) { setShortCuts(aStudy); } @@ -1095,7 +1081,6 @@ public class StudyServiceImpl implements StudyService { getStudyDAO().merge(aStudy); } - /** * {@inheritDoc} * @see org.splat.service.StudyService#getDescription(java.lang.Long) @@ -1131,8 +1116,8 @@ public class StudyServiceImpl implements StudyService { } study.setAttribute(new DescriptionAttribute(study, descriptionText)); } - - /** + + /** * {@inheritDoc} * @see org.splat.service.StudyService#removeStudyDescription(java.lang.Long) */ @@ -1457,7 +1442,7 @@ public class StudyServiceImpl implements StudyService { public void setUserService(final UserService userService) { _userService = userService; } - + /** * Get the publicationDAO. * @return the publicationDAO @@ -1522,4 +1507,5 @@ public class StudyServiceImpl implements StudyService { final DescriptionAttributeDAO descriptionAttributeDAO) { _descriptionAttributeDAO = descriptionAttributeDAO; } + } diff --git a/Workspace/Siman-Common/src/org/splat/service/technical/IndexServiceImpl.java b/Workspace/Siman-Common/src/org/splat/service/technical/IndexServiceImpl.java index 7e76020..c3b11cc 100644 --- a/Workspace/Siman-Common/src/org/splat/service/technical/IndexServiceImpl.java +++ b/Workspace/Siman-Common/src/org/splat/service/technical/IndexServiceImpl.java @@ -35,22 +35,21 @@ import org.splat.service.dto.Proxy; import org.splat.som.Step; /** - * Implementation of the service for work with Lucen index. + * Implementation of the service for work with Lucen index. */ public class IndexServiceImpl implements IndexService { /** * The logger for this service. */ - private static final Logger LOG = Logger - .getLogger(IndexServiceImpl.class); + private static final Logger LOG = Logger.getLogger(IndexServiceImpl.class); - private final static String PROP_INDEX = "index"; - private final static String PROP_REF = "ref"; - private final static String PROP_STATE = "state"; + private final static String PROP_INDEX = "index"; + private final static String PROP_REF = "ref"; + private final static String PROP_STATE = "state"; private final static String PROP_AUTHOR = "author"; - private final static String PROP_TITLE = "title"; - + private final static String PROP_TITLE = "title"; + private transient Directory _index; private transient org.apache.lucene.document.Document _body; private ProjectElementService _projectElementService; @@ -58,6 +57,7 @@ public class IndexServiceImpl implements IndexService { protected static StandardAnalyzer analyzer = new StandardAnalyzer( Version.LUCENE_29); + private class Entry extends IndexWriter { private transient final org.apache.lucene.document.Document _entry; @@ -101,8 +101,9 @@ public class IndexServiceImpl implements IndexService { setContextAt(getProjectElementService().getSteps(study)); } - private Entry(final KnowledgeElement kelm) throws CorruptIndexException, - LockObtainFailedException, IOException { + private Entry(final KnowledgeElement kelm) + throws CorruptIndexException, LockObtainFailedException, + IOException { super(_index, analyzer, false, IndexWriter.MaxFieldLength.UNLIMITED); // Addition of mandatory fields @@ -145,19 +146,35 @@ public class IndexServiceImpl implements IndexService { } private void add() throws CorruptIndexException, IOException { - addDocument(_entry); - // Save the new entry - optimize(); // Should be called before committing the index - close(); // Commits the index + try { + addDocument(_entry); + // Save the new entry + optimize(); // Should be called before committing the index + close(); // Commits the index + } finally { + if (IndexWriter.isLocked(FSDirectory.open(getRepositoryService() + .getRepositoryIndexDirectory()))) { + IndexWriter.unlock(FSDirectory.open(getRepositoryService() + .getRepositoryIndexDirectory())); + } + } } private void update() throws CorruptIndexException, IOException { - String value = _entry.getField(PROP_REF).stringValue(); // Only field with unique value - Term term = new Term(PROP_REF).createTerm(value); - updateDocument(term, _entry); - // Save the updated entry - optimize(); // Should be called before committing the index - close(); // Commits the index + try { + String value = _entry.getField(PROP_REF).stringValue(); // Only field with unique value + Term term = new Term(PROP_REF).createTerm(value); + updateDocument(term, _entry); + // Save the updated entry + optimize(); // Should be called before committing the index + close(); // Commits the index + } finally { + if (IndexWriter.isLocked(FSDirectory.open(getRepositoryService() + .getRepositoryIndexDirectory()))) { + IndexWriter.unlock(FSDirectory.open(getRepositoryService() + .getRepositoryIndexDirectory())); + } + } } private void setContextAt(final Step[] step) { @@ -243,6 +260,17 @@ public class IndexServiceImpl implements IndexService { public void configure() throws IOException { File indir = getRepositoryService().getRepositoryIndexDirectory(); + if (_index != null) { + try { + _index.close(); + } finally { + if (IndexWriter.isLocked(FSDirectory.open(getRepositoryService() + .getRepositoryIndexDirectory()))) { + IndexWriter.unlock(FSDirectory.open(getRepositoryService() + .getRepositoryIndexDirectory())); + } + } + } _index = FSDirectory.open(indir); _body = new org.apache.lucene.document.Document(); _body.add(new Field(PROP_INDEX, "", Field.Store.YES, @@ -251,32 +279,50 @@ public class IndexServiceImpl implements IndexService { Field.Index.NOT_ANALYZED)); _body.add(new Field("type", "", Field.Store.YES, Field.Index.NOT_ANALYZED)); - _body - .add(new Field(PROP_REF, "", Field.Store.YES, - Field.Index.NOT_ANALYZED)); - _body - .add(new Field("area", "", Field.Store.NO, - Field.Index.NOT_ANALYZED)); + _body.add(new Field(PROP_REF, "", Field.Store.YES, + Field.Index.NOT_ANALYZED)); + _body.add(new Field("area", "", Field.Store.NO, + Field.Index.NOT_ANALYZED)); _body.add(new Field(PROP_STATE, "", Field.Store.YES, Field.Index.NOT_ANALYZED)); _body.add(new Field(PROP_AUTHOR, "", Field.Store.YES, Field.Index.NOT_ANALYZED)); _body.add(new Field(PROP_TITLE, "", Field.Store.YES, Field.Index.NOT_ANALYZED)); - _body - .add(new Field("contents", "", Field.Store.NO, - Field.Index.ANALYZED)); + _body.add(new Field("contents", "", Field.Store.NO, + Field.Index.ANALYZED)); if (!this.exists()) { this.create(); // Happens when re-indexing all studies } } public void create() throws IOException { + if (IndexWriter.isLocked(FSDirectory.open(getRepositoryService() + .getRepositoryIndexDirectory()))) { + IndexWriter.unlock(FSDirectory.open(getRepositoryService() + .getRepositoryIndexDirectory())); + } Directory index = FSDirectory.open(getRepositoryService() .getRepositoryIndexDirectory()); - IndexWriter writer = new IndexWriter(index, analyzer, true, - IndexWriter.MaxFieldLength.UNLIMITED); - writer.close(); // ==== Creates an empty index + if (IndexWriter.isLocked(index)) { + IndexWriter.unlock(index); + } + IndexWriter writer = null; + try { + writer = new IndexWriter(index, analyzer, true, + IndexWriter.MaxFieldLength.UNLIMITED); + } finally { + if (writer != null) { + try { + writer.optimize(); + writer.close(); // ==== Creates an empty index + } finally { + if (IndexWriter.isLocked(index)) { + IndexWriter.unlock(index); + } + } + } + } } // ============================================================================================================================== diff --git a/Workspace/Siman-Common/src/spring/businessServiceContext.xml b/Workspace/Siman-Common/src/spring/businessServiceContext.xml index 2a1874f..bb1b461 100644 --- a/Workspace/Siman-Common/src/spring/businessServiceContext.xml +++ b/Workspace/Siman-Common/src/spring/businessServiceContext.xml @@ -104,6 +104,7 @@ http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> + @@ -154,6 +155,7 @@ http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> + diff --git a/Workspace/Siman-Common/src/test/splat/common/BaseTest.java b/Workspace/Siman-Common/src/test/splat/common/BaseTest.java index fb7af6c..2282a86 100644 --- a/Workspace/Siman-Common/src/test/splat/common/BaseTest.java +++ b/Workspace/Siman-Common/src/test/splat/common/BaseTest.java @@ -50,7 +50,7 @@ import org.testng.annotations.Test; "/spring/technicalServiceContext.xml" }) @TransactionConfiguration(defaultRollback = true, transactionManager = "txManager") -@Test(sequential=true, groups = {"service", "functional", "business"}) +@Test(singleThreaded=true, groups = {"service", "functional", "business"}) public class BaseTest extends TestListingAndOrder { // ========================================= static methods diff --git a/Workspace/Siman-Common/src/test/splat/common/TestListingAndOrder.java b/Workspace/Siman-Common/src/test/splat/common/TestListingAndOrder.java index 6af2cde..cd26bc1 100644 --- a/Workspace/Siman-Common/src/test/splat/common/TestListingAndOrder.java +++ b/Workspace/Siman-Common/src/test/splat/common/TestListingAndOrder.java @@ -27,7 +27,7 @@ import org.testng.annotations.Test; * @author Vera POLYANSKIKH (VPH) * @author Roman Kozlov (RKV) */ -@Test(sequential=true, groups = {"service", "functional", "business"}) +@Test(singleThreaded=true, groups = {"service", "functional", "business"}) public class TestListingAndOrder extends AbstractTransactionalTestNGSpringContextTests { diff --git a/Workspace/Siman-Common/src/test/splat/dao/TestKnowledgeElementDAO.java b/Workspace/Siman-Common/src/test/splat/dao/TestKnowledgeElementDAO.java index 47bc675..79513b4 100644 --- a/Workspace/Siman-Common/src/test/splat/dao/TestKnowledgeElementDAO.java +++ b/Workspace/Siman-Common/src/test/splat/dao/TestKnowledgeElementDAO.java @@ -282,7 +282,7 @@ public class TestKnowledgeElementDAO extends BaseTest { compareObjects(aKelmFound, aKelm); - // Call DAO's create method for a knowledge element with non-zero id. + // Call DAO's update method for a bad knowledge element with zero id. KnowledgeElement aBadKelm = new KnowledgeElement( (new KnowledgeElement.Properties()) .setTitle("Test knowledge element") diff --git a/Workspace/Siman-Common/src/test/splat/service/TestSearchService.java b/Workspace/Siman-Common/src/test/splat/service/TestSearchService.java index 2c2f85a..b8b03fe 100644 --- a/Workspace/Siman-Common/src/test/splat/service/TestSearchService.java +++ b/Workspace/Siman-Common/src/test/splat/service/TestSearchService.java @@ -9,12 +9,17 @@ package test.splat.service; import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; import java.util.Iterator; import java.util.List; import org.splat.dal.bo.kernel.User; import org.splat.dal.bo.som.ContributorRelation; import org.splat.dal.bo.som.DocumentType; +import org.splat.dal.bo.som.KnowledgeElement; +import org.splat.dal.bo.som.KnowledgeElementType; +import org.splat.dal.bo.som.Scenario; import org.splat.dal.bo.som.SimulationContext; import org.splat.dal.bo.som.Study; import org.splat.dal.bo.som.ValidationCycle; @@ -23,6 +28,9 @@ import org.splat.dal.bo.som.ValidationStep; import org.splat.dal.bo.som.Visibility; import org.splat.dal.dao.kernel.UserDAO; import org.splat.dal.dao.som.Database; +import org.splat.dal.dao.som.KnowledgeElementDAO; +import org.splat.dal.dao.som.KnowledgeElementTypeDAO; +import org.splat.dal.dao.som.ScenarioDAO; import org.splat.dal.dao.som.StudyDAO; import org.splat.dal.dao.som.ValidationCycleDAO; import org.splat.exception.BusinessException; @@ -33,6 +41,7 @@ import org.splat.service.SearchService; import org.splat.service.SimulationContextService; import org.splat.service.StepService; import org.splat.service.StudyService; +import org.splat.service.dto.KnowledgeSearchFilterDTO; import org.splat.service.dto.Proxy; import org.splat.service.dto.StudySearchFilterDTO; import org.splat.service.technical.ProjectSettingsService; @@ -66,6 +75,27 @@ public class TestSearchService extends BaseTest { @Qualifier("studyDAO") private transient StudyDAO _studyDAO; + /** + * The ScenarioDAO. Later injected by Spring. + */ + @Autowired + @Qualifier("scenarioDAO") + private transient ScenarioDAO _scenarioDAO; + + /** + * The KnowledgeElementDAO. Later injected by Spring. + */ + @Autowired + @Qualifier("knowledgeElementDAO") + private transient KnowledgeElementDAO _knowledgeElementDAO; + + /** + * The KnowledgeElementTypeDAO. Later injected by Spring. + */ + @Autowired + @Qualifier("knowledgeElementTypeDAO") + private transient KnowledgeElementTypeDAO _knowledgeElementTypeDAO; + /** * The PublicationService. Later injected by Spring. */ @@ -161,10 +191,13 @@ public class TestSearchService extends BaseTest { */ @Test public void testSelectStudiesWhere() throws BusinessException { - LOG.debug(">>>>> BEGIN testGenerateLocalIndex()"); + LOG.debug(">>>>> BEGIN testSelectStudiesWhere()"); startNestedTransaction(); HibernateTemplate ht = getHibernateTemplate(); + Calendar calend = java.util.Calendar.getInstance(); + calend.roll(Calendar.DATE, false); + Date beforeCreation = calend.getTime(); Database.getInstance().reset(); _projectSettings.getAllSteps().clear(); // Clear config to be able to load it again @@ -183,6 +216,7 @@ public class TestSearchService extends BaseTest { User thirdUser = TestEntitiesGenerator.getTestUser("thirdUser"); _userDAO.create(thirdUser); + // ============== STUDY 0: Private : goodUser // Create private study Study aStudy = TestEntitiesGenerator.getTestStudy(goodUser); aStudy.setTitle("0.This is private study"); @@ -195,6 +229,7 @@ public class TestSearchService extends BaseTest { SimulationContext ctx = _studyService.addProjectContext(aStudy, cprop); ht.flush(); + // ============== STUDY 1: Public : goodUser : otherUser is contributor // Create public study with predefined title aStudy = TestEntitiesGenerator.getTestStudy(goodUser); aStudy.setVisibility(Visibility.PUBLIC); @@ -202,13 +237,13 @@ public class TestSearchService extends BaseTest { aStudy.addRelation(new ContributorRelation(aStudy, otherUser)); Long titleStudyId = _studyDAO.create(aStudy); - // Add simulation context to the study 2 - SimulationContext.Properties cprop1 = new SimulationContext.Properties(); + // Add simulation context to the study 1 cprop.setType(_simulationContextService.selectType("product")) .setValue("Test Simulation Context: Product1"); - SimulationContext ctx1 = _studyService.addProjectContext(aStudy, cprop); + _studyService.addProjectContext(aStudy, cprop); ht.flush(); + // ============== STUDY 2: Public : otherUser // Create public study with predefined reference aStudy = TestEntitiesGenerator.getTestStudy(otherUser); aStudy.setVisibility(Visibility.PUBLIC); @@ -216,6 +251,7 @@ public class TestSearchService extends BaseTest { aStudy.setReference("TEST_REF"); Long refStudyId = _studyDAO.create(aStudy); + // ============== STUDY 3: Private : thirdUser : otherUser is contributor // Create private study of third user with otherUser as a reviewer aStudy = TestEntitiesGenerator.getTestStudy(thirdUser); aStudy.setTitle("3.This is a private study of third user"); @@ -231,7 +267,11 @@ public class TestSearchService extends BaseTest { ValidationCycleRelation link = cycle.getContext(); aStudy.addRelation(link); ht.flush(); + calend = java.util.Calendar.getInstance(); + calend.roll(Calendar.DATE, true); + Date afterCreation = calend.getTime(); + // ============== START OF TEST CALLS // Search by study author StudySearchFilterDTO filter = new StudySearchFilterDTO(); filter.setAuthor(String.valueOf(goodUser.getIndex())); @@ -257,8 +297,8 @@ public class TestSearchService extends BaseTest { Assert.assertNotNull(res); Assert.assertEquals(res.size(), 3); Assert.assertEquals(res.get(0).getIndex(), privateStudyId); // goodUser is author - Assert.assertEquals(res.get(2).getIndex(), titleStudyId); // Public study Assert.assertEquals(res.get(1).getIndex(), refStudyId); // Public study + Assert.assertEquals(res.get(2).getIndex(), titleStudyId); // Public study // Search by study title contents filter = new StudySearchFilterDTO(); @@ -288,16 +328,307 @@ public class TestSearchService extends BaseTest { Assert.assertEquals(res.size(), 1); Assert.assertEquals(res.get(0).getIndex(), privateStudyId); // Check simualtion contexts of the found study - aStudy = _studyService.selectStudy(res.get(0).getIndex()); - Iterator ctxIter = aStudy.SimulationContextIterator(); + for (Proxy proxy: res) { + aStudy = _studyService.selectStudy(proxy.getIndex()); + Iterator ctxIter = aStudy + .SimulationContextIterator(); contexts.clear(); while (ctxIter.hasNext()) { contexts.add(ctxIter.next()); } Assert.assertEquals(contexts.size(), 1); Assert.assertEquals(contexts.get(0), ctx); + } + // Search for dates + filter = new StudySearchFilterDTO(); + filter.setCreatedAfter(beforeCreation); + filter.setCreatedBefore(afterCreation); + res = _searchService.selectStudiesWhere(filter); + Assert.assertNotNull(res); + Assert.assertEquals(res.size(), 2); + Assert.assertEquals(res.get(0).getIndex(), refStudyId); + Assert.assertEquals(res.get(1).getIndex(), titleStudyId); + + // Search for dates with no result + filter = new StudySearchFilterDTO(); + filter.setCreatedAfter(afterCreation); + res = _searchService.selectStudiesWhere(filter); + Assert.assertNotNull(res); + Assert.assertEquals(res.size(), 0); + + rollbackNestedTransaction(); + LOG.debug(">>>>> END testSelectStudiesWhere()"); + } + + /** + * Test of searching a study.
+ * Description :
+ * Create studies and try to find them according next document index.
+ * Action :
+ * + *
    + *
  1. Search study by state
  2. + *
  3. Search study by reference
  4. + *
  5. Search study by author
  6. + *
  7. Search study by actor
  8. + *
  9. Search study by title
  10. + *
  11. Search study by simulation contexts
  12. + *
  13. Search study by all criteria
  14. + *
  15. Search study by any criteria
  16. + *
+ *
Test data :
+ * no input parameters
+ * + * Outcome results:
+ * + *
    + *
  • A study must be found according to the given criteria
    + *
  • + *
+ *
+ * + * @throws BusinessException + * if can't create test user or study + */ + @Test + public void testSelectKnowledgeElementsWhere() throws BusinessException { + LOG.debug(">>>>> BEGIN testSelectKnowledgeElementsWhere()"); + startNestedTransaction(); + + HibernateTemplate ht = getHibernateTemplate(); + + Calendar calend = java.util.Calendar.getInstance(); + calend.roll(Calendar.DATE, false); + Date beforeCreation = calend.getTime(); + + Database.getInstance().reset(); + _projectSettings.getAllSteps().clear(); // Clear config to be able to load it again + // Load workflow customization + try { + _projectSettings.configure(ClassLoader.getSystemResource( + "test/som.xml").getPath()); + } catch (Exception e) { + Assert.fail("Can't load som.xml: ", e); + } + + User goodUser = TestEntitiesGenerator.getTestUser("goodUser"); + _userDAO.create(goodUser); + User otherUser = TestEntitiesGenerator.getTestUser("otherUser"); + _userDAO.create(otherUser); + User thirdUser = TestEntitiesGenerator.getTestUser("thirdUser"); + _userDAO.create(thirdUser); + KnowledgeElementType ktype1 = new KnowledgeElementType("testKType1"); + KnowledgeElementType ktype2 = new KnowledgeElementType("testKType2"); + _knowledgeElementTypeDAO.create(ktype1); + _knowledgeElementTypeDAO.create(ktype2); + + // ============== STUDY 0: Private : goodUser + // Create private study + Study aStudy = TestEntitiesGenerator.getTestStudy(goodUser); + aStudy.setTitle("0.This is private study"); + Long privateStudyId = _studyDAO.create(aStudy); + + // Add simulation context to the study 0 + SimulationContext.Properties cprop = new SimulationContext.Properties(); + cprop.setType(_simulationContextService.selectType("product")) + .setValue("Test Simulation Context: Product"); + SimulationContext ctx = _studyService.addProjectContext(aStudy, cprop); + ht.flush(); + + // Add a scenario to the study 0 + Scenario scen = TestEntitiesGenerator.getTestScenario(aStudy); + _scenarioDAO.create(scen); + ht.flush(); + + // Add knowledge elements to the scenario + KnowledgeElement kelm01 = TestEntitiesGenerator + .getTestKnowledgeElement(scen, ktype1, "TestKelm01 title"); + KnowledgeElement kelm02 = TestEntitiesGenerator + .getTestKnowledgeElement(scen, ktype2, "TestKelm02 title"); + _knowledgeElementDAO.create(kelm01); + _knowledgeElementDAO.create(kelm02); + ht.flush(); + + // ============== STUDY 1: Public : goodUser : otherUser is contributor + // Create public study with predefined title + aStudy = TestEntitiesGenerator.getTestStudy(goodUser); + aStudy.setVisibility(Visibility.PUBLIC); + aStudy.setTitle("2.This is a public study"); + aStudy.addRelation(new ContributorRelation(aStudy, otherUser)); + Long titleStudyId = _studyDAO.create(aStudy); + + // Add a scenario to the study 1 + scen = TestEntitiesGenerator.getTestScenario(aStudy); + _scenarioDAO.create(scen); + ht.flush(); + + // Add knowledge elements to the scenario + KnowledgeElement kelm11 = TestEntitiesGenerator + .getTestKnowledgeElement(scen, ktype1, "TestKelm11 title"); + KnowledgeElement kelm12 = TestEntitiesGenerator + .getTestKnowledgeElement(scen, ktype2, "TestKelm12 title"); + _knowledgeElementDAO.create(kelm11); + _knowledgeElementDAO.create(kelm12); + + // Add simulation context to the study 1 + cprop.setType(_simulationContextService.selectType("product")) + .setValue("Test Simulation Context: Product1"); + _studyService.addProjectContext(aStudy, cprop); + ht.flush(); + + // ============== STUDY 2: Public : otherUser + // Create public study with predefined reference + aStudy = TestEntitiesGenerator.getTestStudy(otherUser); + aStudy.setVisibility(Visibility.PUBLIC); + aStudy.setTitle("1.This is another public study"); + aStudy.setReference("TEST_REF"); + Long refStudyId = _studyDAO.create(aStudy); + // Add a scenario to the study 2 + scen = TestEntitiesGenerator.getTestScenario(aStudy); + _scenarioDAO.create(scen); + ht.flush(); + + // Add knowledge elements to the scenario + KnowledgeElement kelm21 = TestEntitiesGenerator + .getTestKnowledgeElement(scen, ktype1, "TestKelm21 title"); + KnowledgeElement kelm22 = TestEntitiesGenerator + .getTestKnowledgeElement(scen, ktype2, "TestKelm22 title"); + _knowledgeElementDAO.create(kelm21); + _knowledgeElementDAO.create(kelm22); + ht.flush(); + + // ============== STUDY 3: Private : thirdUser : otherUser is contributor + // Create private study of third user with otherUser as a reviewer + aStudy = TestEntitiesGenerator.getTestStudy(thirdUser); + aStudy.setTitle("3.This is a private study of third user"); + Long reviewStudyId = _studyDAO.create(aStudy); + + // Create validation cycle for the last study + ValidationCycle.Properties vprop = new ValidationCycle.Properties(); + DocumentType type = _documentTypeService.selectType("specification"); + vprop.setDocumentType(type); + vprop.setActor(ValidationStep.REVIEW, otherUser); + ValidationCycle cycle = new ValidationCycle(aStudy, vprop); + _validationCycleDAO.create(cycle); + ValidationCycleRelation link = cycle.getContext(); + aStudy.addRelation(link); + ht.flush(); + // Add a scenario to the study 3 + scen = TestEntitiesGenerator.getTestScenario(aStudy); + _scenarioDAO.create(scen); + ht.flush(); + + // Add knowledge elements to the scenario + KnowledgeElement kelm31 = TestEntitiesGenerator + .getTestKnowledgeElement(scen, ktype1, "TestKelm31 title"); + KnowledgeElement kelm32 = TestEntitiesGenerator + .getTestKnowledgeElement(scen, ktype2, "TestKelm32 title"); + _knowledgeElementDAO.create(kelm31); + _knowledgeElementDAO.create(kelm32); + ht.flush(); + calend = java.util.Calendar.getInstance(); + calend.roll(Calendar.DATE, true); + Date afterCreation = calend.getTime(); + + // ============== START OF TEST CALLS + // Search by author goodUser as not logged in user + KnowledgeSearchFilterDTO filter = new KnowledgeSearchFilterDTO(); + filter.setAuthor(String.valueOf(goodUser.getIndex())); + List res = _searchService.selectKnowledgeElementsWhere(filter); + Assert.assertNotNull(res); + Assert.assertEquals(res.size(), 2); + Assert.assertEquals(res.get(0).getTitle(), kelm11.getTitle()); + Assert.assertEquals(res.get(1).getTitle(), kelm12.getTitle()); + + // Search for other logged in study contributor (what is visible for otherUser by default) + filter = new KnowledgeSearchFilterDTO(); + filter.setConnectedUserId(otherUser.getIndex()); + res = _searchService.selectKnowledgeElementsWhere(filter); + Assert.assertNotNull(res); + Assert.assertEquals(res.size(), 6); + Assert.assertEquals(res.get(0).getTitle(), kelm11.getTitle()); + Assert.assertEquals(res.get(1).getTitle(), kelm12.getTitle()); + Assert.assertEquals(res.get(2).getTitle(), kelm21.getTitle()); + Assert.assertEquals(res.get(3).getTitle(), kelm22.getTitle()); + Assert.assertEquals(res.get(4).getTitle(), kelm31.getTitle()); + Assert.assertEquals(res.get(5).getTitle(), kelm32.getTitle()); + + // Search for logged in study contributor + filter = new KnowledgeSearchFilterDTO(); + filter.setConnectedUserId(goodUser.getIndex()); + res = _searchService.selectKnowledgeElementsWhere(filter); + Assert.assertNotNull(res); + Assert.assertEquals(res.size(), 6); + Assert.assertEquals(res.get(0).getTitle(), kelm01.getTitle()); + Assert.assertEquals(res.get(1).getTitle(), kelm02.getTitle()); + Assert.assertEquals(res.get(2).getTitle(), kelm11.getTitle()); + Assert.assertEquals(res.get(3).getTitle(), kelm12.getTitle()); + Assert.assertEquals(res.get(4).getTitle(), kelm21.getTitle()); + Assert.assertEquals(res.get(5).getTitle(), kelm22.getTitle()); + + // Search by title contents + filter = new KnowledgeSearchFilterDTO(); + filter.setWords("TestKelm22"); + res = _searchService.selectKnowledgeElementsWhere(filter); + Assert.assertNotNull(res); + Assert.assertEquals(res.size(), 1); + Assert.assertEquals(res.get(0).getTitle(), kelm22.getTitle()); + + // Search by reference + filter = new KnowledgeSearchFilterDTO(); + filter.setReference(kelm22.getReference()); + res = _searchService.selectKnowledgeElementsWhere(filter); + Assert.assertNotNull(res); + Assert.assertEquals(res.size(), 1); + Assert.assertEquals(res.get(0).getTitle(), kelm22.getTitle()); + + // Search by simulation context + filter = new KnowledgeSearchFilterDTO(); + filter.setConnectedUserId(goodUser.getIndex()); + List contexts = new ArrayList(); + contexts.add(ctx); + filter.setSimContexts(contexts); + res = _searchService.selectKnowledgeElementsWhere(filter); + Assert.assertNotNull(res); + Assert.assertEquals(res.size(), 2); + Assert.assertEquals(res.get(0).getTitle(), kelm01.getTitle()); + Assert.assertEquals(res.get(1).getTitle(), kelm02.getTitle()); + // Check simualtion contexts of the found study + for (Proxy proxy : res) { + KnowledgeElement kelm = _knowledgeElementDAO.get(proxy.getIndex()); + aStudy = _studyService.selectStudy(kelm.getOwnerScenario() + .getOwnerStudy().getIndex()); + Iterator ctxIter = aStudy + .SimulationContextIterator(); + contexts.clear(); + while (ctxIter.hasNext()) { + contexts.add(ctxIter.next()); + } + Assert.assertEquals(contexts.size(), 1); + Assert.assertEquals(contexts.get(0), ctx); + } + + // Search for dates + filter = new KnowledgeSearchFilterDTO(); + filter.setCreatedAfter(beforeCreation); + filter.setCreatedBefore(afterCreation); + res = _searchService.selectKnowledgeElementsWhere(filter); + Assert.assertNotNull(res); + Assert.assertEquals(res.size(), 4); + Assert.assertEquals(res.get(0).getTitle(), kelm11.getTitle()); + Assert.assertEquals(res.get(1).getTitle(), kelm12.getTitle()); + Assert.assertEquals(res.get(2).getTitle(), kelm21.getTitle()); + Assert.assertEquals(res.get(3).getTitle(), kelm22.getTitle()); + + // Search for dates with no result + filter = new KnowledgeSearchFilterDTO(); + filter.setCreatedAfter(afterCreation); + res = _searchService.selectKnowledgeElementsWhere(filter); + Assert.assertNotNull(res); + Assert.assertEquals(res.size(), 0); + rollbackNestedTransaction(); - LOG.debug(">>>>> END testGenerateLocalIndex()"); + LOG.debug(">>>>> END testSelectKnowledgeElementsWhere()"); } } diff --git a/Workspace/Siman-Common/src/test/splat/util/TestEntitiesGenerator.java b/Workspace/Siman-Common/src/test/splat/util/TestEntitiesGenerator.java index 95783bd..7e8c9f3 100644 --- a/Workspace/Siman-Common/src/test/splat/util/TestEntitiesGenerator.java +++ b/Workspace/Siman-Common/src/test/splat/util/TestEntitiesGenerator.java @@ -7,13 +7,16 @@ * @version $Revision$ *****************************************************************************/ -package test.splat.util; +package test.splat.util; import java.util.ArrayList; import java.util.Date; import org.splat.dal.bo.kernel.User; +import org.splat.dal.bo.som.KnowledgeElement; +import org.splat.dal.bo.som.KnowledgeElementType; import org.splat.dal.bo.som.ProgressState; +import org.splat.dal.bo.som.Scenario; import org.splat.dal.bo.som.SimulationContext; import org.splat.dal.bo.som.Study; import org.splat.exception.BusinessException; @@ -22,23 +25,24 @@ import org.splat.exception.BusinessException; * Utility class for creating test entities. */ public class TestEntitiesGenerator { - + /** * Create a transient user. - * - * @param userName the userName + * + * @param userName + * the userName * @return a transient StepCommentDTO - * @throws BusinessException if something's wrong + * @throws BusinessException + * if something's wrong */ - public static User getTestUser(final String userName) throws BusinessException { + public static User getTestUser(final String userName) + throws BusinessException { User.Properties uprop = new User.Properties(); - uprop.setUsername(userName) - .setName("TST_Username") - .setFirstName("TST_FirstName") - .setDisplayName("TST_test.user") - .setMailAddress("noreply@salome-platform.org") - .addRole("TST-User"); + uprop.setUsername(userName).setName("TST_Username").setFirstName( + "TST_FirstName").setDisplayName("TST_test.user") + .setMailAddress("noreply@salome-platform.org").addRole( + "TST-User"); uprop.disableCheck(); User user = new User(uprop); return user; @@ -46,22 +50,73 @@ public class TestEntitiesGenerator { /** * Create a transient study. - * - * @param user the user that will be placed in 'manager' and 'actor' properties + * + * @param user + * the user that will be placed in 'manager' and 'actor' properties * @return the test study - * @throws BusinessException if something's wrong + * @throws BusinessException + * if something's wrong */ - public static Study getTestStudy(final User user) throws BusinessException{ + public static Study getTestStudy(final User user) throws BusinessException { Study.Properties studyProps = new Study.Properties(); - studyProps.setActor(user) - .setManager(user) + studyProps.setActor(user).setManager(user) .setTitle("a test study") - //.setDescription("description") - .setDate(new Date()) - .setReference("test reference") + // .setDescription("description") + .setDate(new Date()).setReference("test reference") .setSimulationContexts(new ArrayList()) .setState(ProgressState.inWORK); Study study = new Study(studyProps); return study; } + + /** + * Create a transient test scenario. + * + * @param study + * the owner study + * @return the created scenario + * @throws BusinessException + * if creation is failed + */ + public static Scenario getTestScenario(final Study study) + throws BusinessException { + Scenario.Properties sprops = new Scenario.Properties().setTitle( + "TST_Scenario").setManager(study.getAuthor()).setOwnerStudy( + study); + Scenario aScenario = new Scenario(sprops); + study.getScenariiList().add(aScenario); + return aScenario; + } + + /** + * Create a transient knowledge element. + * + * @param scen + * the owner scenario + * @param ktype + * the knowledge type + * @param title + * the knowledge title + * @return the created knowledge element + * @throws BusinessException + * if creation is failed + */ + public static KnowledgeElement getTestKnowledgeElement(final Scenario scen, + final KnowledgeElementType ktype, final String title) + throws BusinessException { + + KnowledgeElement.Properties kprops = new KnowledgeElement.Properties(); + Date aDate = new Date(); + + kprops + .setTitle(title) + .setAuthor(scen.getAuthor()) + .setOwnerScenario(scen) + .setType(ktype) + .setDate(aDate) + .setValue( + "This is the test knowledge element.\nIt is created by the unit test."); + + return new KnowledgeElement(kprops); + } } diff --git a/Workspace/Siman/src/org/splat/simer/SearchKnowledgeAction.java b/Workspace/Siman/src/org/splat/simer/SearchKnowledgeAction.java index 031766f..d8c83c1 100644 --- a/Workspace/Siman/src/org/splat/simer/SearchKnowledgeAction.java +++ b/Workspace/Siman/src/org/splat/simer/SearchKnowledgeAction.java @@ -4,12 +4,9 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import org.splat.dal.bo.kernel.User; -import org.splat.dal.bo.som.KnowledgeElement; import org.splat.dal.bo.som.KnowledgeElementType; import org.splat.dal.bo.som.ProgressState; import org.splat.dal.bo.som.SimulationContextType; -import org.splat.dal.bo.som.Visibility; import org.splat.kernel.InvalidPropertyException; import org.splat.service.KnowledgeElementTypeService; import org.splat.service.SearchService; @@ -95,35 +92,11 @@ public class SearchKnowledgeAction extends */ @Override protected String doSearch() throws InvalidPropertyException { - initializationScreenContext(Constants.OPEN); - KnowledgeElement.Properties sprop = new KnowledgeElement.Properties(); - - // Search matching all criteria - sprop.setType(getKnowledgeElementTypeService().selectType( - Integer.valueOf(getFilter().getKtype()))); - if (getFilter().getWords().length() > 0) { - sprop.setTitle(getFilter().getWords()); - } - if (getFilter().getReference().length() > 0) { - sprop.setReference(getFilter().getReference()); - } - if (getFilter().getSimContexts().size() > 0) { - sprop.setSimulationContexts(getFilter().getSimContexts()); - } - int index = Integer.valueOf(getFilter().getAuthor()); - if (index > 0) { - User him = getUserService().selectUser(index); - sprop.setAuthor(him); + if (getConnectedUser() != null) { + getFilter().setConnectedUserId(getConnectedUser().getIndex()); } - // Set of the visibility - KnowledgeElement.Properties other = sprop.copy(); - - other.setVisibility(Visibility.PUBLIC); - sprop.setVisibility(Visibility.PRIVATE); - sprop.setActor(getConnectedUser()); - - _result = getSearchService().selectKnowledgeElementsWhere(sprop, other); + _result = getSearchService().selectKnowledgeElementsWhere(getFilter()); getSession().put(RESULT_KEY, _result); // For redisplaying the page without re-executing the search return "refresh"; } @@ -132,6 +105,11 @@ public class SearchKnowledgeAction extends // Getters // ============================================================================================================================== + /** + * Get available knowledge types. + * + * @return map of knowledge type ids and translations. + */ public Map getKnowledgeTypes() { return _knowledgeTypes; } -- 2.30.2