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