001: /*
002: * WorkspaceItem.java
003: *
004: * Version: $Revision: 2079 $
005: *
006: * Date: $Date: 2007-07-20 15:49:01 -0500 (Fri, 20 Jul 2007) $
007: *
008: * Copyright (c) 2002-2005, Hewlett-Packard Company and Massachusetts
009: * Institute of Technology. All rights reserved.
010: *
011: * Redistribution and use in source and binary forms, with or without
012: * modification, are permitted provided that the following conditions are
013: * met:
014: *
015: * - Redistributions of source code must retain the above copyright
016: * notice, this list of conditions and the following disclaimer.
017: *
018: * - Redistributions in binary form must reproduce the above copyright
019: * notice, this list of conditions and the following disclaimer in the
020: * documentation and/or other materials provided with the distribution.
021: *
022: * - Neither the name of the Hewlett-Packard Company nor the name of the
023: * Massachusetts Institute of Technology nor the names of their
024: * contributors may be used to endorse or promote products derived from
025: * this software without specific prior written permission.
026: *
027: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
028: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
029: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
030: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
031: * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
032: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
033: * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
034: * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
035: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
036: * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
037: * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
038: * DAMAGE.
039: */
040: package org.dspace.content;
041:
042: import java.io.IOException;
043: import java.sql.SQLException;
044: import java.util.ArrayList;
045: import java.util.List;
046:
047: import org.apache.log4j.Logger;
048: import org.dspace.authorize.AuthorizeException;
049: import org.dspace.authorize.AuthorizeManager;
050: import org.dspace.core.Constants;
051: import org.dspace.core.Context;
052: import org.dspace.core.LogManager;
053: import org.dspace.eperson.EPerson;
054: import org.dspace.eperson.Group;
055: import org.dspace.storage.rdbms.DatabaseManager;
056: import org.dspace.storage.rdbms.TableRow;
057: import org.dspace.storage.rdbms.TableRowIterator;
058:
059: /**
060: * Class representing an item in the process of being submitted by a user
061: *
062: * @author Robert Tansley
063: * @version $Revision: 2079 $
064: */
065: public class WorkspaceItem implements InProgressSubmission {
066: /** log4j logger */
067: private static Logger log = Logger.getLogger(WorkspaceItem.class);
068:
069: /** The item this workspace object pertains to */
070: private Item item;
071:
072: /** Our context */
073: private Context ourContext;
074:
075: /** The table row corresponding to this workspace item */
076: private TableRow wiRow;
077:
078: /** The collection the item is being submitted to */
079: private Collection collection;
080:
081: /**
082: * Construct a workspace item corresponding to the given database row
083: *
084: * @param context
085: * the context this object exists in
086: * @param row
087: * the database row
088: */
089: WorkspaceItem(Context context, TableRow row) throws SQLException {
090: ourContext = context;
091: wiRow = row;
092:
093: item = Item.find(context, wiRow.getIntColumn("item_id"));
094: collection = Collection.find(context, wiRow
095: .getIntColumn("collection_id"));
096:
097: // Cache ourselves
098: context.cache(this , row.getIntColumn("workspace_item_id"));
099: }
100:
101: /**
102: * Get a workspace item from the database. The item, collection and
103: * submitter are loaded into memory.
104: *
105: * @param context
106: * DSpace context object
107: * @param id
108: * ID of the workspace item
109: *
110: * @return the workspace item, or null if the ID is invalid.
111: */
112: public static WorkspaceItem find(Context context, int id)
113: throws SQLException {
114: // First check the cache
115: WorkspaceItem fromCache = (WorkspaceItem) context.fromCache(
116: WorkspaceItem.class, id);
117:
118: if (fromCache != null) {
119: return fromCache;
120: }
121:
122: TableRow row = DatabaseManager.find(context, "workspaceitem",
123: id);
124:
125: if (row == null) {
126: if (log.isDebugEnabled()) {
127: log.debug(LogManager.getHeader(context,
128: "find_workspace_item",
129: "not_found,workspace_item_id=" + id));
130: }
131:
132: return null;
133: } else {
134: if (log.isDebugEnabled()) {
135: log.debug(LogManager.getHeader(context,
136: "find_workspace_item", "workspace_item_id="
137: + id));
138: }
139:
140: return new WorkspaceItem(context, row);
141: }
142: }
143:
144: /**
145: * Create a new workspace item, with a new ID. An Item is also created. The
146: * submitter is the current user in the context.
147: *
148: * @param c
149: * DSpace context object
150: * @param coll
151: * Collection being submitted to
152: * @param template
153: * if <code>true</code>, the workspace item starts as a copy
154: * of the collection's template item
155: *
156: * @return the newly created workspace item
157: */
158: public static WorkspaceItem create(Context c, Collection coll,
159: boolean template) throws AuthorizeException, SQLException,
160: IOException {
161: // Check the user has permission to ADD to the collection
162: AuthorizeManager.authorizeAction(c, coll, Constants.ADD);
163:
164: // Create an item
165: Item i = Item.create(c);
166: i.setSubmitter(c.getCurrentUser());
167:
168: // Now create the policies for the submitter and workflow
169: // users to modify item and contents
170: // contents = bitstreams, bundles
171: // FIXME: icky hardcoded workflow steps
172: Group step1group = coll.getWorkflowGroup(1);
173: Group step2group = coll.getWorkflowGroup(2);
174: Group step3group = coll.getWorkflowGroup(3);
175:
176: EPerson e = c.getCurrentUser();
177:
178: // read permission
179: AuthorizeManager.addPolicy(c, i, Constants.READ, e);
180:
181: if (step1group != null) {
182: AuthorizeManager
183: .addPolicy(c, i, Constants.READ, step1group);
184: }
185:
186: if (step2group != null) {
187: AuthorizeManager
188: .addPolicy(c, i, Constants.READ, step2group);
189: }
190:
191: if (step3group != null) {
192: AuthorizeManager
193: .addPolicy(c, i, Constants.READ, step3group);
194: }
195:
196: // write permission
197: AuthorizeManager.addPolicy(c, i, Constants.WRITE, e);
198:
199: if (step1group != null) {
200: AuthorizeManager.addPolicy(c, i, Constants.WRITE,
201: step1group);
202: }
203:
204: if (step2group != null) {
205: AuthorizeManager.addPolicy(c, i, Constants.WRITE,
206: step2group);
207: }
208:
209: if (step3group != null) {
210: AuthorizeManager.addPolicy(c, i, Constants.WRITE,
211: step3group);
212: }
213:
214: // add permission
215: AuthorizeManager.addPolicy(c, i, Constants.ADD, e);
216:
217: if (step1group != null) {
218: AuthorizeManager.addPolicy(c, i, Constants.ADD, step1group);
219: }
220:
221: if (step2group != null) {
222: AuthorizeManager.addPolicy(c, i, Constants.ADD, step2group);
223: }
224:
225: if (step3group != null) {
226: AuthorizeManager.addPolicy(c, i, Constants.ADD, step3group);
227: }
228:
229: // remove contents permission
230: AuthorizeManager.addPolicy(c, i, Constants.REMOVE, e);
231:
232: if (step1group != null) {
233: AuthorizeManager.addPolicy(c, i, Constants.REMOVE,
234: step1group);
235: }
236:
237: if (step2group != null) {
238: AuthorizeManager.addPolicy(c, i, Constants.REMOVE,
239: step2group);
240: }
241:
242: if (step3group != null) {
243: AuthorizeManager.addPolicy(c, i, Constants.REMOVE,
244: step3group);
245: }
246:
247: // Copy template if appropriate
248: Item templateItem = coll.getTemplateItem();
249:
250: if (template && (templateItem != null)) {
251: DCValue[] md = templateItem.getMetadata(Item.ANY, Item.ANY,
252: Item.ANY, Item.ANY);
253:
254: for (int n = 0; n < md.length; n++) {
255: i.addMetadata(md[n].schema, md[n].element,
256: md[n].qualifier, md[n].language, md[n].value);
257: }
258: }
259:
260: i.update();
261:
262: // Create the workspace item row
263: TableRow row = DatabaseManager.create(c, "workspaceitem");
264:
265: row.setColumn("item_id", i.getID());
266: row.setColumn("collection_id", coll.getID());
267:
268: log.info(LogManager.getHeader(c, "create_workspace_item",
269: "workspace_item_id="
270: + row.getIntColumn("workspace_item_id")
271: + "item_id=" + i.getID() + "collection_id="
272: + coll.getID()));
273:
274: DatabaseManager.update(c, row);
275:
276: WorkspaceItem wi = new WorkspaceItem(c, row);
277:
278: return wi;
279: }
280:
281: /**
282: * Get all workspace items for a particular e-person. These are ordered by
283: * workspace item ID, since this should likely keep them in the order in
284: * which they were created.
285: *
286: * @param context
287: * the context object
288: * @param ep
289: * the eperson
290: *
291: * @return the corresponding workspace items
292: */
293: public static WorkspaceItem[] findByEPerson(Context context,
294: EPerson ep) throws SQLException {
295: List wsItems = new ArrayList();
296:
297: TableRowIterator tri = DatabaseManager.queryTable(context,
298: "workspaceitem",
299: "SELECT workspaceitem.* FROM workspaceitem, item WHERE "
300: + "workspaceitem.item_id=item.item_id AND "
301: + "item.submitter_id= ? "
302: + "ORDER BY workspaceitem.workspace_item_id",
303: ep.getID());
304:
305: while (tri.hasNext()) {
306: TableRow row = tri.next();
307:
308: // Check the cache
309: WorkspaceItem wi = (WorkspaceItem) context.fromCache(
310: WorkspaceItem.class, row
311: .getIntColumn("workspace_item_id"));
312:
313: if (wi == null) {
314: wi = new WorkspaceItem(context, row);
315: }
316:
317: wsItems.add(wi);
318: }
319: // close the TableRowIterator to free up resources
320: tri.close();
321:
322: WorkspaceItem[] wsArray = new WorkspaceItem[wsItems.size()];
323: wsArray = (WorkspaceItem[]) wsItems.toArray(wsArray);
324:
325: return wsArray;
326: }
327:
328: /**
329: * Get all workspace items for a particular collection.
330: *
331: * @param context
332: * the context object
333: * @param c
334: * the collection
335: *
336: * @return the corresponding workspace items
337: */
338: public static WorkspaceItem[] findByCollection(Context context,
339: Collection c) throws SQLException {
340: List wsItems = new ArrayList();
341:
342: TableRowIterator tri = DatabaseManager.queryTable(context,
343: "workspaceitem",
344: "SELECT workspaceitem.* FROM workspaceitem WHERE "
345: + "workspaceitem.collection_id= ? ", c.getID());
346:
347: while (tri.hasNext()) {
348: TableRow row = tri.next();
349:
350: // Check the cache
351: WorkspaceItem wi = (WorkspaceItem) context.fromCache(
352: WorkspaceItem.class, row
353: .getIntColumn("workspace_item_id"));
354:
355: // not in cache? turn row into workspaceitem
356: if (wi == null) {
357: wi = new WorkspaceItem(context, row);
358: }
359:
360: wsItems.add(wi);
361: }
362: // close the TableRowIterator to free up resources
363: tri.close();
364:
365: WorkspaceItem[] wsArray = new WorkspaceItem[wsItems.size()];
366: wsArray = (WorkspaceItem[]) wsItems.toArray(wsArray);
367:
368: return wsArray;
369: }
370:
371: /**
372: * Get all workspace items in the whole system
373: *
374: * @param context the context object
375: *
376: * @return all workspace items
377: */
378: public static WorkspaceItem[] findAll(Context context)
379: throws SQLException {
380: List wsItems = new ArrayList();
381: String query = "SELECT * FROM workspaceitem ORDER BY item_id";
382: TableRowIterator tri = DatabaseManager.queryTable(context,
383: "workspaceitem", query);
384:
385: while (tri.hasNext()) {
386: TableRow row = tri.next();
387:
388: // Check the cache
389: WorkspaceItem wi = (WorkspaceItem) context.fromCache(
390: WorkspaceItem.class, row
391: .getIntColumn("workspace_item_id"));
392:
393: // not in cache? turn row into workspaceitem
394: if (wi == null) {
395: wi = new WorkspaceItem(context, row);
396: }
397:
398: wsItems.add(wi);
399: }
400:
401: tri.close();
402:
403: WorkspaceItem[] wsArray = new WorkspaceItem[wsItems.size()];
404: wsArray = (WorkspaceItem[]) wsItems.toArray(wsArray);
405:
406: return wsArray;
407: }
408:
409: /**
410: * Get the internal ID of this workspace item
411: *
412: * @return the internal identifier
413: */
414: public int getID() {
415: return wiRow.getIntColumn("workspace_item_id");
416: }
417:
418: /**
419: * Get the value of the stage reached column
420: *
421: * @return the value of the stage reached column
422: */
423: public int getStageReached() {
424: return wiRow.getIntColumn("stage_reached");
425: }
426:
427: /**
428: * Set the value of the stage reached column
429: *
430: * @param v
431: * the value of the stage reached column
432: */
433: public void setStageReached(int v) {
434: wiRow.setColumn("stage_reached", v);
435: }
436:
437: /**
438: * Get the value of the page reached column (which represents the page
439: * reached within a stage/step)
440: *
441: * @return the value of the page reached column
442: */
443: public int getPageReached() {
444: return wiRow.getIntColumn("page_reached");
445: }
446:
447: /**
448: * Set the value of the page reached column (which represents the page
449: * reached within a stage/step)
450: *
451: * @param v
452: * the value of the page reached column
453: */
454: public void setPageReached(int v) {
455: wiRow.setColumn("page_reached", v);
456: }
457:
458: /**
459: * Update the workspace item, including the unarchived item.
460: */
461: public void update() throws SQLException, AuthorizeException,
462: IOException {
463: // Authorisation is checked by the item.update() method below
464:
465: log.info(LogManager
466: .getHeader(ourContext, "update_workspace_item",
467: "workspace_item_id=" + getID()));
468:
469: // Update the item
470: item.update();
471:
472: // Update ourselves
473: DatabaseManager.update(ourContext, wiRow);
474: }
475:
476: /**
477: * Delete the workspace item. The entry in workspaceitem, the unarchived
478: * item and its contents are all removed (multiple inclusion
479: * notwithstanding.)
480: */
481: public void deleteAll() throws SQLException, AuthorizeException,
482: IOException {
483: /*
484: * Authorisation is a special case. The submitter won't have REMOVE
485: * permission on the collection, so our policy is this: Only the
486: * original submitter or an administrator can delete a workspace item.
487: */
488: if (!AuthorizeManager.isAdmin(ourContext)
489: && ((ourContext.getCurrentUser() == null) || (ourContext
490: .getCurrentUser().getID() != item
491: .getSubmitter().getID()))) {
492: // Not an admit, not the submitter
493: throw new AuthorizeException(
494: "Must be an administrator or the "
495: + "original submitter to delete a workspace item");
496: }
497:
498: log.info(LogManager.getHeader(ourContext,
499: "delete_workspace_item", "workspace_item_id=" + getID()
500: + "item_id=" + item.getID() + "collection_id="
501: + collection.getID()));
502:
503: //deleteSubmitPermissions();
504: // Remove from cache
505: ourContext.removeCached(this , getID());
506:
507: // Need to delete the epersongroup2workspaceitem row first since it refers
508: // to workspaceitem ID
509: deleteEpersonGroup2WorkspaceItem();
510:
511: // Need to delete the workspaceitem row first since it refers
512: // to item ID
513: DatabaseManager.delete(ourContext, wiRow);
514:
515: // Delete item
516: item.delete();
517: }
518:
519: private void deleteEpersonGroup2WorkspaceItem() throws SQLException {
520:
521: String removeSQL = "DELETE FROM epersongroup2workspaceitem WHERE workspace_item_id = ?";
522: DatabaseManager.updateQuery(ourContext, removeSQL, getID());
523:
524: }
525:
526: public void deleteWrapper() throws SQLException,
527: AuthorizeException, IOException {
528: // Check authorisation. We check permissions on the enclosed item.
529: AuthorizeManager.authorizeAction(ourContext, item,
530: Constants.WRITE);
531:
532: log.info(LogManager.getHeader(ourContext,
533: "delete_workspace_item", "workspace_item_id=" + getID()
534: + "item_id=" + item.getID() + "collection_id="
535: + collection.getID()));
536:
537: // deleteSubmitPermissions();
538: // Remove from cache
539: ourContext.removeCached(this , getID());
540:
541: // Need to delete the workspaceitem row first since it refers
542: // to item ID
543: DatabaseManager.delete(ourContext, wiRow);
544: }
545:
546: // InProgressSubmission methods
547: public Item getItem() {
548: return item;
549: }
550:
551: public Collection getCollection() {
552: return collection;
553: }
554:
555: public EPerson getSubmitter() throws SQLException {
556: return item.getSubmitter();
557: }
558:
559: public boolean hasMultipleFiles() {
560: return wiRow.getBooleanColumn("multiple_files");
561: }
562:
563: public void setMultipleFiles(boolean b) {
564: wiRow.setColumn("multiple_files", b);
565: }
566:
567: public boolean hasMultipleTitles() {
568: return wiRow.getBooleanColumn("multiple_titles");
569: }
570:
571: public void setMultipleTitles(boolean b) {
572: wiRow.setColumn("multiple_titles", b);
573: }
574:
575: public boolean isPublishedBefore() {
576: return wiRow.getBooleanColumn("published_before");
577: }
578:
579: public void setPublishedBefore(boolean b) {
580: wiRow.setColumn("published_before", b);
581: }
582: }
|