Project

General

Profile

Revision a38e2585

IDa38e2585039171f028d1ca790949860b74f852be
Parent aa8405de
Child a38340e1

Added by Andreas Kohlbecker about 1 month ago

fix #7862 full documentation on TaxonGraphHibernateListener, TaxonGraphBeforeTransactionCompleteProcess etc.

View differences:

cdmlib-persistence/src/main/java/eu/etaxonomy/cdm/config/CdmHibernateListenerConfiguration.java
19 19
import eu.etaxonomy.cdm.persistence.hibernate.TaxonGraphHibernateListener;
20 20

  
21 21
/**
22
 * Spring configuration to provide the {@link TaxonGraphHibernateListener} bean.
23
 * This configuration can be activated by adding {@code @CdmHibernateListener}
24
 * to a java spring configuration see
25
 * <code>eu.etaxonomy.cdm.addon.config.CdmVaadinConfiguration</code> in <a href=
26
 * "https://github.com/cybertaxonomy/cdm-vaadin">https://github.com/cybertaxonomy/cdm-vaadin</a>
27
 * for an example.
28
 *
29
 * @see {@link CdmHibernateListener}
30
 * @see <a href=
31
 *      "https://dev.e-taxonomy.eu/redmine/issues/7648">https://dev.e-taxonomy.eu/redmine/issues/7648</a>
32
 *
22 33
 * @author a.kohlbecker
23 34
 * @since Oct 10, 2018
24 35
 *
cdmlib-persistence/src/main/java/eu/etaxonomy/cdm/persistence/dao/hibernate/taxonGraph/AbstractHibernateTaxonGraphProcessor.java
31 31
import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;
32 32
import eu.etaxonomy.cdm.persistence.dao.hibernate.common.CdmPreferenceLookup;
33 33
import eu.etaxonomy.cdm.persistence.dao.taxonGraph.TaxonGraphException;
34
import eu.etaxonomy.cdm.persistence.hibernate.TaxonGraphHibernateListener;
34 35

  
35 36
/**
37
 * Provides the business logic to manage multiple classifications as
38
 * classification fragments in a graph of
39
 * {@link eu.etaxonomy.cdm.model.taxon.Taxon Taxa} and
40
 * {@link eu.etaxonomy.cdm.model.taxon.TaxonRelationship TaxonRelationships}.
41
 * <p>
42
 * This abstract class provides the base for
43
 * {@link eu.etaxonomy.cdm.api.service.taxonGraph.TaxonGraphBeforeTransactionCompleteProcess}
44
 * and {@link TaxonGraphDaoHibernateImpl} which both are operating on the persisted
45
 * graph structures and thus are sharing this business logic in common:
46
 * <ul>
47
 * <li><code>TaxonGraphBeforeTransactionCompleteProcess</code>: Manages the
48
 * graph and is the only class allowed to modify it.</li>
49
 * <li><code>TaxonGraphDaoHibernateImpl</code>: Provides read only access to the
50
 * graph structure.</li>
51
 * <ul>
52
 * <p>
53
 * The conceptual idea for the resulting graph is described in <a href=
54
 * "https://dev.e-taxonomy.eu/redmine/issues/6173#6-N1T-Higher-taxon-graphs-with-includedIn-relations-taxon-relationships">#6173
55
 * 6) [N1T] Higher taxon-graphs with includedIn relations taxon
56
 * relationships}</a> The
57
 * <code>TaxonGraphBeforeTransactionCompleteProcess</code> is instantiated and
58
 * used in the {@link TaxonGraphHibernateListener}
59
 *
36 60
 * @author a.kohlbecker
37 61
 * @since Oct 4, 2018
38 62
 *
......
91 115
        }
92 116
    }
93 117

  
118
    /**
119
     * Provides the sec reference for all taxa in the graph. The Reference uuid
120
     * is expected to be stored in the CDM perferences under the preference key
121
     * {@link TaxonGraphDaoHibernateImpl#CDM_PREF_KEY_SEC_REF_UUID}
122
     *
123
     *
124
     * @return The reference for all taxa in the graph
125
     */
94 126
    public Reference secReference(){
95 127
        if(secReference == null){
96 128
            Query q = getSession().createQuery("SELECT r FROM Reference r WHERE r.uuid = :uuid");
......
118 150

  
119 151

  
120 152
    /**
121
     * Create all missing edges from the <code>taxon</code>.
153
     * Create all missing edges from the <code>taxon</code> to names with higher
154
     * rank and edges from names with lower rank to this taxon. No longer needed
155
     * relations (edges) are removed.
122 156
     *
123
     * @param taxonName
157
     * @param taxon
158
     *            The taxon to update the edges for.
124 159
     */
125 160
    public void updateEdges(Taxon taxon) throws TaxonGraphException {
126 161

  
......
219 254

  
220 255
    abstract public Session getSession();
221 256

  
257
    /**
258
     * Same as {@link #assureSingleTaxon(TaxonName, boolean)} with
259
     * <code>createMissing = true</code>
260
     */
222 261
    public Taxon assureSingleTaxon(TaxonName taxonName) throws TaxonGraphException {
223 262
        return assureSingleTaxon(taxonName, true);
224 263
    }
225 264

  
265
    /**
266
     * Assurers that there is only one {@link Taxon} for the given name
267
     * (<code>taxonName</code>) having the the default sec reference
268
     * ({@link #getSecReferenceUUID()}).
269
     * <p>
270
     * If there is no such taxon it will be created when
271
     * <code>createMissing=true</code>. A <code>TaxonGraphException</code> is
272
     * thrown when more than one taxa with the default sec reference
273
     * ({@link #getSecReferenceUUID()}) are found for the given name
274
     * (<code>taxonName</code>)
275
     *
276
     * @param taxonName
277
     *            The name to check
278
     * @param createMissing
279
     *            A missing taxon is created when this is <code>true</code>.
280
     * @return
281
     * @throws TaxonGraphException
282
     *             A <code>TaxonGraphException</code> is thrown when more than
283
     *             one taxa with the default sec reference
284
     *             ({@link #getSecReferenceUUID()}) are found for the given name
285
     *             (<code>taxonName</code>)
286
     */
226 287
    public Taxon assureSingleTaxon(TaxonName taxonName, boolean createMissing) throws TaxonGraphException {
227 288

  
228 289
        UUID secRefUuid = getSecReferenceUUID();
cdmlib-persistence/src/main/java/eu/etaxonomy/cdm/persistence/dao/hibernate/taxonGraph/TaxonGraphDaoHibernateImpl.java
28 28
import eu.etaxonomy.cdm.persistence.dao.taxonGraph.ITaxonGraphDao;
29 29
import eu.etaxonomy.cdm.persistence.dao.taxonGraph.TaxonGraphException;
30 30
import eu.etaxonomy.cdm.persistence.dto.TaxonGraphEdgeDTO;
31
import eu.etaxonomy.cdm.persistence.hibernate.TaxonGraphHibernateListener;
31 32

  
32
/**Ta
33
 * Provides the business logic to manage multiple classifications as
34
 * classification fragments in a graph of
35
 * {@link eu.etaxonomy.cdm.model.taxon.Taxon Taxa} and {@link eu.etaxonomy.cdm.model.taxon.TaxonRelationship TaxonRelationships}.
36
 *
37
 * For further details on the concept and related discussion see https://dev.e-taxonomy.eu/redmine/issues/6173
33
/**
34
 * Implementation of the abstract {@link AbstractHibernateTaxonGraphProcessor}
35
 * business logic to provide a <b>purely read only access</b> to graphs
36
 * consisting of {@link eu.etaxonomy.cdm.model.taxon.Taxon Taxa} and
37
 * {@link eu.etaxonomy.cdm.model.taxon.TaxonRelationship TaxonRelationships}.
38
 * These graphs allow for managing classification fragments in a graph
39
 * structure. All <code>write operation</code>, that is all modification of the
40
 * graph is done automatically solely by
41
 * {@link eu.etaxonomy.cdm.api.service.taxonGraph.TaxonGraphBeforeTransactionCompleteProcess}.
42
 * <p>
43
 * The conceptual idea for the resulting graph is described in <a href=
44
 * "https://dev.e-taxonomy.eu/redmine/issues/6173#6-N1T-Higher-taxon-graphs-with-includedIn-relations-taxon-relationships">#6173
45
 * 6) [N1T] Higher taxon-graphs with includedIn relations taxon
46
 * relationships}</a>. The
47
 * <code>TaxonGraphBeforeTransactionCompleteProcess</code> is instantiated and
48
 * used in the {@link TaxonGraphHibernateListener}.
38 49
 *
50
 * 
39 51
 * @author a.kohlbecker
40 52
 * @since Sep 26, 2018
41 53
 */
cdmlib-persistence/src/main/java/eu/etaxonomy/cdm/persistence/hibernate/ITaxonGraphHibernateListener.java
16 16
import org.hibernate.persister.entity.EntityPersister;
17 17

  
18 18
/**
19
 * see https://dev.e-taxonomy.eu/redmine/issues/7648
19
 * Interface for {@link TaxonGraphHibernateListener}.
20
 * Please refer to that class for more information.
20 21
 *
21 22
 * @author a.kohlbecker
22 23
 * @since Oct 10, 2018
cdmlib-persistence/src/main/java/eu/etaxonomy/cdm/persistence/hibernate/TaxonGraphHibernateListener.java
19 19
import org.hibernate.event.spi.PostUpdateEvent;
20 20
import org.hibernate.persister.entity.EntityPersister;
21 21

  
22
import eu.etaxonomy.cdm.config.CdmHibernateListenerConfiguration;
22 23
import eu.etaxonomy.cdm.model.name.TaxonName;
23 24

  
24 25
/**
25
 * see https://dev.e-taxonomy.eu/redmine/issues/7648
26
 * The {@code TaxonGraphHibernateListener} it the implementation of the
27
 * according interface. The listener in initially empty and thus will do nothing
28
 * unless configured with the {@link TaxonGraphBeforeTransactionCompleteProces}
29
 *
30
 * @see <a href=
31
 *      "https://dev.e-taxonomy.eu/redmine/issues/7648">https://dev.e-taxonomy.eu/redmine/issues/7648</a>
32
 * @see {@link TaxonGraphBeforeTransactionCompleteProcess}
33
 * @see {@link CdmHibernateListenerConfiguration}
26 34
 *
27 35
 * @author a.kohlbecker
28 36
 * @since Sep 27, 2018
cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/taxonGraph/TaxonGraphBeforeTransactionCompleteProcess.java
23 23
import org.hibernate.event.spi.PostUpdateEvent;
24 24

  
25 25
import eu.etaxonomy.cdm.api.application.IRunAs;
26
import eu.etaxonomy.cdm.config.CdmHibernateListenerConfiguration;
26 27
import eu.etaxonomy.cdm.model.name.TaxonName;
27 28
import eu.etaxonomy.cdm.model.reference.Reference;
28 29
import eu.etaxonomy.cdm.model.taxon.Taxon;
30
import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
29 31
import eu.etaxonomy.cdm.persistence.dao.hibernate.taxonGraph.AbstractHibernateTaxonGraphProcessor;
30 32
import eu.etaxonomy.cdm.persistence.dao.taxonGraph.TaxonGraphException;
33
import eu.etaxonomy.cdm.persistence.hibernate.TaxonGraphHibernateListener;
31 34

  
32 35
/**
33
 * see https://dev.e-taxonomy.eu/redmine/issues/7648
36
 * A {@link BeforeTransactionCompletionProcess} implementation which manages
37
 * graphs of taxon relationships automatically. The graph consists of nodes
38
 * ({@link Taxon}) and edges ({@link TaxonRelationship}) where the taxa all have
39
 * the same {@link Taxon#getSec() sec reference}. The concept reference of a
40
 * classification is being projected onto the edge
41
 * ({@link TaxonRelationship}) having that reference as
42
 * {@link TaxonRelationship#getSource() TaxonRelationship.source.citation}.
43
 * <p>
44
 * The conceptual idea for the resulting graph is described in <a href=
45
 * "https://dev.e-taxonomy.eu/redmine/issues/6173#6-N1T-Higher-taxon-graphs-with-includedIn-relations-taxon-relationships">#6173
46
 * 6) [N1T] Higher taxon-graphs with includedIn relations taxon
47
 * relationships}</a> The
48
 * <code>TaxonGraphBeforeTransactionCompleteProcess</code> is instantiated and
49
 * used in the {@link TaxonGraphHibernateListener}
50
 * <p>
51
 * To activate this <code>BeforeTransactionCompletionProcess</code> class it needs to be registered at the
52
 * {@link TaxonGraphHibernateListener} like:
53
 * {@code taxonGraphHibernateListener.registerProcessClass(TaxonGraphBeforeTransactionCompleteProcess.class); }
54
 * <p>
55
 * On insert, update and delete events a new temporary session is being created
56
 * ({@link {@link #createTempSession(SessionImplementor)} to create, remove or
57
 * modify the nodes ({@link Taxon}) and edges ({@link TaxonRelationship}) of the
58
 * graph. The events on which the graph is modified are (see method descriptions
59
 * for more details on the processes being performed):
60
 * <ul>
61
 * <li>Change of a name or a names rank
62
 * ({@link #onNameOrRankChange(TaxonName)})</li>
63
 * <li>Creation of a new name ({@link #onNewTaxonName(TaxonName)})</li>
64
 * <li>Change of a nomenclatural reference
65
 * ({@link #onNomReferenceChange(TaxonName, Reference)})</li>
66
 *
67
 *
68
 * @see {@link TaxonGraphHibernateListener}
69
 * @see {@link CdmHibernateListenerConfiguration}
70
 * @see <a href=
71
 *      "https://dev.e-taxonomy.eu/redmine/issues/7648">https://dev.e-taxonomy.eu/redmine/issues/7648</a>
34 72
 *
35 73
 * @author a.kohlbecker
36 74
 * @since Sep 26, 2018
......
171 209
    }
172 210

  
173 211
    /**
174
     * Concept of creation of sub-sessions found in AuditProcess.doBeforeTransactionCompletion(SessionImplementor session)
212
     * Concept of creation of sub-sessions found in
213
     * AuditProcess.doBeforeTransactionCompletion(SessionImplementor session)
175 214
     * and adapted to make it work for this case.
176 215
     *
177 216
     * @param session
......
192 231
        }
193 232
    }
194 233

  
234
    /**
235
     * Same as {@link #onNameOrRankChange(TaxonName)}
236
     */
195 237
    public void onNewTaxonName(TaxonName taxonName) throws TaxonGraphException {
196 238
        onNameOrRankChange(taxonName);
197 239
    }
198 240

  
241
    /**
242
     * Create a taxon with graph sec reference {@link #secReference()) for the
243
     * <code>taxonName</code> if not yet existing and updates the edges
244
     * from and to this taxon by creating missing and removing obsolete ones.
245
     *
246
     * @throws TaxonGraphException
247
     *             A <code>TaxonGraphException</code> is thrown when more than
248
     *             one taxa with the default sec reference
249
     *             ({@link #getSecReferenceUUID()}) are found for the given name
250
     *             (<code>taxonName</code>). Originates from
251
     *             {@link #assureSingleTaxon(TaxonName, boolean)}
252
     */
199 253
    public void onNameOrRankChange(TaxonName taxonName) throws TaxonGraphException {
200 254
        boolean isNotDeleted = parentSession.contains(taxonName) && taxonName.isPersited();
201 255
        // TODO use audit event to check for deletion?
......
215 269
        }
216 270
    }
217 271

  
218

  
272
    /**
273
     * This method manages updates to the edges from and to a taxon which
274
     * reflects the concept reference of the original classification. The
275
     * concept reference of each classification is being projected onto the
276
     * graph as edge ({@link TaxonRelationship}) having that reference as
277
     * {@link TaxonRelationship#getSource() TaxonRelationship.source.citation}.
278
     * <p>
279
     * Delegates to {@link #onNewTaxonName(TaxonName)} in case the
280
     * <code>oldNomReference</code> is <code>null</code>. Otherwise the
281
     * {@link #assureSingleTaxon(TaxonName)} check is performed to create the
282
     * taxon if missing and the concept reference in the edges
283
     * <code>source</code> field is finally updated.
284
     *
285
     * @param taxonName
286
     *   The updated taxon name having a new nomenclatural reference
287
     * @param oldNomReference
288
     *   The nomenclatural reference as before the update of the <code>taxonName</code>
289
     * @throws TaxonGraphException
290
     *             A <code>TaxonGraphException</code> is thrown when more than
291
     *             one taxa with the default sec reference
292
     *             ({@link #getSecReferenceUUID()}) are found for the given name
293
     *             (<code>taxonName</code>). Originates from
294
     *             {@link #assureSingleTaxon(TaxonName, boolean)}
295
     */
219 296
    public void onNomReferenceChange(TaxonName taxonName, Reference oldNomReference) throws TaxonGraphException {
220 297
        if(oldNomReference == null){
221 298
            onNewTaxonName(taxonName);
cdmlib-services/src/test/java/eu/etaxonomy/cdm/api/service/taxonGraph/TaxonGraphHibernateListenerTest.java
46 46
import eu.etaxonomy.cdm.test.unitils.CleanSweepInsertLoadStrategy;
47 47

  
48 48
/**
49
 * Tests the business logic of {@link TaxonGraphBeforeTransactionCompleteProcess}.
50
 *
49 51
 * @author a.kohlbecker
50 52
 * @since Oct 1, 2018
51 53
 */

Also available in: Unified diff

Add picture from clipboard (Maximum size: 40 MB)