• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

IQSS / dataverse / #22002

01 Apr 2024 07:56PM CUT coverage: 20.716% (+0.5%) from 20.173%
#22002

push

github

web-flow
Merge pull request #10453 from IQSS/develop

Merge 6.2 into master

704 of 2679 new or added lines in 152 files covered. (26.28%)

81 existing lines in 49 files now uncovered.

17160 of 82836 relevant lines covered (20.72%)

0.21 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/main/java/edu/harvard/iq/dataverse/DvObjectServiceBean.java
1
package edu.harvard.iq.dataverse;
2

3
import edu.harvard.iq.dataverse.authorization.users.AuthenticatedUser;
4
import edu.harvard.iq.dataverse.pidproviders.PidProvider;
5
import edu.harvard.iq.dataverse.pidproviders.PidProviderFactoryBean;
6
import edu.harvard.iq.dataverse.pidproviders.PidUtil;
7
import java.sql.Timestamp;
8
import java.util.ArrayList;
9
import java.util.Date;
10
import java.util.HashMap;
11
import java.util.List;
12
import java.util.Map;
13
import java.util.Set;
14
import java.util.logging.Level;
15
import java.util.logging.Logger;
16

17
import jakarta.ejb.EJB;
18
import jakarta.ejb.Stateless;
19
import jakarta.ejb.TransactionAttribute;
20
import static jakarta.ejb.TransactionAttributeType.REQUIRES_NEW;
21
import jakarta.inject.Named;
22
import jakarta.persistence.EntityManager;
23
import jakarta.persistence.NoResultException;
24
import jakarta.persistence.NonUniqueResultException;
25
import jakarta.persistence.PersistenceContext;
26
import jakarta.persistence.Query;
27
import jakarta.persistence.StoredProcedureQuery;
28

29
import org.apache.commons.lang3.StringUtils;
30

31
/**
32
 * Your goto bean for everything {@link DvObject}, that's not tied to any
33
 * concrete subclass.
34
 *
35
 * @author michael
36
 */
37
@Stateless
38
@Named
39
public class DvObjectServiceBean implements java.io.Serializable {
×
40

41
    @PersistenceContext(unitName = "VDCNet-ejbPU")
42
    private EntityManager em;
43
    
44
    @EJB
45
    PidProviderFactoryBean pidProviderFactoryBean;
46
    
UNCOV
47
    private static final Logger logger = Logger.getLogger(DvObjectServiceBean.class.getCanonicalName());
×
48
    /**
49
     * @param dvoc The object we check
50
     * @return {@code true} iff the passed object is the owner of any
51
     * {@link DvObject}.
52
     */
53
    public boolean hasData(DvObjectContainer dvoc) {
54
        return em.createNamedQuery("DvObject.ownedObjectsById", Long.class)
×
55
                .setParameter("id", dvoc.getId())
×
56
                .getSingleResult() > 0;
×
57
    }
58

59
    public DvObject findDvObject(Long id) {
60
        try {
61
            return em.createNamedQuery("DvObject.findById", DvObject.class)
×
62
                    .setParameter("id", id)
×
63
                    .getSingleResult();
×
64
        } catch (NoResultException | NonUniqueResultException ex) {
×
65
            return null;
×
66
        }
67
    }
68

69
    public List<DvObject> findAll() {
70
        return em.createNamedQuery("DvObject.findAll", DvObject.class).getResultList();
×
71
    }
72
    
73
    
74
    public List<DvObject> findByOwnerId(Long ownerId) {
75
        return em.createNamedQuery("DvObject.findByOwnerId").setParameter("ownerId", ownerId).getResultList();
×
76
    }
77
    
78
    public List<DvObject> findByAuthenticatedUserId(AuthenticatedUser user) {
79
        Query query = em.createNamedQuery("DvObject.findByAuthenticatedUserId"); 
×
80
        query.setParameter("ownerId", user.getId());
×
81
        query.setParameter("releaseUserId", user.getId());
×
82
        return query.getResultList();
×
83
    }
84
    
85
    public boolean checkExists(Long id) {
86
        Query query = em.createNamedQuery("DvObject.checkExists");
×
87
        query.setParameter("id", id);
×
88
        Long result =(Long)query.getSingleResult();
×
89
        return result > 0;
×
90
    }   
91

92
    public DvObject findByGlobalId(String globalIdString, DvObject.DType dtype) {
93
        try {
94
            GlobalId gid = PidUtil.parseAsGlobalID(globalIdString);
×
95
            return findByGlobalId(gid, dtype);
×
96
        } catch (IllegalArgumentException iae) {
×
97
            logger.fine("Invalid identifier: " + globalIdString);
×
98
            return null;
×
99
        }
100

101
    }
102
    
103
    public DvObject findByAltGlobalId(String globalIdString, DvObject.DType dtype) {
104
        try {
105
            GlobalId gid = PidUtil.parseAsGlobalID(globalIdString);
×
106
            return findByAltGlobalId(gid, dtype);
×
107
        } catch (IllegalArgumentException iae) {
×
108
            logger.fine("Invalid alternate identifier: " + globalIdString);
×
109
            return null;
×
110
        }
111

112
    }
113

114
    public DvObject findByGlobalId(GlobalId globalId, DvObject.DType dtype) {
115
        Query query = em.createNamedQuery("DvObject.findByGlobalId");
×
116
        return runFindByGlobalId(query, globalId, dtype);
×
117
    }
118

119
    public DvObject findByAltGlobalId(GlobalId globalId, DvObject.DType dtype) {
120
        Query query = em.createNamedQuery("DvObject.findByAlternativeGlobalId");
×
121
        return runFindByGlobalId(query, globalId, dtype);
×
122
    }
123

124
    public Long findIdByGlobalId(GlobalId globalId, DvObject.DType dtype) {
125
        Query query = em.createNamedQuery("DvObject.findIdByGlobalId");
×
126
        return runFindIdByGlobalId(query, globalId, dtype);
×
127
    }
128

129
    public Long findIdByAltGlobalId(GlobalId globalId, DvObject.DType dtype) {
130
        Query query = em.createNamedQuery("DvObject.findIdByAlternativeGlobalId");
×
131
        return runFindIdByGlobalId(query, globalId, dtype);
×
132
    }
133

134
    private DvObject runFindByGlobalId(Query query, GlobalId gid, DvObject.DType dtype) {
135
        DvObject foundDvObject = null;
×
136
        try {
137
            query.setParameter("identifier", gid.getIdentifier());
×
138
            query.setParameter("protocol", gid.getProtocol());
×
139
            query.setParameter("authority", gid.getAuthority());
×
140
            query.setParameter("dtype", dtype.getDType());
×
141
            foundDvObject = (DvObject) query.getSingleResult();
×
142
        } catch (NoResultException e) {
×
143
            // (set to .info, this can fill the log file with thousands of
144
            // these messages during a large harvest run)
145
            logger.fine("no dvObject found: " + gid.asString());
×
146
            // DO nothing, just return null.
147
            return null;
×
148
        } catch (Exception ex) {
×
149
            logger.info("Exception caught in findByGlobalId: " + ex.getLocalizedMessage());
×
150
            return null;
×
151
        }
×
152
        return foundDvObject;
×
153
    }
154

155
    private Long runFindIdByGlobalId(Query query, GlobalId gid, DvObject.DType dtype) {
156
        Long foundDvObject = null;
×
157
        try {
158
            query.setParameter("identifier", gid.getIdentifier());
×
159
            query.setParameter("protocol", gid.getProtocol());
×
160
            query.setParameter("authority", gid.getAuthority());
×
161
            query.setParameter("dtype", dtype.getDType());
×
162
            foundDvObject = (Long) query.getSingleResult();
×
163
        } catch (NoResultException e) {
×
164
            // (set to .info, this can fill the log file with thousands of
165
            // these messages during a large harvest run)
166
            logger.fine("no dvObject found: " + gid.asString());
×
167
            // DO nothing, just return null.
168
            return null;
×
169
        } catch (Exception ex) {
×
170
            logger.info("Exception caught in findByGlobalId: " + ex.getLocalizedMessage());
×
171
            return null;
×
172
        }
×
173
        return foundDvObject;
×
174
    }
175
    
176
    public DvObject findByGlobalId(GlobalId globalId) {
177
        try {
178
            return (DvObject) em.createNamedQuery("DvObject.findByProtocolIdentifierAuthority")
×
179
                    .setParameter("identifier", globalId.getIdentifier())
×
180
                    .setParameter("authority", globalId.getAuthority()).setParameter("protocol", globalId.getProtocol())
×
181
                    .getSingleResult();
×
182
        } catch (NoResultException nre) {
×
183
            return null;
×
184
        }
185
    }
186
    
187
    public boolean isGlobalIdLocallyUnique(GlobalId globalId) {
188
        return em.createNamedQuery("DvObject.findByProtocolIdentifierAuthority")
×
189
            .setParameter("identifier", globalId.getIdentifier())
×
190
            .setParameter("authority", globalId.getAuthority())
×
191
            .setParameter("protocol", globalId.getProtocol())
×
192
            .getResultList().isEmpty();
×
193
    }
194

195
    public DvObject updateContentIndexTime(DvObject dvObject) {
196
        /**
197
         * @todo to avoid a possible OptimisticLockException, should we merge
198
         * dvObject before we try to setIndexTime? See
199
         * https://github.com/IQSS/dataverse/commit/6ad0ebb272c8cb46368cb76784b55dbf33eea947
200
         */
201
        DvObject dvObjectToModify = findDvObject(dvObject.getId());
×
202
        dvObjectToModify.setIndexTime(new Timestamp(new Date().getTime()));
×
203
        DvObject savedDvObject = em.merge(dvObjectToModify);
×
204
        return savedDvObject;
×
205
    }
206

207
    /**
208
     * @param dvObject
209
     * @return 
210
     * @todo DRY! Perhaps we should merge this with the older
211
     * updateContentIndexTime method.
212
     */
213
    public DvObject updatePermissionIndexTime(DvObject dvObject) {
214
        /**
215
         * @todo to avoid a possible OptimisticLockException, should we merge
216
         * dvObject before we try to set this timestamp? See
217
         * https://github.com/IQSS/dataverse/commit/6ad0ebb272c8cb46368cb76784b55dbf33eea947
218
         */
219
        Long dvObjectId = dvObject.getId();
×
220
        DvObject dvObjectToModify = findDvObject(dvObjectId);
×
221
        if (dvObjectToModify == null) {
×
222
            logger.log(Level.FINE, "Unable to update permission index time on DvObject with id of {0}", dvObjectId);
×
223
            return dvObject;
×
224
        }
225
        dvObjectToModify.setPermissionIndexTime(new Timestamp(new Date().getTime()));
×
226
        DvObject savedDvObject = em.merge(dvObjectToModify);
×
227
        logger.log(Level.FINE, "Updated permission index time for DvObject id {0}", dvObjectId);
×
228
        return savedDvObject;
×
229
    }
230

231
    @TransactionAttribute(REQUIRES_NEW)
232
    public int clearAllIndexTimes() {
233
        Query clearIndexTimes = em.createQuery("UPDATE DvObject o SET o.indexTime = NULL, o.permissionIndexTime = NULL");
×
234
        int numRowsUpdated = clearIndexTimes.executeUpdate();
×
235
        return numRowsUpdated;
×
236
    }
237

238
    public int clearIndexTimes(long dvObjectId) {
239
        Query clearIndexTimes = em.createQuery("UPDATE DvObject o SET o.indexTime = NULL, o.permissionIndexTime = NULL WHERE o.id =:dvObjectId");
×
240
        clearIndexTimes.setParameter("dvObjectId", dvObjectId);
×
241
        int numRowsUpdated = clearIndexTimes.executeUpdate();
×
242
        return numRowsUpdated;
×
243
    }
244
    
245
    private String getDvObjectIdListClause(List<Long> dvObjectIdList){
246
        if (dvObjectIdList == null){
×
247
            return null;
×
248
        }
249
        List<String> outputList = new ArrayList<>();
×
250
        
251
        for(Long id : dvObjectIdList){
×
252
            if (id != null){
×
253
                outputList.add(id.toString());
×
254
            }
255
        }
×
256
        if (outputList.isEmpty()){
×
257
            return null;
×
258
        }        
259
        return " (" + StringUtils.join(outputList, ",") + ")";        
×
260
    }
261
    
262
    public List<Object[]> getDvObjectInfoForMyData(List<Long> dvObjectIdList){
263
        //msgt("getAssigneeAndRoleIdListFor");
264

265
        String dvObjectClause = getDvObjectIdListClause(dvObjectIdList);
×
266
        if (dvObjectClause==null){
×
267
            return null;
×
268
        }
269
        
270
        String qstr = "SELECT dv.id, dv.dtype, dv.owner_id"; // dv.modificationtime,
×
271
        qstr += " FROM dvobject dv";
×
272
        qstr += " WHERE  dv.id IN " + dvObjectClause;
×
273
        qstr += ";";
×
274

275
        return em.createNativeQuery(qstr).getResultList();
×
276
        
277
    }
278
    
279
    /**
280
     * Used for retrieving DvObject based on a list of parent Ids
281
     *  MyData use case: The Dataverse has file permissions and we want to know 
282
     *  the Datasets under that Dataverse (and subsequently query files by
283
     *  their parent id--but in solr)
284
     * 
285
     * @param dvObjectParentIdList
286
     * @return 
287
     */
288
    public List<Object[]> getDvObjectInfoByParentIdForMyData(List<Long> dvObjectParentIdList){
289
        //msgt("getAssigneeAndRoleIdListFor");
290

291
        String dvObjectClause = getDvObjectIdListClause(dvObjectParentIdList);
×
292
        if (dvObjectClause==null){
×
293
            return null;
×
294
        }
295
        
296
        String qstr = "SELECT dv.id, dv.dtype, dv.owner_id"; // dv.modificationtime,
×
297
        qstr += " FROM dvobject dv";
×
298
        qstr += " WHERE  dv.owner_id IN " + dvObjectClause;
×
299
        qstr += ";";
×
300

301
        return em.createNativeQuery(qstr).getResultList();
×
302
        
303
    }
304
    
305
    /**
306
     * Used to exclude Harvested Data from the Mydata page
307
     * 
308
     * @return 
309
     */
310
    public List<Long> getAllHarvestedDataverseIds(){
311
        
312
        String qstr = "SELECT h.dataverse_id FROM harvestingclient h;";
×
313

314
        return em.createNativeQuery(qstr).getResultList();
×
315
        
316
    }
317
    
318
    /**
319
     * Used to calculate the dvObject tree paths for the search results on the
320
     * dataverse page. (In order to determine if "linked" or not).
321
     * *done in recursive 1 query!*
322
     * 
323
     * @param objectIds
324
     * @return 
325
     */
326
    public Map<Long, String> getObjectPathsByIds(Set<Long> objectIds){
327
        if (objectIds == null || objectIds.size() < 1) {
×
328
            return null;
×
329
        }
330
        
331
        String datasetIdStr = StringUtils.join(objectIds, ", ");
×
332
        
333
        String qstr = "WITH RECURSIVE path_elements AS ((" +
×
334
            " SELECT id, owner_id FROM dvobject WHERE id in (" + datasetIdStr + "))" +
335
            " UNION\n" +
336
            " SELECT o.id, o.owner_id FROM path_elements p, dvobject o WHERE o.id = p.owner_id) " +
337
            "SELECT id, owner_id FROM path_elements WHERE owner_id IS NOT NULL;"; // ORDER by id ASC;";
338
        
339
        List<Object[]> searchResults;
340
        
341
        try {
342
            searchResults = em.createNativeQuery(qstr).getResultList();
×
343
        } catch (Exception ex) {
×
344
            searchResults = null;
×
345
        }
×
346
        
347
        if (searchResults == null || searchResults.size() < 1) {
×
348
            return null;
×
349
        }
350
        
351
        Map<Long, Long> treeMap = new HashMap<>();
×
352
        
353
        for (Object[] result : searchResults) {
×
354
            Long objectId;
355
            Long ownerId;
356
            if (result[0] != null) {
×
357
                try {
358
                    objectId = ((Integer) result[0]).longValue();
×
359
                } catch (Exception ex) {
×
360
                    logger.warning("OBJECT PATH: could not cast result[0] (dvobject id) to Integer!");
×
361
                    objectId = null;
×
362
                }
×
363
                if (objectId == null) {
×
364
                    continue;
×
365
                }
366
                
367
                ownerId = (Long)result[1];
×
368
                logger.fine("OBJECT PATH: id: "+objectId+", owner: "+ownerId);
×
369
                if (ownerId != null && (ownerId != 1L)) {
×
370
                    treeMap.put(objectId, ownerId);
×
371
                }
372
            }
373
        }
×
374
        
375
        Map<Long, String> ret = new HashMap<>();
×
376
        
377
        for (Long objectId : objectIds) {
×
378
            String treePath = "/" + objectId;
×
379
            Long treePosition = treeMap.get(objectId);
×
380
            
381
            while (treePosition != null) {
×
382
                treePath = "/" + treePosition + treePath;
×
383
                treePosition = treeMap.get(treePosition);
×
384
            }
385
            
386
            logger.fine("OBJECT PATH: returning "+treePath+" for "+objectId);
×
387
            ret.put(objectId, treePath);
×
388
        }
×
389
        return ret;        
×
390
    }
391
    
392
    public String generateNewIdentifierByStoredProcedure() {
393
        StoredProcedureQuery query = this.em.createNamedStoredProcedureQuery("Dataset.generateIdentifierFromStoredProcedure");
×
394
        query.execute();
×
395
        return (String) query.getOutputParameterValue(1);
×
396
    }
397
    
398
    /** @deprecated Backward-compatibility method to get the effective pid generator for a DvObjectContainer.
399
     * If the dvObjectContainer method fails, this method will check for the old global default settings.
400
     * If/when those are no longer supported, this method can be removed and replaced with calls directly 
401
     * to dvObjectContainer.getEffectivePidGenerator();
402
     * 
403
     */
404
    @Deprecated(forRemoval = true, since = "2024-02-09")
405
    public PidProvider getEffectivePidGenerator(DvObjectContainer dvObjectContainer) {
NEW
406
        PidProvider pidGenerator = dvObjectContainer.getEffectivePidGenerator();
×
NEW
407
        if (pidGenerator == null) {
×
NEW
408
            pidGenerator = pidProviderFactoryBean.getDefaultPidGenerator();
×
409
        }
NEW
410
        return pidGenerator;
×
411
    }
412
    
413
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc