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

IQSS / dataverse / #22540

17 Jun 2024 02:25PM CUT coverage: 20.63% (+0.06%) from 20.574%
#22540

Pull #10543

github

stevenwinship
remove hard coded datasetschema.json and load from file
Pull Request #10543: Improved JSON Schema validation for datasets

66 of 106 new or added lines in 2 files covered. (62.26%)

1 existing line in 1 file now uncovered.

17307 of 83891 relevant lines covered (20.63%)

0.21 hits per line

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

1.72
/src/main/java/edu/harvard/iq/dataverse/DataverseServiceBean.java
1
/*
2
 * To change this license header, choose License Headers in Project Properties.
3
 * To change this template file, choose Tools | Templates
4
 * and open the template in the editor.
5
 */
6
package edu.harvard.iq.dataverse;
7

8
import edu.harvard.iq.dataverse.authorization.AuthenticationServiceBean;
9
import edu.harvard.iq.dataverse.authorization.DataverseRole;
10
import edu.harvard.iq.dataverse.authorization.Permission;
11
import edu.harvard.iq.dataverse.authorization.groups.Group;
12
import edu.harvard.iq.dataverse.authorization.groups.GroupServiceBean;
13
import edu.harvard.iq.dataverse.authorization.users.AuthenticatedUser;
14
import edu.harvard.iq.dataverse.authorization.users.User;
15
import edu.harvard.iq.dataverse.batch.util.LoggingUtil;
16
import edu.harvard.iq.dataverse.dataaccess.ImageThumbConverter;
17
import edu.harvard.iq.dataverse.engine.command.DataverseRequest;
18
import edu.harvard.iq.dataverse.search.IndexServiceBean;
19
import edu.harvard.iq.dataverse.search.SolrIndexServiceBean;
20
import edu.harvard.iq.dataverse.search.SolrSearchResult;
21
import edu.harvard.iq.dataverse.util.BundleUtil;
22
import edu.harvard.iq.dataverse.storageuse.StorageQuota;
23
import edu.harvard.iq.dataverse.util.StringUtil;
24
import edu.harvard.iq.dataverse.util.SystemConfig;
25

26
import java.io.File;
27
import java.io.IOException;
28
import java.sql.Timestamp;
29
import java.util.ArrayList;
30
import java.util.Date;
31
import java.util.HashMap;
32
import java.util.List;
33
import java.util.Map;
34
import java.util.logging.Logger;
35
import java.util.Properties;
36

37
import edu.harvard.iq.dataverse.validation.JSONDataValidation;
38
import jakarta.ejb.EJB;
39
import jakarta.ejb.Stateless;
40
import jakarta.inject.Inject;
41
import jakarta.inject.Named;
42
import jakarta.json.Json;
43
import jakarta.json.JsonArrayBuilder;
44
import jakarta.persistence.EntityManager;
45
import jakarta.persistence.NoResultException;
46
import jakarta.persistence.NonUniqueResultException;
47
import jakarta.persistence.PersistenceContext;
48
import jakarta.persistence.TypedQuery;
49
import java.nio.file.Files;
50
import java.nio.file.Paths;
51
import org.apache.commons.lang3.StringUtils;
52
import org.apache.solr.client.solrj.SolrServerException;
53
import org.everit.json.schema.Schema;
54
import org.everit.json.schema.ValidationException;
55
import org.everit.json.schema.loader.SchemaLoader;
56
import org.json.JSONObject;
57
import org.json.JSONTokener;
58

59
/**
60
 *
61
 * @author gdurand
62
 */
63
@Stateless
64
@Named
65
public class DataverseServiceBean implements java.io.Serializable {
1✔
66

67
    private static final Logger logger = Logger.getLogger(DataverseServiceBean.class.getCanonicalName());
1✔
68
    @EJB
69
    IndexServiceBean indexService;
70
    
71
    @EJB
72
    SolrIndexServiceBean solrIndexService; 
73

74
    @EJB
75
    AuthenticationServiceBean authService;
76
    
77
    @EJB
78
    DatasetServiceBean datasetService;
79
    
80
    @EJB
81
    DataverseLinkingServiceBean dataverseLinkingService;
82

83
    @EJB
84
    DatasetLinkingServiceBean datasetLinkingService;
85
    
86
    @EJB
87
    GroupServiceBean groupService;
88
    
89
    @EJB
90
    DataverseRoleServiceBean rolesService;
91
    
92
    @EJB
93
    PermissionServiceBean permissionService;
94
    
95
    @EJB
96
    DataverseFieldTypeInputLevelServiceBean dataverseFieldTypeInputLevelService;
97
    
98
    @EJB
99
    SystemConfig systemConfig;
100

101
    @Inject
102
    DataverseSession session;
103

104
    @PersistenceContext(unitName = "VDCNet-ejbPU")
105
    private EntityManager em;
106

107
    private static final String BASE_QUERY_DATASET_TITLES_WITHIN_DV = "select v.value, o.id\n" 
108
                + "from datasetfieldvalue v, dvobject o "
109
                + "where " 
110
                + "v.datasetfield_id = (select id from datasetfield f where datasetfieldtype_id = 1 " 
111
                + "and datasetversion_id = (select max(id) from datasetversion where dataset_id = o.id))";
112

113
    public Dataverse save(Dataverse dataverse) {
114
       
115
        dataverse.setModificationTime(new Timestamp(new Date().getTime()));
×
116
        Dataverse savedDataverse = em.merge(dataverse);
×
117
        return savedDataverse;
×
118
    }
119
    
120
    public boolean index(Dataverse dataverse) {
121
        return index(dataverse, false);
×
122

123
    }
124
        
125
    public boolean index(Dataverse dataverse, boolean indexPermissions) {    
126
        /**
127
         * @todo check the result to see if indexing was successful or not
128
         * added logging of exceptions 
129
         */
130
        try {
131
            indexService.indexDataverse(dataverse);
×
132
            if (indexPermissions) {
×
133
                solrIndexService.indexPermissionsOnSelfAndChildren(dataverse);
×
134
            }
135
        } catch (IOException | SolrServerException e) {
×
136
            String failureLogText = "Post-save indexing failed. You can kickoff a re-index of this dataverse with: \r\n curl http://localhost:8080/api/admin/index/dataverses/" + dataverse.getId().toString();
×
137
            failureLogText += "\r\n" + e.getLocalizedMessage();
×
138
            LoggingUtil.writeOnSuccessFailureLog(null, failureLogText, dataverse);
×
139
            return false;
×
140
        }
×
141

142
        return true;
×
143
    }    
144

145
    public Dataverse find(Object pk) {
146
        return em.find(Dataverse.class, pk);
×
147
    }
148

149
    public List<Dataverse> findAll() {
150
        return em.createNamedQuery("Dataverse.findAll").getResultList();
×
151
    }
152
    
153
    public List<Long> findIdStale() {
154
        return em.createNamedQuery("Dataverse.findIdStale").getResultList();
×
155
    }
156
    public List<Long> findIdStalePermission() {
157
        return em.createNamedQuery("Dataverse.findIdStalePermission").getResultList();
×
158
    }
159

160
    /**
161
     * @param numPartitions The number of partitions you intend to split the
162
     * indexing job into. Perhaps you have three Glassfish servers and you'd
163
     * like each one to operate on a subset of dataverses.
164
     *
165
     * @param partitionId Maybe "partitionId" is the wrong term but it's what we
166
     * call in the (text) UI. If you've specified three partitions the three
167
     * partitionIds are 0, 1, and 2. We do `dataverseId % numPartitions =
168
     * partitionId` to figure out which partition the dataverseId falls into.
169
     * 
170
     * @param skipIndexed If true, will skip any dvObjects that have a indexTime set 
171
     *
172
     * @return All dataverses if you say numPartitions=1 and partitionId=0.
173
     * Otherwise, a subset of dataverses.
174
     */
175
    public List<Dataverse> findAllOrSubset(long numPartitions, long partitionId, boolean skipIndexed) {
176
        if (numPartitions < 1) {
×
177
            long saneNumPartitions = 1;
×
178
            numPartitions = saneNumPartitions;
×
179
        }
180
        String skipClause = skipIndexed ? "AND o.indexTime is null " : "";
×
181
        TypedQuery<Dataverse> typedQuery = em.createQuery("SELECT OBJECT(o) FROM Dataverse AS o WHERE MOD( o.id, :numPartitions) = :partitionId " +
×
182
                skipClause +
183
                "ORDER BY o.id", Dataverse.class);
184
        typedQuery.setParameter("numPartitions", numPartitions);
×
185
        typedQuery.setParameter("partitionId", partitionId);
×
186
        return typedQuery.getResultList();
×
187
    }
188
    
189
    public List<Long> findDataverseIdsForIndexing(boolean skipIndexed) {
190
        if (skipIndexed) {
×
191
            return em.createQuery("SELECT o.id FROM Dataverse o WHERE o.indexTime IS null ORDER BY o.id", Long.class).getResultList();
×
192
        }
193
        return em.createQuery("SELECT o.id FROM Dataverse o ORDER BY o.id", Long.class).getResultList();
×
194
        
195
    }
196

197
    public List<Dataverse> findByCreatorId(Long creatorId) {
198
        return em.createNamedQuery("Dataverse.findByCreatorId").setParameter("creatorId", creatorId).getResultList();
×
199
    }
200

201
    public List<Dataverse> findByReleaseUserId(Long releaseUserId) {
202
        return em.createNamedQuery("Dataverse.findByReleaseUserId").setParameter("releaseUserId", releaseUserId).getResultList();
×
203
    }
204

205
    public List<Dataverse> findByOwnerId(Long ownerId) {
206
        return em.createNamedQuery("Dataverse.findByOwnerId").setParameter("ownerId", ownerId).getResultList();
×
207
    }
208
    
209
    public List<Long> findIdsByOwnerId(Long ownerId) {
210
        String qr = "select o.id from Dataverse as o where o.owner.id =:ownerId order by o.id";
×
211
        return em.createQuery(qr, Long.class).setParameter("ownerId", ownerId).getResultList();
×
212
    }
213
    
214
    public List<Dataverse> findPublishedByOwnerId(Long ownerId) {
215
        String qr ="select object(o) from Dataverse as o where o.owner.id =:ownerId and o.publicationDate is not null order by o.name";
×
216
        return em.createQuery(qr, Dataverse.class).setParameter("ownerId", ownerId).getResultList();
×
217
    }
218

219
    /**
220
     * @return the root dataverse
221
     * @todo Do we really want this method to sometimes throw a
222
     * NoResultException which is a RuntimeException?
223
     */
224
    public Dataverse findRootDataverse() {
225
        return em.createNamedQuery("Dataverse.findRoot", Dataverse.class).getSingleResult();
×
226
    }
227
    
228
    
229
    //Similarly - if the above throws that exception, do we need to catch it here?
230
    //ToDo - consider caching?
231
    public String getRootDataverseName() {
232
        Dataverse root = findRootDataverse();
×
233
        String rootDataverseName=root.getName();
×
234
        return StringUtil.isEmpty(rootDataverseName) ? "" : rootDataverseName; 
×
235
    }
236
    
237
    public List<Dataverse> findAllPublishedByOwnerId(Long ownerId) {
238
        List<Dataverse> retVal = new ArrayList<>();       
×
239
        List<Dataverse> previousLevel = findPublishedByOwnerId(ownerId);
×
240
        
241
        retVal.addAll(previousLevel);
×
242
        /*
243
        if (!previousLevel.isEmpty()) {
244
            for (Dataverse dv : previousLevel) {
245
                retVal.addAll(findPublishedByOwnerId(dv.getId()));
246
            }
247
        }*/
248
        return retVal;
×
249
    }
250

251
    /**
252
     * A lookup of a dataverse alias should be case insensitive. If "cfa"
253
     * belongs to the Center for Astrophysics, we don't want to allow Code for
254
     * America to start using "CFA". Force all queries to be lower case.
255
     * @param anAlias
256
     * @return 
257
     */
258
    public Dataverse findByAlias(String anAlias) {
259
        try {
260
            return (anAlias.toLowerCase().equals(":root"))
×
261
              ? findRootDataverse()
×
262
              : em.createNamedQuery("Dataverse.findByAlias", Dataverse.class)
×
263
                  .setParameter("alias", anAlias.toLowerCase())
×
264
                  .getSingleResult();
×
265
        } catch ( NoResultException|NonUniqueResultException ex ) {
×
266
            logger.warning("Unable to find a single dataverse using alias \"" + anAlias + "\": " + ex);
×
267
            return null;
×
268
        }
269
    }
270
    
271
        public boolean hasData( Dataverse dv ) {
272
                TypedQuery<Long> amountQry = em.createNamedQuery("Dataverse.ownedObjectsById", Long.class)
×
273
                                                                .setParameter("id", dv.getId());
×
274
                
275
                return (amountQry.getSingleResult()>0);
×
276
        }
277
        
278
    public boolean isRootDataverseExists() {
279
        long count = em.createQuery("SELECT count(dv) FROM Dataverse dv WHERE dv.owner.id=null", Long.class).getSingleResult();
×
280
        return (count == 1);
×
281
    }
282

283
    public String determineDataversePath(Dataverse dataverse) {
284
        List<String> dataversePathSegments = new ArrayList<>();
×
285
        indexService.findPathSegments(dataverse, dataversePathSegments);
×
286
        StringBuilder dataversePath = new StringBuilder();
×
287
        for (String segment : dataversePathSegments) {
×
288
            dataversePath.append("/").append(segment);
×
289
        }
×
290
        return dataversePath.toString();
×
291
    }
292

293
    public MetadataBlock findMDB(Long id) {
294
        return em.find(MetadataBlock.class, id);
×
295
    }
296

297
    public MetadataBlock findMDBByName(String name) {
298
        return em.createQuery("select m from MetadataBlock m WHERE m.name=:name", MetadataBlock.class)
×
299
                .setParameter("name", name)
×
300
                .getSingleResult();
×
301
    }
302

303
    public List<MetadataBlock> findAllMetadataBlocks() {
304
        return em.createQuery("select object(o) from MetadataBlock as o order by o.id", MetadataBlock.class).getResultList();
×
305
    }
306
    
307
    public List<MetadataBlock> findSystemMetadataBlocks(){
308
        String qr = "select object(o) from MetadataBlock as o where o.owner.id=null  order by o.id";
×
309
        return em.createQuery(qr, MetadataBlock.class).getResultList();
×
310
    }
311
    
312
    public List<MetadataBlock> findMetadataBlocksByDataverseId(Long dataverse_id) {
313
        String qr = "select object(o) from MetadataBlock as o where o.owner.id=:dataverse_id order by o.id";
×
314
        return em.createQuery(qr, MetadataBlock.class)
×
315
                .setParameter("dataverse_id", dataverse_id).getResultList();
×
316
    }
317
    
318
    public DataverseFacet findFacet(Long id) {
319
        return em.find(DataverseFacet.class, id);
×
320
    }
321
    
322
    public List<DataverseFacet> findAllDataverseFacets() {
323
        return em.createQuery("select object(o) from DataverseFacet as o order by o.display", DataverseFacet.class).getResultList();
×
324
    }
325
    
326
    public String getDataverseLogoThumbnailAsBase64(Dataverse dataverse, User user) {
327
        
328
        if (dataverse == null) {
×
329
            return null;
×
330
        }
331

332
        File dataverseLogoFile = getLogo(dataverse);
×
333
        if (dataverseLogoFile != null) {
×
334
            String logoThumbNailPath;
335

336
            if (dataverseLogoFile.exists()) {
×
337
                logoThumbNailPath = ImageThumbConverter.generateImageThumbnailFromFile(dataverseLogoFile.getAbsolutePath(), 48);
×
338
                if (logoThumbNailPath != null) {
×
339
                    return ImageThumbConverter.getImageAsBase64FromFile(new File(logoThumbNailPath));
×
340

341
                }
342
            }
343
        } 
344
        return null;
×
345
    }
346
    
347
    public String getDataverseLogoThumbnailAsBase64ById(Long dvId) {
348
     
349
        File dataverseLogoFile = getLogoById(dvId);
×
350
        
351
        if (dataverseLogoFile != null) {
×
352
            String logoThumbNailPath;
353

354
            if (dataverseLogoFile.exists()) {
×
355
                logoThumbNailPath = ImageThumbConverter.generateImageThumbnailFromFile(dataverseLogoFile.getAbsolutePath(), 48);
×
356
                if (logoThumbNailPath != null) {
×
357
                    return ImageThumbConverter.getImageAsBase64FromFile(new File(logoThumbNailPath));
×
358

359
                }
360
            }
361
        } 
362
        return null;
×
363
    }
364
        
365
    private File getLogo(Dataverse dataverse) {
366
        if (dataverse.getId() == null) {
×
367
            return null; 
×
368
        }
369
        
370
        DataverseTheme theme = dataverse.getDataverseTheme(); 
×
371
        if (theme != null && theme.getLogo() != null && !theme.getLogo().isEmpty()) {
×
372
            return ThemeWidgetFragment.getLogoDir(dataverse.getLogoOwnerId()).resolve(theme.getLogo()).toFile();
×
373
        }
374
            
375
        return null;         
×
376
    }
377
    
378
    private File getLogoById(Long id) {
379
        if (id == null) {
×
380
            return null; 
×
381
        }
382
        
383
        String logoFileName;
384
        
385
        try {
386
                logoFileName = (String) em.createNativeQuery("SELECT logo FROM dataversetheme WHERE dataverse_id = " + id).getSingleResult();
×
387
            
388
        } catch (Exception ex) {
×
389
            return null;
×
390
        }
×
391
        
392
        if (logoFileName != null && !logoFileName.isEmpty()) {
×
393
            Properties p = System.getProperties();
×
394
            String domainRoot = p.getProperty("com.sun.aas.instanceRoot");
×
395
  
396
            if (domainRoot != null && !"".equals(domainRoot)) {
×
397
                return new File (domainRoot + File.separator + 
×
398
                    "docroot" + File.separator + 
399
                    "logos" + File.separator + 
400
                    id + File.separator + 
401
                    logoFileName);
402
            }
403
        }
404
            
405
        return null;         
×
406
    }
407
    
408
    public DataverseTheme findDataverseThemeByIdQuick(Long id) {
409
        if (id == null) {
×
410
            return null; 
×
411
        }
412
        
413
        Object[] result;
414
        
415
        try {
416
                result = (Object[]) em.createNativeQuery("SELECT logo, logoFormat FROM dataversetheme WHERE dataverse_id = " + id).getSingleResult();
×
417
            
418
        } catch (Exception ex) {
×
419
            return null;
×
420
        }
×
421
        
422
        if (result == null) {
×
423
            return null;
×
424
        }
425
        
426
        DataverseTheme theme = new DataverseTheme();
×
427
        
428
        if (result[0] != null) {
×
429
            theme.setLogo((String) result[0]);
×
430
        }
431

432
        if (result[1] != null) {
×
433
            String format = (String) result[1];
×
434
            switch (format) {
×
435
                case "RECTANGLE":
436
                theme.setLogoFormat(DataverseTheme.ImageFormat.RECTANGLE);
×
437
                    break;
×
438
                case "SQUARE":
439
                theme.setLogoFormat(DataverseTheme.ImageFormat.SQUARE);
×
440
                    break;
441
            }
442
        }
443
        
444
        return theme;
×
445
    }
446

447
    public List<Dataverse> findDataversesThisIdHasLinkedTo(long dataverseId) {
448
        return dataverseLinkingService.findLinkedDataverses(dataverseId);
×
449
    }
450

451
    public List<Dataverse> findDataversesThatLinkToThisDvId(long dataverseId) {
452
        return dataverseLinkingService.findLinkingDataverses(dataverseId);
×
453
    }
454

455
    public List<Dataset> findDatasetsThisIdHasLinkedTo(long dataverseId) {
456
        return datasetLinkingService.findLinkedDatasets(dataverseId);
×
457
    }
458

459
    public List<Dataverse> findDataversesThatLinkToThisDatasetId(long datasetId) {
460
        return datasetLinkingService.findLinkingDataverses(datasetId);
×
461
    }
462
    
463
    public List<Dataverse> filterByAliasQuery(String filterQuery) {
464
        //Query query = em.createNativeQuery("select o from Dataverse o where o.alias LIKE '" + filterQuery + "%' order by o.alias");
465
        //Query query = em.createNamedQuery("Dataverse.filterByAlias", Dataverse.class).setParameter("alias", filterQuery.toLowerCase() + "%");
466
        List<Dataverse> ret = em.createNamedQuery("Dataverse.filterByAliasNameAffiliation", Dataverse.class)
×
467
                .setParameter("alias", filterQuery.toLowerCase() + "%")
×
468
                .setParameter("name", "%" + filterQuery.toLowerCase() + "%")
×
469
                .setParameter("affiliation", "%" + filterQuery.toLowerCase() + "%").getResultList();
×
470
        //logger.info("created native query: select o from Dataverse o where o.alias LIKE '" + filterQuery + "%' order by o.alias");
471
        logger.info("created named query");
×
472
        if (ret != null) {
×
473
            logger.info("results list: "+ret.size()+" results.");
×
474
        }
475
        return ret;
×
476
    }
477
    
478
    public List<Dataverse> filterDataversesForLinking(String query, DataverseRequest req, Dataset dataset) {
479

480
        List<Dataverse> dataverseList = new ArrayList<>();
×
481

482
        List<Dataverse> results = filterDataversesByNamePattern(query);
×
483
        
484
        if (results == null || results.size() == 0) {
×
485
            return null; 
×
486
        }
487

488
        List<Object> alreadyLinkeddv_ids = em.createNativeQuery("SELECT linkingdataverse_id   FROM datasetlinkingdataverse WHERE dataset_id = " + dataset.getId()).getResultList();
×
489
        List<Dataverse> remove = new ArrayList<>();
×
490

491
        if (alreadyLinkeddv_ids != null && !alreadyLinkeddv_ids.isEmpty()) {
×
492
            alreadyLinkeddv_ids.stream().map((testDVId) -> this.find(testDVId)).forEachOrdered((removeIt) -> {
×
493
                remove.add(removeIt);
×
494
            });
×
495
        }
496
        
497
        for (Dataverse res : results) {
×
498
            if (!remove.contains(res)) {
×
499
                if (this.permissionService.requestOn(req, res).has(Permission.PublishDataset)) {
×
500
                    dataverseList.add(res);
×
501
                }
502
            }
503
        }
×
504

505
        return dataverseList;
×
506
    }
507
    
508
    public List<Dataverse> filterDataversesForHosting(String pattern, DataverseRequest req) {
509

510
        // Find the dataverses matching the search parameters: 
511
        
512
        List<Dataverse> searchResults = filterDataversesByNamePattern(pattern);
×
513
        
514
        if (searchResults == null || searchResults.size() == 0) {
×
515
            return null; 
×
516
        }
517
        
518
        logger.fine("search query found " + searchResults.size() + " results");
×
519
        
520
        // Filter the results and drop the dataverses where the user is not allowed to 
521
        // add datasets:
522
        
523
        if (req.getAuthenticatedUser().isSuperuser()) {
×
524
            logger.fine("will skip permission check...");
×
525
            return searchResults;
×
526
        }
527
        
528
        List<Dataverse> finalResults = new ArrayList<>();
×
529
        
530
        for (Dataverse res : searchResults) {
×
531
            if (this.permissionService.requestOn(req, res).has(Permission.AddDataset)) {
×
532
                finalResults.add(res);
×
533
            }
534
        }
×
535
        
536
        logger.fine("returning " + finalResults.size() + " final results");
×
537

538
        return finalResults;
×
539
    }
540
    
541
    
542
    /* 
543
        This method takes a search parameter and expands it into a list of 
544
        Dataverses with matching names. 
545
        The search is performed on the name with the trailing word "dataverse"
546
        stripped (if present). This way the search on "data" (or on "da" pr 
547
        "dat") does NOT return almost every dataverse in the database - since
548
        most of them have names that end in "... Dataverse". 
549
        The query isn't pretty, but it works, and it's still EJB QL (and NOT a 
550
        native query). 
551
    */
552
    public List<Dataverse> filterDataversesByNamePattern(String pattern) {
553

554
        pattern = pattern.toLowerCase();
×
555
        
556
        String pattern1 = pattern + "%";
×
557
        String pattern2 = "% " + pattern + "%";
×
558

559
        // Adjust the queries for very short, 1 and 2-character patterns:
560
        if (pattern.length() == 1) {
×
561
            pattern1 = pattern;
×
562
            pattern2 = pattern + " %";
×
563
        } 
564
        /*if (pattern.length() == 2) {
565
            pattern2 = pattern + "%";
566
        }*/
567
        
568
        
569
        String qstr = "select dv from Dataverse dv "
×
570
                + "where (LOWER(dv.name) LIKE :dataverse and ((SUBSTRING(LOWER(dv.name),0,(LENGTH(dv.name)-9)) LIKE :pattern1) "
571
                + "     or (SUBSTRING(LOWER(dv.name),0,(LENGTH(dv.name)-9)) LIKE :pattern2))) "
572
                + "or (LOWER(dv.name) NOT LIKE :dataverse and ((LOWER(dv.name) LIKE :pattern1) "
573
                + "     or (LOWER(dv.name) LIKE :pattern2))) "
574
                + "order by dv.alias";
575
                
576
        List<Dataverse> searchResults = null;
×
577
        
578
        try {
579
            searchResults = em.createQuery(qstr, Dataverse.class)
×
580
                    .setParameter("dataverse", "%dataverse")
×
581
                    .setParameter("pattern1", pattern1)
×
582
                    .setParameter("pattern2", pattern2)
×
583
                    .getResultList();
×
584
        } catch (Exception ex) {
×
585
            searchResults = null;
×
586
        }
×
587
        
588
        return searchResults;
×
589
    }
590
    
591
    /**
592
     * Used to identify and properly display Harvested objects on the dataverse page.
593
     * 
594
     *//*
595
    @Deprecated
596
    public Map<Long, String> getAllHarvestedDataverseDescriptions(){
597
        
598
        String qstr = "SELECT dataverse_id, archiveDescription FROM harvestingClient;";
599
        List<Object[]> searchResults = null;
600
        
601
        try {
602
            searchResults = em.createNativeQuery(qstr).getResultList();
603
        } catch (Exception ex) {
604
            searchResults = null;
605
        }
606
        
607
        if (searchResults == null) {
608
            return null;
609
        }
610
        
611
        Map<Long, String> ret = new HashMap<>();
612
        
613
        for (Object[] result : searchResults) {
614
            Long dvId = null;
615
            if (result[0] != null) {
616
                try {
617
                    dvId = (Long)result[0];
618
                } catch (Exception ex) {
619
                    dvId = null;
620
                }
621
                if (dvId == null) {
622
                    continue;
623
                }
624
                
625
                ret.put(dvId, (String)result[1]);
626
            }
627
        }
628
        
629
        return ret;        
630
    }*/
631
    
632
    public String getParentAliasString(SolrSearchResult solrSearchResult){
633
        Long dvId = solrSearchResult.getEntityId();
×
634
        String retVal = "";
×
635
        
636
        if (dvId == null) {
×
637
            return retVal;
×
638
        }
639
        
640
        String searchResult;
641
        try {
642
            searchResult = (String) em.createNativeQuery("select  t0.ALIAS FROM DATAVERSE t0, DVOBJECT t1,  DVOBJECT t2 WHERE (t0.ID = t1.ID) AND (t2.OWNER_ID = t1.ID)  AND (t2.ID =" + dvId + ")").getSingleResult();
×
643

644
        } catch (Exception ex) {
×
645
            return retVal;
×
646
        }
×
647

648
        if (searchResult == null) {
×
649
            return retVal;
×
650
        }
651

652
        if (searchResult != null) {
×
653
            return searchResult;
×
654
        }
655
        
656
        return retVal;
×
657
    }
658
    
659
    
660
    public void populateDvSearchCard(SolrSearchResult solrSearchResult) {
661
  
662
        Long dvId = solrSearchResult.getEntityId();
×
663
        
664
        if (dvId == null) {
×
665
            return;
×
666
        }
667
        
668
        Long parentDvId = null;
×
669
        String parentId = solrSearchResult.getParent().get("id");
×
670
        if (parentId != null) {
×
671
            try {
672
                parentDvId = Long.parseLong(parentId);
×
673
            } catch (NumberFormatException ex) {
×
674
                parentDvId = null;
×
675
            }
×
676
        }
677
        
678
        Object[] searchResult;
679
        
680
        try {
681
            if (parentDvId == null) {
×
682
                searchResult = (Object[]) em.createNativeQuery("SELECT t0.AFFILIATION, t0.ALIAS FROM DATAVERSE t0 WHERE t0.ID = " + dvId).getSingleResult();
×
683
            } else {
684
                searchResult = (Object[]) em.createNativeQuery("SELECT t0.AFFILIATION, t0.ALIAS, t2.ALIAS FROM DATAVERSE t0, DVOBJECT t1, DATAVERSE t2, DVOBJECT t3 WHERE (t0.ID = t1.ID) AND (t1.OWNER_ID = t3.ID) AND (t2.ID = t3.ID) AND (t0.ID = " + dvId + ")").getSingleResult();
×
685
            }
686
        } catch (Exception ex) {
×
687
            return;
×
688
        }
×
689

690
        if (searchResult == null) {
×
691
            return;
×
692
        }
693
        
694
        if (searchResult[0] != null) {
×
695
            solrSearchResult.setDataverseAffiliation((String) searchResult[0]);
×
696
        }
697

698
        if (searchResult[1] != null) {
×
699
            solrSearchResult.setDataverseAlias((String) searchResult[1]);
×
700
        }
701
        
702
        if (parentDvId != null) {
×
703
            if (searchResult[2] != null) {
×
704
                solrSearchResult.setDataverseParentAlias((String) searchResult[2]);
×
705
            }
706
        }
707
    }
×
708
    
709
    // function to recursively find ids of all children of a dataverse that 
710
    // are also of type dataverse
711
    public List<Long> findAllDataverseDataverseChildren(Long dvId) {
712
        // get list of Dataverse children
713
        List<Long> dataverseChildren = findIdsByOwnerId(dvId);
×
714
        
715
        if (dataverseChildren == null) {
×
716
            return dataverseChildren;
×
717
        } else {
718
            List<Long> newChildren = new ArrayList<>();
×
719
            for (Long childDvId : dataverseChildren) {
×
720
                newChildren.addAll(findAllDataverseDataverseChildren(childDvId));
×
721
            }
×
722
            dataverseChildren.addAll(newChildren);
×
723
            return dataverseChildren;
×
724
        }
725
    }
726
    
727
    // function to recursively find ids of all children of a dataverse that are 
728
    // of type dataset
729
    public List<Long> findAllDataverseDatasetChildren(Long dvId) {
730
        // get list of Dataverse children
731
        List<Long> dataverseChildren = findIdsByOwnerId(dvId);
×
732
        // get list of Dataset children
733
        List<Long> datasetChildren = datasetService.findIdsByOwnerId(dvId);
×
734
        
735
        if (dataverseChildren == null) {
×
736
            return datasetChildren;
×
737
        } else {
738
            for (Long childDvId : dataverseChildren) {
×
739
                datasetChildren.addAll(findAllDataverseDatasetChildren(childDvId));
×
740
            }
×
741
            return datasetChildren;
×
742
        }
743
    }
744
    
745
    public String addRoleAssignmentsToChildren(Dataverse owner, ArrayList<String> rolesToInherit,
746
            boolean inheritAllRoles) {
747
        /*
748
         * This query recursively finds all Dataverses that are inside/children of the
749
         * specified one. It recursively finds dvobjects of dtype 'Dataverse' whose
750
         * owner_id equals an id already in the list and then returns the list of ids
751
         * found, excluding the id of the original specified Dataverse.
752
         */
753
        String qstr = "WITH RECURSIVE path_elements AS ((" + " SELECT id, dtype FROM dvobject WHERE id in ("
×
754
                + owner.getId() + "))" + " UNION\n"
×
755
                + " SELECT o.id, o.dtype FROM path_elements p, dvobject o WHERE o.owner_id = p.id and o.dtype='Dataverse') "
756
                + "SELECT id FROM path_elements WHERE id !=" + owner.getId() + ";";
×
757

758
        List<Integer> childIds;
759
        try {
760
            childIds = em.createNativeQuery(qstr).getResultList();
×
761
        } catch (Exception ex) {
×
762
            childIds = null;
×
763
        }
×
764

765
        // Set up to track the set of users/groups that get assigned a role and those
766
        // that don't
767
        JsonArrayBuilder usedNames = Json.createArrayBuilder();
×
768
        JsonArrayBuilder unusedNames = Json.createArrayBuilder();
×
769
        // Set up to track the list of dataverses, by id and alias, that are traversed.
770
        JsonArrayBuilder dataverseIds = Json.createArrayBuilder();
×
771
        JsonArrayBuilder dataverseAliases = Json.createArrayBuilder();
×
772
        // Get the Dataverses for the returned ids
773

774
        List<Dataverse> children = new ArrayList<Dataverse>();
×
775

776
        for (int i = 0; i < childIds.size(); i++) {
×
777
            Integer childId = childIds.get(i);
×
778
            Dataverse child = find(new Long(childId.longValue()));
×
779
            if (child != null) {
×
780
                // Add to the list of Dataverses
781
                children.add(child);
×
782
                // Add ids and aliases to the tracking arrays
783
                dataverseIds.add(childId.longValue());
×
784
                dataverseAliases.add(child.getAlias());
×
785
            }
786
        }
787
        // Find the role assignments on the specified Dataverse
788
        List<RoleAssignment> allRAsOnOwner = rolesService.directRoleAssignments(owner);
×
789

790
        // Create a list of just the inheritable role assignments on the original
791
        // dataverse
792
        List<RoleAssignment> inheritableRAsOnOwner = new ArrayList<RoleAssignment>();
×
793
        for (RoleAssignment role : allRAsOnOwner) {
×
794
            if (inheritAllRoles || rolesToInherit.contains(role.getRole().getAlias())) {
×
795
                //Only supporting built-in/non-dataverse-specific custom roles. Custom roles all have an owner.
796
                if(role.getRole().getOwner()==null) {
×
797
                    inheritableRAsOnOwner.add(role);
×
798
                }
799
            }
800
        }
×
801

802
        String privateUrlToken = null;
×
803
        // Create lists of the existing inheritable roles for each child Dataverse
804
        Map<Long, List<RoleAssignment>> existingRAs = new HashMap<Long, List<RoleAssignment>>();
×
805
        for (Dataverse childDv : children) {
×
806
            List<RoleAssignment> allRAsOnChild = rolesService.directRoleAssignments(childDv);
×
807
            List<RoleAssignment> inheritableRoles = new ArrayList<RoleAssignment>();
×
808
            for (RoleAssignment role : allRAsOnChild) {
×
809
                if (inheritAllRoles || rolesToInherit.contains(role.getRole().getAlias())) {
×
810
                    inheritableRoles.add(role);
×
811
                }
812
            }
×
813
            existingRAs.put(childDv.getId(), inheritableRoles);
×
814
        }
×
815

816
        for (RoleAssignment roleAssignment : inheritableRAsOnOwner) {
×
817
            DataverseRole inheritableRole = roleAssignment.getRole();
×
818
            String identifier = roleAssignment.getAssigneeIdentifier();
×
819
            if (identifier.startsWith(AuthenticatedUser.IDENTIFIER_PREFIX)) {
×
820
                // The RoleAssignment is for an individual user
821
                // Add their name to the tracking list
822
                usedNames.add(identifier);
×
823
                // Strip the Identifier prefix so we can retrieve the user
824
                identifier = identifier.substring(AuthenticatedUser.IDENTIFIER_PREFIX.length());
×
825
                AuthenticatedUser roleUser = authService.getAuthenticatedUser(identifier);
×
826
                // Now loop over all children and add the roleUser in this role if they don't
827
                // yet have this role
828
                for (Dataverse childDv : children) {
×
829
                    try {
830
                        RoleAssignment ra = new RoleAssignment(inheritableRole, roleUser, childDv, privateUrlToken);
×
831
                        if (!existingRAs.get(childDv.getId()).contains(ra)) {
×
832
                            rolesService.save(ra);
×
833
                        }
834
                    } catch (Exception e) {
×
835
                        logger.warning("Unable to assign " + roleAssignment.getAssigneeIdentifier()
×
836
                                + "as an admin for new Dataverse: " + childDv.getName());
×
837
                        logger.warning(e.getMessage());
×
838
                        throw (e);
×
839
                    }
×
840
                }
×
841
            } else if (identifier.startsWith(Group.IDENTIFIER_PREFIX)) {
×
842
                // The role assignment is for a group
843
                usedNames.add(identifier);
×
844
                identifier = identifier.substring(Group.IDENTIFIER_PREFIX.length());
×
845
                Group roleGroup = groupService.getGroup(identifier);
×
846
                if (roleGroup != null) {
×
847
                    for (Dataverse childDv : children) {
×
848
                        try {
849
                            RoleAssignment ra = new RoleAssignment(inheritableRole, roleGroup, childDv,
×
850
                                    privateUrlToken);
851
                            if (!existingRAs.get(childDv.getId()).contains(ra)) {
×
852
                                rolesService.save(ra);
×
853
                            }
854
                        } catch (Exception e) {
×
855
                            logger.warning("Unable to assign " + roleAssignment.getAssigneeIdentifier()
×
856
                                    + "as an admin for new Dataverse: " + childDv.getName());
×
857
                            logger.warning(e.getMessage());
×
858
                            throw (e);
×
859
                        }
×
860
                    }
×
861
                } else {
862
                    // Add any groups of types not yet supported
863
                    unusedNames.add(identifier);
×
864
                }
865
            } else {
×
866
                // Add any other types of entity found (not user or group) that aren't supported
867
                unusedNames.add(identifier);
×
868
            }
869
        }
×
870
        /*
871
         * Report the list of Dataverses affected and the set of users/groups that
872
         * should now have admin roles on them (they may already have had them) and any
873
         * entities that had an admin role on the specified dataverse which were not
874
         * handled. Add this to the log and the API return message.
875
         */
876
        String result = Json.createObjectBuilder().add("Dataverses Updated", dataverseIds)
×
877
                .add("Updated Dataverse Aliases", dataverseAliases).add("Assignments added for", usedNames)
×
878
                .add("Assignments not added for", unusedNames).build().toString();
×
879
        logger.info(result);
×
880
        return (result);
×
881
    }
882
    
883
    // A quick custom query that finds all the (direct children) dataset titles 
884
    // with a dataverse and returns a list of (dataset_id, title) pairs. 
885
    public List<Object[]> getDatasetTitlesWithinDataverse(Long dataverseId) {
886
        String cqString = BASE_QUERY_DATASET_TITLES_WITHIN_DV
×
887
                + "and o.owner_id = " + dataverseId;
888

889
        return em.createNativeQuery(cqString).getResultList();
×
890
    }
891

892
    public  String getCollectionDatasetSchema(String dataverseAlias) {
NEW
893
        return getCollectionDatasetSchema(dataverseAlias, null);
×
894
    }
895
    public  String getCollectionDatasetSchema(String dataverseAlias, Map<String, Map<String,List<String>>> schemaChildMap) {
896
        
897
        Dataverse testDV = this.findByAlias(dataverseAlias);
×
898
        
899
        while (!testDV.isMetadataBlockRoot()) {
×
900
            if (testDV.getOwner() == null) {
×
NEW
901
                break; // we are at the root; which by definition is metadata block root, regardless of the value
×
902
            }
903
            testDV = testDV.getOwner();
×
904
        }
905
        
906
        /* Couldn't get the 'return base if no extra required fields to work with the path provided
907
        leaving it as 'out of scope' for now SEK 11/27/2023
908

909
        List<DataverseFieldTypeInputLevel> required = new ArrayList<>();
910

911
        required = dataverseFieldTypeInputLevelService.findRequiredByDataverseId(testDV.getId());
912
        
913
        if (required == null || required.isEmpty()){
914
            String pathToJsonFile = "src/main/resources/edu/harvas/iq/dataverse/baseDatasetSchema.json";
915
            String baseSchema = getBaseSchemaStringFromFile(pathToJsonFile);
916
            if (baseSchema != null && !baseSchema.isEmpty()){
917
                return baseSchema;
918
            }
919
        }
920
        
921
        */
922
        List<MetadataBlock> selectedBlocks = new ArrayList<>();
×
923
        List<DatasetFieldType> requiredDSFT = new ArrayList<>();
×
924
        
925
        selectedBlocks.addAll(testDV.getMetadataBlocks());
×
926

927
        for (MetadataBlock mdb : selectedBlocks) {
×
928
            for (DatasetFieldType dsft : mdb.getDatasetFieldTypes()) {
×
929
                if (!dsft.isChild()) {
×
930
                    DataverseFieldTypeInputLevel dsfIl = dataverseFieldTypeInputLevelService.findByDataverseIdDatasetFieldTypeId(testDV.getId(), dsft.getId());
×
931
                    if (dsfIl != null) {
×
932
                        dsft.setRequiredDV(dsfIl.isRequired());
×
933
                        dsft.setInclude(dsfIl.isInclude());
×
934
                    } else {
935
                        dsft.setRequiredDV(dsft.isRequired());
×
936
                        dsft.setInclude(true);
×
937
                    }
NEW
938
                    List<String> childrenRequired = new ArrayList<>();
×
NEW
939
                    List<String> childrenAllowed = new ArrayList<>();
×
940
                    if (dsft.isHasChildren()) {
×
941
                        for (DatasetFieldType child : dsft.getChildDatasetFieldTypes()) {
×
942
                            DataverseFieldTypeInputLevel dsfIlChild = dataverseFieldTypeInputLevelService.findByDataverseIdDatasetFieldTypeId(testDV.getId(), child.getId());
×
943
                            if (dsfIlChild != null) {
×
944
                                child.setRequiredDV(dsfIlChild.isRequired());
×
945
                                child.setInclude(dsfIlChild.isInclude());
×
946
                            } else {
947
                                // in the case of conditionally required (child = true, parent = false)
948
                                // we set this to false; i.e this is the default "don't override" value
949
                                child.setRequiredDV(child.isRequired() && dsft.isRequired());
×
950
                                child.setInclude(true);
×
951
                            }
NEW
952
                            if (child.isRequired()) {
×
NEW
953
                                childrenRequired.add(child.getName());
×
954
                            }
NEW
955
                            childrenAllowed.add(child.getName());
×
UNCOV
956
                        }
×
957
                    }
NEW
958
                    if (schemaChildMap != null) {
×
NEW
959
                        Map<String, List<String>> map = new HashMap<>();
×
NEW
960
                        map.put("required", childrenRequired);
×
NEW
961
                        map.put("allowed", childrenAllowed);
×
NEW
962
                        schemaChildMap.put(dsft.getName(), map);
×
963
                    }
964
                    if(dsft.isRequiredDV()){
×
965
                        requiredDSFT.add(dsft);
×
966
                    }
967
                }
968
            }            
×
969

970
        }
×
971
        
972
        String reqMDBNames = "";
×
973
        List<MetadataBlock> hasReqFields = new ArrayList<>();
×
974
        String retval = datasetSchemaPreface;
×
975
        for (MetadataBlock mdb : selectedBlocks) {
×
976
            for (DatasetFieldType dsft : requiredDSFT) {
×
977
                if (dsft.getMetadataBlock().equals(mdb)) {
×
978
                    hasReqFields.add(mdb);
×
979
                    if (!reqMDBNames.isEmpty()) reqMDBNames += ",";
×
980
                    reqMDBNames += "\"" + mdb.getName() + "\"";
×
981
                    break;
×
982
                }
983
            }
×
984
        }
×
985
        int countMDB = 0;
×
986
        for (MetadataBlock mdb : hasReqFields) {
×
987
            if (countMDB>0){
×
988
                retval += ",";
×
989
            }
990
            retval += getCustomMDBSchema(mdb, requiredDSFT);
×
991
            countMDB++;            
×
992
        }
×
993
        
994
        retval += "\n                     }";
×
995
        
996
        retval += endOfjson.replace("blockNames", reqMDBNames);
×
997

998
        return retval;
×
999
    
1000
    }    
1001
    
1002
    private String getCustomMDBSchema (MetadataBlock mdb, List<DatasetFieldType> requiredDSFT){
1003
        String retval = "";
×
1004
        boolean mdbHasReqField = false;
×
1005
        int numReq = 0;
×
1006
        List<DatasetFieldType> requiredThisMDB = new ArrayList<>();
×
1007
        
1008
        for (DatasetFieldType dsft : requiredDSFT ){
×
1009

1010
            if(dsft.getMetadataBlock().equals(mdb)){
×
1011
                numReq++;
×
1012
                mdbHasReqField = true;
×
1013
                requiredThisMDB.add(dsft);
×
1014
            }
1015
        }
×
1016
        if (mdbHasReqField){
×
1017
        retval  += startOfMDB.replace("blockName", mdb.getName());
×
1018
        
1019
        retval += minItemsTemplate.replace("numMinItems", Integer.toString(requiredThisMDB.size()));
×
1020
        int count = 0;
×
1021
        for (DatasetFieldType dsft:requiredThisMDB ){
×
1022
            count++;
×
1023
            String reqValImp = reqValTemplate.replace("reqFieldTypeName", dsft.getName());
×
1024
            if (count < requiredThisMDB.size()){
×
1025
                retval += reqValImp + "\n";
×
1026
            } else {
1027
               reqValImp = StringUtils.substring(reqValImp, 0, reqValImp.length() - 1);
×
1028
               retval += reqValImp+ "\n";
×
1029
               retval += endOfReqVal;
×
1030
            }            
1031
        }
×
1032
        
1033
        }
1034
        
1035
        return retval;
×
1036
    }
1037
    
1038
    public String isDatasetJsonValid(String dataverseAlias, String jsonInput) {
NEW
1039
        Map<String, Map<String,List<String>>> schemaChildMap = new HashMap<>();
×
NEW
1040
        JSONObject rawSchema = new JSONObject(new JSONTokener(getCollectionDatasetSchema(dataverseAlias, schemaChildMap)));
×
1041
        
1042
        try {
1043
            Schema schema = SchemaLoader.load(rawSchema);
×
1044
            schema.validate(new JSONObject(jsonInput)); // throws a ValidationException if this object is invalid
×
NEW
1045
            JSONDataValidation.validate(schema, schemaChildMap, jsonInput); // throws a ValidationException if any objects are invalid
×
1046
        } catch (ValidationException vx) {
×
1047
            logger.info(BundleUtil.getStringFromBundle("dataverses.api.validate.json.failed") + " " + vx.getErrorMessage()); 
×
1048
            String accumulatedexceptions = "";
×
1049
            for (ValidationException va : vx.getCausingExceptions()){
×
1050
                accumulatedexceptions = accumulatedexceptions + va;
×
1051
                accumulatedexceptions = accumulatedexceptions.replace("org.everit.json.schema.ValidationException:", " ");
×
1052
            }
×
1053
            if (!accumulatedexceptions.isEmpty()){
×
1054
                return BundleUtil.getStringFromBundle("dataverses.api.validate.json.failed") + " "  + accumulatedexceptions;
×
1055
            } else {
1056
                return BundleUtil.getStringFromBundle("dataverses.api.validate.json.failed") + " "  + vx.getErrorMessage();
×
1057
            }
1058
            
1059
        } catch (Exception ex) {            
×
1060
            logger.info(BundleUtil.getStringFromBundle("dataverses.api.validate.json.exception") + ex.getLocalizedMessage());
×
1061
            return BundleUtil.getStringFromBundle("dataverses.api.validate.json.exception") + ex.getLocalizedMessage();
×
1062
        } 
×
1063

1064
        return BundleUtil.getStringFromBundle("dataverses.api.validate.json.succeeded");
×
1065
    }
1066
    
1067
    static String getBaseSchemaStringFromFile(String pathToJsonFile) {
1068
        File datasetSchemaJson = new File(pathToJsonFile);
×
1069
        try {
1070
            String datasetSchemaAsJson = new String(Files.readAllBytes(Paths.get(datasetSchemaJson.getAbsolutePath())));
×
1071
            return datasetSchemaAsJson;
×
1072
        } catch (IOException ex) {
×
1073
            logger.info("IO - failed to get schema file  - will build on fly " +ex.getMessage());
×
1074
            return null;
×
1075
        } catch (Exception e){
×
1076
            logger.info("Other exception - failed to get schema file  - will build on fly. " + e.getMessage());
×
1077
            return null;
×
1078
        }
1079
    }
1080
    
1081
    private  String datasetSchemaPreface = 
1✔
1082
    "{\n" +
1083
    "    \"$schema\": \"http://json-schema.org/draft-04/schema#\",\n" +
1084
    "    \"$defs\": {\n" +
1085
    "    \"field\": {\n" + 
1086
    "        \"type\": \"object\",\n" +
1087
    "        \"required\": [\"typeClass\", \"multiple\", \"typeName\"],\n" +
1088
    "        \"properties\": {\n" + 
1089
    "            \"value\": {\n" +
1090
    "                \"anyOf\": [\n" +
1091
    "                    {\n" +
1092
    "                        \"type\": \"array\"\n" +
1093
    "                    },\n" +
1094
    "                    {\n" + 
1095
    "                        \"type\": \"string\"\n" +
1096
    "                    },\n" +
1097
    "                    {\n" +
1098
    "                        \"$ref\": \"#/$defs/field\"\n" +
1099
    "                    }\n" + 
1100
    "                ]\n" + 
1101
    "            },\n" + 
1102
    "            \"typeClass\": {\n" +
1103
    "                \"type\": \"string\"\n" +
1104
    "            },\n" +
1105
    "            \"multiple\": {\n" +
1106
    "                \"type\": \"boolean\"\n" +
1107
    "            },\n" +
1108
    "            \"typeName\": {\n" + 
1109
    "                \"type\": \"string\"\n" +
1110
    "            }\n" +
1111
    "        }\n" +
1112
    "    }\n" + 
1113
    "},\n" + 
1114
    "\"type\": \"object\",\n" +
1115
    "\"properties\": {\n" + 
1116
    "    \"datasetVersion\": {\n" + 
1117
    "        \"type\": \"object\",\n" +
1118
    "        \"properties\": {\n" + 
1119
    "           \"license\": {\n" + 
1120
    "                \"type\": \"object\",\n" + 
1121
    "                \"properties\": {\n" + 
1122
    "                    \"name\": {\n" +
1123
    "                        \"type\": \"string\"\n" + 
1124
    "                    },\n" + 
1125
    "                    \"uri\": {\n" + 
1126
    "                        \"type\": \"string\",\n" + 
1127
    "                        \"format\": \"uri\"\n" + 
1128
    "                   }\n" + 
1129
    "                },\n" + 
1130
    "                \"required\": [\"name\", \"uri\"]\n" + 
1131
    "            },\n" + 
1132
    "            \"metadataBlocks\": {\n" + 
1133
    "                \"type\": \"object\",\n" + 
1134
    "               \"properties\": {\n" +
1135
    ""  ;
1136
    
1137
    private String startOfMDB = "" +
1✔
1138
"                           \"blockName\": {\n" +
1139
"                            \"type\": \"object\",\n" +
1140
"                            \"properties\": {\n" +
1141
"                                \"fields\": {\n" +
1142
"                                    \"type\": \"array\",\n" +
1143
"                                    \"items\": {\n" +
1144
"                                        \"$ref\": \"#/$defs/field\"\n" +
1145
"                                    },";
1146
    
1147
    private String reqValTemplate = "                                        {\n" +
1✔
1148
"                                            \"contains\": {\n" +
1149
"                                                \"properties\": {\n" +
1150
"                                                    \"typeName\": {\n" +
1151
"                                                        \"const\": \"reqFieldTypeName\"\n" +
1152
"                                                    }\n" +
1153
"                                                }\n" +
1154
"                                            }\n" +
1155
"                                        },";
1156
    
1157
    private String minItemsTemplate = "\n                                    \"minItems\": numMinItems,\n" +
1✔
1158
"                                    \"allOf\": [\n";
1159
    private String endOfReqVal = "                                    ]\n" +
1✔
1160
"                                }\n" +
1161
"                            },\n" +
1162
"                            \"required\": [\"fields\"]\n" +
1163
"                        }";
1164
    
1165
    private String endOfjson = ",\n" +
1✔
1166
"                    \"required\": [blockNames]\n" +
1167
"                }\n" +
1168
"            },\n" +
1169
"            \"required\": [\"metadataBlocks\"]\n" +
1170
"        }\n" +
1171
"    },\n" +
1172
"    \"required\": [\"datasetVersion\"]\n" +
1173
"}\n";
1174
    
1175
    public void saveStorageQuota(Dataverse target, Long allocation) {
1176
        StorageQuota storageQuota = target.getStorageQuota();
×
1177
        
1178
        if (storageQuota != null) {
×
1179
            storageQuota.setAllocation(allocation);
×
1180
            em.merge(storageQuota);
×
1181
        } else {
1182
            storageQuota = new StorageQuota(); 
×
1183
            storageQuota.setDefinitionPoint(target);
×
1184
            storageQuota.setAllocation(allocation);
×
1185
            target.setStorageQuota(storageQuota);
×
1186
            em.persist(storageQuota);
×
1187
        }
1188
        em.flush();
×
1189
    }
×
1190
    
1191
    public void disableStorageQuota(StorageQuota storageQuota) {
1192
        if (storageQuota != null && storageQuota.getAllocation() != null) {
×
1193
            storageQuota.setAllocation(null);
×
1194
            em.merge(storageQuota);
×
1195
            em.flush();
×
1196
        }
1197
    }
×
1198
}
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