0001: /*
0002: * Copyright (c) 2001 - 2005 ivata limited.
0003: * All rights reserved.
0004: * -----------------------------------------------------------------------------
0005: * ivata groupware may be redistributed under the GNU General Public
0006: * License as published by the Free Software Foundation;
0007: * version 2 of the License.
0008: *
0009: * These programs are free software; you can redistribute them and/or
0010: * modify them under the terms of the GNU General Public License
0011: * as published by the Free Software Foundation; version 2 of the License.
0012: *
0013: * These programs are distributed in the hope that they will be useful,
0014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
0016: *
0017: * See the GNU General Public License in the file LICENSE.txt for more
0018: * details.
0019: *
0020: * If you would like a copy of the GNU General Public License write to
0021: *
0022: * Free Software Foundation, Inc.
0023: * 59 Temple Place - Suite 330
0024: * Boston, MA 02111-1307, USA.
0025: *
0026: *
0027: * To arrange commercial support and licensing, contact ivata at
0028: * http://www.ivata.com/contact.jsp
0029: * -----------------------------------------------------------------------------
0030: * $Log: LibraryImpl.java,v $
0031: * Revision 1.5 2005/04/29 02:48:16 colinmacleod
0032: * Data bugfixes.
0033: * Changed primary key back to Integer.
0034: *
0035: * Revision 1.4 2005/04/26 15:21:54 colinmacleod
0036: * Renamed Faq to FAQ.
0037: *
0038: * Revision 1.3 2005/04/10 20:09:44 colinmacleod
0039: * Added new themes.
0040: * Changed id type to String.
0041: * Changed i tag to em and b tag to strong.
0042: * Improved PicoContainerFactory with NanoContainer scripts.
0043: *
0044: * Revision 1.2 2005/04/09 17:19:44 colinmacleod
0045: * Changed copyright text to GPL v2 explicitly.
0046: *
0047: * Revision 1.1.1.1 2005/03/10 17:51:54 colinmacleod
0048: * Restructured ivata op around Hibernate/PicoContainer.
0049: * Renamed ivata groupware.
0050: *
0051: * Revision 1.11 2004/11/12 18:16:06 colinmacleod
0052: * Ordered imports.
0053: *
0054: * Revision 1.10 2004/11/12 15:57:15 colinmacleod
0055: * Removed dependencies on SSLEXT.
0056: * Moved Persistence classes to ivata masks.
0057: *
0058: * Revision 1.9 2004/09/30 14:59:06 colinmacleod
0059: * Added methods to sanitize the entire library and update the search index.
0060: *
0061: * Revision 1.8 2004/08/01 11:45:19 colinmacleod
0062: * Restructured search engine into separate subproject.
0063: *
0064: * Revision 1.7 2004/07/31 10:26:38 colinmacleod
0065: * Fixed comment tree.
0066: *
0067: * Revision 1.6 2004/07/29 20:51:33 colinmacleod
0068: * Set the page order (page numbers) before adding/amending library items.
0069: *
0070: * Revision 1.5 2004/07/19 22:01:31 colinmacleod
0071: * Changed recent items from collection to list.
0072: *
0073: * Revision 1.4 2004/07/18 22:30:35 colinmacleod
0074: * Synchronized lists and collections.
0075: *
0076: * Revision 1.3 2004/07/18 21:59:14 colinmacleod
0077: * Removed Person from User - now you need to use addressbook/persistence manager to find the person (makes the app run faster.)
0078: *
0079: * Revision 1.2 2004/07/13 19:47:28 colinmacleod
0080: * Moved project to POJOs from EJBs.
0081: * Applied PicoContainer to services layer (replacing session EJBs).
0082: * Applied Hibernate to persistence layer (replacing entity EJBs).
0083: *
0084: * Revision 1.1 2004/03/27 10:31:25 colinmacleod
0085: * Split off business logic from remote facades to POJOs.
0086: * -----------------------------------------------------------------------------
0087: */
0088: package com.ivata.groupware.business.library;
0089:
0090: import java.text.MessageFormat;
0091: import java.util.Collections;
0092: import java.util.Comparator;
0093: import java.util.Iterator;
0094: import java.util.List;
0095: import java.util.Vector;
0096:
0097: import javax.mail.MethodNotSupportedException;
0098:
0099: import org.apache.log4j.Logger;
0100:
0101: import com.ivata.groupware.admin.security.server.SecuritySession;
0102: import com.ivata.groupware.admin.security.user.UserDO;
0103: import com.ivata.groupware.admin.setting.Settings;
0104: import com.ivata.groupware.business.BusinessLogic;
0105: import com.ivata.groupware.business.addressbook.AddressBook;
0106: import com.ivata.groupware.business.addressbook.person.PersonDO;
0107: import com.ivata.groupware.business.library.comment.CommentDO;
0108: import com.ivata.groupware.business.library.faq.FAQDO;
0109: import com.ivata.groupware.business.library.faq.category.FAQCategoryDO;
0110: import com.ivata.groupware.business.library.item.LibraryItemConstants;
0111: import com.ivata.groupware.business.library.item.LibraryItemDO;
0112: import com.ivata.groupware.business.library.page.PageDO;
0113: import com.ivata.groupware.business.library.topic.TopicDO;
0114: import com.ivata.groupware.business.mail.Mail;
0115: import com.ivata.groupware.business.mail.session.MailSession;
0116: import com.ivata.groupware.business.search.SearchEngine;
0117: import com.ivata.groupware.container.persistence.QueryPersistenceManager;
0118: import com.ivata.groupware.container.persistence.TimestampDOHandling;
0119: import com.ivata.groupware.web.format.SanitizerFormat;
0120: import com.ivata.mask.Mask;
0121: import com.ivata.mask.MaskFactory;
0122: import com.ivata.mask.persistence.PersistenceException;
0123: import com.ivata.mask.persistence.PersistenceSession;
0124: import com.ivata.mask.util.StringHandling;
0125: import com.ivata.mask.util.SystemException;
0126: import com.ivata.mask.validation.ValidationError;
0127: import com.ivata.mask.validation.ValidationErrors;
0128: import com.ivata.mask.validation.ValidationException;
0129: import com.ivata.mask.web.format.CharacterEntityFormat;
0130: import com.ivata.mask.web.format.FormatConstants;
0131: import com.ivata.mask.web.format.HTMLFormatter;
0132: import com.ivata.mask.web.format.LineBreakFormat;
0133:
0134: /**
0135: * @author Colin MacLeod
0136: * <a href='mailto:colin.macleod@ivata.com'>colin.macleod@ivata.com</a>
0137: * @since Mar 26, 2004
0138: * @version $Revision: 1.5 $
0139: */
0140: public class LibraryImpl extends BusinessLogic implements Library {
0141:
0142: /**
0143: * <p>This class is used to sort the comments.</p>
0144: */
0145: private class CommentComparator implements Comparator {
0146:
0147: /**
0148: * <p>Compare two objects (in this case, both are instances of Comment.</p>
0149: */
0150: public int compare(final Object o1, final Object o2) {
0151: CommentDO comment1 = (CommentDO) o1;
0152: CommentDO comment2 = (CommentDO) o2;
0153: long test1 = comment1.getModified().getTime();
0154: long test2 = comment2.getModified().getTime();
0155:
0156: // note: purposely don't allow an equals case here!! If two are
0157: // equal, then only one will appear in the final set
0158: return (test1 > test2) ? -1 : 1;
0159: }
0160: }
0161:
0162: /**
0163: * <p>This class is used to sort the library item rights.</p>
0164: */
0165: private class LibraryItemComparator implements Comparator {
0166:
0167: /**
0168: * <p>Compare two objects (in this case, both are instances of
0169: * {@link com.ivata.groupware.business.library.item.right.LibraryItemRightLocal
0170: * LibraryItemRightLocal}) and return which is the higher priority.</p>
0171: *
0172: * @param o1 first instance of {@link
0173: * com.ivata.groupware.business.library.item.right.LibraryItemRightLocal
0174: * LibraryItemRightLocal} to be compared.
0175: * @param o2 second instance of {@link
0176: * com.ivata.groupware.business.library.item.right.LibraryItemRightLocal
0177: * LibraryItemRightLocal} to be compared.
0178: * @return a negative integer, zero, or a positive integer as the first argument
0179: * comes after, same as, or before the second.
0180: */
0181: public int compare(final Object o1, final Object o2) {
0182: LibraryItemDO itemRight1 = (LibraryItemDO) o1;
0183: LibraryItemDO itemRight2 = (LibraryItemDO) o2;
0184: long test1 = itemRight1.getModified().getTime();
0185: long test2 = itemRight2.getModified().getTime();
0186:
0187: // note: purposely don't allow an equals case here!! If two are
0188: // equal, then only one will appear in the final set
0189: return (test1 > test2) ? -1 : 1;
0190: }
0191: }
0192:
0193: /**
0194: * <p>
0195: * <strong>Log4J</strong> logger.
0196: * </p>
0197: */
0198: private static Logger log = Logger.getLogger(Library.class);
0199: private AddressBook addressBook;
0200: private HTMLFormatter formatter;
0201: private Mail mail;
0202: /**
0203: * Persistence manger used to store/retrieve data objects.
0204: */
0205: private QueryPersistenceManager persistenceManager;
0206: private SearchEngine searchEngine;
0207: private Settings settings;
0208: private MaskFactory maskFactory;
0209:
0210: /**
0211: * Construct a new address book.
0212: *
0213: * @param persistenceManager used to store objects in db.
0214: */
0215: public LibraryImpl(QueryPersistenceManager persistenceManager,
0216: AddressBook addressBook, Mail mail, Settings settings,
0217: SearchEngine searchEngine, HTMLFormatter formatter,
0218: MaskFactory maskFactory) {
0219: this .persistenceManager = persistenceManager;
0220: this .addressBook = addressBook;
0221: this .mail = mail;
0222: this .settings = settings;
0223: this .searchEngine = searchEngine;
0224: this .formatter = formatter;
0225: this .maskFactory = maskFactory;
0226: }
0227:
0228: /**
0229: * <p>Add a new comment to the system. The user supplied is checked, to make
0230: * sure she has the necessary permission to add the comment, then the comment
0231: * is added and the new primary key value (id) is returned.</p>
0232: *
0233: * @throws BusinessException if the user
0234: * provided is not entitled to add this topic.
0235: * @throws BusinessException
0236: * if either the <code>subject</code>, <code>subject</code> or
0237: * <code>item id</code> fields are <code>null</code>.
0238: * @param securitySession mail session used to post notifications about the new
0239: * comment.
0240: * @param commentParam data object containing all values of the new
0241: * object to add.
0242: * @param replyToId the unique identifier of the comment this is a reply to,
0243: * or <code>null</code> if this is the first comment in a thread.
0244: * @return new value of the comment as it is now in the system.
0245: */
0246: public CommentDO addComment(final SecuritySession securitySession,
0247: final CommentDO commentParam) throws SystemException {
0248: PersistenceSession persistenceSession = persistenceManager
0249: .openSession(securitySession);
0250: try {
0251: // before creating the event, check we have reasonable data
0252: ValidationErrors errors = validate(securitySession,
0253: commentParam);
0254: if (!errors.isEmpty()) {
0255: throw new ValidationException(errors);
0256: }
0257: TimestampDOHandling.add(securitySession, commentParam);
0258: CommentDO comment = (CommentDO) persistenceManager.add(
0259: persistenceSession, commentParam);
0260:
0261: LibraryItemDO item = comment.getItem();
0262: searchEngine.updateIndex(securitySession, item.getId(),
0263: LibraryItemDO.class.getName(), item.getTopic()
0264: .getId().toString(), comment.getId(),
0265: CommentDO.class.getName(), comment.getText(),
0266: comment.getFormat());
0267: return comment;
0268: } catch (Exception e) {
0269: persistenceSession.cancel();
0270: throw new SystemException(e);
0271: } finally {
0272: persistenceSession.close();
0273: }
0274: }
0275:
0276: /**
0277: * <p>Add a new library item to the system. The <code>created</code> and
0278: * <code>modified</code> timestamps are set automatically by this method
0279: * (any values in <code>item</code> are ignored). The <code>user</code>,
0280: * <code>createdBy<code> and <code>modifiedBy<code> fields are set to the
0281: * user name you provide.</p>
0282: *
0283: * <p>For the topic, the <code>topicId</code> field is taken from the
0284: * data object: settings for the caption and image are
0285: * ignored.</p>
0286: *
0287: * @param userName the name of the user who wants to add the item. This is
0288: * used to check user rights.
0289: * @param itemParam a data object containing all the details
0290: * of the item to add.
0291: * @param securitySession mail session used to post notifications about the new
0292: * library item.
0293: * @param comment the comment used in revision control
0294: * @exception com.ivata.groupware.ejb.entity.InvalidFieldValueException
0295: * if a field has an incorrect value.
0296: * @exception com.ivata.groupware.ejb.entity.MandatoryFieldException
0297: * if a mandatory field has no value.
0298: * @exception com.ivata.groupware.ejb.entity.UserRightException if the user
0299: * provided is not entitled to add this item.
0300: * @return the new item data object, with the details as they
0301: * now are in the adressbook.
0302: */
0303: public LibraryItemDO addItem(final SecuritySession securitySession,
0304: final LibraryItemDO itemParam, final String comment)
0305: throws SystemException {
0306: LibraryItemDO item = itemParam;
0307: PersistenceSession persistenceSession = persistenceManager
0308: .openSession(securitySession);
0309: try {
0310: // before creating the event, check we have reasonable data
0311: ValidationErrors errors = validate(securitySession, item);
0312: if (!errors.isEmpty()) {
0313: throw new ValidationException(errors);
0314: }
0315:
0316: // set the page order, and set all ids null (to create new pages)
0317: if (item.getPages() != null) {
0318: Iterator pagesIterator = item.getPages().iterator();
0319: int pageNumber = 0;
0320: while (pagesIterator.hasNext()) {
0321: PageDO page = (PageDO) pagesIterator.next();
0322: // only new pages allowed!
0323: page.setId(null);
0324: page.setNumber(new Integer(pageNumber++));
0325: }
0326: }
0327:
0328: TimestampDOHandling.add(securitySession, item);
0329: item = (LibraryItemDO) persistenceManager.add(
0330: persistenceSession, item);
0331: updateSearchIndexForItem(securitySession, item);
0332:
0333: /*
0334: DirectoryDO parentDirectory = (DirectoryDO)
0335: persistenceManager.findByPrimaryKey(persistenceSession,
0336: DirectoryDO.class, DirectoryConstants.LIBRARY_DIRECTORY);
0337: // create the directory for attachments and doc versions
0338: DirectoryDO attachmentsDirectory = new DirectoryDO();
0339: attachmentsDirectory.setName(item.getId().toString());
0340: attachmentsDirectory.setParent(parentDirectory);
0341: // TODO attachmentsDirectory = drive.addDirectory(securitySession, attachmentsDirectory);
0342:
0343: DirectoryDO versionsDirectory = new DirectoryDO();
0344: versionsDirectory.setName("versions");
0345: versionsDirectory.setParent(attachmentsDirectory);
0346: // TODO versionsDirectory = drive.addDirectory(securitySession, versionsDirectory);
0347:
0348:
0349: // commit this ITEM do CVS as XML file
0350: DriveFileDO driveFile = new DriveFileDO();
0351:
0352: String tmpItemFilePath;
0353: try {
0354: tmpItemFilePath = item.saveToFile();
0355: } catch(IOException e) {
0356: log.error("Saving to file.", e);
0357: throw new SystemException(e);
0358: }
0359: File tmpFile = new File(tmpItemFilePath);
0360:
0361: driveFile.setDirectory(versionsDirectory);
0362: driveFile.setName("document.xml");
0363: driveFile.setMimeType("text/xml");
0364: driveFile.setSize(new Integer((int)(tmpFile.length())));
0365: FileRevisionDO fileRevision = new FileRevisionDO();
0366: fileRevision.setComment(StringHandling.getNotNull(comment, "new revision"));
0367: driveFile.setHeadRevision(fileRevision);
0368:
0369: // drive.checkAndCreate("library" + File.separator + this.getId() + File.separator + "versions" + File.separator, item.getCreatedBy());
0370: // TODO drive.commitFile(securitySession, driveFile, tmpItemFilePath);
0371: // delete tmp file
0372: tmpFile.delete();
0373: tmpFile = null;
0374: */
0375: } catch (Exception e) {
0376: persistenceSession.cancel();
0377: throw new SystemException(e);
0378: } finally {
0379: persistenceSession.close();
0380: }
0381: notifyForSubmission(securitySession, item, true);
0382: return item;
0383: }
0384:
0385: /**
0386: * <p>Add a new topic to the system. The user supplied is checked, to make
0387: * sure she has the necessary permission to add the topic, then the topic
0388: * is added and the new primary key value (id) is returned.</p>
0389: *
0390: * @exception com.ivata.groupware.ejb.entity.UserRightException if the user
0391: * provided is not entitled to add this topic.
0392: * @exception com.ivata.groupware.ejb.entity.InvalidFieldValueException
0393: * if either the <code>caption</code> or <code>image</code> fields are
0394: * <code>null</code>.
0395: * @param userName the user who is trying to add the topic (to check the
0396: * user right permissions).
0397: * @param topic details of new TOPIC.
0398: *
0399: * @return TopicDO which was added.
0400: */
0401: public TopicDO addTopic(final SecuritySession securitySession,
0402: final TopicDO topic) throws SystemException {
0403: PersistenceSession persistenceSession = persistenceManager
0404: .openSession(securitySession);
0405: try {
0406: // before creating the event, check we have reasonable data
0407: ValidationErrors errors = validate(securitySession, topic);
0408: if (!errors.isEmpty()) {
0409: throw new ValidationException(errors);
0410: }
0411: return (TopicDO) persistenceManager.add(persistenceSession,
0412: topic);
0413: } catch (Exception e) {
0414: persistenceSession.cancel();
0415: throw new SystemException(e);
0416: } finally {
0417: persistenceSession.close();
0418: }
0419: }
0420:
0421: /**
0422: * <p>Amend an existing comment in the system. The user supplied is
0423: * checked, to make sure she has the necessary permission to amend the
0424: * comment, then the comment is changed and the current comment values
0425: * are returned, as they now are in the database.</p>
0426: *
0427: * @exception com.ivata.groupware.ejb.entity.UserRightException if the user
0428: * provided is not entitled to add this topic.
0429: * @exception com.ivata.groupware.ejb.entity.MandatoryFieldException
0430: * if the <code>id</code> field is <code>null</code>.
0431: * @param userName the user who is trying to add the comment (to check the
0432: * user right permissions).
0433: * @param comment data object containing all values of the
0434: * object to amend.
0435: * @param securitySession mail session used to post notifications about the amended
0436: * comment.
0437: * @return new value of the comment as it is now in the system.
0438: */
0439: public CommentDO amendComment(
0440: final SecuritySession securitySession,
0441: final CommentDO comment) throws SystemException {
0442: PersistenceSession persistenceSession = persistenceManager
0443: .openSession(securitySession);
0444: try {
0445: // before changing the event, check we have reasonable data
0446: ValidationErrors errors = validate(securitySession, comment);
0447: if (!errors.isEmpty()) {
0448: throw new ValidationException(errors);
0449: }
0450: TimestampDOHandling.amend(securitySession, comment);
0451: persistenceManager.amend(persistenceSession, comment);
0452:
0453: LibraryItemDO item = comment.getItem();
0454: searchEngine.updateIndex(securitySession, item.getId(),
0455: LibraryItemDO.class.getName(), item.getTopic()
0456: .getId().toString(), comment.getId(),
0457: CommentDO.class.getName(), comment.getText(),
0458: comment.getFormat());
0459: return comment;
0460: } catch (Exception e) {
0461: persistenceSession.cancel();
0462: throw new SystemException(e);
0463: } finally {
0464: persistenceSession.close();
0465: }
0466: }
0467:
0468: /**
0469: * <p>Amend an existing library item in the system. The
0470: * <code>modified</code> timestamp is set automatically by this method
0471: * (any values in <code>item</code> are ignored). Values for the
0472: * <code>created</code> timestamp are not changed.</p>
0473: *
0474: * <p>The <code>modifiedBy<code> field is set to the user name you
0475: * provide.</p>
0476: *
0477: * <p>For the topic, the <code>topicId</code> field is taken from the
0478: * data object: settings for the caption and image are
0479: * ignored.</p>
0480: *
0481: * @param userName the name of the user who wants to amend the item. This is
0482: * used to check user rights.
0483: * @param item a data object containing all the details
0484: * of the item to amend.
0485: * @param securitySession mail server used to post notifications about the amended
0486: * library item.
0487: * @param comment the comment used in revision control
0488: * @exception com.ivata.groupware.ejb.entity.MandatoryFieldException
0489: * if a mandatory field has no value.
0490: * @exception com.ivata.groupware.ejb.entity.UserRightException if the user
0491: * provided is not entitled to add this item.
0492: * @return the new item data object, with the details as they
0493: * now are in the adressbook.
0494: */
0495: public LibraryItemDO amendItem(
0496: final SecuritySession securitySession,
0497: final LibraryItemDO item, final String comment)
0498: throws SystemException {
0499: PersistenceSession persistenceSession = persistenceManager
0500: .openSession(securitySession);
0501: try {
0502: // before changing the event, check we have reasonable data
0503: ValidationErrors errors = validate(securitySession, item);
0504: if (!errors.isEmpty()) {
0505: throw new ValidationException(errors);
0506: }
0507: // set the page order
0508: if (item.getPages() != null) {
0509: Iterator pagesIterator = item.getPages().iterator();
0510: int pageNumber = 0;
0511: while (pagesIterator.hasNext()) {
0512: PageDO page = (PageDO) pagesIterator.next();
0513: page.setNumber(new Integer(pageNumber++));
0514: }
0515: }
0516: TimestampDOHandling.amend(securitySession, item);
0517: persistenceManager.amend(persistenceSession, item);
0518: updateSearchIndexForItem(securitySession, item);
0519:
0520: /*TODO
0521: DirectoryDO attachmentsDirectory = (DirectoryDO)
0522: persistenceManager.find(persistenceSession,
0523: "driveDirectoryByParentIdName",
0524: new Object[] {DirectoryConstants.LIBRARY_DIRECTORY, item.getId().toString()});
0525: DirectoryDO versionsDirectory = (DirectoryDO)
0526: persistenceManager.find(persistenceSession,
0527: "driveDirectoryByParentIdName",
0528: new Object[] {attachmentsDirectory.getId(), "versions"});
0529:
0530: String tmpItemFilePath;
0531: try {
0532: tmpItemFilePath = item.saveToFile();
0533: } catch (IOException e) {
0534: throw new SystemException(e);
0535: }
0536: File tmpFile = new File(tmpItemFilePath);
0537:
0538: // commit the new version
0539: DriveFileDO driveFile = new DriveFileDO();
0540:
0541: driveFile.setDirectory(versionsDirectory);
0542: driveFile.setName("document.xml");
0543: driveFile.setMimeType("text/xml");
0544: driveFile.setSize(new Integer((int)tmpFile.length()));
0545: FileRevisionDO fileRevision = new FileRevisionDO();
0546: fileRevision.setComment(StringHandling.getNotNull(comment, "new revision"));
0547: driveFile.setHeadRevision(fileRevision);
0548:
0549: drive.commitFile(securitySession, driveFile, tmpItemFilePath);
0550: // delete tmp file
0551: tmpFile.delete();
0552: tmpFile = null;
0553: */
0554:
0555: notifyForSubmission(securitySession, item, false);
0556: return item;
0557: } catch (Exception e) {
0558: persistenceSession.cancel();
0559: throw new SystemException(e);
0560: } finally {
0561: persistenceSession.close();
0562: }
0563: }
0564:
0565: /**
0566: * <p>Amend an existing topic in the system. The user supplied is checked,
0567: * to make sure she has the necessary permission to amend the topic, then
0568: * the topic is changed.</p>
0569: *
0570: * @exception com.ivata.groupware.ejb.entity.UserRightException if the user
0571: * provided is not entitled to amend this topic.
0572: * @exception com.ivata.groupware.ejb.entity.InvalidFieldValueException
0573: * if the id provided is <code>null</code>.
0574: * @param userName the user who is trying to add the topic (to check the
0575: * user right permissions).
0576: * @param topic details of TOPIC.
0577: *
0578: * @return TopicDO which was amend
0579: */
0580: public TopicDO amendTopic(final SecuritySession securitySession,
0581: final TopicDO topic) throws SystemException {
0582: PersistenceSession persistenceSession = persistenceManager
0583: .openSession(securitySession);
0584: try {
0585: // before changing the event, check we have reasonable data
0586: ValidationErrors errors = validate(securitySession, topic);
0587: if (!errors.isEmpty()) {
0588: throw new ValidationException(errors);
0589: }
0590: persistenceManager.amend(persistenceSession, topic);
0591: return topic;
0592: } catch (Exception e) {
0593: persistenceSession.cancel();
0594: throw new SystemException(e);
0595: } finally {
0596: persistenceSession.close();
0597: }
0598: }
0599:
0600: /**
0601: * <p>
0602: * Find out how many comments exists in total for a library item.
0603: * </p>
0604: *
0605: * @param itemId unique identifier for the item to count comments for.
0606: * @return Total number of comments for the library item specified.
0607: */
0608: public int countCommentsForItem(
0609: final SecuritySession securitySession, final Integer itemId)
0610: throws SystemException {
0611: PersistenceSession persistenceSession = persistenceManager
0612: .openSession(securitySession);
0613: try {
0614: Integer count = persistenceManager.findInteger(
0615: persistenceSession, "libraryCountCommentByItemId",
0616: new Object[] { itemId });
0617: return (count == null) ? 0 : count.intValue();
0618: } catch (Exception e) {
0619: persistenceSession.cancel();
0620: throw new SystemException(e);
0621: } finally {
0622: persistenceSession.close();
0623: }
0624: }
0625:
0626: /**
0627: * <p>Locate a list of top-level comments in a specificy item. Note:
0628: * this does not include comments which are replies - only top-level
0629: * comments</p>
0630: *
0631: * @param itemId the unique identifier of comment item to locate.
0632: * @return data object containing all values of the
0633: * object as they are now in the system.
0634: */
0635: public List findCommentByItem(
0636: final SecuritySession securitySession, final Integer itemId)
0637: throws SystemException {
0638: PersistenceSession persistenceSession = persistenceManager
0639: .openSession(securitySession);
0640: try {
0641: return persistenceManager.find(persistenceSession,
0642: "libraryCommentByItemId", new Object[] { itemId });
0643: } catch (Exception e) {
0644: persistenceSession.cancel();
0645: throw new SystemException(e);
0646: } finally {
0647: persistenceSession.close();
0648: }
0649: }
0650:
0651: /**
0652: * <p>Locate a list of comments in the system by their parents.</p>
0653: *
0654: * @param parentId the unique identifier of parent comment to locate.
0655: * @return data object containing all values of the
0656: * object as they are now in the system.
0657: */
0658: public List findCommentByParent(
0659: final SecuritySession securitySession,
0660: final Integer parentId) throws SystemException {
0661: PersistenceSession persistenceSession = persistenceManager
0662: .openSession(securitySession);
0663: try {
0664: return persistenceManager.find(persistenceSession,
0665: "libraryCommentByParentId",
0666: new Object[] { parentId });
0667: } catch (Exception e) {
0668: persistenceSession.cancel();
0669: throw new SystemException(e);
0670: } finally {
0671: persistenceSession.close();
0672: }
0673: }
0674:
0675: /**
0676: * <p>Locate a comment in the system by its unique identifier, and return
0677: * all the comment values.</p>
0678: *
0679: * @exception com.ivata.groupware.ejb.entity.MandatoryFieldException
0680: * if the <code>id</code> field is <code>null</code>.
0681: * @param id the unique identifier of the comment to locate.
0682: * @return data object containing all values of the
0683: * object as they are now in the system.
0684: */
0685: public CommentDO findCommentByPrimaryKey(
0686: final SecuritySession securitySession, final Integer id)
0687: throws SystemException {
0688: PersistenceSession persistenceSession = persistenceManager
0689: .openSession(securitySession);
0690: try {
0691: return (CommentDO) persistenceManager.findByPrimaryKey(
0692: persistenceSession, CommentDO.class, id);
0693: } catch (Exception e) {
0694: persistenceSession.cancel();
0695: throw new SystemException(e);
0696: } finally {
0697: persistenceSession.close();
0698: }
0699: }
0700:
0701: /**
0702: * <p>Find an item in the library by its unique identifier.</p>
0703: *
0704: * @param id the unique identifier of the library item to find.
0705: * @return the library item data object which matches this id,
0706: * with the details as they now are in the library.
0707: */
0708: public LibraryItemDO findItemByPrimaryKey(
0709: final SecuritySession securitySession, final Integer id)
0710: throws SystemException {
0711: PersistenceSession persistenceSession = persistenceManager
0712: .openSession(securitySession);
0713: try {
0714: return (LibraryItemDO) persistenceManager.findByPrimaryKey(
0715: persistenceSession, LibraryItemDO.class, id);
0716: } catch (Exception e) {
0717: persistenceSession.cancel();
0718: throw new SystemException(e);
0719: } finally {
0720: persistenceSession.close();
0721: }
0722: }
0723:
0724: /**
0725: * <p>This merhod searches for an item by revision.</p>
0726: *
0727: * @param rev revision number
0728: * @param userName user who is doing this
0729: * @return
0730: */
0731: public LibraryItemDO findItemByRevision(
0732: final SecuritySession securitySession, final String itemId,
0733: final String rev) throws SystemException {
0734: PersistenceSession persistenceSession = persistenceManager
0735: .openSession(securitySession);
0736: try {
0737: // let's find actual version
0738: LibraryItemDO item = (LibraryItemDO) persistenceManager
0739: .findByPrimaryKey(persistenceSession,
0740: LibraryItemDO.class, itemId);
0741:
0742: /*TODO
0743: // let's find revision
0744: DriveLocalHome driveHome = (DriveLocalHome)
0745: ApplicationServer.findLocalHome("DriveLocal",
0746: DriveLocalHome.class);
0747: DriveLocal drive = driveHome.create();
0748:
0749: DriveFileDO versionsFileDO =
0750: drive.findFileByPathFileName("/library/" + item.getId().toString() + "/versions", "document.xml", userName);
0751: FileContentDO fileContent = drive.getFileRevision(versionsFileDO.getId(), rev, userName);
0752:
0753: // convert xml file to ItemDO
0754: item = itemHome.convertFileToItem(fileContent);
0755: */
0756: return item;
0757: } catch (Exception e) {
0758: persistenceSession.cancel();
0759: throw new SystemException(e);
0760: } finally {
0761: persistenceSession.close();
0762: }
0763: }
0764:
0765: /**
0766: * <p>Find items sorted by modification date/time, to the count provided in
0767: * the parameter. If there are less items in the library than
0768: * <code>count</code>, then all library items are returned.</p>
0769: *
0770: * <p>The items are filtered using a view, so that only those items with the
0771: * <code>access</code> level indicated are shown for the user requested.</p>
0772: *
0773: * @param count the total number of items to return. Specify
0774: * <code>null</code> to return all items.
0775: * @param userName the user to display results for. The results filtered so
0776: * that only those items are return which the user is entitled to see.
0777: * @param access the access level which the user should see. This is defined
0778: * as one of the constants in {@link
0779: * com.ivata.groupware.business.addressbook.person.user.group.right.RightConstants
0780: * RightConstants}.
0781: * @param topicId unique identifier of the topic to filter items for, or all
0782: * topics, if <code>null</code>.
0783: * @return a <code>Collection</code> of all of the item as {@link
0784: * LibraryItemDO item dependent value}
0785: * instances.
0786: */
0787: public List findRecentItems(final SecuritySession securitySession,
0788: final Integer count, final Integer access,
0789: final Integer topicId) throws SystemException {
0790: PersistenceSession persistenceSession = persistenceManager
0791: .openSession(securitySession);
0792: try {
0793: if (topicId == null) {
0794: return Collections
0795: .synchronizedList(persistenceManager.find(
0796: persistenceSession,
0797: "libraryItemRecent", new Object[] {},
0798: count, new Integer(0)));
0799: } else {
0800: return Collections.synchronizedList(persistenceManager
0801: .find(persistenceSession,
0802: "libraryItemRecentByTopic",
0803: new Object[] { topicId }, count,
0804: new Integer(0)));
0805: }
0806: } catch (Exception e) {
0807: persistenceSession.cancel();
0808: throw new SystemException(e);
0809: } finally {
0810: persistenceSession.close();
0811: }
0812: }
0813:
0814: /**
0815: * <p>when we need to find library item by meeting ID</p>
0816: *
0817: * @return libraryItemDO
0818: */
0819: /* public LibraryItemDO findItemByMeetingId(String id) {
0820: LibraryItemDO item = null;
0821:
0822: // check we have an id
0823: if (id == null) {
0824: throw new EJBException("Please specify an id to find. Cannot find an item with a null id.");
0825: }
0826: try {
0827: LibraryItemDOHome itemHome = (LibraryItemDOHome)
0828: ApplicationServer.findLocalHome("LibraryItemDO",
0829: LibraryItemDOHome.class);
0830: MeetingLocalHome meetingHome = (MeetingLocalHome)
0831: ApplicationServer.findLocalHome("MeetingLocal",
0832: MeetingLocalHome.class);
0833: MeetingLocal meeting = meetingHome.findByPrimaryKey(id);
0834: LibraryItemDO item = itemHome.findByPrimaryKey(meeting.getLibraryItem().getId());
0835:
0836: item = item.getDO();
0837: } catch (NamingException e) {
0838: throw new EJBException(e);
0839: } catch (FinderException e) {
0840: throw new EJBException(e);
0841: }
0842: return item;
0843: }*/
0844:
0845: /**
0846: * <p>Find Topic by primary keyand return <code>TopicDO.</code></p>
0847: *
0848: * @param id of Topic which we are trying yo find
0849: * @return TopicDO which is containing all details of finded Topic
0850: */
0851: public TopicDO findTopicByPrimaryKey(
0852: final SecuritySession securitySession, final Integer id)
0853: throws SystemException {
0854: PersistenceSession persistenceSession = persistenceManager
0855: .openSession(securitySession);
0856: try {
0857: return (TopicDO) persistenceManager.findByPrimaryKey(
0858: persistenceSession, TopicDO.class, id);
0859: } catch (Exception e) {
0860: persistenceSession.cancel();
0861: throw new SystemException(e);
0862: } finally {
0863: persistenceSession.close();
0864: }
0865: }
0866:
0867: /**
0868: * <p>Find all topics with the given access rights for the user name
0869: * provided.</p>
0870: *
0871: * @param userName the user to display results for. The results filtered so
0872: * that only those topics are return which the user is entitled to access.
0873: * @param access the access level which the user should see. This is defined
0874: * as one of the constants in {@link
0875: * com.ivata.groupware.business.addressbook.person.user.group.right.RightConstants
0876: * RightConstants}.
0877: * @param detail, at this moment we are trying to find Topics for :
0878: * - add, amend, delete and view LIBRARY ITEMS
0879: * - amend, delete and view TOPICS
0880: * @return a <code>List</code> containing two <code>Map</code>s. The map
0881: * in element <code>0</code> contains a <code>Map</code> of all of the
0882: * topic captions. The map in element <code>1</code> contains a
0883: * <code>Map</code> of all of the topic images. In each <code>Map</code>,
0884: * the key is topic id.
0885: */
0886: public List findTopics(final SecuritySession securitySession)
0887: throws SystemException {
0888: PersistenceSession persistenceSession = persistenceManager
0889: .openSession(securitySession);
0890: try {
0891: return Collections.synchronizedList(persistenceManager
0892: .findAll(persistenceSession, TopicDO.class));
0893: } catch (Exception e) {
0894: persistenceSession.cancel();
0895: throw new SystemException(e);
0896: } finally {
0897: persistenceSession.close();
0898: }
0899: }
0900:
0901: /**
0902: * <p>Find all comments to which there has been no reply.</p>
0903: * @param userName
0904: * @param count
0905: * @return
0906: */
0907: public List findUnacknowledgedComments(
0908: final SecuritySession securitySession, final Integer count)
0909: throws SystemException {
0910: PersistenceSession persistenceSession = persistenceManager
0911: .openSession(securitySession);
0912: try {
0913: return Collections
0914: .synchronizedList(persistenceManager
0915: .find(
0916: persistenceSession,
0917: "libraryCommentByUserNameUnacknowledged",
0918: new Object[] {
0919: securitySession.getUser()
0920: .getName(),
0921: Boolean.FALSE }, count,
0922: new Integer(0)));
0923: } catch (Exception e) {
0924: persistenceSession.cancel();
0925: throw new SystemException(e);
0926: } finally {
0927: persistenceSession.close();
0928: }
0929: }
0930:
0931: /**
0932: * <p>Helper method. Notify everyone who can view a certain topic of a new
0933: * submission. This could be a new library item or a new comment.</p>
0934: *
0935: * @param submission instance of either <code>LibraryItemDO</code> or
0936: * <code>CommentDO</code>.
0937: * @param isNew set to <code>true</code> if this is a new submission,
0938: * otherwise false.
0939: * @param userName the user who has entered the new item or comment.
0940: * @param securitySession mail session used to post notifications.
0941: * @throws NotificationException if the mail cannot be sent for any reason.
0942: */
0943: private void notifyForSubmission(
0944: final SecuritySession securitySession,
0945: final Object submission, final boolean isNew)
0946: throws NotificationException, PersistenceException {
0947: // prerequisite: ignore any submission which didn't supply a valid mail object
0948: if (securitySession == null) {
0949: // just return: in codetutorial.com, for example, we don't want
0950: // notifications
0951: return;
0952: }
0953: PersistenceSession persistenceSession = persistenceManager
0954: .openSession(securitySession);
0955: String senderAddress = null;
0956: List recipientAddresses = null;
0957: List to = null;
0958: List cc = null;
0959: try {
0960: UserDO user = securitySession.getUser();
0961:
0962: String URL = settings.getStringSetting(securitySession,
0963: "pathContext", user);
0964:
0965: Integer topicId; // topic of the item
0966: UserDO originalAuthor = null; // person who wrote original item/comment
0967: UserDO author; // author of this submission
0968: senderAddress = "\"ivata groupware library\" <" // email address for replies
0969: + settings.getStringSetting(securitySession,
0970: "emailLibrary", user) + ">";
0971: String content; // content of the message
0972: String subject; // subject of the comment or title of the item
0973:
0974: // let's look at the submission item
0975: // itself, to find out spcifically who this is addressed to
0976: if (LibraryItemDO.class.isInstance(submission)) {
0977: LibraryItemDO item = (LibraryItemDO) submission;
0978: String settingName = "libraryNotificationContentItem";
0979:
0980: topicId = item.getTopic().getId();
0981: author = item.getCreatedBy();
0982: subject = item.getTitle();
0983: URL += "/display.jsp?id=" + item.getId();
0984: // if this is a change, rather than a new submission, append "Amend"
0985: // to the setting name
0986: if (!isNew) {
0987: settingName += "Amend";
0988: author = item.getModifiedBy();
0989: }
0990: String[] arguments = { author.getName(),
0991: item.getTitle(), item.getSummary(), URL };
0992: String setting = settings.getStringSetting(
0993: securitySession, settingName, user);
0994:
0995: if (setting == null) {
0996: throw new SystemException(
0997: "ERROR in Library.notifyForSubmission: "
0998: + "the administrator must set the system setting '"
0999: + settingName + "'");
1000: }
1001: content = MessageFormat.format(setting, arguments);
1002: } else {
1003: // check this really _is_ a comment
1004: if (!CommentDO.class.isInstance(submission)) {
1005: throw new SystemException(
1006: "ERROR in Library: cannot notify on "
1007: + "submission of class '"
1008: + submission.getClass() + "'");
1009: }
1010: CommentDO comment = (CommentDO) submission;
1011:
1012: topicId = comment.getItem().getTopic().getId();
1013: author = comment.getCreatedBy();
1014: subject = comment.getSubject();
1015:
1016: // if this is a reply to another comment, the original author is
1017: // the author of that comment
1018: String settingName, replyTitle, replySummary, commentText;
1019:
1020: int formatOfOrigComment = -1;
1021: int formatOfComment = comment.getFormat();
1022:
1023: if (comment.getParent() != null) {
1024: originalAuthor = comment.getParent().getCreatedBy();
1025: settingName = "libraryNotificationContentComment";
1026: replyTitle = comment.getParent().getSubject();
1027: replySummary = comment.getParent().getText();
1028: formatOfOrigComment = comment.getParent()
1029: .getFormat();
1030: // for case that comment was changed
1031: // carefull user could change not his comment
1032: if (!isNew) {
1033: settingName += "Amend";
1034: if (!author.getId().equals(user.getId())) {
1035: settingName += "Strange";
1036: author = user;
1037: originalAuthor = comment.getCreatedBy();
1038: replyTitle = comment.getSubject();
1039: }
1040: }
1041: } else {
1042: // otherwise the original author is the author of the
1043: // item
1044: originalAuthor = comment.getItem().getCreatedBy();
1045: settingName = "libraryNotificationContentItemReply";
1046: replyTitle = comment.getItem().getTitle();
1047: replySummary = comment.getItem().getSummary();
1048: formatOfOrigComment = FormatConstants.FORMAT_HTML;
1049: // for case that comment was changed
1050: if (!isNew) {
1051: settingName += "Amend";
1052: if (!author.getId().equals(user.getId())) {
1053: author = user;
1054: settingName = "libraryNotificationContentCommentAmendStrange";
1055: originalAuthor = comment.getCreatedBy();
1056: replyTitle = comment.getSubject();
1057: }
1058: }
1059: }
1060: commentText = comment.getText();
1061: LineBreakFormat lineBreakFormat = new LineBreakFormat();
1062:
1063: lineBreakFormat.setConvertLineBreaks(true);
1064: formatter.add(new CharacterEntityFormat());
1065: formatter.add(lineBreakFormat);
1066: if (formatOfComment == FormatConstants.FORMAT_TEXT) {
1067: // if this is a plain text message, do HTML paragraph
1068: commentText = formatter.format(commentText);
1069: }
1070: if (formatOfOrigComment == FormatConstants.FORMAT_TEXT) {
1071: // if this is a plain text message, do HTML paragraph
1072: replySummary = formatter.format(replySummary);
1073: }
1074: URL += "/display.jsp?id=" + comment.getItem().getId()
1075: + "#comments";
1076: String[] arguments = { author.getName(),
1077: originalAuthor.getName(), replyTitle,
1078: replySummary, comment.getSubject(),
1079: commentText, URL };
1080: String setting = settings.getStringSetting(
1081: securitySession, settingName, user);
1082:
1083: if (setting == null) {
1084: throw new SystemException(
1085: "ERROR in Library.notifyForSubmission: "
1086: + "the administrator must set the system setting '"
1087: + settingName + "'");
1088: }
1089: content = MessageFormat.format(setting, arguments);
1090: }
1091: // next thing to do is construct a set of all of the recipients of
1092: // the message
1093: // TODO: users should subscribe
1094: List recipients = persistenceManager.findAll(
1095: persistenceSession, UserDO.class);
1096:
1097: // now remove the author from the recipients
1098: recipients.remove(author);
1099: // if there is an original author, remove her from the recipients too
1100: PersonDO originalAuthorPerson = null;
1101: if (originalAuthor != null) {
1102: recipients.remove(originalAuthor);
1103: originalAuthorPerson = addressBook
1104: .findPersonByUserName(securitySession,
1105: originalAuthor.getName());
1106: }
1107: // since we are using the remote mail interface, we need to convert
1108: // the emailAddressses here
1109: recipientAddresses = new Vector(recipients.size());
1110:
1111: for (Iterator i = recipients.iterator(); i.hasNext();) {
1112: UserDO this User = (UserDO) i.next();
1113: // only add enabled users
1114: PersonDO this Person = addressBook.findPersonByUserName(
1115: securitySession, this User.getName());
1116: String address = this Person.getEmailAddress();
1117:
1118: if (user.isEnabled() && !user.isDeleted()
1119: && (address != null)) {
1120: recipientAddresses.add(address);
1121: }
1122: }
1123: String address;
1124:
1125: // if there is an original author, we'll use that person as the 'to'
1126: // recipient and make everyone else a cc
1127: if ((originalAuthor != null)
1128: && (!originalAuthor.isDeleted())
1129: && ((address = originalAuthorPerson
1130: .getEmailAddress()) != null)) {
1131: to = new Vector();
1132: to.add(address);
1133: cc = recipientAddresses;
1134: } else {
1135: to = recipientAddresses;
1136: cc = null;
1137: }
1138: String contentType = settings.getStringSetting(
1139: securitySession, "libraryNotificationContentType",
1140: user);
1141: if (!to.isEmpty()
1142: && (securitySession instanceof MailSession)) {
1143: mail.send((MailSession) securitySession, senderAddress,
1144: to, cc, null, subject, content, contentType,
1145: false);
1146: }
1147: } catch (Exception e) {
1148: persistenceSession.cancel();
1149: List allRecipients = new Vector();
1150: if (to != null) {
1151: allRecipients.addAll(to);
1152: }
1153: if (cc != null) {
1154: allRecipients.addAll(cc);
1155: }
1156: throw new NotificationException(e, senderAddress,
1157: allRecipients);
1158: } finally {
1159: persistenceSession.close();
1160: }
1161: }
1162:
1163: /**
1164: * <p>Remove an existing comment from the system. The user supplied is
1165: * checked, to make sure she has the necessary permission to remove the
1166: * comment, then the comment is removed.</p>
1167: *
1168: * @exception com.ivata.groupware.ejb.entity.UserRightException if the user
1169: * provided is not entitled to add this topic.
1170: * @exception com.ivata.groupware.ejb.entity.MandatoryFieldException
1171: * if the <code>id</code> field is <code>null</code>.
1172: * @param userName the user who is trying to add the comment (to check the
1173: * user right permissions).
1174: * @param comment data object containing all values of the
1175: * object to amend. Only the <code>id</code> field is read.
1176: */
1177: public void removeComment(final SecuritySession securitySession,
1178: final CommentDO comment) throws SystemException {
1179: PersistenceSession persistenceSession = persistenceManager
1180: .openSession(securitySession);
1181: try {
1182: persistenceManager.remove(persistenceSession, comment
1183: .getClass(), comment.getId());
1184: } catch (Exception e) {
1185: persistenceSession.cancel();
1186: throw new SystemException(e);
1187: } finally {
1188: persistenceSession.close();
1189: }
1190: }
1191:
1192: /**
1193: * <p>Remove a library item to the system. The item with the id specified in
1194: * <code>item</code> is removed.</p>
1195: *
1196: * @param userName the name of the user who wants to add the item. This is
1197: * used to check user rights.
1198: * @param item a data object containing all the details
1199: * of the item to remove. Only the <code>id</code> from this object is
1200: * actually used.
1201: * @exception com.ivata.groupware.ejb.entity.UserRightException if the user
1202: * provided is not entitled to add this item.
1203: */
1204: public void removeItem(final SecuritySession securitySession,
1205: final LibraryItemDO item) throws SystemException {
1206: PersistenceSession persistenceSession = persistenceManager
1207: .openSession(securitySession);
1208: try {
1209: /* TODO
1210: searchEngine.removeFromIndex(securitySession,
1211: LibraryItemDO.class.getName(),
1212: item.getId(), item.getTopic().getId().toString());
1213: */
1214: persistenceManager.remove(persistenceSession, item
1215: .getClass(), item.getId());
1216:
1217: /*TODO // remove the directory with attachments (if any)
1218: // remove attachments and versions recursively
1219: DirectoryDO directory = (DirectoryDO)
1220: persistenceManager.findInstance(persistenceSession,
1221: "libraryDirectoryByParentIdName",
1222: new Object[] {
1223: DirectoryConstants.LIBRARY_DIRECTORY,
1224: item.getId().toString()});
1225:
1226: drive.removeDirectory(securitySession, directory);
1227: */
1228: } catch (Exception e) {
1229: persistenceSession.cancel();
1230: throw new SystemException(e);
1231: } finally {
1232: persistenceSession.close();
1233: }
1234: }
1235:
1236: /**
1237: * <p>Remove a topic from the system. The user supplied is checked,
1238: * to make sure she has the necessary permission to remove the topic, then
1239: * the topic is removed.</p>
1240: *
1241: * @exception com.ivata.groupware.ejb.entity.UserRightException if the user
1242: * provided is not entitled to remove this topic.
1243: * @exception com.ivata.groupware.ejb.entity.InvalidFieldValueException
1244: * if the id provided is <code>null</code> or doesn't exist.
1245: * @param userName the user who is trying to add the topic (to check the
1246: * user right permissions).
1247: * @param topic topic which we are going to remove.
1248: */
1249: public void removeTopic(final SecuritySession securitySession,
1250: final TopicDO topic) throws SystemException {
1251: PersistenceSession persistenceSession = persistenceManager
1252: .openSession(securitySession);
1253: try {
1254: persistenceManager.remove(persistenceSession, topic
1255: .getClass(), topic.getId());
1256: } catch (Exception e) {
1257: persistenceSession.cancel();
1258: throw new SystemException(e);
1259: } finally {
1260: persistenceSession.close();
1261: }
1262: }
1263:
1264: /**
1265: * <p>
1266: * TODO
1267: * </p>
1268: *
1269: * @param itemId
1270: * @param revision
1271: * @param userName
1272: * @return
1273: */
1274: public LibraryItemDO revertItemToRevision(
1275: final SecuritySession securitySession, final String itemId,
1276: final String revision, final String comment)
1277: throws SystemException {
1278: throw new SystemException(new MethodNotSupportedException(
1279: "ERROR: revertItemToRevision not implemented."));
1280: /*TODO LibraryItemDO revisedItemDO = null;
1281:
1282: try {
1283: if (itemId == null) {
1284: throw new InvalidFieldValueException("You must specify an identifier to revert a library item");
1285: }
1286: // find the current version
1287: LibraryItemDO item = itemHome.findByPrimaryKey(itemId);
1288:
1289: DriveLocalHome driveHome = (DriveLocalHome)
1290: ApplicationServer.findLocalHome("DriveLocal",
1291: DriveLocalHome.class);
1292: DriveLocal drive = driveHome.create();
1293:
1294: // fidn Id of file
1295: DriveFileDO versionsFileDO =
1296: drive.findFileByPathFileName("/library/" + itemId.toString() + "/versions", "document.xml", userName);
1297:
1298: // find that head revision in CVS
1299: FileContentDO fileContent = drive.getFileRevision(versionsFileDO.getId(), revision, userName);
1300:
1301: // convert xml file to ItemDO
1302: revisedItemDO = itemHome.convertFileToItem(fileContent);
1303: // try to find that TOPIC, if not we will stay on actual
1304: try {
1305: TopicDO topic = topicHome.findByPrimaryKey(revisedItemDO.getTopicId());
1306: } catch (FinderException e) {
1307: revisedItemDO.setTopicId(item.getTopic().getId());
1308: }
1309: // if user changed topic we have to ask if user has right to add to that topic
1310: // if he didn't changed topic so we have to ask if he has right amend in that topic
1311: boolean canAmend = false;
1312:
1313: if (item.getTopic().getId().equals(revisedItemDO.getTopicId())) {
1314: canAmend = rights.canAmendInTopic(userName, item.getTopic().getId());
1315: } else {
1316: canAmend = rights.canAddToTopic(userName, revisedItemDO.getTopicId());
1317: }
1318: if (!canAmend && !userName.equals(item.getCreatedBy().getIntranetUserName())) {
1319: TopicDO topic = topicHome.findByPrimaryKey(item.getTopic().getId());
1320:
1321: throw new UserRightException("You do not have the necessary rights to amend an item in '" +
1322: topic.getCaption() +
1323: "'");
1324: }
1325:
1326: // let's do the business
1327: revisedItemDO.setModifiedBy(userName);
1328: revisedItemDO.setCreated(item.getCreated());
1329: revisedItemDO = item.setDO(revisedItemDO, comment);
1330:
1331: // submit the new version:
1332: Integer attachmentsDirectoryId =
1333: directoryHome.findByParentIdName(DirectoryConstants.LIBRARY_DIRECTORY, item.getId().toString()).getId();
1334: Integer versionsDirectoryId =
1335: directoryHome.findByParentIdName(attachmentsDirectoryId, "versions").getId();
1336:
1337:
1338: String tmpItemFilePath = item.convertItemToFile(revisedItemDO);
1339:
1340: // commit the new version
1341: DriveFileDO driveFile = new DriveFileDO();
1342: File tmpFile = new File(tmpItemFilePath);
1343:
1344: driveFile.setDirectoryId(versionsDirectoryId);
1345: driveFile.setFileName("document.xml");
1346: driveFile.setMimeType("text/xml");
1347: driveFile.setSize(new Integer((int)tmpFile.length()));
1348: FileRevisionDO fileRevision = new FileRevisionDO();
1349: fileRevision.setComment(StringHandling.getNotNull(comment, "new revision"));
1350: driveFile.setHeadRevision(fileRevision);
1351:
1352:
1353:
1354: drive.commitFile(driveFile, revisedItemDO.getModifiedBy(), tmpItemFilePath);
1355: // delete tmp file
1356: tmpFile.delete();tmpFile = null;
1357:
1358: notifyForSubmission(securitySession, userName, item, false);
1359: } catch (NamingException e) {
1360: throw new EJBException(e);
1361: } catch (CreateException e) {
1362: throw new EJBException(e);
1363: } catch (FinderException e) {
1364: throw new EJBException(e);
1365: }
1366: return revisedItemDO;
1367: */
1368: }
1369:
1370: /**
1371: * <p>
1372: * Sanitize all library contents.
1373: * </p>
1374: *
1375: * @param item
1376: * @param persistenceSession
1377: */
1378: public void sanitize(SecuritySession securitySession)
1379: throws SystemException {
1380: PersistenceSession persistenceSession = persistenceManager
1381: .openSession(securitySession);
1382: SanitizerFormat sanitizer = new SanitizerFormat();
1383: sanitizer.setOnlyBodyContents(true);
1384:
1385: try {
1386: List allItems = Collections
1387: .synchronizedList(persistenceManager.findAll(
1388: persistenceSession, LibraryItemDO.class));
1389: Iterator itemIterator = allItems.iterator();
1390: while (itemIterator.hasNext()) {
1391: sanitizeItem((LibraryItemDO) itemIterator.next(),
1392: persistenceSession, sanitizer);
1393: }
1394: List allComments = Collections
1395: .synchronizedList(persistenceManager.findAll(
1396: persistenceSession, CommentDO.class));
1397: Iterator commentIterator = allComments.iterator();
1398: List commentsToRemove = new Vector();
1399: while (commentIterator.hasNext()) {
1400: CommentDO comment = (CommentDO) commentIterator.next();
1401: if (comment.getFormat() == FormatConstants.FORMAT_HTML) {
1402: if (log.isDebugEnabled()) {
1403: log.debug("Sanitize text for comment id "
1404: + comment.getId() + " - subject '"
1405: + comment.getSubject() + "'");
1406: }
1407: String newText = sanitizer
1408: .format(comment.getText());
1409: if (StringHandling.isNullOrEmpty(newText)) {
1410: commentsToRemove.add(comment);
1411: } else {
1412: comment.setText(newText);
1413: persistenceManager.amend(persistenceSession,
1414: comment);
1415: }
1416: } else {
1417: if (log.isDebugEnabled()) {
1418: log
1419: .debug("Ignoring non-HTML text for comment id "
1420: + comment.getId()
1421: + " - subject '"
1422: + comment.getSubject() + "'");
1423: }
1424:
1425: }
1426: }
1427: commentIterator = commentsToRemove.iterator();
1428: while (commentIterator.hasNext()) {
1429: CommentDO comment = (CommentDO) commentIterator.next();
1430: persistenceManager.remove(persistenceSession, comment);
1431: }
1432: } catch (Exception e) {
1433: persistenceSession.cancel();
1434: throw new SystemException(e);
1435: } finally {
1436: persistenceSession.close();
1437: }
1438:
1439: }
1440:
1441: /**
1442: * <p>
1443: * Private helper to clean up the HTML in an item.
1444: * </p>
1445: *
1446: * @param item The item to sanitize the HTML for.
1447: * @param persistenceSession Used to update the changed items.
1448: * @param sanitizer This sanitizer does all the hard work.
1449: */
1450: private void sanitizeItem(final LibraryItemDO item,
1451: final PersistenceSession persistenceSession,
1452: final SanitizerFormat sanitizer)
1453: throws PersistenceException {
1454: if (log.isDebugEnabled()) {
1455: log.debug("Sanitize text for item id " + item.getId()
1456: + " - title '" + item.getTitle() + "'");
1457: }
1458: item.setSummary(sanitizer.format(item.getSummary()));
1459:
1460: // update the index for the pages
1461: if (item.getPages() != null) {
1462: Iterator pagesIterator = item.getPages().iterator();
1463: // page number for debugging
1464: int pageNumber = 0;
1465: List pagesToRemove = new Vector();
1466: while (pagesIterator.hasNext()) {
1467: if (log.isDebugEnabled()) {
1468: log.debug("Sanitize text for item id "
1469: + item.getId() + " - page " + ++pageNumber);
1470: }
1471: PageDO page = (PageDO) pagesIterator.next();
1472: String newText = sanitizer.format(page.getText());
1473: // remove empty pages
1474: if (StringHandling.isNullOrEmpty(newText)) {
1475: pagesToRemove.add(page);
1476: } else {
1477: page.setText(newText);
1478: persistenceManager.amend(persistenceSession, page);
1479: }
1480: }
1481: pagesIterator = pagesToRemove.iterator();
1482: while (pagesIterator.hasNext()) {
1483: PageDO page = (PageDO) pagesIterator.next();
1484: persistenceManager.remove(persistenceSession, page);
1485: item.getPages().remove(page);
1486: }
1487:
1488: }
1489: // update the index for the faqs
1490: if (item.getFAQCategories() != null) {
1491: Iterator fAQCategoriesIterator = item.getFAQCategories()
1492: .iterator();
1493: while (fAQCategoriesIterator.hasNext()) {
1494: FAQCategoryDO faqCategory = (FAQCategoryDO) fAQCategoriesIterator
1495: .next();
1496:
1497: if (log.isDebugEnabled()) {
1498: log.debug("Sanitize text for item id "
1499: + item.getId() + " - faq category "
1500: + faqCategory.getName());
1501: }
1502: faqCategory.setDescription(sanitizer.format(faqCategory
1503: .getDescription()));
1504:
1505: if (faqCategory.getFAQs() != null) {
1506: Iterator faqIterator = faqCategory.getFAQs()
1507: .iterator();
1508: while (faqIterator.hasNext()) {
1509: FAQDO faq = (FAQDO) faqIterator.next();
1510: faq
1511: .setAnswer(sanitizer.format(faq
1512: .getAnswer()));
1513: persistenceManager.amend(persistenceSession,
1514: faq);
1515: }
1516: }
1517: persistenceManager.amend(persistenceSession,
1518: faqCategory);
1519: }
1520: }
1521: persistenceManager.amend(persistenceSession, item);
1522:
1523: }
1524:
1525: /**
1526: * <p>
1527: * Re-index all library contents (items and comments) in the search engine.
1528: * This is useful after an upgrade, if the search functionality has changed.
1529: * </p>
1530: */
1531: public void updateSearchIndex(SecuritySession securitySession)
1532: throws SystemException {
1533: PersistenceSession persistenceSession = persistenceManager
1534: .openSession(securitySession);
1535: try {
1536: List allItems = Collections
1537: .synchronizedList(persistenceManager.findAll(
1538: persistenceSession, LibraryItemDO.class));
1539: Iterator itemIterator = allItems.iterator();
1540: while (itemIterator.hasNext()) {
1541: updateSearchIndexForItem(securitySession,
1542: (LibraryItemDO) itemIterator.next());
1543: }
1544: List allComments = Collections
1545: .synchronizedList(persistenceManager.findAll(
1546: persistenceSession, CommentDO.class));
1547: Iterator commentIterator = allComments.iterator();
1548: while (commentIterator.hasNext()) {
1549: CommentDO comment = (CommentDO) commentIterator.next();
1550: LibraryItemDO item = comment.getItem();
1551: searchEngine.updateIndex(securitySession, item.getId(),
1552: LibraryItemDO.class.getName(), item.getTopic()
1553: .getId().toString(), comment.getId(),
1554: CommentDO.class.getName(), comment.getText(),
1555: comment.getFormat());
1556: }
1557: } catch (Exception e) {
1558: persistenceSession.cancel();
1559: throw new SystemException(e);
1560: } finally {
1561: persistenceSession.close();
1562: }
1563: }
1564:
1565: /**
1566: * <p>
1567: * Private helper to update the search index for an item which was added
1568: * or amended. This method goes thro' all the faq categories and pages,
1569: * and updates the index for each.
1570: * </p>
1571: *
1572: * @param item The item to update the search index for.
1573: * @throws SystemException See {@link
1574: * com.ivata.groupware.business.search.Search#updateIndex Search.updateIndex}
1575: */
1576: private void updateSearchIndexForItem(
1577: final SecuritySession securitySession,
1578: final LibraryItemDO item) throws SystemException {
1579: if (log.isDebugEnabled()) {
1580: log.debug("Update search index for item id " + item.getId()
1581: + " - title '" + item.getTitle() + "'");
1582: }
1583:
1584: // update the title and summary
1585: searchEngine.updateIndex(securitySession, item.getId(),
1586: LibraryItemDO.class.getName(), item.getTopic().getId()
1587: .toString(), item.getId(), LibraryItemDO.class
1588: .getName(), item.getTitle() + " "
1589: + item.getSummary(),
1590: FormatConstants.FORMAT_HTML);
1591:
1592: // update the index for the pages
1593: if (item.getPages() != null) {
1594: Iterator pagesIterator = item.getPages().iterator();
1595: // page number for debugging
1596: int pageNumber = 0;
1597: while (pagesIterator.hasNext()) {
1598: if (log.isDebugEnabled()) {
1599: log.debug("Update search index for item id "
1600: + item.getId() + " - page " + ++pageNumber);
1601: }
1602: PageDO page = (PageDO) pagesIterator.next();
1603: searchEngine.updateIndex(securitySession, item.getId(),
1604: LibraryItemDO.class.getName(), item.getTopic()
1605: .getId().toString(), page.getId(),
1606: PageDO.class.getName(), page.getText(),
1607: FormatConstants.FORMAT_HTML);
1608: }
1609: }
1610: // update the index for the faqs
1611: if (item.getFAQCategories() != null) {
1612: Iterator fAQCategoriesIterator = item.getFAQCategories()
1613: .iterator();
1614: while (fAQCategoriesIterator.hasNext()) {
1615: FAQCategoryDO faqCategory = (FAQCategoryDO) fAQCategoriesIterator
1616: .next();
1617:
1618: if (log.isDebugEnabled()) {
1619: log.debug("Update search index for item id "
1620: + item.getId() + " - faq category "
1621: + faqCategory.getName());
1622: }
1623:
1624: searchEngine.updateIndex(securitySession, item.getId(),
1625: LibraryItemDO.class.getName(), item.getTopic()
1626: .getId().toString(), faqCategory
1627: .getId(),
1628: FAQCategoryDO.class.getName(), faqCategory
1629: .getName()
1630: + " " + faqCategory.getDescription(),
1631: FormatConstants.FORMAT_HTML);
1632:
1633: if (faqCategory.getFAQs() != null) {
1634: Iterator faqIterator = faqCategory.getFAQs()
1635: .iterator();
1636: while (faqIterator.hasNext()) {
1637: FAQDO faq = (FAQDO) faqIterator.next();
1638:
1639: searchEngine.updateIndex(securitySession, item
1640: .getId(),
1641: LibraryItemDO.class.getName(), item
1642: .getTopic().getId().toString(),
1643: faq.getId(), FAQDO.class.getName(), faq
1644: .getQuestion()
1645: + " " + faq.getAnswer(),
1646: FormatConstants.FORMAT_HTML);
1647: }
1648: }
1649: }
1650: }
1651: }
1652:
1653: /**
1654: * <p>Confirm all of the elements of the comment are valid before it
1655: * is submitted.</p>
1656: *
1657: * @param comment data object to check for consistency and
1658: * completeness.
1659: * @return a collection of validation errors if any of the
1660: * mandatory fields are missing, or if fields contain invalid values.
1661: */
1662: public ValidationErrors validate(
1663: final SecuritySession securitySession,
1664: final CommentDO comment) {
1665: if (log.isDebugEnabled()) {
1666: log.debug("START validating " + comment);
1667: }
1668:
1669: ValidationErrors errors = new ValidationErrors();
1670: Mask mask = maskFactory.getMask(CommentDO.class);
1671:
1672: if (comment.getItem() == null) {
1673: errors.add(new ValidationError("submitComment",
1674: Library.BUNDLE_PATH, mask.getField("item"),
1675: "errors.required"));
1676: }
1677: if (StringHandling.isNullOrEmpty(comment.getSubject())) {
1678: errors.add(new ValidationError("submitComment",
1679: Library.BUNDLE_PATH, mask.getField("subject"),
1680: "errors.required"));
1681: }
1682: if (StringHandling.isNullOrEmpty(comment.getText())) {
1683: errors.add(new ValidationError("submitComment",
1684: Library.BUNDLE_PATH, mask.getField("text"),
1685: "errors.required"));
1686: }
1687: if (comment.getCreatedBy() == null) {
1688: errors.add(new ValidationError("submitComment",
1689: Library.BUNDLE_PATH, mask.getField("createdBy"),
1690: "errors.required"));
1691: }
1692:
1693: if (log.isDebugEnabled()) {
1694: log.debug("END validating " + comment + "- errors: "
1695: + errors);
1696: }
1697: return errors;
1698: }
1699:
1700: /**
1701: * <p>Confirm all of the elements of the item are present and valid,
1702: * before the item is submitted.</p>
1703: *
1704: * @param item data object to check for consistency and
1705: * completeness.
1706: * @return a collection of validation errors if any of the
1707: * mandatory fields are missing, or if fields contain invalid values.
1708: */
1709: public ValidationErrors validate(
1710: final SecuritySession securitySession,
1711: final LibraryItemDO item) {
1712: if (log.isDebugEnabled()) {
1713: log.debug("START validating " + item);
1714: }
1715:
1716: ValidationErrors errors = new ValidationErrors();
1717: Mask mask = maskFactory.getMask(LibraryItemDO.class);
1718:
1719: if (StringHandling.isNullOrEmpty(item.getSummary())) {
1720: errors.add(new ValidationError("submit",
1721: Library.BUNDLE_PATH, mask.getField("summary"),
1722: "errors.required"));
1723: }
1724: if (StringHandling.isNullOrEmpty(item.getTitle())) {
1725: errors.add(new ValidationError("submit",
1726: Library.BUNDLE_PATH, mask.getField("title"),
1727: "errors.required"));
1728: }
1729: if (item.getTopic() == null) {
1730: errors.add(new ValidationError("submit",
1731: Library.BUNDLE_PATH, mask.getField("topic"),
1732: "errors.required"));
1733: }
1734: if (item.getType() == null) {
1735: errors.add(new ValidationError("submit",
1736: Library.BUNDLE_PATH, mask.getField("type"),
1737: "errors.required"));
1738: }
1739: // if this is a faq, it must have faq categories
1740: if (LibraryItemConstants.ITEM_FAQ.equals(item.getType())) {
1741: boolean noCategoryName = false;
1742:
1743: for (Iterator i = item.getFAQCategories().iterator(); i
1744: .hasNext();) {
1745: FAQCategoryDO faqCategory = (FAQCategoryDO) i.next();
1746: String categoryName = faqCategory.getName();
1747:
1748: if (!noCategoryName
1749: && StringHandling.isNullOrEmpty(categoryName)) {
1750: errors.add(new ValidationError("submitFaq",
1751: Library.BUNDLE_PATH, mask
1752: .getField("category"),
1753: "errors.required"));
1754: // we only want to show the error once
1755: noCategoryName = true;
1756: }
1757: for (Iterator j = faqCategory.getFAQs().iterator(); j
1758: .hasNext();) {
1759: FAQDO faq = (FAQDO) j.next();
1760:
1761: if (StringHandling.isNullOrEmpty(faq.getQuestion())) {
1762: errors.add(new ValidationError("submitFaq",
1763: Library.BUNDLE_PATH, mask
1764: .getField("question"),
1765: "errors.required"));
1766: break;
1767: }
1768: }
1769: }
1770: }
1771:
1772: if (log.isDebugEnabled()) {
1773: log.debug("END validating " + item + "- errors: " + errors);
1774: }
1775: return errors;
1776: }
1777:
1778: /**
1779: * <p>Confirm all of the elements of the topic are present and valid,
1780: * before the topic is submitted.</p>
1781: *
1782: * @param topic data object to check for consistency and
1783: * completeness.
1784: * @return a collection of validation errors if any of the
1785: * mandatory fields are missing, or if fields contain invalid values.
1786: */
1787: public ValidationErrors validate(
1788: final SecuritySession securitySession, final TopicDO topic) {
1789: ValidationErrors errors = new ValidationErrors();
1790: Mask mask = maskFactory.getMask(TopicDO.class);
1791:
1792: if (StringHandling.isNullOrEmpty(topic.getCaption())) {
1793: errors.add(new ValidationError("topicModify",
1794: Library.BUNDLE_PATH, mask.getField("caption"),
1795: "errors.required"));
1796: }
1797: return errors;
1798: }
1799:
1800: }
|