Project

General

Profile

Download (9.98 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.Team;
22
import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
23
import eu.etaxonomy.cdm.model.common.CdmBase;
24
import eu.etaxonomy.cdm.model.common.ICdmBase;
25
import eu.etaxonomy.cdm.model.common.ITreeNode;
26
import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
27
import eu.etaxonomy.cdm.model.common.VersionableEntity;
28
import eu.etaxonomy.cdm.model.molecular.Amplification;
29
import eu.etaxonomy.cdm.model.name.TaxonName;
30
import eu.etaxonomy.cdm.model.occurrence.DeterminationEvent;
31
import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
32
import eu.etaxonomy.cdm.model.permission.User;
33
import eu.etaxonomy.cdm.model.reference.Reference;
34

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

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

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

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

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

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

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

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

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

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

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

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

    
152
            if (IdentifiableEntity.class.isAssignableFrom(entityClazz)){
153
                IdentifiableEntity<?> identifiableEntity = (IdentifiableEntity<?>)entity;
154
                if(TaxonName.class.isAssignableFrom(entityClazz)) {
155
                    //non-viral-name caches  (was NonViralName)
156
                    TaxonName nonViralName = (TaxonName)entity;
157
                    nonViralName.getAuthorshipCache();
158
                    nonViralName.getNameCache();
159
                    nonViralName.getTitleCache();
160
                    nonViralName.getFullTitleCache();
161
                }else if(TeamOrPersonBase.class.isAssignableFrom(entityClazz)){
162
                    //team-or-person caches
163
                    TeamOrPersonBase<?> teamOrPerson = (TeamOrPersonBase<?>)entity;
164
                    String nomTitle = teamOrPerson.getNomenclaturalTitleCache();
165
                    if (teamOrPerson instanceof Team){
166
                        Team team = (Team)teamOrPerson;
167
                        //nomTitle is not necessarily cached when it is created
168
                        team.setNomenclaturalTitleCache(nomTitle, team.isProtectedNomenclaturalTitleCache());
169
                        String collectorCache = team.getCollectorTitleCache();
170
                        if (! team.isProtectedCollectorTitleCache()){
171
                            team.setCollectorTitleCache(collectorCache, false);
172
                        }
173
                    }else{
174
                        teamOrPerson.setNomenclaturalTitle(nomTitle);
175
                    }
176
                    String titleCache = teamOrPerson.getTitleCache();
177
                    if (! teamOrPerson.isProtectedTitleCache()){
178
                        teamOrPerson.setTitleCache(titleCache, false);
179
                    }
180
                    teamOrPerson.getCollectorTitleCache();
181
                    //if this is changed in future, change also in ImportDeduplicationHelper
182
                }else if(Reference.class.isAssignableFrom(entityClazz)){
183
                    //reference caches
184
                    Reference ref = (Reference)entity;
185
                    ref.getAbbrevTitleCache();
186
                    ref.getTitleCache();
187
                }else if (SpecimenOrObservationBase.class.isAssignableFrom(entityClazz)){
188
                    //specimen
189
                    SpecimenOrObservationBase<?> specimen = (SpecimenOrObservationBase<?>)entity;
190
                    if (!specimen.isProtectedTitleCache()){
191
                        specimen.setTitleCache(specimen.generateTitle(), false);
192
                    }
193
                //any other
194
                }   else{
195
                   // identifiableEntity.setTitleCache(identifiableEntity.generateTitle(), identifiableEntity.isProtectedTitleCache());
196
                    identifiableEntity.getTitleCache();
197
                }
198

    
199
                //titleCache should never be empty, even if protected #5763, #5849
200
                if (identifiableEntity.isProtectedTitleCache() && identifiableEntity.hasEmptyTitleCache()){
201
                    identifiableEntity.setTitleCache(null, false);
202
                    identifiableEntity.getTitleCache();
203
                }
204
                if (identifiableEntity.hasEmptyTitleCache()){
205
                    identifiableEntity.setTitleCache(identifiableEntity.toString(), false);
206
                }
207
            }else if(Amplification.class.isAssignableFrom(entityClazz)) {
208
                Amplification amplification = (Amplification)entity;
209
                amplification.updateCache();
210
            }
211
        }
212
    }
213
}
(9-9/21)