Merge branch 'release/5.4.0'
[cdmlib.git] / cdmlib-persistence / src / main / java / eu / etaxonomy / cdm / persistence / hibernate / TaxonGraphHibernateListener.java
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.persister.entity.EntityPersister;
21
22 import eu.etaxonomy.cdm.model.name.TaxonName;
23
24 /**
25 * see https://dev.e-taxonomy.eu/redmine/issues/7648
26 *
27 * @author a.kohlbecker
28 * @since Sep 27, 2018
29 *
30 */
31 public class TaxonGraphHibernateListener implements ITaxonGraphHibernateListener {
32
33 private static final long serialVersionUID = 5062518307839173935L;
34
35 private Map<Class<? extends BeforeTransactionCompletionProcess>, ProcessConstructorData<? extends BeforeTransactionCompletionProcess>> beforeTransactionCompletionProcessTypes = new HashMap<>();
36
37 @Override
38 public void registerProcessClass(Class<? extends BeforeTransactionCompletionProcess> processClass, Object[] constructorArgs, Class<?>[] paramterTypes) throws NoSuchMethodException, SecurityException{
39 if(constructorArgs == null){
40 constructorArgs = new Object[]{};
41 }
42 beforeTransactionCompletionProcessTypes.put(processClass, new ProcessConstructorData(processClass, constructorArgs, paramterTypes));
43 }
44
45 @Override
46 public void unRegisterProcessClass(Class<? extends BeforeTransactionCompletionProcess> processClass){
47 beforeTransactionCompletionProcessTypes.remove(processClass);
48 }
49
50 @Override
51 public void onPostUpdate(PostUpdateEvent event) {
52
53 if(event.getEntity() instanceof TaxonName){
54 for(Class<? extends BeforeTransactionCompletionProcess> type : beforeTransactionCompletionProcessTypes.keySet()){
55 try {
56 ProcessConstructorData<? extends BeforeTransactionCompletionProcess> pcd = beforeTransactionCompletionProcessTypes.get(type);
57 BeforeTransactionCompletionProcess processorInstance = pcd.postUpdateEventConstructor.newInstance(pcd.buildConstructorArgs(event));
58 event.getSession().getActionQueue().registerProcess(processorInstance);
59 } catch (InstantiationException | IllegalAccessException | IllegalArgumentException
60 | InvocationTargetException | SecurityException e) {
61 Logger.getLogger(TaxonGraphHibernateListener.class).error("Error creating new instance of " + type.toString(), e);
62 }
63 }
64 }
65 }
66
67 @Override
68 public void onPostInsert(PostInsertEvent event) {
69
70 if(event.getEntity() instanceof TaxonName){
71 for(Class<? extends BeforeTransactionCompletionProcess> type : beforeTransactionCompletionProcessTypes.keySet()){
72 try {
73 ProcessConstructorData<? extends BeforeTransactionCompletionProcess> pcd = beforeTransactionCompletionProcessTypes.get(type);
74 BeforeTransactionCompletionProcess processorInstance = pcd.postInsertEventConstructor.newInstance(pcd.buildConstructorArgs(event));
75 event.getSession().getActionQueue().registerProcess(processorInstance);
76 } catch (InstantiationException | IllegalAccessException | IllegalArgumentException
77 | InvocationTargetException | SecurityException e) {
78 Logger.getLogger(TaxonGraphHibernateListener.class).error("Error creating new instance of " + type.toString(), e);
79 }
80 }
81 }
82 }
83
84 @Override
85 public boolean requiresPostCommitHanding(EntityPersister persister) {
86 return true;
87 }
88
89 class ProcessConstructorData<T extends BeforeTransactionCompletionProcess> {
90
91 Constructor<T> postInsertEventConstructor;
92
93 Constructor<T> postUpdateEventConstructor;
94
95 Object[] constructorArgs;
96 /**
97 * @param constructor
98 * @param constructorArgs
99 */
100 public ProcessConstructorData(Class<T> type, Object[] constructorArgs, Class<?>[] paramterTypes) throws NoSuchMethodException, SecurityException {
101
102 this.constructorArgs = constructorArgs;
103
104 Class<?>[] postInsertEventConstructorArgTypes = new Class<?>[constructorArgs.length + 1];
105 Class<?>[] postUpdateEventConstructorArgTypes = new Class<?>[constructorArgs.length + 1];
106 postInsertEventConstructorArgTypes[0] = PostInsertEvent.class;
107 postUpdateEventConstructorArgTypes[0] = PostUpdateEvent.class;
108 int i = 1;
109 for(Class<?> ptype : paramterTypes){
110 postInsertEventConstructorArgTypes[i] = ptype;
111 postUpdateEventConstructorArgTypes[i] = ptype;
112 }
113 postInsertEventConstructor = type.getConstructor(postInsertEventConstructorArgTypes);
114 postUpdateEventConstructor = type.getConstructor(postUpdateEventConstructorArgTypes);
115 }
116
117 public Object[] buildConstructorArgs(Object firstArg){
118 Object[] cargs = new Object[constructorArgs.length + 1];
119 cargs[0] = firstArg;
120 int i = 1;
121 for(Object arg : constructorArgs){
122 cargs[i++] = arg;
123 }
124 return cargs;
125 }
126
127 }
128
129
130
131 }