Project

General

Profile

Download (14.4 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
* Copyright (C) 2017 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.dao.hibernate.name;
10

    
11
import java.util.Collection;
12
import java.util.Collections;
13
import java.util.HashMap;
14
import java.util.List;
15
import java.util.Map;
16
import java.util.Optional;
17
import java.util.UUID;
18

    
19
import org.apache.commons.lang3.StringUtils;
20
import org.apache.log4j.Logger;
21
import org.hibernate.Query;
22
import org.springframework.stereotype.Repository;
23

    
24
import eu.etaxonomy.cdm.model.name.Registration;
25
import eu.etaxonomy.cdm.model.name.RegistrationStatus;
26
import eu.etaxonomy.cdm.model.reference.Reference;
27
import eu.etaxonomy.cdm.model.reference.ReferenceType;
28
import eu.etaxonomy.cdm.persistence.dao.hibernate.common.AnnotatableDaoImpl;
29
import eu.etaxonomy.cdm.persistence.dao.name.IRegistrationDao;
30
import eu.etaxonomy.cdm.persistence.query.MatchMode;
31
import eu.etaxonomy.cdm.persistence.query.OrderHint;
32

    
33
/**
34
 * @author a.kohlbecker
35
 * @since May 2, 2017
36
 */
37
@Repository
38
public class RegistrationDaoHibernateImpl
39
            extends AnnotatableDaoImpl<Registration>
40
            implements IRegistrationDao {
41

    
42
    @SuppressWarnings("unused")
43
    private static final Logger logger = Logger.getLogger(RegistrationDaoHibernateImpl.class);
44

    
45
    public RegistrationDaoHibernateImpl() {
46
        super(Registration.class);
47
    }
48

    
49
    @Override
50
    public Long count(Optional<Reference> reference, Collection<RegistrationStatus> includedStatus) {
51
        //return 0 for detached volatile references
52
        if (isVolatile(reference)){
53
            return Long.valueOf(0);
54
        }
55
        Query query = makeReferenceQuery(reference, includedStatus, true);
56
        @SuppressWarnings("unchecked")
57
        List<Long> list = query.list();
58
        return list.isEmpty()? Long.valueOf(0) : list.get(0);
59
    }
60

    
61
    @Override
62
    public List<Registration> list(Optional<Reference> reference, Collection<RegistrationStatus> includedStatus,
63
            Integer limit, Integer start, List<String> propertyPaths) {
64

    
65
        if (isVolatile(reference)){
66
            return Collections.emptyList();
67
        }
68

    
69
        Query query = makeReferenceQuery(reference, includedStatus, false);
70

    
71
        // TODO complete ....
72
        if(limit != null /*&&  !doCount*/) {
73
            query.setMaxResults(limit);
74
            if(start != null) {
75
                query.setFirstResult(start);
76
            }
77
        }
78

    
79
        //TODO order hints do not work with queries
80

    
81
        @SuppressWarnings("unchecked")
82
        List<Registration> results = query.list();
83
        defaultBeanInitializer.initializeAll(results, propertyPaths);
84

    
85
        return results;
86
    }
87

    
88
    private boolean isVolatile(Optional<Reference> reference) {
89
        return reference != null && reference.isPresent() && reference.get().getId() == 0;
90
    }
91

    
92
    private Query makeReferenceQuery(Optional<Reference> reference,
93
            Collection<RegistrationStatus> includedStatus,
94
            boolean isCount) {
95

    
96
        String select = "SELECT " + (isCount? " count(DISTINCT r) as cn ": "DISTINCT r ");
97
        String from = " FROM Registration r LEFT JOIN r.typeDesignations desig "
98
                + "     LEFT JOIN r.name n ";
99
        String where = " WHERE (1=1) ";
100
        String orderBy = isCount ? "" : " ORDER BY r.id ";
101

    
102
        ReferenceType refTypeParameter = null;
103

    
104
        if (reference == null){
105
            //do nothing
106
        }else if (reference.isPresent()){
107
           from += "   LEFT JOIN n.nomenclaturalSource nomSource "
108
                   + " LEFT JOIN nomSource.citation nomRef "
109
                   + " LEFT JOIN desig.source desigSource "
110
                   + " LEFT JOIN desigSource.citation desigRef ";
111
           where += " AND ("
112
                   + "     nomRef =:ref "
113
                   + "     OR (nomRef.type =:refType AND nomRef.inReference =:ref) "
114
                   + "     OR desigRef =:ref "
115
                   + "     OR (desigRef.type =:refType AND desigRef.inReference =:ref)"
116
                + ")";
117
           refTypeParameter = ReferenceType.Section;
118
        }else{  //ref is null
119
            from += "   LEFT JOIN n.nomenclaturalSource nomSource "
120
                    + " LEFT JOIN desig.source desigSource ";
121
            where += " AND ((r.name IS NULL AND size(r.typeDesignations) = 0 ) "
122
                   + "     OR (n IS NOT NULL AND (nomSource.citation IS NULL)) "
123
                   + "     OR (size(r.typeDesignations) > 0 AND (desigSource.citation IS NULL))"
124
                   + ") "
125
                   ;
126
        }
127
        boolean hasStatus = includedStatus != null && !includedStatus.isEmpty();
128
        if (hasStatus){
129
            where += " AND r.status IN (:status) ";
130
        }
131

    
132
        String hql = select + from + where + orderBy;
133
        Query query = getSession().createQuery(hql);
134
        if (reference != null && reference.isPresent()){
135
            query.setParameter("ref", reference.get());
136
        }
137
        if(refTypeParameter != null){
138
            query.setParameter("refType", refTypeParameter);
139
        }
140
        if (hasStatus){
141
            query.setParameterList("status", includedStatus);
142
        }
143
        return query;
144
    }
145

    
146
    @Override
147
    public long count(UUID submitterUuid, Collection<RegistrationStatus> includedStatus, String identifierFilterPattern,
148
            String taxonNameFilterPattern, String referenceFilterPattern, Collection<UUID> typeDesignationStatusUuids) {
149
        Query query = makeFilteredSearchQuery(submitterUuid, includedStatus, identifierFilterPattern,
150
                taxonNameFilterPattern, referenceFilterPattern, typeDesignationStatusUuids, true, null);
151
        //Logger.getLogger("org.hibernate.SQL").setLevel(Level.DEBUG);
152
        @SuppressWarnings("unchecked")
153
        List<Long> list = query.list();
154
        //Logger.getLogger("org.hibernate.SQL").setLevel(Level.WARN);
155
        return list.isEmpty()? Long.valueOf(0) : list.get(0);
156
    }
157

    
158
    @Override
159
    public List<Registration> list(UUID submitterUuid, Collection<RegistrationStatus> includedStatus, String identifierFilterPattern,
160
            String taxonNameFilterPattern, String referenceFilterPattern, Collection<UUID> typeDesignationStatusUuids, Integer limit, Integer start,
161
            List<OrderHint> orderHints, List<String> propertyPaths) {
162

    
163
        Query query = makeFilteredSearchQuery(submitterUuid, includedStatus, identifierFilterPattern,
164
                taxonNameFilterPattern, referenceFilterPattern, typeDesignationStatusUuids, false, orderHints);
165

    
166
        if(limit != null /*&&  !doCount*/) {
167
            query.setMaxResults(limit);
168
            if(start != null) {
169
                query.setFirstResult(start);
170
            }
171
        }
172

    
173
        //Logger.getLogger("org.hibernate.SQL").setLevel(Level.DEBUG);
174
        @SuppressWarnings("unchecked")
175
        List<Registration> results = query.list();
176
        //Logger.getLogger("org.hibernate.SQL").setLevel(Level.WARN);
177
        defaultBeanInitializer.initializeAll(results, propertyPaths);
178

    
179
        return results;
180
    }
181

    
182
    @Override
183
    public List<Registration> list(UUID submitterUuid, Collection<RegistrationStatus> includedStatus, Collection<UUID> taxonNameUUIDs,
184
            Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {
185

    
186
        Query query = makeByNameUUIDQuery(submitterUuid, includedStatus, taxonNameUUIDs, false, orderHints);
187

    
188
        if(limit != null /*&&  !doCount*/) {
189
            query.setMaxResults(limit);
190
            if(start != null) {
191
                query.setFirstResult(start);
192
            }
193
        }
194

    
195
        //Logger.getLogger("org.hibernate.SQL").setLevel(Level.DEBUG);
196
        @SuppressWarnings("unchecked")
197
        List<Registration> results = query.list();
198
        //Logger.getLogger("org.hibernate.SQL").setLevel(Level.WARN);
199
        defaultBeanInitializer.initializeAll(results, propertyPaths);
200

    
201
        return results;
202
    }
203

    
204
    @Override
205
    public long count(UUID submitterUuid, Collection<RegistrationStatus> includedStatus, Collection<UUID> taxonNameUUIDs) {
206
        Query query = makeByNameUUIDQuery(submitterUuid, includedStatus, taxonNameUUIDs, true, null);
207
        //Logger.getLogger("org.hibernate.SQL").setLevel(Level.DEBUG);
208
        @SuppressWarnings("unchecked")
209
        List<Long> list = query.list();
210
        //Logger.getLogger("org.hibernate.SQL").setLevel(Level.WARN);
211
        return list.isEmpty()? Long.valueOf(0) : list.get(0);
212
    }
213

    
214
    private Query makeByNameUUIDQuery(UUID submitterUuid, Collection<RegistrationStatus> includedStatus,
215
            Collection<UUID> taxonNameUUIDs, boolean isCount, List<OrderHint> orderHints) {
216

    
217
        Map<String, Object> parameters = new HashMap<>();
218

    
219
        String select = "SELECT " + (isCount? " count(DISTINCT r) as cn ": "DISTINCT r ");
220
        String from = " FROM Registration r "
221
                + "     LEFT JOIN r.typeDesignations desig "
222
                + "     LEFT JOIN r.name n "
223
                + "     LEFT JOIN desig.typifiedNames typifiedNames "
224
                ;
225
        String where = " WHERE (1=1) ";
226
        String orderBy = "";
227
        if(!isCount){
228
            orderBy = orderByClause("r", orderHints).toString();
229
        }
230

    
231
        if(submitterUuid != null){
232
            from += " LEFT JOIN r.submitter submitter "; // without this join hibernate would make a cross join here
233
            where += " AND submitter.uuid =:submitterUuid";
234
            parameters.put("submitterUuid", submitterUuid);
235
        }
236
        if(includedStatus != null && includedStatus.size() > 0) {
237
            where += " AND r.status in (:includedStatus)";
238
            parameters.put("includedStatus", includedStatus);
239
        }
240

    
241
        where += " AND (r.name.uuid in(:nameUUIDs) OR typifiedNames.uuid in(:nameUUIDs))";
242
        parameters.put("nameUUIDs", taxonNameUUIDs);
243

    
244

    
245
        String hql = select + from + where + orderBy;
246
        Query query = getSession().createQuery(hql);
247

    
248
        for(String paramName : parameters.keySet()){
249
            Object value = parameters.get(paramName);
250
            if(value instanceof Collection){
251
                query.setParameterList(paramName, (Collection)value);
252
            } else {
253
                query.setParameter(paramName, value);
254
            }
255
        }
256

    
257
        return query;
258

    
259
    }
260

    
261
    private Query makeFilteredSearchQuery(UUID submitterUuid, Collection<RegistrationStatus> includedStatus,
262
            String identifierFilterPattern, String taxonNameFilterPattern, String referenceFilterPattern,
263
            Collection<UUID> typeDesignationStatusUuids, boolean isCount, List<OrderHint> orderHints) {
264

    
265
        Map<String, Object> parameters = new HashMap<>();
266

    
267
        boolean doNameFilter = StringUtils.isNoneBlank(taxonNameFilterPattern);
268
        boolean doReferenceFilter = StringUtils.isNoneBlank(referenceFilterPattern);
269
        boolean doTypeStatusFilter = typeDesignationStatusUuids != null && typeDesignationStatusUuids.size() > 0;
270

    
271
        String select = "SELECT " + (isCount? " count(DISTINCT r) as cn ": "DISTINCT r ");
272
        String from = " FROM Registration r "
273
                + "     LEFT JOIN r.typeDesignations desig "
274
                + "     LEFT JOIN r.name n "
275
                + (doNameFilter ?  " LEFT JOIN desig.typifiedNames typifiedNames ":"")
276
                + (doTypeStatusFilter ? " LEFT JOIN desig.typeStatus typeStatus":"")  // without this join hibernate would make a cross join here
277
                + (doReferenceFilter
278
                        ?   " LEFT JOIN desig.source typeDesignationSource "
279
                          + " LEFT JOIN typeDesignationSource.citation typeDesignationCitation "
280
                          + " LEFT JOIN n.nomenclaturalSource nomSource "
281
                          + " LEFT JOIN nomSource.citation nomRef "
282
                        : "")
283
            ;
284
        // further JOIN
285
        String where = " WHERE (1=1) ";
286
        String orderBy = "";
287
        if(!isCount){
288
            orderBy = orderByClause("r", orderHints).toString();
289
        }
290

    
291
        if(submitterUuid != null){
292
            from += " LEFT JOIN r.submitter submitter "; // without this join hibernate would make a cross join here
293
            where += " AND submitter.uuid =:submitterUuid";
294
            parameters.put("submitterUuid", submitterUuid);
295
        }
296
        if(includedStatus != null && includedStatus.size() > 0) {
297
            where += " AND r.status in (:includedStatus)";
298
            parameters.put("includedStatus", includedStatus);
299
        }
300
        if(StringUtils.isNoneBlank(identifierFilterPattern)){
301
            where += " AND r.identifier LIKE :identifierFilterPattern";
302
            parameters.put("identifierFilterPattern", MatchMode.ANYWHERE.queryStringFrom(identifierFilterPattern));
303
        }
304
        if(doNameFilter){
305
            where += " AND (r.name.titleCache LIKE :taxonNameFilterPattern OR typifiedNames.titleCache LIKE :taxonNameFilterPattern)";
306
            parameters.put("taxonNameFilterPattern", MatchMode.ANYWHERE.queryStringFrom(taxonNameFilterPattern));
307
        }
308
        if(doReferenceFilter){
309
            where += " AND (typeDesignationCitation.titleCache LIKE :referenceFilterPattern OR nomRef.titleCache LIKE :referenceFilterPattern)";
310
            parameters.put("referenceFilterPattern", MatchMode.ANYWHERE.queryStringFrom(referenceFilterPattern));
311
        }
312
        if(doTypeStatusFilter){
313
            boolean addNullFilter = false;
314
            while(typeDesignationStatusUuids.contains(null)){
315
                addNullFilter = true;
316
                typeDesignationStatusUuids.remove(null);
317
            }
318
            String typeStatusWhere = "";
319
            if(!typeDesignationStatusUuids.isEmpty()){
320
                typeStatusWhere += " typeStatus.uuid in (:typeDesignationStatusUuids)";
321
                parameters.put("typeDesignationStatusUuids", typeDesignationStatusUuids);
322
            }
323
            if(addNullFilter){
324
                typeStatusWhere += (!typeStatusWhere.isEmpty() ? " OR ":"") + "typeStatus is null";
325
            }
326
            where += " AND ( " +  typeStatusWhere + ")";
327
        }
328
        String hql = select + from + where + orderBy;
329
        Query query = getSession().createQuery(hql);
330

    
331
        for(String paramName : parameters.keySet()){
332
            Object value = parameters.get(paramName);
333
            if(value instanceof Collection){
334
                query.setParameterList(paramName, (Collection)value);
335
            } else {
336
                query.setParameter(paramName, value);
337
            }
338
        }
339

    
340
        return query;
341
    }
342
}
(3-3/5)