Author: echatellier Date: 2013-03-04 12:33:07 +0100 (Mon, 04 Mar 2013) New Revision: 168 Url: http://forge.codelutin.com/projects/cantharella/repository/revisions/168 Log: fixes #1643: Add search engine security implementation Added: trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/config/HibernateSearchIntegrator.java trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/search/CampagnePersonneBridge.java trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/search/IndexEventListener.java trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/search/LotPersonneBridge.java Modified: trunk/cantharella.data/pom.xml trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/config/DataContext.java trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/dao/GenericDao.java trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/dao/impl/HibernateTemplateDao.java trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/Campagne.java trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/CampagnePersonneDroits.java trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/Document.java trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/Extraction.java trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/Extrait.java trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/Lot.java trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/LotPersonneDroits.java trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/Molecule.java trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/MoleculeProvenance.java trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/Personne.java trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/Produit.java trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/Purification.java trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/Specimen.java trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/Station.java trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/TestBio.java trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/search/ProduitBridge.java trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/search/UtilisateurSearchFilter.java trunk/cantharella.data/src/main/resources/META-INF/services/org.hibernate.integrator.spi.Integrator trunk/cantharella.service/src/main/java/nc/ird/cantharella/service/services/LotService.java trunk/cantharella.service/src/main/java/nc/ird/cantharella/service/services/impl/LotServiceImpl.java trunk/cantharella.service/src/main/java/nc/ird/cantharella/service/services/impl/SearchServiceImpl.java trunk/cantharella.web/src/main/java/nc/ird/cantharella/web/pages/domain/utilisateur/ManageUtilisateurPage.java Modified: trunk/cantharella.data/pom.xml =================================================================== --- trunk/cantharella.data/pom.xml 2013-03-04 11:31:56 UTC (rev 167) +++ trunk/cantharella.data/pom.xml 2013-03-04 11:33:07 UTC (rev 168) @@ -119,6 +119,10 @@ <artifactId>hibernate-search-engine</artifactId> </dependency> <dependency> + <groupId>org.hibernate</groupId> + <artifactId>hibernate-search-orm</artifactId> + </dependency> + <dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-core</artifactId> </dependency> Modified: trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/config/DataContext.java =================================================================== --- trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/config/DataContext.java 2013-03-04 11:31:56 UTC (rev 167) +++ trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/config/DataContext.java 2013-03-04 11:33:07 UTC (rev 168) @@ -315,7 +315,7 @@ hibernateProperties.setProperty("hibernate.search.default.directory_provider", "filesystem"); hibernateProperties.setProperty("hibernate.search.default.indexBase", hibernateSearchIndexBase); hibernateProperties.setProperty("hibernate.search.analyzer", hibernateSearchAnalyzer); - + hibernateProperties.setProperty("hibernate.search.enable_dirty_check", "false"); // Hibernate: Session //hibernateProperties.setProperty("hibernate.current_session_context_class", "thread"); //hibernateProperties.setProperty(Environment.JTA_PLATFORM, "hibernate.transaction.factory_class", SpringTransactionFactory.class.getName()); Added: trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/config/HibernateSearchIntegrator.java =================================================================== --- trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/config/HibernateSearchIntegrator.java (rev 0) +++ trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/config/HibernateSearchIntegrator.java 2013-03-04 11:33:07 UTC (rev 168) @@ -0,0 +1,142 @@ +package nc.ird.cantharella.data.config; + +/* + * #%L + * Cantharella :: Data + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2009 - 2013 IRD (Institut de Recherche pour le Developpement) and by respective authors (see below) + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * #L% + */ + +import java.util.List; + +import nc.ird.cantharella.data.model.Campagne; +import nc.ird.cantharella.data.model.CampagnePersonneDroits; +import nc.ird.cantharella.data.model.Lot; +import nc.ird.cantharella.data.model.LotPersonneDroits; +import nc.ird.cantharella.data.model.search.IndexEventListener; + +import org.hibernate.Session; +import org.hibernate.cfg.Configuration; +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.event.service.spi.EventListenerRegistry; +import org.hibernate.event.spi.EventType; +import org.hibernate.event.spi.PostDeleteEvent; +import org.hibernate.event.spi.PostDeleteEventListener; +import org.hibernate.event.spi.PostInsertEvent; +import org.hibernate.event.spi.PostInsertEventListener; +import org.hibernate.event.spi.PostUpdateEvent; +import org.hibernate.event.spi.PostUpdateEventListener; +import org.hibernate.integrator.spi.Integrator; +import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.search.FullTextSession; +import org.hibernate.search.Search; +import org.hibernate.service.spi.SessionFactoryServiceRegistry; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Register cantharella validator into hibernate using integrator. + * + * @author echatellier + */ +public class HibernateSearchIntegrator implements Integrator, PostDeleteEventListener, PostUpdateEventListener, + PostInsertEventListener { + + /** Logger */ + private static final Logger LOG = LoggerFactory.getLogger(HibernateSearchIntegrator.class); + + /** {@inheritDoc} */ + @Override + public void integrate(Configuration configuration, SessionFactoryImplementor sessionFactory, + SessionFactoryServiceRegistry serviceRegistry) { + if (LOG.isDebugEnabled()) { + LOG.debug("Registering custom search listener into hibernate"); + } + + // register validator + EventListenerRegistry eventRegistry = serviceRegistry.getService(EventListenerRegistry.class); + + IndexEventListener listener = new IndexEventListener(IndexEventListener.Installation.SINGLE_INSTANCE); + eventRegistry.prependListeners(EventType.POST_DELETE, listener); + eventRegistry.prependListeners(EventType.POST_UPDATE, listener); + eventRegistry.prependListeners(EventType.POST_INSERT, listener); + listener.initialize(configuration); + } + + /** {@inheritDoc} */ + @Override + public void integrate(MetadataImplementor metadata, SessionFactoryImplementor sessionFactory, + SessionFactoryServiceRegistry serviceRegistry) { + integrate((Configuration) null, sessionFactory, serviceRegistry); + } + + /** {@inheritDoc} */ + @Override + public void disintegrate(SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) { + + } + + /** {@inheritDoc} */ + @Override + public void onPostInsert(PostInsertEvent event) { + Object entity = event.getEntity(); + LOG.debug("[Event] onPostInsert on : " + entity); + reIndexEntity(event.getSession(), event.getEntity()); + } + + /** {@inheritDoc} */ + @Override + public void onPostUpdate(PostUpdateEvent event) { + Object entity = event.getEntity(); + LOG.debug("[Event] onPostUpdate on : " + entity); + reIndexEntity(event.getSession(), event.getEntity()); + } + + /** {@inheritDoc} */ + @Override + public void onPostDelete(PostDeleteEvent event) { + Object entity = event.getEntity(); + LOG.debug("[Event] onPostDelete on : " + entity); + reIndexEntity(event.getSession(), event.getEntity()); + } + + /** + * Reindex entity associated with event entity depending on + * entity type. + * + * @param session current session + * @param entity current entity + */ + protected void reIndexEntity(Session session, Object entity) { + if (entity instanceof LotPersonneDroits) { + Lot lot = ((LotPersonneDroits) entity).getId().getPk1(); + lot = (Lot) session.merge(lot); + FullTextSession fullTextSession = Search.getFullTextSession(session); + fullTextSession.index(lot); + } else if (entity instanceof CampagnePersonneDroits) { + Campagne campagne = ((CampagnePersonneDroits) entity).getId().getPk1(); + campagne = (Campagne) session.merge(campagne); + FullTextSession fullTextSession = Search.getFullTextSession(session); + List<Lot> lots = campagne.getLots(); + for (Lot lot : lots) { + fullTextSession.index(lot); + } + } + } +} Property changes on: trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/config/HibernateSearchIntegrator.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Modified: trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/dao/GenericDao.java =================================================================== --- trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/dao/GenericDao.java 2013-03-04 11:31:56 UTC (rev 167) +++ trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/dao/GenericDao.java 2013-03-04 11:33:07 UTC (rev 168) @@ -287,7 +287,8 @@ * Merge a model from the hibernate session. * @param <M> Model type * @param model Model (not null) + * @return merged object */ @Transactional - <M extends AbstractModel> void merge(M model); + <M extends AbstractModel> M merge(M model); } Modified: trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/dao/impl/HibernateTemplateDao.java =================================================================== --- trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/dao/impl/HibernateTemplateDao.java 2013-03-04 11:31:56 UTC (rev 167) +++ trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/dao/impl/HibernateTemplateDao.java 2013-03-04 11:33:07 UTC (rev 168) @@ -298,9 +298,10 @@ } /** {@inheritDoc} */ + @SuppressWarnings("unchecked") @Override - public <M extends AbstractModel> void merge(M model) { + public <M extends AbstractModel> M merge(M model) { AssertTools.assertNotNull(model); - sessionFactory.getCurrentSession().merge(model); + return (M) sessionFactory.getCurrentSession().merge(model); } } \ No newline at end of file Modified: trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/Campagne.java =================================================================== --- trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/Campagne.java 2013-03-04 11:31:56 UTC (rev 167) +++ trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/Campagne.java 2013-03-04 11:33:07 UTC (rev 168) @@ -50,8 +50,12 @@ import org.apache.commons.beanutils.BeanComparator; import org.hibernate.annotations.Cascade; import org.hibernate.annotations.CascadeType; +import org.hibernate.annotations.Fetch; +import org.hibernate.annotations.FetchMode; import org.hibernate.annotations.Type; +import org.hibernate.search.annotations.ContainedIn; import org.hibernate.search.annotations.Field; +import org.hibernate.search.annotations.IndexedEmbedded; import org.hibernate.search.annotations.Store; import org.hibernate.validator.constraints.Length; import org.hibernate.validator.constraints.NotEmpty; @@ -119,6 +123,7 @@ /** Lots */ @NotNull @OneToMany(mappedBy = "campagne", fetch = FetchType.LAZY) + @ContainedIn private List<Lot> lots; /** Créateur */ @@ -135,6 +140,7 @@ /** Droits personnes */ @NotNull @OneToMany(mappedBy = "id.pk1", fetch = FetchType.LAZY) + @IndexedEmbedded private List<CampagnePersonneDroits> personnesDroits; /** Stations prospectées **/ @@ -144,9 +150,11 @@ private List<Station> stations; /** Attached documents. */ - @OneToMany(fetch = FetchType.LAZY, orphanRemoval = true) + @OneToMany(fetch = FetchType.EAGER, orphanRemoval = true) @JoinColumn(name = "campagne") @Cascade( { CascadeType.SAVE_UPDATE }) + @Fetch(value = FetchMode.SUBSELECT) + // see HHH-1718 private List<Document> documents; /** Modified: trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/CampagnePersonneDroits.java =================================================================== --- trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/CampagnePersonneDroits.java 2013-03-04 11:31:56 UTC (rev 167) +++ trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/CampagnePersonneDroits.java 2013-03-04 11:33:07 UTC (rev 168) @@ -22,20 +22,29 @@ */ package nc.ird.cantharella.data.model; +import javax.persistence.Embeddable; import javax.persistence.EmbeddedId; import javax.persistence.Entity; import javax.persistence.Table; import javax.validation.constraints.NotNull; +import nc.ird.cantharella.data.model.search.CampagnePersonneBridge; import nc.ird.cantharella.data.model.utils.AbstractModel; import nc.ird.cantharella.data.model.utils.CompositeId; +import org.hibernate.search.annotations.ClassBridge; +import org.hibernate.search.annotations.Index; +import org.hibernate.search.annotations.IndexedEmbedded; +import org.hibernate.search.annotations.Store; + /** * Modèle : droits d'une personne sur une campagne * @author Mickael Tricot */ @Entity @Table +@Embeddable +@ClassBridge(name = "campagne", index = Index.YES, store = Store.YES, impl = CampagnePersonneBridge.class) public class CampagnePersonneDroits extends AbstractModel { /** Droits */ @@ -45,6 +54,7 @@ /** ID */ @EmbeddedId @NotNull + @IndexedEmbedded private CompositeId<Campagne, Personne> id; /** Modified: trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/Document.java =================================================================== --- trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/Document.java 2013-03-04 11:31:56 UTC (rev 167) +++ trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/Document.java 2013-03-04 11:33:07 UTC (rev 168) @@ -26,6 +26,7 @@ import java.util.Date; import javax.persistence.Basic; +import javax.persistence.Embeddable; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; @@ -49,6 +50,7 @@ * @author Eric Chatellier */ @Entity +@Embeddable public class Document extends AbstractModel { /** Id du document. */ Modified: trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/Extraction.java =================================================================== --- trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/Extraction.java 2013-03-04 11:31:56 UTC (rev 167) +++ trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/Extraction.java 2013-03-04 11:33:07 UTC (rev 168) @@ -53,6 +53,8 @@ import org.apache.commons.collections.comparators.ComparatorChain; import org.hibernate.annotations.Cascade; import org.hibernate.annotations.CascadeType; +import org.hibernate.annotations.Fetch; +import org.hibernate.annotations.FetchMode; import org.hibernate.annotations.Type; import org.hibernate.search.annotations.ContainedIn; import org.hibernate.search.annotations.Field; @@ -103,7 +105,7 @@ /** Lot utilisé pour l'extraction **/ @NotNull @ManyToOne(fetch = FetchType.EAGER, optional = false) - @IndexedEmbedded(depth = 1) + @IndexedEmbedded private Lot lot; /** Masse avant l'extraction **/ @@ -132,9 +134,11 @@ private List<Extrait> extraits; /** Attached documents. */ - @OneToMany(fetch = FetchType.LAZY, orphanRemoval = true) + @OneToMany(fetch = FetchType.EAGER, orphanRemoval = true) @JoinColumn(name = "extraction") @Cascade( { CascadeType.SAVE_UPDATE }) + @Fetch(value = FetchMode.SUBSELECT) + // see HHH-1718 private List<Document> documents; /** Modified: trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/Extrait.java =================================================================== --- trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/Extrait.java 2013-03-04 11:31:56 UTC (rev 167) +++ trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/Extrait.java 2013-03-04 11:33:07 UTC (rev 168) @@ -28,10 +28,10 @@ import javax.persistence.ManyToOne; import javax.validation.constraints.NotNull; +import org.hibernate.search.annotations.IndexedEmbedded; + import nc.ird.cantharella.data.validation.CollectionUniqueField; -import org.hibernate.search.annotations.IndexedEmbedded; - /** * Modèle : Produit issue d'une extraction * @author Adrien Cheype Modified: trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/Lot.java =================================================================== --- trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/Lot.java 2013-03-04 11:31:56 UTC (rev 167) +++ trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/Lot.java 2013-03-04 11:33:07 UTC (rev 168) @@ -53,7 +53,10 @@ import org.apache.commons.beanutils.BeanComparator; import org.hibernate.annotations.Cascade; import org.hibernate.annotations.CascadeType; +import org.hibernate.annotations.Fetch; +import org.hibernate.annotations.FetchMode; import org.hibernate.annotations.Type; +import org.hibernate.search.annotations.ContainedIn; import org.hibernate.search.annotations.Field; import org.hibernate.search.annotations.FullTextFilterDef; import org.hibernate.search.annotations.FullTextFilterDefs; @@ -90,7 +93,7 @@ /** Campagne */ @NotNull @ManyToOne(fetch = FetchType.EAGER, optional = false) - @IndexedEmbedded(depth = 1) + @IndexedEmbedded private Campagne campagne; /** complement */ @@ -147,6 +150,7 @@ /** Droits attribués aux personnes */ @OneToMany(mappedBy = "id.pk1", fetch = FetchType.LAZY) @NotNull + @IndexedEmbedded private List<LotPersonneDroits> personnesDroits; /** Spécimen source */ @@ -158,18 +162,21 @@ /** Station */ @NotNull @ManyToOne(fetch = FetchType.EAGER, optional = false) - @IndexedEmbedded(depth = 1) + @IndexedEmbedded private Station station; /** Extractions provenants du lot */ @OneToMany(mappedBy = "lot", fetch = FetchType.LAZY) @NotNull + @ContainedIn private List<Extraction> extractions; /** Attached documents. */ - @OneToMany(fetch = FetchType.LAZY, orphanRemoval = true) + @OneToMany(fetch = FetchType.EAGER, orphanRemoval = true) @JoinColumn(name = "lot") @Cascade( { CascadeType.SAVE_UPDATE }) + @Fetch(value = FetchMode.SUBSELECT) + // see HHH-1718 private List<Document> documents; /** Modified: trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/LotPersonneDroits.java =================================================================== --- trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/LotPersonneDroits.java 2013-03-04 11:31:56 UTC (rev 167) +++ trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/LotPersonneDroits.java 2013-03-04 11:33:07 UTC (rev 168) @@ -22,20 +22,29 @@ */ package nc.ird.cantharella.data.model; +import javax.persistence.Embeddable; import javax.persistence.EmbeddedId; import javax.persistence.Entity; import javax.persistence.Table; import javax.validation.constraints.NotNull; +import nc.ird.cantharella.data.model.search.LotPersonneBridge; import nc.ird.cantharella.data.model.utils.AbstractModel; import nc.ird.cantharella.data.model.utils.CompositeId; +import org.hibernate.search.annotations.ClassBridge; +import org.hibernate.search.annotations.Index; +import org.hibernate.search.annotations.IndexedEmbedded; +import org.hibernate.search.annotations.Store; + /** * Modèle : droits d'une personne sur un lot * @author Mickael Tricot */ @Entity @Table +@Embeddable +@ClassBridge(name = "lot", index = Index.YES, store = Store.YES, impl = LotPersonneBridge.class) public class LotPersonneDroits extends AbstractModel { /** Droits */ @@ -45,6 +54,7 @@ /** ID */ @EmbeddedId @NotNull + @IndexedEmbedded private CompositeId<Lot, Personne> id; /** Modified: trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/Molecule.java =================================================================== --- trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/Molecule.java 2013-03-04 11:31:56 UTC (rev 167) +++ trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/Molecule.java 2013-03-04 11:33:07 UTC (rev 168) @@ -46,6 +46,8 @@ import org.hibernate.annotations.Cascade; import org.hibernate.annotations.CascadeType; +import org.hibernate.annotations.Fetch; +import org.hibernate.annotations.FetchMode; import org.hibernate.annotations.Type; import org.hibernate.search.annotations.Field; import org.hibernate.search.annotations.Indexed; @@ -105,7 +107,7 @@ /** Campagne. */ @ManyToOne(fetch = FetchType.EAGER) - @IndexedEmbedded(depth = 1) + @IndexedEmbedded private Campagne campagne; /** Identifiee par. */ @@ -134,12 +136,15 @@ /** Produit utilisé obtenir le résultat */ @OneToMany(mappedBy = "molecule", fetch = FetchType.LAZY, orphanRemoval = true) @Cascade( { CascadeType.SAVE_UPDATE }) + @IndexedEmbedded private List<MoleculeProvenance> provenances; /** Attached documents. */ - @OneToMany(fetch = FetchType.LAZY, orphanRemoval = true) + @OneToMany(fetch = FetchType.EAGER, orphanRemoval = true) @JoinColumn(name = "molecule") @Cascade( { CascadeType.SAVE_UPDATE }) + @Fetch(value = FetchMode.SUBSELECT) + // see HHH-1718 private List<Document> documents; /** Modified: trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/MoleculeProvenance.java =================================================================== --- trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/MoleculeProvenance.java 2013-03-04 11:31:56 UTC (rev 167) +++ trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/MoleculeProvenance.java 2013-03-04 11:33:07 UTC (rev 168) @@ -34,6 +34,9 @@ import javax.validation.constraints.Min; import javax.validation.constraints.NotNull; +import org.hibernate.search.annotations.ContainedIn; +import org.hibernate.search.annotations.IndexedEmbedded; + import nc.ird.cantharella.data.config.DataContext; import nc.ird.cantharella.data.model.utils.AbstractModel; @@ -59,11 +62,13 @@ /** Molecule dont fait partie la provenance */ @NotNull @ManyToOne(fetch = FetchType.EAGER, optional = false) + @ContainedIn private Molecule molecule; /** Produit sur lequel porte la provenance **/ @NotNull @ManyToOne(fetch = FetchType.EAGER, optional = false) + @IndexedEmbedded private Produit produit; /** Modified: trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/Personne.java =================================================================== --- trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/Personne.java 2013-03-04 11:31:56 UTC (rev 167) +++ trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/Personne.java 2013-03-04 11:33:07 UTC (rev 168) @@ -50,6 +50,8 @@ import org.apache.commons.collections.comparators.ComparatorChain; import org.hibernate.annotations.Cascade; import org.hibernate.annotations.CascadeType; +import org.hibernate.annotations.Fetch; +import org.hibernate.annotations.FetchMode; import org.hibernate.annotations.Index; import org.hibernate.annotations.Type; import org.hibernate.validator.constraints.Email; @@ -184,9 +186,11 @@ private List<TestBio> testsBioCrees; /** Attached documents. */ - @OneToMany(fetch = FetchType.LAZY, orphanRemoval = true) + @OneToMany(fetch = FetchType.EAGER, orphanRemoval = true) @JoinColumn(name = "personne") @Cascade( { CascadeType.SAVE_UPDATE }) + @Fetch(value = FetchMode.SUBSELECT) + // see HHH-1718 private List<Document> documents; /** Modified: trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/Produit.java =================================================================== --- trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/Produit.java 2013-03-04 11:31:56 UTC (rev 167) +++ trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/Produit.java 2013-03-04 11:33:07 UTC (rev 168) @@ -57,7 +57,7 @@ */ @Entity @Inheritance(strategy = InheritanceType.JOINED) -@ClassBridge(name = "produitBridge", index = Index.YES, store = Store.YES, impl = ProduitBridge.class) +@ClassBridge(name = "produit", index = Index.YES, store = Store.YES, impl = ProduitBridge.class) public abstract class Produit extends AbstractModel implements Cloneable, Comparable<Produit> { /** Id du produit */ @@ -81,6 +81,7 @@ /** Purifications effectuées à partir du produit */ @NotNull @OneToMany(mappedBy = "produit", fetch = FetchType.LAZY) + @ContainedIn private List<Purification> purificationsSuivantes; /** Résultats de tests biologiques effectués à partir du produit */ @@ -210,5 +211,4 @@ public void setResultatsTestsBioSuivants(List<ResultatTestBio> resultatsTestsBioSuivants) { this.resultatsTestsBioSuivants = resultatsTestsBioSuivants; } - } Modified: trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/Purification.java =================================================================== --- trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/Purification.java 2013-03-04 11:31:56 UTC (rev 167) +++ trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/Purification.java 2013-03-04 11:33:07 UTC (rev 168) @@ -55,7 +55,10 @@ import org.apache.commons.collections.comparators.ComparatorChain; import org.hibernate.annotations.Cascade; import org.hibernate.annotations.CascadeType; +import org.hibernate.annotations.Fetch; +import org.hibernate.annotations.FetchMode; import org.hibernate.annotations.Type; +import org.hibernate.search.annotations.ContainedIn; import org.hibernate.search.annotations.Field; import org.hibernate.search.annotations.FullTextFilterDef; import org.hibernate.search.annotations.FullTextFilterDefs; @@ -143,6 +146,7 @@ @NotNull @OneToMany(mappedBy = "purification", fetch = FetchType.LAZY, orphanRemoval = true) @Cascade( { CascadeType.REFRESH, CascadeType.SAVE_UPDATE }) + @ContainedIn private List<Fraction> fractions; /** @@ -153,9 +157,11 @@ private Lot lotSource; /** Attached documents. */ - @OneToMany(fetch = FetchType.LAZY, orphanRemoval = true) + @OneToMany(fetch = FetchType.EAGER, orphanRemoval = true) @JoinColumn(name = "purification") @Cascade( { CascadeType.SAVE_UPDATE }) + @Fetch(value = FetchMode.SUBSELECT) + // see HHH-1718 private List<Document> documents; /** Modified: trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/Specimen.java =================================================================== --- trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/Specimen.java 2013-03-04 11:31:56 UTC (rev 167) +++ trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/Specimen.java 2013-03-04 11:33:07 UTC (rev 168) @@ -50,6 +50,8 @@ import org.apache.commons.beanutils.BeanComparator; import org.hibernate.annotations.Cascade; import org.hibernate.annotations.CascadeType; +import org.hibernate.annotations.Fetch; +import org.hibernate.annotations.FetchMode; import org.hibernate.annotations.Type; import org.hibernate.search.annotations.Field; import org.hibernate.search.annotations.FullTextFilterDef; @@ -146,11 +148,11 @@ @Temporal(TemporalType.DATE) private Date dateDepot; - /** Embranchement */ + /** Num dépot */ @Length(max = LENGTH_TINY_TEXT) private String numDepot; - /** Embranchement */ + /** Lieu depot */ @Length(max = LENGTH_MEDIUM_TEXT) private String lieuDepot; @@ -172,9 +174,11 @@ private Personne createur; /** Attached documents. */ - @OneToMany(fetch = FetchType.LAZY, orphanRemoval = true) + @OneToMany(fetch = FetchType.EAGER, orphanRemoval = true) @JoinColumn(name = "specimen") @Cascade( { CascadeType.SAVE_UPDATE }) + @Fetch(value = FetchMode.SUBSELECT) + // see HHH-1718 private List<Document> documents; /** Modified: trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/Station.java =================================================================== --- trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/Station.java 2013-03-04 11:31:56 UTC (rev 167) +++ trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/Station.java 2013-03-04 11:33:07 UTC (rev 168) @@ -51,7 +51,10 @@ import org.hibernate.annotations.AccessType; import org.hibernate.annotations.Cascade; import org.hibernate.annotations.CascadeType; +import org.hibernate.annotations.Fetch; +import org.hibernate.annotations.FetchMode; import org.hibernate.annotations.Type; +import org.hibernate.search.annotations.ContainedIn; import org.hibernate.search.annotations.Field; import org.hibernate.search.annotations.FullTextFilterDef; import org.hibernate.search.annotations.FullTextFilterDefs; @@ -124,6 +127,7 @@ /** Lots */ @NotNull @OneToMany(mappedBy = "station", fetch = FetchType.LAZY) + @ContainedIn private List<Lot> lots; /** Stations */ @@ -133,12 +137,15 @@ /** Spécimens de référence qui sont rattachés à cette station */ @OneToMany(mappedBy = "station", fetch = FetchType.LAZY) + @ContainedIn private List<Specimen> specimensRattaches; /** Attached documents. */ - @OneToMany(fetch = FetchType.LAZY, orphanRemoval = true) + @OneToMany(fetch = FetchType.EAGER, orphanRemoval = true) @JoinColumn(name = "station") @Cascade( { CascadeType.SAVE_UPDATE }) + @Fetch(value = FetchMode.SUBSELECT) + // see HHH-1718 private List<Document> documents; /** Modified: trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/TestBio.java =================================================================== --- trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/TestBio.java 2013-03-04 11:31:56 UTC (rev 167) +++ trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/TestBio.java 2013-03-04 11:33:07 UTC (rev 168) @@ -57,6 +57,8 @@ import org.apache.commons.beanutils.BeanComparator; import org.hibernate.annotations.Cascade; import org.hibernate.annotations.CascadeType; +import org.hibernate.annotations.Fetch; +import org.hibernate.annotations.FetchMode; import org.hibernate.annotations.Type; import org.hibernate.search.annotations.ContainedIn; import org.hibernate.search.annotations.Field; @@ -146,9 +148,11 @@ private List<ResultatTestBio> resultats; /** Attached documents. */ - @OneToMany(fetch = FetchType.LAZY, orphanRemoval = true) + @OneToMany(fetch = FetchType.EAGER, orphanRemoval = true) @JoinColumn(name = "resultatTestBio") @Cascade( { CascadeType.SAVE_UPDATE }) + @Fetch(value = FetchMode.SUBSELECT) + // see HHH-1718 private List<Document> documents; /** Added: trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/search/CampagnePersonneBridge.java =================================================================== --- trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/search/CampagnePersonneBridge.java (rev 0) +++ trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/search/CampagnePersonneBridge.java 2013-03-04 11:33:07 UTC (rev 168) @@ -0,0 +1,68 @@ +package nc.ird.cantharella.data.model.search; + +/* + * #%L + * Cantharella :: Data + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2010 - 2013 IRD (Institut de Recherche pour le Developpement) and by respective authors (see below) + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * #L% + */ + +import nc.ird.cantharella.data.model.Campagne; +import nc.ird.cantharella.data.model.CampagnePersonneDroits; +import nc.ird.cantharella.data.model.Personne; +import nc.ird.cantharella.data.model.utils.CompositeId; + +import org.apache.lucene.document.Document; +import org.apache.lucene.document.Field; +import org.hibernate.search.bridge.FieldBridge; +import org.hibernate.search.bridge.LuceneOptions; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Hibernate search can't index CompositeId by himself. + * + * To index right on entities, we add a field "droit.pk2" containing user + * id, meaning "this user can see this indexed document". + * + * @author Eric Chatellier + */ +public class CampagnePersonneBridge implements FieldBridge { + + /** Logger */ + private static final Logger LOG = LoggerFactory.getLogger(CampagnePersonneBridge.class); + + /** {@inheritDoc} */ + @Override + public void set(String name, Object value, Document document, LuceneOptions luceneOptions) { + + CampagnePersonneDroits campagnePersonneDroits = (CampagnePersonneDroits) value; + if (LOG.isTraceEnabled()) { + LOG.trace("Custom indexing of CampagnePersonneDroits : " + + campagnePersonneDroits.getId().getPk1().getIdCampagne() + "," + + campagnePersonneDroits.getId().getPk2().getIdPersonne()); + } + + CompositeId<Campagne, Personne> compositeId = campagnePersonneDroits.getId(); + + // commons information for all produit + document.add(new Field("droit.pk2", String.valueOf(compositeId.getPk2().getIdPersonne()), luceneOptions + .getStore(), luceneOptions.getIndex(), luceneOptions.getTermVector())); + } +} Property changes on: trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/search/CampagnePersonneBridge.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/search/IndexEventListener.java =================================================================== --- trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/search/IndexEventListener.java (rev 0) +++ trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/search/IndexEventListener.java 2013-03-04 11:33:07 UTC (rev 168) @@ -0,0 +1,105 @@ +/* + * #%L + * Cantharella :: Data + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2012 - 2013 IRD (Institut de Recherche pour le Developpement) and by respective authors (see below) + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * #L% + */ +package nc.ird.cantharella.data.model.search; + +import java.io.Serializable; + +import nc.ird.cantharella.data.model.Campagne; +import nc.ird.cantharella.data.model.CampagnePersonneDroits; +import nc.ird.cantharella.data.model.Lot; +import nc.ird.cantharella.data.model.LotPersonneDroits; + +import org.hibernate.Session; +import org.hibernate.event.spi.AbstractEvent; +import org.hibernate.event.spi.PostDeleteEvent; +import org.hibernate.event.spi.PostInsertEvent; +import org.hibernate.event.spi.PostUpdateEvent; +import org.hibernate.search.backend.spi.WorkType; +import org.hibernate.search.event.impl.FullTextIndexEventListener; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Hibernate event listener to force reindexation on custom indexed entity: + * {@link LotPersonneDroits} and {@link CampagnePersonneDroits}. + * + * @author Eric Chatellier + */ +public class IndexEventListener extends FullTextIndexEventListener { + + /** Logger */ + private static final Logger LOG = LoggerFactory.getLogger(IndexEventListener.class); + + /** + * Constructor. + * @param installation installation strategy + */ + public IndexEventListener(Installation installation) { + super(installation); + } + + /** {@inheritDoc}. */ + @Override + public void onPostDelete(PostDeleteEvent event) { + Object entity = event.getEntity(); + LOG.debug("[Event] onPostDelete on : " + entity); + reIndexEntity(event, event.getEntity(), event.getId()); + } + + /** {@inheritDoc}. */ + @Override + public void onPostInsert(PostInsertEvent event) { + Object entity = event.getEntity(); + LOG.debug("[Event] onPostInsert on : " + entity); + reIndexEntity(event, event.getEntity(), event.getId()); + } + + /** {@inheritDoc}. */ + @Override + public void onPostUpdate(PostUpdateEvent event) { + Object entity = event.getEntity(); + LOG.debug("[Event] onPostUpdate on : " + entity); + reIndexEntity(event, event.getEntity(), event.getId()); + } + + /** + * Reindex entity associated with event entity depending on + * entity type. + * + * @param event event + * @param entity current entity + * @param id entity id + */ + protected void reIndexEntity(AbstractEvent event, Object entity, Serializable id) { + Session session = event.getSession(); + if (entity instanceof LotPersonneDroits) { + Lot lot = ((LotPersonneDroits) entity).getId().getPk1(); + lot = (Lot) session.merge(lot); + super.processWork(lot, id, WorkType.INDEX, event, false); + } else if (entity instanceof CampagnePersonneDroits) { + Campagne campagne = ((CampagnePersonneDroits) entity).getId().getPk1(); + campagne = (Campagne) session.merge(campagne); + super.processWork(campagne, id, WorkType.INDEX, event, false); + } + } +} Property changes on: trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/search/IndexEventListener.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/search/LotPersonneBridge.java =================================================================== --- trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/search/LotPersonneBridge.java (rev 0) +++ trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/search/LotPersonneBridge.java 2013-03-04 11:33:07 UTC (rev 168) @@ -0,0 +1,67 @@ +package nc.ird.cantharella.data.model.search; + +/* + * #%L + * Cantharella :: Data + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2010 - 2013 IRD (Institut de Recherche pour le Developpement) and by respective authors (see below) + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * #L% + */ + +import nc.ird.cantharella.data.model.Lot; +import nc.ird.cantharella.data.model.LotPersonneDroits; +import nc.ird.cantharella.data.model.Personne; +import nc.ird.cantharella.data.model.utils.CompositeId; + +import org.apache.lucene.document.Document; +import org.apache.lucene.document.Field; +import org.hibernate.search.bridge.FieldBridge; +import org.hibernate.search.bridge.LuceneOptions; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Hibernate search can't index CompositeId by himself. + * + * To index right on entities, we add a field "droit.pk2" containing user + * id, meaning "this user can see this indexed document". + * + * @author Eric Chatellier + */ +public class LotPersonneBridge implements FieldBridge { + + /** Logger */ + private static final Logger LOG = LoggerFactory.getLogger(LotPersonneBridge.class); + + /** {@inheritDoc} */ + @Override + public void set(String name, Object value, Document document, LuceneOptions luceneOptions) { + + LotPersonneDroits lotPersonneDroits = (LotPersonneDroits) value; + if (LOG.isTraceEnabled()) { + LOG.trace("Custom indexing of LotPersonneDroits : " + lotPersonneDroits.getId().getPk1().getIdLot() + "," + + lotPersonneDroits.getId().getPk2().getIdPersonne()); + } + + CompositeId<Lot, Personne> compositeId = lotPersonneDroits.getId(); + + // commons information for all produit + document.add(new Field("droit.pk2", String.valueOf(compositeId.getPk2().getIdPersonne()), luceneOptions + .getStore(), luceneOptions.getIndex(), luceneOptions.getTermVector())); + } +} Property changes on: trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/search/LotPersonneBridge.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Modified: trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/search/ProduitBridge.java =================================================================== --- trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/search/ProduitBridge.java 2013-03-04 11:31:56 UTC (rev 167) +++ trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/search/ProduitBridge.java 2013-03-04 11:33:07 UTC (rev 168) @@ -23,24 +23,29 @@ * #L% */ +import java.util.List; + +import nc.ird.cantharella.data.model.CampagnePersonneDroits; import nc.ird.cantharella.data.model.Extrait; import nc.ird.cantharella.data.model.Fraction; +import nc.ird.cantharella.data.model.Lot; +import nc.ird.cantharella.data.model.LotPersonneDroits; import nc.ird.cantharella.data.model.Produit; import nc.ird.cantharella.data.model.ResultatTestBio; import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.hibernate.search.bridge.FieldBridge; import org.hibernate.search.bridge.LuceneOptions; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * {@link ResultatTestBio} class contains a polymorphic entity that can't be * properly indexed by hibernate search. * - * @author echatellier + * @author Eric Chatellier */ public class ProduitBridge implements FieldBridge { @@ -52,68 +57,57 @@ public void set(String name, Object value, Document document, LuceneOptions luceneOptions) { Produit produit = (Produit) value; - if (LOG.isDebugEnabled()) { - LOG.debug("Custom indexing of Produit entity : " + produit); + if (LOG.isTraceEnabled()) { + LOG.trace("Custom indexing of Produit entity : " + produit); } // commons information for all produit - document.add(new Field("ref", produit.getRef(), luceneOptions.getStore(), luceneOptions.getIndex(), - luceneOptions.getTermVector())); + //document.add(new Field("produit.ref", produit.getRef(), luceneOptions.getStore(), luceneOptions.getIndex(), + // luceneOptions.getTermVector())); + Lot lot = null; if (produit instanceof Extrait) { - if (LOG.isDebugEnabled()) { - LOG.debug("Custom indexing of Extrait entity"); + if (LOG.isTraceEnabled()) { + LOG.trace("Custom indexing of Extrait entity"); } Extrait extrait = (Extrait) produit; - document.add(new Field("extraction.lot.ref", extrait.getExtraction().getLot().getRef(), luceneOptions - .getStore(), luceneOptions.getIndex(), luceneOptions.getTermVector())); - document.add(new Field("extraction.lot.specimen.embranchement", extrait.getExtraction().getLot() - .getSpecimenRef().getEmbranchement(), luceneOptions.getStore(), luceneOptions.getIndex(), - luceneOptions.getTermVector())); - if (StringUtils.isNotBlank(extrait.getExtraction().getLot().getSpecimenRef().getFamille())) { - document.add(new Field("extraction.lot.specimen.famille", extrait.getExtraction().getLot() - .getSpecimenRef().getFamille(), luceneOptions.getStore(), luceneOptions.getIndex(), - luceneOptions.getTermVector())); - } - if (StringUtils.isNotBlank(extrait.getExtraction().getLot().getSpecimenRef().getGenre())) { - document.add(new Field("extraction.lot.specimen.genre", extrait.getExtraction().getLot() - .getSpecimenRef().getGenre(), luceneOptions.getStore(), luceneOptions.getIndex(), luceneOptions - .getTermVector())); - } - if (StringUtils.isNotBlank(extrait.getExtraction().getLot().getSpecimenRef().getEspece())) { - document.add(new Field("extraction.lot.specimen.expece", extrait.getExtraction().getLot() - .getSpecimenRef().getEspece(), luceneOptions.getStore(), luceneOptions.getIndex(), - luceneOptions.getTermVector())); - } - document.add(new Field("extraction.lot.campagne.nom", extrait.getExtraction().getLot().getCampagne() - .getNom(), luceneOptions.getStore(), luceneOptions.getIndex(), luceneOptions.getTermVector())); + lot = extrait.getExtraction().getLot(); } else if (produit instanceof Fraction) { - if (LOG.isDebugEnabled()) { - LOG.debug("Custom indexing of Fraction entity"); + if (LOG.isTraceEnabled()) { + LOG.trace("Custom indexing of Fraction entity"); } Fraction fraction = (Fraction) produit; - document.add(new Field("purification.lotSource.ref", fraction.getPurification().getLotSource().getRef(), + lot = fraction.getPurification().getLotSource(); + } + + document.add(new Field("produit.lot.ref", lot.getRef(), luceneOptions.getStore(), luceneOptions.getIndex(), + luceneOptions.getTermVector())); + document.add(new Field("produit.lot.speciment.embranchement", lot.getSpecimenRef().getEmbranchement(), + luceneOptions.getStore(), luceneOptions.getIndex(), luceneOptions.getTermVector())); + if (StringUtils.isNotBlank(lot.getSpecimenRef().getFamille())) { + document.add(new Field("produit.lot.speciment.famille", lot.getSpecimenRef().getFamille(), luceneOptions + .getStore(), luceneOptions.getIndex(), luceneOptions.getTermVector())); + } + if (StringUtils.isNotBlank(lot.getSpecimenRef().getGenre())) { + document.add(new Field("produit.lot.speciment.genre", lot.getSpecimenRef().getGenre(), luceneOptions + .getStore(), luceneOptions.getIndex(), luceneOptions.getTermVector())); + } + if (StringUtils.isNotBlank(lot.getSpecimenRef().getEspece())) { + document.add(new Field("produit.lot.speciment.expece", lot.getSpecimenRef().getEspece(), luceneOptions + .getStore(), luceneOptions.getIndex(), luceneOptions.getTermVector())); + } + document.add(new Field("produit.lot.campagne.nom", lot.getCampagne().getNom(), luceneOptions.getStore(), + luceneOptions.getIndex(), luceneOptions.getTermVector())); + + // commons information for all produit + List<LotPersonneDroits> personnesDroits = lot.getPersonnesDroits(); + for (LotPersonneDroits lotPersonneDroit : personnesDroits) { + document.add(new Field("droit.pk2", String.valueOf(lotPersonneDroit.getId().getPk2().getIdPersonne()), luceneOptions.getStore(), luceneOptions.getIndex(), luceneOptions.getTermVector())); - document.add(new Field("purification.lotSource.speciment.embranchement", fraction.getPurification() - .getLotSource().getSpecimenRef().getEmbranchement(), luceneOptions.getStore(), luceneOptions - .getIndex(), luceneOptions.getTermVector())); - if (StringUtils.isNotBlank(fraction.getPurification().getLotSource().getSpecimenRef().getFamille())) { - document.add(new Field("purification.lotSource.speciment.famille", fraction.getPurification() - .getLotSource().getSpecimenRef().getFamille(), luceneOptions.getStore(), luceneOptions - .getIndex(), luceneOptions.getTermVector())); - } - if (StringUtils.isNotBlank(fraction.getPurification().getLotSource().getSpecimenRef().getGenre())) { - document.add(new Field("purification.lotSource.speciment.genre", fraction.getPurification() - .getLotSource().getSpecimenRef().getGenre(), luceneOptions.getStore(), - luceneOptions.getIndex(), luceneOptions.getTermVector())); - } - if (StringUtils.isNotBlank(fraction.getPurification().getLotSource().getSpecimenRef().getEspece())) { - document.add(new Field("purification.lotSource.speciment.expece", fraction.getPurification() - .getLotSource().getSpecimenRef().getEspece(), luceneOptions.getStore(), luceneOptions - .getIndex(), luceneOptions.getTermVector())); - } - document.add(new Field("purification.lotSource.campagne.nom", fraction.getPurification().getLotSource() - .getCampagne().getNom(), luceneOptions.getStore(), luceneOptions.getIndex(), luceneOptions - .getTermVector())); } + List<CampagnePersonneDroits> campagnesDroits = lot.getCampagne().getPersonnesDroits(); + for (CampagnePersonneDroits campagnesDroit : campagnesDroits) { + document.add(new Field("droit.pk2", String.valueOf(campagnesDroit.getId().getPk2().getIdPersonne()), + luceneOptions.getStore(), luceneOptions.getIndex(), luceneOptions.getTermVector())); + } } } Modified: trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/search/UtilisateurSearchFilter.java =================================================================== --- trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/search/UtilisateurSearchFilter.java 2013-03-04 11:31:56 UTC (rev 167) +++ trunk/cantharella.data/src/main/java/nc/ird/cantharella/data/model/search/UtilisateurSearchFilter.java 2013-03-04 11:33:07 UTC (rev 168) @@ -43,7 +43,7 @@ * Filtre lucene utilisé par hibernate search pour filtrer les resultats * suivant l'utilisateur connecté. * - * @author echatellier + * @author Eric Chatellier */ public class UtilisateurSearchFilter extends Filter { @@ -96,7 +96,7 @@ LOG.debug("Filtering term docs for administrator"); } // all docs - for (int idx = 0; idx < bitSet.length(); idx++) { + for (int idx = 0; idx < reader.maxDoc(); idx++) { if (!reader.isDeleted(idx)) { bitSet.set(idx); } @@ -105,12 +105,23 @@ if (LOG.isDebugEnabled()) { LOG.debug("Filtering term docs for utilisateur"); } - // only docs matching terms - TermDocs termDocs = reader.termDocs(new Term("createur.idPersonne", String.valueOf(utilisateur + // only docs where user is creator + TermDocs termDocsCreateur = reader.termDocs(new Term("createur.idPersonne", String.valueOf(utilisateur .getIdPersonne()))); - while (termDocs.next()) { - bitSet.set(termDocs.doc()); + while (termDocsCreateur.next()) { + if (!reader.isDeleted(termDocsCreateur.doc())) { + bitSet.set(termDocsCreateur.doc()); + } } + + // and docs where user has rights on + TermDocs termDocsDroits = reader + .termDocs(new Term("droit.pk2", String.valueOf(utilisateur.getIdPersonne()))); + while (termDocsDroits.next()) { + if (!reader.isDeleted(termDocsCreateur.doc())) { + bitSet.set(termDocsDroits.doc()); + } + } } return bitSet; Modified: trunk/cantharella.data/src/main/resources/META-INF/services/org.hibernate.integrator.spi.Integrator =================================================================== --- trunk/cantharella.data/src/main/resources/META-INF/services/org.hibernate.integrator.spi.Integrator 2013-03-04 11:31:56 UTC (rev 167) +++ trunk/cantharella.data/src/main/resources/META-INF/services/org.hibernate.integrator.spi.Integrator 2013-03-04 11:33:07 UTC (rev 168) @@ -1 +1,2 @@ -nc.ird.cantharella.data.config.ValidationIntegrator \ No newline at end of file +nc.ird.cantharella.data.config.ValidationIntegrator +nc.ird.cantharella.data.config.HibernateSearchIntegrator \ No newline at end of file Modified: trunk/cantharella.service/src/main/java/nc/ird/cantharella/service/services/LotService.java =================================================================== --- trunk/cantharella.service/src/main/java/nc/ird/cantharella/service/services/LotService.java 2013-03-04 11:31:56 UTC (rev 167) +++ trunk/cantharella.service/src/main/java/nc/ird/cantharella/service/services/LotService.java 2013-03-04 11:33:07 UTC (rev 168) @@ -25,8 +25,6 @@ import java.util.List; import java.util.SortedSet; -import org.springframework.transaction.annotation.Transactional; - import nc.ird.cantharella.data.exceptions.DataConstraintException; import nc.ird.cantharella.data.exceptions.DataNotFoundException; import nc.ird.cantharella.data.model.Lot; @@ -37,6 +35,8 @@ import nc.ird.cantharella.service.utils.normalizers.UniqueFieldNormalizer; import nc.ird.cantharella.service.utils.normalizers.utils.Normalize; +import org.springframework.transaction.annotation.Transactional; + /** * Service : lots * @author Mickael Tricot @@ -51,6 +51,12 @@ long countLots(); /** + * Rafraichit un lot (pour éviter des LazyLoadingException) + * @param lot Lot + */ + void refreshLot(Lot lot); + + /** * Créée un lot * @param lot Lot * @throws DataConstraintException Si le lot (nom) existe déjà Modified: trunk/cantharella.service/src/main/java/nc/ird/cantharella/service/services/impl/LotServiceImpl.java =================================================================== --- trunk/cantharella.service/src/main/java/nc/ird/cantharella/service/services/impl/LotServiceImpl.java 2013-03-04 11:31:56 UTC (rev 167) +++ trunk/cantharella.service/src/main/java/nc/ird/cantharella/service/services/impl/LotServiceImpl.java 2013-03-04 11:33:07 UTC (rev 168) @@ -27,6 +27,8 @@ import java.util.SortedSet; import java.util.TreeSet; +import javax.annotation.Resource; + import nc.ird.cantharella.data.dao.GenericDao; import nc.ird.cantharella.data.exceptions.DataConstraintException; import nc.ird.cantharella.data.exceptions.DataNotFoundException; @@ -39,6 +41,10 @@ import nc.ird.cantharella.service.services.LotService; import nc.ird.cantharella.utils.AssertTools; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.search.FullTextSession; +import org.hibernate.search.Search; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -59,6 +65,10 @@ @Autowired private GenericDao dao; + /** Hibernate session factory. */ + @Resource + private SessionFactory sessionFactory; + /** {@inheritDoc} */ @Override public long countLots() { @@ -67,6 +77,13 @@ /** {@inheritDoc} */ @Override + public void refreshLot(Lot lot) { + AssertTools.assertNotNull(lot); + dao.refresh(lot); + } + + /** {@inheritDoc} */ + @Override public void createLot(Lot lot) throws DataConstraintException { LOG.info("createLot " + lot.getRef()); dao.create(lot); @@ -198,12 +215,17 @@ @Override public void updateLot(Lot lot) throws DataConstraintException { LOG.info("updateLot " + lot.getRef()); - try { - dao.update(lot); - } catch (DataNotFoundException e) { + //try { + dao.merge(lot); + + Session session = sessionFactory.getCurrentSession(); + FullTextSession fullTextSession = Search.getFullTextSession(session); + fullTextSession.index(lot); + + /*} catch (DataNotFoundException e) { LOG.error(e.getMessage(), e); throw new UnexpectedException(e); - } + }*/ } /** {@inheritDoc} */ Modified: trunk/cantharella.service/src/main/java/nc/ird/cantharella/service/services/impl/SearchServiceImpl.java =================================================================== --- trunk/cantharella.service/src/main/java/nc/ird/cantharella/service/services/impl/SearchServiceImpl.java 2013-03-04 11:31:56 UTC (rev 167) +++ trunk/cantharella.service/src/main/java/nc/ird/cantharella/service/services/impl/SearchServiceImpl.java 2013-03-04 11:33:07 UTC (rev 168) @@ -116,7 +116,7 @@ // passer les tests pour que les indexes lucene contiennent des données // nécéssaire car il ne sont écrits que lorsque Spring commmit la // transaction (c'est à dire jamais dans les tests) - fullTextSession.flushToIndexes(); + //fullTextSession.flushToIndexes(); //fullTextSession.setFlushMode(FlushMode.MANUAL); //fullTextSession.setCacheMode(CacheMode.IGNORE); @@ -206,7 +206,7 @@ String fieldName = fieldInfos.fieldName(i); // il semble impossible de ne pas recuperer l'id du document // on l'exclut donc manuellement - if (!fieldName.startsWith("id") && !fieldName.contains(".id")) { + if (!fieldName.startsWith("id") && !fieldName.contains(".id") && !fieldName.endsWith(".pk2")) { fieldList.add(fieldInfos.fieldName(i)); } } Modified: trunk/cantharella.web/src/main/java/nc/ird/cantharella/web/pages/domain/utilisateur/ManageUtilisateurPage.java =================================================================== --- trunk/cantharella.web/src/main/java/nc/ird/cantharella/web/pages/domain/utilisateur/ManageUtilisateurPage.java 2013-03-04 11:31:56 UTC (rev 167) +++ trunk/cantharella.web/src/main/java/nc/ird/cantharella/web/pages/domain/utilisateur/ManageUtilisateurPage.java 2013-03-04 11:33:07 UTC (rev 168) @@ -39,7 +39,11 @@ import nc.ird.cantharella.data.validation.utils.ModelValidator; import nc.ird.cantharella.service.exceptions.EmailException; import nc.ird.cantharella.service.services.CampagneService; +import nc.ird.cantharella.service.services.LotService; import nc.ird.cantharella.service.services.PersonneService; +import nc.ird.cantharella.utils.BeanTools; +import nc.ird.cantharella.utils.BeanTools.AccessType; +import nc.ird.cantharella.utils.CollectionTools; import nc.ird.cantharella.web.pages.TemplatePage; import nc.ird.cantharella.web.pages.domain.personne.panels.ManagePersonnePanel; import nc.ird.cantharella.web.pages.model.ManageUtilisateurModel; @@ -50,13 +54,8 @@ import nc.ird.cantharella.web.utils.renderers.EnumChoiceRenderer; import nc.ird.cantharella.web.utils.security.AuthRole; import nc.ird.cantharella.web.utils.security.AuthRoles; -import nc.ird.cantharella.utils.BeanTools; -import nc.ird.cantharella.utils.BeanTools.AccessType; -import nc.ird.cantharella.utils.CollectionTools; import org.apache.commons.collections.comparators.ComparatorChain; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.apache.wicket.AttributeModifier; import org.apache.wicket.MarkupContainer; import org.apache.wicket.ajax.AjaxRequestTarget; @@ -76,6 +75,8 @@ import org.apache.wicket.model.Model; import org.apache.wicket.model.PropertyModel; import org.apache.wicket.spring.injection.annot.SpringBean; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Gestion d'un utilisateur par un admin @@ -119,6 +120,10 @@ @SpringBean private CampagneService campagneService; + /** Service : lot */ + @SpringBean + private LotService lotService; + /** Modèle : droits sur un lot, en cours de saisie */ private final IModel<LotPersonneDroits> lotsPersonneDroitsModel; @@ -295,8 +300,10 @@ throw new UnexpectedException(e); } // Recharge la campagne pour éviter une LazyLoadingException - campagneService.refreshCampagne(droits.getId().getPk1()); - manageUtilisateurModel.getObject().getCampagnesDroits().put(droits.getId().getPk1(), droits); + Campagne campagne = droits.getId().getPk1(); + campagneService.refreshCampagne(campagne); + manageUtilisateurModel.getObject().getCampagnesDroits().put(campagne, droits); + campagne.getPersonnesDroits().add(droits); // puisque droits sur Campagne-Tous, suppression des Campagne-Lot de cette campagne // Se base sur le réf de lot plutôt que l'objet pour être indépendant du contexte de persistance @@ -314,7 +321,11 @@ LOG.error(e.getMessage(), e); throw new UnexpectedException(e); } - manageUtilisateurModel.getObject().getLotsDroits().put(droits.getId().getPk1(), droits); + Lot lot = droits.getId().getPk1(); + // Evite une LazyLoadingException car la campagne n'est plus dans la session + lotService.refreshLot(lot); + manageUtilisateurModel.getObject().getLotsDroits().put(lot, droits); + lot.getPersonnesDroits().add(droits); } // Mise à jour des listes updateAvailableCampagnes();