Project

General

Profile

Download (7.55 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
* Copyright (C) 2018 EDIT
3
* European Distributed Institute of Taxonomy
4
* http://www.e-taxonomy.eu
5
*
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.
8
*/
9
package eu.etaxonomy.cdm.persistence.hibernate;
10

    
11
import java.lang.reflect.Constructor;
12
import java.lang.reflect.InvocationTargetException;
13
import java.util.HashMap;
14
import java.util.Map;
15

    
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;
22

    
23
import eu.etaxonomy.cdm.config.CdmHibernateListenerConfiguration;
24
import eu.etaxonomy.cdm.model.name.NomenclaturalSource;
25
import eu.etaxonomy.cdm.model.name.TaxonName;
26

    
27
/**
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}
31
 *
32
 * @see <a href=
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}
36
 *
37
 * @author a.kohlbecker
38
 * @since Sep 27, 2018
39
 *
40
 */
41
public class TaxonGraphHibernateListener implements ITaxonGraphHibernateListener {
42

    
43
    private static final long serialVersionUID = 5062518307839173935L;
44

    
45
    private Map<Class<? extends BeforeTransactionCompletionProcess>, ProcessConstructorData<? extends BeforeTransactionCompletionProcess>> beforeTransactionCompletionProcessTypes = new HashMap<>();
46

    
47
    @Override
48
    public void registerProcessClass(Class<? extends BeforeTransactionCompletionProcess> processClass, Object[] constructorArgs, Class<?>[] paramterTypes) throws NoSuchMethodException, SecurityException{
49
        if(constructorArgs == null){
50
            constructorArgs = new Object[]{};
51
        }
52
       beforeTransactionCompletionProcessTypes.put(processClass, new ProcessConstructorData(processClass, constructorArgs, paramterTypes));
53
    }
54

    
55
    @Override
56
    public void unRegisterProcessClass(Class<? extends BeforeTransactionCompletionProcess> processClass){
57
        beforeTransactionCompletionProcessTypes.remove(processClass);
58
    }
59

    
60
    @Override
61
    public void onPostUpdate(PostUpdateEvent event) {
62

    
63
        if(event.getEntity() instanceof TaxonName || event.getEntity() instanceof NomenclaturalSource){
64
            for(Class<? extends BeforeTransactionCompletionProcess> type : beforeTransactionCompletionProcessTypes.keySet()){
65
                try {
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);
72
                }
73
            }
74
        }
75
    }
76

    
77
    @Override
78
    public void onPostInsert(PostInsertEvent event) {
79

    
80
        if(event.getEntity() instanceof TaxonName || event.getEntity() instanceof NomenclaturalSource){
81
            for(Class<? extends BeforeTransactionCompletionProcess> type : beforeTransactionCompletionProcessTypes.keySet()){
82
                try {
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);
89
                }
90
            }
91
        }
92
    }
93

    
94
    @Override
95
    public boolean onPreDelete(PreDeleteEvent event) {
96

    
97
        if(event.getEntity() instanceof TaxonName || event.getEntity() instanceof NomenclaturalSource){
98
            for(Class<? extends BeforeTransactionCompletionProcess> type : beforeTransactionCompletionProcessTypes.keySet()){
99
                try {
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);
106
                }
107
            }
108
        }
109
        return false; // no veto
110
    }
111

    
112
    @Override
113
    public boolean requiresPostCommitHanding(EntityPersister persister) {
114
        return true;
115
    }
116

    
117
    class ProcessConstructorData<T extends BeforeTransactionCompletionProcess> {
118

    
119
        Constructor<T> postInsertEventConstructor;
120
        Constructor<T> postUpdateEventConstructor;
121
        Constructor<T> preDeleteEventConstructor;
122
        Object[] constructorArgs;
123

    
124
        public ProcessConstructorData(Class<T> type, Object[] constructorArgs, Class<?>[] paramterTypes) throws NoSuchMethodException, SecurityException {
125

    
126
            this.constructorArgs = constructorArgs;
127

    
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;
134
            int i = 1;
135
            for(Class<?> ptype : paramterTypes){
136
                postInsertEventConstructorArgTypes[i] = ptype;
137
                postUpdateEventConstructorArgTypes[i] = ptype;
138
                preDeleteEventConstructorArgTypes[i] = ptype;
139
            }
140
            postInsertEventConstructor = type.getConstructor(postInsertEventConstructorArgTypes);
141
            postUpdateEventConstructor = type.getConstructor(postUpdateEventConstructorArgTypes);
142
            preDeleteEventConstructor = type.getConstructor(preDeleteEventConstructorArgTypes);
143
        }
144

    
145
        public Object[] buildConstructorArgs(Object firstArg){
146
            Object[] cargs = new Object[constructorArgs.length + 1];
147
            cargs[0] = firstArg;
148
            int i = 1;
149
            for(Object arg : constructorArgs){
150
                cargs[i++] = arg;
151
            }
152
            return cargs;
153
        }
154
    }
155
}
(19-19/21)