2 * Copyright (C) 2018 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
9 package eu
.etaxonomy
.cdm
.persistence
.hibernate
;
11 import java
.lang
.reflect
.Constructor
;
12 import java
.lang
.reflect
.InvocationTargetException
;
13 import java
.util
.HashMap
;
16 import org
.apache
.log4j
.Logger
;
17 import org
.hibernate
.action
.spi
.BeforeTransactionCompletionProcess
;
18 import org
.hibernate
.event
.spi
.PostInsertEvent
;
19 import org
.hibernate
.event
.spi
.PostUpdateEvent
;
20 import org
.hibernate
.event
.spi
.PreDeleteEvent
;
21 import org
.hibernate
.persister
.entity
.EntityPersister
;
23 import eu
.etaxonomy
.cdm
.config
.CdmHibernateListenerConfiguration
;
24 import eu
.etaxonomy
.cdm
.model
.name
.NomenclaturalSource
;
25 import eu
.etaxonomy
.cdm
.model
.name
.TaxonName
;
28 * The {@code TaxonGraphHibernateListener} it the implementation of the
29 * according interface. The listener in initially empty and thus will do nothing
30 * unless configured with the {@link TaxonGraphBeforeTransactionCompleteProces}
33 * "https://dev.e-taxonomy.eu/redmine/issues/7648">https://dev.e-taxonomy.eu/redmine/issues/7648</a>
34 * @see {@link TaxonGraphBeforeTransactionCompleteProcess}
35 * @see {@link CdmHibernateListenerConfiguration}
37 * @author a.kohlbecker
41 public class TaxonGraphHibernateListener
implements ITaxonGraphHibernateListener
{
43 private static final long serialVersionUID
= 5062518307839173935L;
45 private Map
<Class
<?
extends BeforeTransactionCompletionProcess
>, ProcessConstructorData
<?
extends BeforeTransactionCompletionProcess
>> beforeTransactionCompletionProcessTypes
= new HashMap
<>();
48 public void registerProcessClass(Class
<?
extends BeforeTransactionCompletionProcess
> processClass
, Object
[] constructorArgs
, Class
<?
>[] paramterTypes
) throws NoSuchMethodException
, SecurityException
{
49 if(constructorArgs
== null){
50 constructorArgs
= new Object
[]{};
52 beforeTransactionCompletionProcessTypes
.put(processClass
, new ProcessConstructorData(processClass
, constructorArgs
, paramterTypes
));
56 public void unRegisterProcessClass(Class
<?
extends BeforeTransactionCompletionProcess
> processClass
){
57 beforeTransactionCompletionProcessTypes
.remove(processClass
);
61 public void onPostUpdate(PostUpdateEvent event
) {
63 if(event
.getEntity() instanceof TaxonName
|| event
.getEntity() instanceof NomenclaturalSource
){
64 for(Class
<?
extends BeforeTransactionCompletionProcess
> type
: beforeTransactionCompletionProcessTypes
.keySet()){
66 ProcessConstructorData
<?
extends BeforeTransactionCompletionProcess
> pcd
= beforeTransactionCompletionProcessTypes
.get(type
);
67 BeforeTransactionCompletionProcess processorInstance
= pcd
.postUpdateEventConstructor
.newInstance(pcd
.buildConstructorArgs(event
));
68 event
.getSession().getActionQueue().registerProcess(processorInstance
);
69 } catch (InstantiationException
| IllegalAccessException
| IllegalArgumentException
70 | InvocationTargetException
| SecurityException e
) {
71 Logger
.getLogger(TaxonGraphHibernateListener
.class).error("Error creating new instance of " + type
.toString(), e
);
78 public void onPostInsert(PostInsertEvent event
) {
80 if(event
.getEntity() instanceof TaxonName
|| event
.getEntity() instanceof NomenclaturalSource
){
81 for(Class
<?
extends BeforeTransactionCompletionProcess
> type
: beforeTransactionCompletionProcessTypes
.keySet()){
83 ProcessConstructorData
<?
extends BeforeTransactionCompletionProcess
> pcd
= beforeTransactionCompletionProcessTypes
.get(type
);
84 BeforeTransactionCompletionProcess processorInstance
= pcd
.postInsertEventConstructor
.newInstance(pcd
.buildConstructorArgs(event
));
85 event
.getSession().getActionQueue().registerProcess(processorInstance
);
86 } catch (InstantiationException
| IllegalAccessException
| IllegalArgumentException
87 | InvocationTargetException
| SecurityException e
) {
88 Logger
.getLogger(TaxonGraphHibernateListener
.class).error("Error creating new instance of " + type
.toString(), e
);
95 public boolean onPreDelete(PreDeleteEvent event
) {
97 if(event
.getEntity() instanceof TaxonName
|| event
.getEntity() instanceof NomenclaturalSource
){
98 for(Class
<?
extends BeforeTransactionCompletionProcess
> type
: beforeTransactionCompletionProcessTypes
.keySet()){
100 ProcessConstructorData
<?
extends BeforeTransactionCompletionProcess
> pcd
= beforeTransactionCompletionProcessTypes
.get(type
);
101 BeforeTransactionCompletionProcess processorInstance
= pcd
.preDeleteEventConstructor
.newInstance(pcd
.buildConstructorArgs(event
));
102 event
.getSession().getActionQueue().registerProcess(processorInstance
);
103 } catch (InstantiationException
| IllegalAccessException
| IllegalArgumentException
104 | InvocationTargetException
| SecurityException e
) {
105 Logger
.getLogger(TaxonGraphHibernateListener
.class).error("Error creating new instance of " + type
.toString(), e
);
109 return false; // no veto
113 public boolean requiresPostCommitHanding(EntityPersister persister
) {
117 class ProcessConstructorData
<T
extends BeforeTransactionCompletionProcess
> {
119 Constructor
<T
> postInsertEventConstructor
;
120 Constructor
<T
> postUpdateEventConstructor
;
121 Constructor
<T
> preDeleteEventConstructor
;
122 Object
[] constructorArgs
;
124 public ProcessConstructorData(Class
<T
> type
, Object
[] constructorArgs
, Class
<?
>[] paramterTypes
) throws NoSuchMethodException
, SecurityException
{
126 this.constructorArgs
= constructorArgs
;
128 Class
<?
>[] postInsertEventConstructorArgTypes
= new Class
<?
>[constructorArgs
.length
+ 1];
129 Class
<?
>[] postUpdateEventConstructorArgTypes
= new Class
<?
>[constructorArgs
.length
+ 1];
130 Class
<?
>[] preDeleteEventConstructorArgTypes
= new Class
<?
>[constructorArgs
.length
+ 1];
131 postInsertEventConstructorArgTypes
[0] = PostInsertEvent
.class;
132 postUpdateEventConstructorArgTypes
[0] = PostUpdateEvent
.class;
133 preDeleteEventConstructorArgTypes
[0] = PreDeleteEvent
.class;
135 for(Class
<?
> ptype
: paramterTypes
){
136 postInsertEventConstructorArgTypes
[i
] = ptype
;
137 postUpdateEventConstructorArgTypes
[i
] = ptype
;
138 preDeleteEventConstructorArgTypes
[i
] = ptype
;
140 postInsertEventConstructor
= type
.getConstructor(postInsertEventConstructorArgTypes
);
141 postUpdateEventConstructor
= type
.getConstructor(postUpdateEventConstructorArgTypes
);
142 preDeleteEventConstructor
= type
.getConstructor(preDeleteEventConstructorArgTypes
);
145 public Object
[] buildConstructorArgs(Object firstArg
){
146 Object
[] cargs
= new Object
[constructorArgs
.length
+ 1];
149 for(Object arg
: constructorArgs
){