comparison src/main/java/edu/harvard/iq/dataverse/DatasetServiceBean.java @ 10:a50cf11e5178

Rewrite LGDataverse completely upgrading to dataverse4.0
author Zoe Hong <zhong@mpiwg-berlin.mpg.de>
date Tue, 08 Sep 2015 17:00:21 +0200
parents
children
comparison
equal deleted inserted replaced
9:5926d6419569 10:a50cf11e5178
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.users.AuthenticatedUser;
10 import edu.harvard.iq.dataverse.authorization.users.User;
11 import edu.harvard.iq.dataverse.dataaccess.ImageThumbConverter;
12 import edu.harvard.iq.dataverse.settings.SettingsServiceBean;
13 import java.io.ByteArrayOutputStream;
14 import java.io.OutputStream;
15 import java.text.SimpleDateFormat;
16 import java.util.ArrayList;
17 import java.util.Date;
18 import java.util.List;
19 import java.util.logging.Level;
20 import java.util.logging.Logger;
21 import javax.ejb.EJB;
22 import javax.ejb.EJBException;
23 import javax.ejb.Stateless;
24 import javax.ejb.TransactionAttribute;
25 import javax.ejb.TransactionAttributeType;
26 import javax.inject.Named;
27 import javax.persistence.EntityManager;
28 import javax.persistence.PersistenceContext;
29 import javax.persistence.Query;
30 import javax.persistence.TypedQuery;
31 import javax.xml.stream.XMLOutputFactory;
32 import javax.xml.stream.XMLStreamException;
33 import javax.xml.stream.XMLStreamWriter;
34 import org.apache.commons.lang.RandomStringUtils;
35
36 /**
37 *
38 * @author skraffmiller
39 */
40 @Stateless
41 @Named
42 public class DatasetServiceBean implements java.io.Serializable {
43
44 private static final Logger logger = Logger.getLogger(DatasetServiceBean.class.getCanonicalName());
45 @EJB
46 IndexServiceBean indexService;
47
48 @EJB
49 DOIEZIdServiceBean doiEZIdServiceBean;
50
51 @EJB
52 SettingsServiceBean settingsService;
53
54 @EJB
55 DatasetVersionServiceBean versionService;
56
57 @EJB
58 AuthenticationServiceBean authentication;
59
60 @EJB
61 DataFileServiceBean fileService;
62
63 @PersistenceContext(unitName = "VDCNet-ejbPU")
64 private EntityManager em;
65
66 public Dataset find(Object pk) {
67 return em.find(Dataset.class, pk);
68 }
69
70 public List<Dataset> findByOwnerId(Long ownerId) {
71 return findByOwnerId(ownerId, false);
72 }
73
74 public List<Dataset> findPublishedByOwnerId(Long ownerId) {
75 return findByOwnerId(ownerId, true);
76 }
77
78 private List<Dataset> findByOwnerId(Long ownerId, boolean onlyPublished) {
79 List<Dataset> retList = new ArrayList();
80 TypedQuery<Dataset> query = em.createQuery("select object(o) from Dataset as o where o.owner.id =:ownerId order by o.id", Dataset.class);
81 query.setParameter("ownerId", ownerId);
82 if (!onlyPublished) {
83 return query.getResultList();
84 } else {
85 for (Dataset ds : query.getResultList()) {
86 if (ds.isReleased() && !ds.isDeaccessioned()) {
87 retList.add(ds);
88 }
89 }
90 return retList;
91 }
92 }
93
94 public List<Dataset> findAll() {
95 return em.createQuery("select object(o) from Dataset as o order by o.id").getResultList();
96 }
97
98 /**
99 * For docs, see the equivalent method on the DataverseServiceBean.
100 * @see DataverseServiceBean#findAllOrSubset(long, long)
101 */
102 public List<Dataset> findAllOrSubset(long numPartitions, long partitionId, boolean skipIndexed) {
103 if (numPartitions < 1) {
104 long saneNumPartitions = 1;
105 numPartitions = saneNumPartitions;
106 }
107 String skipClause = skipIndexed ? "AND o.indexTime is null " : "";
108 TypedQuery<Dataset> typedQuery = em.createQuery("SELECT OBJECT(o) FROM Dataset AS o WHERE MOD( o.id, :numPartitions) = :partitionId " +
109 skipClause +
110 "ORDER BY o.id", Dataset.class);
111 typedQuery.setParameter("numPartitions", numPartitions);
112 typedQuery.setParameter("partitionId", partitionId);
113 return typedQuery.getResultList();
114 }
115
116 public Dataset findByGlobalId(String globalId) {
117
118 String protocol = "";
119 String authority = "";
120 String identifier = "";
121 int index1 = globalId.indexOf(':');
122 String nonNullDefaultIfKeyNotFound = "";
123 String separator = settingsService.getValueForKey(SettingsServiceBean.Key.DoiSeparator, nonNullDefaultIfKeyNotFound);
124 int index2 = globalId.indexOf(separator, index1 + 1);
125 int index3 = 0;
126 if (index1 == -1) {
127 throw new EJBException("Error parsing identifier: " + globalId + ". ':' not found in string");
128 } else {
129 protocol = globalId.substring(0, index1);
130 }
131 if (index2 == -1 ) {
132 throw new EJBException("Error parsing identifier: " + globalId + ". Second separator not found in string");
133 } else {
134 if (index2 != -1) {
135 authority = globalId.substring(index1 + 1, index2);
136 }
137 }
138 if (protocol.equals("doi")) {
139
140 index3 = globalId.indexOf(separator, index2 + 1);
141 if (index3 == -1 ) {
142 identifier = globalId.substring(index2 + 1).toUpperCase();
143 } else {
144 if (index3 > -1) {
145 authority = globalId.substring(index1 + 1, index3);
146 identifier = globalId.substring(index3 + 1).toUpperCase();
147 }
148 }
149 } else {
150 identifier = globalId.substring(index2 + 1).toUpperCase();
151 }
152 String queryStr = "SELECT s from Dataset s where s.identifier = :identifier and s.protocol= :protocol and s.authority= :authority";
153 Dataset foundDataset = null;
154 try {
155 Query query = em.createQuery(queryStr);
156 query.setParameter("identifier", identifier);
157 query.setParameter("protocol", protocol);
158 query.setParameter("authority", authority);
159 foundDataset = (Dataset) query.getSingleResult();
160 } catch (javax.persistence.NoResultException e) {
161 logger.info("no ds found: " + globalId);
162 // DO nothing, just return null.
163 }
164 return foundDataset;
165 }
166
167 public String generateIdentifierSequence(String protocol, String authority, String separator) {
168
169 String identifier = null;
170 do {
171 identifier = RandomStringUtils.randomAlphanumeric(6).toUpperCase();
172 } while (!isUniqueIdentifier(identifier, protocol, authority, separator));
173
174 return identifier;
175 }
176
177 /**
178 * Check that a identifier entered by the user is unique (not currently used
179 * for any other study in this Dataverse Network) alos check for duplicate
180 * in EZID if needed
181 */
182 public boolean isUniqueIdentifier(String userIdentifier, String protocol, String authority, String separator) {
183 String query = "SELECT d FROM Dataset d WHERE d.identifier = '" + userIdentifier + "'";
184 query += " and d.protocol ='" + protocol + "'";
185 query += " and d.authority = '" + authority + "'";
186 boolean u = em.createQuery(query).getResultList().size() == 0;
187 String nonNullDefaultIfKeyNotFound = "";
188 String doiProvider = settingsService.getValueForKey(SettingsServiceBean.Key.DoiProvider, nonNullDefaultIfKeyNotFound);
189 if (doiProvider.equals("EZID")) {
190 if (!doiEZIdServiceBean.lookupMetadataFromIdentifier(protocol, authority, separator, userIdentifier).isEmpty()) {
191 u = false;
192 }
193 }
194 return u;
195 }
196
197 public String createCitationRIS(DatasetVersion version) {
198 return createCitationRIS(version, null);
199 }
200
201 public String createCitationRIS(DatasetVersion version, FileMetadata fileMetadata) {
202 String publisher = version.getRootDataverseNameforCitation();
203 List<DatasetAuthor> authorList = version.getDatasetAuthors();
204 String retString = "Provider: " + publisher + "\r\n";
205 retString += "Content: text/plain; charset=\"us-ascii\"" + "\r\n";
206 // Using type "DBASE" - "Online Database", for consistency with
207 // EndNote (see the longer comment in the EndNote section below)>
208
209 retString += "TY - DBASE" + "\r\n";
210 retString += "T1 - " + version.getTitle() + "\r\n";
211 for (DatasetAuthor author : authorList) {
212 retString += "AU - " + author.getName().getDisplayValue() + "\r\n";
213 }
214 retString += "DO - " + version.getDataset().getProtocol() + "/" + version.getDataset().getAuthority() + version.getDataset().getDoiSeparator() + version.getDataset().getIdentifier() + "\r\n";
215 retString += "PY - " + version.getVersionYear() + "\r\n";
216 retString += "UR - " + version.getDataset().getPersistentURL() + "\r\n";
217 retString += "PB - " + publisher + "\r\n";
218
219 // a DataFile citation also includes filename und UNF, if applicable:
220 if (fileMetadata != null) {
221 retString += "C1 - " + fileMetadata.getLabel() + "\r\n";
222
223 if (fileMetadata.getDataFile().isTabularData()) {
224 if (fileMetadata.getDataFile().getUnf() != null) {
225 retString += "C2 - " + fileMetadata.getDataFile().getUnf() + "\r\n";
226 }
227 }
228 }
229
230 // closing element:
231 retString += "ER - \r\n";
232
233 return retString;
234 }
235
236 private XMLOutputFactory xmlOutputFactory = null;
237
238 public String createCitationXML(DatasetVersion datasetVersion, FileMetadata fileMetadata) {
239 ByteArrayOutputStream outStream = new ByteArrayOutputStream();
240 createEndNoteCitation(outStream, datasetVersion, fileMetadata);
241 String xml = outStream.toString();
242 return xml;
243 }
244
245 public void createEndNoteCitation(OutputStream os, DatasetVersion datasetVersion, FileMetadata fileMetadata) {
246
247 xmlOutputFactory = javax.xml.stream.XMLOutputFactory.newInstance();
248 XMLStreamWriter xmlw = null;
249 try {
250 xmlw = xmlOutputFactory.createXMLStreamWriter(os);
251 xmlw.writeStartDocument();
252 createEndNoteXML(xmlw, datasetVersion, fileMetadata);
253 xmlw.writeEndDocument();
254 } catch (XMLStreamException ex) {
255 Logger.getLogger("global").log(Level.SEVERE, null, ex);
256 throw new EJBException("ERROR occurred during creating endnote xml.", ex);
257 } finally {
258 try {
259 if (xmlw != null) {
260 xmlw.close();
261 }
262 } catch (XMLStreamException ex) {
263 }
264 }
265 }
266
267 private void createEndNoteXML(XMLStreamWriter xmlw, DatasetVersion version, FileMetadata fileMetadata) throws XMLStreamException {
268
269 String title = version.getTitle();
270 String versionYear = version.getVersionYear();
271 String publisher = version.getRootDataverseNameforCitation();
272
273 List<DatasetAuthor> authorList = version.getDatasetAuthors();
274
275 xmlw.writeStartElement("xml");
276 xmlw.writeStartElement("records");
277
278 xmlw.writeStartElement("record");
279
280 // "Ref-type" indicates which of the (numerous!) available EndNote
281 // schemas this record will be interpreted as.
282 // This is relatively important. Certain fields with generic
283 // names like "custom1" and "custom2" become very specific things
284 // in specific schemas; for example, custom1 shows as "legal notice"
285 // in "Journal Article" (ref-type 84), or as "year published" in
286 // "Government Document".
287 // We don't want the UNF to show as a "legal notice"!
288 // We have found a ref-type that works ok for our purposes -
289 // "Online Database" (type 45). In this one, the fields Custom1
290 // and Custom2 are not translated and just show as is.
291 // And "Custom1" still beats "legal notice".
292 // -- L.A. 12.12.2014 beta 10
293
294 xmlw.writeStartElement("ref-type");
295 xmlw.writeAttribute("name", "Online Database");
296 xmlw.writeCharacters("45");
297 xmlw.writeEndElement(); // ref-type
298
299 xmlw.writeStartElement("contributors");
300 xmlw.writeStartElement("authors");
301 for (DatasetAuthor author : authorList) {
302 xmlw.writeStartElement("author");
303 xmlw.writeCharacters(author.getName().getDisplayValue());
304 xmlw.writeEndElement(); // author
305 }
306 xmlw.writeEndElement(); // authors
307 xmlw.writeEndElement(); // contributors
308
309 xmlw.writeStartElement("titles");
310 xmlw.writeStartElement("title");
311 xmlw.writeCharacters(title);
312 xmlw.writeEndElement(); // title
313
314 xmlw.writeEndElement(); // titles
315
316 xmlw.writeStartElement("section");
317 String sectionString = "";
318 if (version.getDataset().isReleased()) {
319 sectionString = new SimpleDateFormat("yyyy-MM-dd").format(version.getDataset().getPublicationDate());
320 } else {
321 sectionString = new SimpleDateFormat("yyyy-MM-dd").format(version.getLastUpdateTime());
322 }
323
324 xmlw.writeCharacters(sectionString);
325 xmlw.writeEndElement(); // publisher
326
327 xmlw.writeStartElement("dates");
328 xmlw.writeStartElement("year");
329 xmlw.writeCharacters(versionYear);
330 xmlw.writeEndElement(); // year
331 xmlw.writeEndElement(); // dates
332
333 xmlw.writeStartElement("publisher");
334 xmlw.writeCharacters(publisher);
335 xmlw.writeEndElement(); // publisher
336
337 xmlw.writeStartElement("urls");
338 xmlw.writeStartElement("related-urls");
339 xmlw.writeStartElement("url");
340 xmlw.writeCharacters(version.getDataset().getPersistentURL());
341 xmlw.writeEndElement(); // url
342 xmlw.writeEndElement(); // related-urls
343 xmlw.writeEndElement(); // urls
344
345 // a DataFile citation also includes the filename and (for Tabular
346 // files) the UNF signature, that we put into the custom1 and custom2
347 // fields respectively:
348
349
350 if (fileMetadata != null) {
351 xmlw.writeStartElement("custom1");
352 xmlw.writeCharacters(fileMetadata.getLabel());
353 xmlw.writeEndElement(); // custom1
354
355 if (fileMetadata.getDataFile().isTabularData()) {
356 if (fileMetadata.getDataFile().getUnf() != null) {
357 xmlw.writeStartElement("custom2");
358 xmlw.writeCharacters(fileMetadata.getDataFile().getUnf());
359 xmlw.writeEndElement(); // custom2
360 }
361 }
362 }
363
364 xmlw.writeStartElement("electronic-resource-num");
365 String electResourceNum = version.getDataset().getProtocol() + "/" + version.getDataset().getAuthority() + version.getDataset().getDoiSeparator() + version.getDataset().getIdentifier();
366 xmlw.writeCharacters(electResourceNum);
367 xmlw.writeEndElement();
368 //<electronic-resource-num>10.3886/ICPSR03259.v1</electronic-resource-num>
369 xmlw.writeEndElement(); // record
370
371 xmlw.writeEndElement(); // records
372 xmlw.writeEndElement(); // xml
373
374 }
375
376 public DatasetVersionUser getDatasetVersionUser(DatasetVersion version, User user) {
377
378 DatasetVersionUser ddu = null;
379 Query query = em.createQuery("select object(o) from DatasetVersionUser as o "
380 + "where o.datasetVersion.id =:versionId and o.authenticatedUser.id =:userId");
381 query.setParameter("versionId", version.getId());
382 String identifier = user.getIdentifier();
383 identifier = identifier.startsWith("@") ? identifier.substring(1) : identifier;
384 AuthenticatedUser au = authentication.getAuthenticatedUser(identifier);
385 query.setParameter("userId", au.getId());
386 try {
387 ddu = (DatasetVersionUser) query.getSingleResult();
388 } catch (javax.persistence.NoResultException e) {
389 // DO nothing, just return null.
390 }
391 return ddu;
392 }
393
394 public List<DatasetLock> getDatasetLocks() {
395 String query = "SELECT sl FROM DatasetLock sl";
396 return (List<DatasetLock>) em.createQuery(query).getResultList();
397 }
398
399 @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
400 public void addDatasetLock(Long datasetId, Long userId, String info) {
401
402 Dataset dataset = em.find(Dataset.class, datasetId);
403 DatasetLock lock = new DatasetLock();
404 lock.setDataset(dataset);
405 lock.setInfo(info);
406 lock.setStartTime(new Date());
407
408 if (userId != null) {
409 AuthenticatedUser user = em.find(AuthenticatedUser.class, userId);
410 lock.setUser(user);
411 if (user.getDatasetLocks() == null) {
412 user.setDatasetLocks(new ArrayList());
413 }
414 user.getDatasetLocks().add(lock);
415 }
416
417 dataset.setDatasetLock(lock);
418 em.persist(lock);
419 }
420
421 @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
422 public void removeDatasetLock(Long datasetId) {
423 Dataset dataset = em.find(Dataset.class, datasetId);
424 //em.refresh(dataset); (?)
425 DatasetLock lock = dataset.getDatasetLock();
426 if (lock != null) {
427 AuthenticatedUser user = lock.getUser();
428 dataset.setDatasetLock(null);
429 user.getDatasetLocks().remove(lock);
430 /*
431 * TODO - ?
432 * throw an exception if for whatever reason we can't remove the lock?
433 try {
434 */
435 em.remove(lock);
436 /*
437 } catch (TransactionRequiredException te) {
438 ...
439 } catch (IllegalArgumentException iae) {
440 ...
441 }
442 */
443 }
444 }
445
446
447 public boolean isDatasetCardImageAvailable(DatasetVersion datasetVersion, User user) {
448 if (datasetVersion == null) {
449 return false;
450 }
451
452 // First, check if this dataset has a designated thumbnail image:
453
454 if (datasetVersion.getDataset() != null) {
455 DataFile dataFile = datasetVersion.getDataset().getThumbnailFile();
456 if (dataFile != null) {
457 return ImageThumbConverter.isThumbnailAvailable(dataFile, 48);
458 }
459 }
460
461 // If not, we'll try to use one of the files in this dataset version:
462 // (the first file with an available thumbnail, really)
463
464 List<FileMetadata> fileMetadatas = datasetVersion.getFileMetadatas();
465
466 for (FileMetadata fileMetadata : fileMetadatas) {
467 DataFile dataFile = fileMetadata.getDataFile();
468
469 if (fileService.isThumbnailAvailable(dataFile, user)) {
470 return true;
471 }
472
473 }
474
475 return false;
476 }
477 }