Project

General

Profile

Download (9.32 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
* Copyright (C) 2015 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.util.List;
12

    
13
import org.hibernate.event.spi.PreInsertEvent;
14
import org.hibernate.event.spi.PreInsertEventListener;
15
import org.hibernate.event.spi.PreUpdateEvent;
16
import org.hibernate.event.spi.PreUpdateEventListener;
17
import org.joda.time.DateTime;
18
import org.springframework.security.core.Authentication;
19
import org.springframework.security.core.context.SecurityContextHolder;
20

    
21
import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
22
import eu.etaxonomy.cdm.model.common.CdmBase;
23
import eu.etaxonomy.cdm.model.common.ICdmBase;
24
import eu.etaxonomy.cdm.model.common.ITreeNode;
25
import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
26
import eu.etaxonomy.cdm.model.common.VersionableEntity;
27
import eu.etaxonomy.cdm.model.molecular.Amplification;
28
import eu.etaxonomy.cdm.model.name.TaxonName;
29
import eu.etaxonomy.cdm.model.occurrence.DeterminationEvent;
30
import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
31
import eu.etaxonomy.cdm.model.permission.User;
32
import eu.etaxonomy.cdm.model.reference.Reference;
33

    
34
/**
35
 * @author cmathew
36
 * @since 7 Jul 2015
37
 */
38
public class CdmPreDataChangeListener
39
        implements PreInsertEventListener, PreUpdateEventListener {
40

    
41
    private static final long serialVersionUID = -7581071903134036209L;
42

    
43
    @Override
44
    public boolean onPreUpdate(PreUpdateEvent event) {
45
        try {
46
            Object entity = event.getEntity();
47
            if (VersionableEntity.class.isAssignableFrom(entity.getClass())) {
48
                VersionableEntity versionableEntity = (VersionableEntity)entity;
49
                versionableEntity.setUpdated(new DateTime());
50
                Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
51
                if(authentication != null && authentication.getPrincipal() != null && authentication.getPrincipal() instanceof User) {
52
                    User user = (User)authentication.getPrincipal();
53
                    versionableEntity.setUpdatedBy(user);
54
                }
55
            }
56
            insertUpdateMerge(event.getEntity());
57
        } finally {
58
            return false;
59
        }
60
    }
61

    
62
    @Override
63
    public boolean onPreInsert(PreInsertEvent event) {
64
        try {
65
            Object entity = event.getEntity();
66
            Class<?> entityClazz = entity.getClass();
67
            if(ICdmBase.class.isAssignableFrom(entityClazz)) {
68
                ICdmBase cdmBase = (ICdmBase)entity;
69

    
70
                if (cdmBase.getCreated() == null){
71
                    cdmBase.setCreated(new DateTime());
72
                }
73
                if(cdmBase.getCreatedBy() == null) {
74
                    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
75
                    if(authentication != null && authentication.getPrincipal() != null && authentication.getPrincipal() instanceof User) {
76
                        User user = (User)authentication.getPrincipal();
77
                        cdmBase.setCreatedBy(user);
78
                    }
79
                }
80
            }
81
            insertUpdateMerge(entity);
82
        } finally {
83
            //TODO AM: why do we always return false? How to test if this could be changed. Are there exceptions swallowed this way?
84
            return false;
85
        }
86
    }
87

    
88
    //from former SaveOrUpdateEntityListener
89
    public void insertUpdateMerge(Object entity){
90
        if(entity != null && CdmBase.class.isAssignableFrom(entity.getClass())){
91
            cacheDeterminationNames(entity);
92
            generateCaches(entity);
93
            //moved to CdmPreDataChangeListener
94
            if (entity instanceof ITreeNode) {
95
                    ITreeNode<?> node = (ITreeNode<?>)entity;
96
                    reindex(node);
97
                }
98
        }
99
    }
100

    
101
    static String sep = ITreeNode.separator;
102
    static String pref = ITreeNode.treePrefix;
103

    
104
    private <T extends ITreeNode> void reindex(T node) {
105
        String oldChildIndex = node.treeIndex();
106
        ITreeNode<?> parent = node.getParent();
107
        String parentIndex = (parent == null) ? (sep + pref + node.treeId() + sep)  : parent.treeIndex();  //TODO
108
        if (node.getId() > 0){   //TODO
109
            String newChildIndex = parentIndex + node.getId() + sep;
110
            if (oldChildIndex == null || ! oldChildIndex.equals(newChildIndex)){
111
                node.setTreeIndex(newChildIndex);
112

    
113
                //TODO this is a greedy implementation, better use update by replace string
114
                //either using and improving the below code or by using native SQL
115
                //The current approach may run out of memory for large descendant sets.
116
                List<T> childNodes = node.getChildNodes();
117
                for (T child : childNodes){
118
                    if (child != null && ! child.equals(node)){  //node should not be it's own child, however just in case
119
                        reindex(child);
120
                    }
121
                }
122

    
123
                //          String className = event.getEntityName();
124
                //                  String updateQuery = " UPDATE %s tn " +
125
                //                          " SET tn.treeIndex = Replace(tn.treeIndex, '%s', '%s') " +
126
                //                          " WHERE tn.id <> "+ node.getId()+" ";
127
                //                  updateQuery = String.format(updateQuery, className, oldChildIndex, parentIndex);  //dummy
128
                //                  System.out.println(updateQuery);
129
                //                  EventSource session = event.getSession();
130
                //                  Query query = session.createQuery(updateQuery);
131
                //                  query.executeUpdate();
132
            }
133
        }
134
    }
135

    
136
    private static void cacheDeterminationNames(Object entity) {
137
        if (entity instanceof DeterminationEvent) {
138
            DeterminationEvent detEv = (DeterminationEvent)entity;
139
            if (detEv.getTaxon() != null && detEv.getTaxonName() == null && detEv.getTaxon().getName() != null){
140
                detEv.setTaxonName(detEv.getTaxon().getName());
141
            }
142
        }
143
    }
144

    
145
    //TODO shouldn't we use the "updateCaches" method instead?
146
    public static void generateCaches(Object entity){
147
        if (entity != null){
148
            entity = CdmBase.deproxy(entity);
149
            Class<?> entityClazz = entity.getClass();
150

    
151
            if (IdentifiableEntity.class.isAssignableFrom(entityClazz)){
152
                IdentifiableEntity<?> identifiableEntity = (IdentifiableEntity<?>)entity;
153
                if(TaxonName.class.isAssignableFrom(entityClazz)) {
154
                    //non-viral-name caches  (was NonViralName)
155
                    TaxonName nonViralName = (TaxonName)entity;
156
                    nonViralName.getAuthorshipCache();
157
                    nonViralName.getNameCache();
158
                    nonViralName.getTitleCache();
159
                    nonViralName.getFullTitleCache();
160
                }else if(TeamOrPersonBase.class.isAssignableFrom(entityClazz)){
161
                    //team-or-person caches
162
                    TeamOrPersonBase<?> teamOrPerson = (TeamOrPersonBase<?>)entity;
163
                    teamOrPerson.getNomenclaturalTitleCache();
164
                    teamOrPerson.getCollectorTitleCache();
165
                    String titleCache = teamOrPerson.getTitleCache();
166
                    //not sure if this is really needed
167
                    if (! teamOrPerson.isProtectedTitleCache()){
168
                        teamOrPerson.setTitleCache(titleCache, false);
169
                    }
170
                    //if the above is changed in future, change also in ImportDeduplicationHelper
171
                }else if(Reference.class.isAssignableFrom(entityClazz)){
172
                    //reference caches
173
                    Reference ref = (Reference)entity;
174
                    ref.getAbbrevTitleCache();
175
                    ref.getTitleCache();
176
                }else if (SpecimenOrObservationBase.class.isAssignableFrom(entityClazz)){
177
                    //specimen
178
                    SpecimenOrObservationBase<?> specimen = (SpecimenOrObservationBase<?>)entity;
179
                    if (!specimen.isProtectedTitleCache()){
180
                        specimen.setTitleCache(specimen.generateTitle(), false);
181
                    }
182
                //any other
183
                }   else{
184
                   // identifiableEntity.setTitleCache(identifiableEntity.generateTitle(), identifiableEntity.isProtectedTitleCache());
185
                    identifiableEntity.getTitleCache();
186
                }
187

    
188
                //titleCache should never be empty, even if protected #5763, #5849
189
                if (identifiableEntity.isProtectedTitleCache() && identifiableEntity.hasEmptyTitleCache()){
190
                    identifiableEntity.setTitleCache(null, false);
191
                    identifiableEntity.getTitleCache();
192
                }
193
                if (identifiableEntity.hasEmptyTitleCache()){
194
                    identifiableEntity.setTitleCache(identifiableEntity.toString(), false);
195
                }
196
            }else if(Amplification.class.isAssignableFrom(entityClazz)) {
197
                Amplification amplification = (Amplification)entity;
198
                amplification.updateCache();
199
            }
200
        }
201
    }
202
}
(9-9/21)