Source Code Cross Referenced for BaseDiscussionService.java in  » ERP-CRM-Financial » sakai » org » sakaiproject » discussion » impl » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » ERP CRM Financial » sakai » org.sakaiproject.discussion.impl 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /**********************************************************************************
0002:         * $URL: https://source.sakaiproject.org/svn/discussion/tags/sakai_2-4-1/discussion-impl/impl/src/java/org/sakaiproject/discussion/impl/BaseDiscussionService.java $
0003:         * $Id: BaseDiscussionService.java 21006 2007-02-05 02:40:41Z csev@umich.edu $
0004:         ***********************************************************************************
0005:         *
0006:         * Copyright (c) 2003, 2004, 2005, 2006 The Sakai Foundation.
0007:         * 
0008:         * Licensed under the Educational Community License, Version 1.0 (the "License"); 
0009:         * you may not use this file except in compliance with the License. 
0010:         * You may obtain a copy of the License at
0011:         * 
0012:         *      http://www.opensource.org/licenses/ecl1.php
0013:         * 
0014:         * Unless required by applicable law or agreed to in writing, software 
0015:         * distributed under the License is distributed on an "AS IS" BASIS, 
0016:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
0017:         * See the License for the specific language governing permissions and 
0018:         * limitations under the License.
0019:         *
0020:         **********************************************************************************/package org.sakaiproject.discussion.impl;
0021:
0022:        import java.util.HashSet;
0023:        import java.util.Iterator;
0024:        import java.util.List;
0025:        import java.util.NoSuchElementException;
0026:        import java.util.Set;
0027:        import java.util.Stack;
0028:        import java.util.Vector;
0029:
0030:        import org.apache.commons.logging.Log;
0031:        import org.apache.commons.logging.LogFactory;
0032:        import org.sakaiproject.authz.cover.FunctionManager;
0033:        import org.sakaiproject.authz.cover.SecurityService;
0034:        import org.sakaiproject.content.api.ContentResource;
0035:        import org.sakaiproject.content.cover.ContentHostingService;
0036:        import org.sakaiproject.discussion.api.DiscussionChannel;
0037:        import org.sakaiproject.discussion.api.DiscussionChannelEdit;
0038:        import org.sakaiproject.discussion.api.DiscussionMessage;
0039:        import org.sakaiproject.discussion.api.DiscussionMessageEdit;
0040:        import org.sakaiproject.discussion.api.DiscussionMessageHeader;
0041:        import org.sakaiproject.discussion.api.DiscussionMessageHeaderEdit;
0042:        import org.sakaiproject.discussion.api.DiscussionService;
0043:        import org.sakaiproject.entity.api.ContextObserver;
0044:        import org.sakaiproject.entity.api.Edit;
0045:        import org.sakaiproject.entity.api.Entity;
0046:        import org.sakaiproject.entity.api.EntityTransferrer;
0047:        import org.sakaiproject.entity.api.Summary;
0048:        import org.sakaiproject.entity.api.Reference;
0049:        import org.sakaiproject.entity.api.ResourceProperties;
0050:        import org.sakaiproject.entity.api.ResourcePropertiesEdit;
0051:        import org.sakaiproject.event.api.Event;
0052:        import org.sakaiproject.event.cover.EventTrackingService;
0053:        import org.sakaiproject.event.cover.NotificationService;
0054:        import org.sakaiproject.exception.IdInvalidException;
0055:        import org.sakaiproject.exception.IdUnusedException;
0056:        import org.sakaiproject.exception.IdUsedException;
0057:        import org.sakaiproject.exception.InUseException;
0058:        import org.sakaiproject.exception.PermissionException;
0059:        import org.sakaiproject.javax.Filter;
0060:        import org.sakaiproject.message.api.Message;
0061:        import org.sakaiproject.message.api.MessageChannel;
0062:        import org.sakaiproject.message.api.MessageChannelEdit;
0063:        import org.sakaiproject.message.api.MessageHeader;
0064:        import org.sakaiproject.message.api.MessageHeaderEdit;
0065:        import org.sakaiproject.message.impl.BaseMessageService;
0066:        import org.sakaiproject.site.cover.SiteService;
0067:        import org.sakaiproject.time.api.Time;
0068:        import org.sakaiproject.time.cover.TimeService;
0069:        import org.sakaiproject.tool.cover.SessionManager;
0070:        import org.sakaiproject.tool.cover.ToolManager;
0071:        import org.sakaiproject.user.api.UserNotDefinedException;
0072:        import org.sakaiproject.util.StringUtil;
0073:        import org.sakaiproject.util.Validator;
0074:        import org.w3c.dom.Document;
0075:        import org.w3c.dom.Element;
0076:        import org.w3c.dom.Node;
0077:        import org.w3c.dom.NodeList;
0078:
0079:        /**
0080:         * <p>
0081:         * BaseDiscussionService extends the BaseMessageService for the specifics of Discussion.
0082:         * </p>
0083:         * <p>
0084:         * Note: when a message is posted to a channel, it may have a new category.<br />
0085:         * This category is NOT automatically added to the categories of a channel, which may exist without a message.<br />
0086:         * To get the full list of categories, you must get the channel's categories, and add any that the set of messages for the channel has.
0087:         * </p>
0088:         */
0089:        public abstract class BaseDiscussionService extends BaseMessageService
0090:                implements  DiscussionService, ContextObserver,
0091:                EntityTransferrer {
0092:            /** Our logger. */
0093:            private static Log M_log = LogFactory
0094:                    .getLog(BaseDiscussionService.class);
0095:
0096:            /**********************************************************************************************************************************************************************************************************************************************************
0097:             * Init and Destroy
0098:             *********************************************************************************************************************************************************************************************************************************************************/
0099:
0100:            /**
0101:             * Final initialization, once all dependencies are set.
0102:             */
0103:            public void init() {
0104:                super .init();
0105:
0106:                // register functions
0107:                FunctionManager.registerFunction(eventId(SECURE_READ));
0108:                FunctionManager.registerFunction(eventId(SECURE_ADD));
0109:                FunctionManager.registerFunction(eventId(SECURE_ADD_TOPIC));
0110:                FunctionManager.registerFunction(eventId(SECURE_REMOVE_ANY));
0111:                FunctionManager.registerFunction(eventId(SECURE_REMOVE_OWN));
0112:                FunctionManager.registerFunction(eventId(SECURE_UPDATE_ANY));
0113:                FunctionManager.registerFunction(eventId(SECURE_UPDATE_OWN));
0114:
0115:                // entity producer registration
0116:                m_entityManager.registerEntityProducer(this , REFERENCE_ROOT);
0117:            }
0118:
0119:            /**********************************************************************************************************************************************************************************************************************************************************
0120:             * StorageUser implementation
0121:             *********************************************************************************************************************************************************************************************************************************************************/
0122:
0123:            /**
0124:             * Construct a new continer given just ids.
0125:             * 
0126:             * @param ref
0127:             *        The channel reference.
0128:             * @return The new containe Resource.
0129:             */
0130:            public Entity newContainer(String ref) {
0131:                return new BaseDiscussionChannelEdit(ref);
0132:            }
0133:
0134:            /**
0135:             * Construct a new container resource, from an XML element.
0136:             * 
0137:             * @param element
0138:             *        The XML.
0139:             * @return The new container resource.
0140:             */
0141:            public Entity newContainer(Element element) {
0142:                return new BaseDiscussionChannelEdit(element);
0143:            }
0144:
0145:            /**
0146:             * Construct a new container resource, as a copy of another
0147:             * 
0148:             * @param other
0149:             *        The other contianer to copy.
0150:             * @return The new container resource.
0151:             */
0152:            public Entity newContainer(Entity other) {
0153:                return new BaseDiscussionChannelEdit((MessageChannel) other);
0154:            }
0155:
0156:            /**
0157:             * Construct a new rsource given just an id.
0158:             * 
0159:             * @param container
0160:             *        The Resource that is the container for the new resource (may be null).
0161:             * @param id
0162:             *        The id for the new object.
0163:             * @param others
0164:             *        (options) array of objects to load into the Resource's fields.
0165:             * @return The new resource.
0166:             */
0167:            public Entity newResource(Entity container, String id,
0168:                    Object[] others) {
0169:                return new BaseDiscussionMessageEdit(
0170:                        (MessageChannel) container, id);
0171:            }
0172:
0173:            /**
0174:             * Construct a new resource, from an XML element.
0175:             * 
0176:             * @param container
0177:             *        The Resource that is the container for the new resource (may be null).
0178:             * @param element
0179:             *        The XML.
0180:             * @return The new resource from the XML.
0181:             */
0182:            public Entity newResource(Entity container, Element element) {
0183:                return new BaseDiscussionMessageEdit(
0184:                        (MessageChannel) container, element);
0185:            }
0186:
0187:            /**
0188:             * Construct a new resource from another resource of the same type.
0189:             * 
0190:             * @param container
0191:             *        The Resource that is the container for the new resource (may be null).
0192:             * @param other
0193:             *        The other resource.
0194:             * @return The new resource as a copy of the other.
0195:             */
0196:            public Entity newResource(Entity container, Entity other) {
0197:                return new BaseDiscussionMessageEdit(
0198:                        (MessageChannel) container, (Message) other);
0199:            }
0200:
0201:            /**
0202:             * Construct a new continer given just ids.
0203:             * 
0204:             * @param ref
0205:             *        The channel reference.
0206:             * @return The new containe Resource.
0207:             */
0208:            public Edit newContainerEdit(String ref) {
0209:                BaseDiscussionChannelEdit rv = new BaseDiscussionChannelEdit(
0210:                        ref);
0211:                rv.activate();
0212:                return rv;
0213:            }
0214:
0215:            /**
0216:             * Construct a new container resource, from an XML element.
0217:             * 
0218:             * @param element
0219:             *        The XML.
0220:             * @return The new container resource.
0221:             */
0222:            public Edit newContainerEdit(Element element) {
0223:                BaseDiscussionChannelEdit rv = new BaseDiscussionChannelEdit(
0224:                        element);
0225:                rv.activate();
0226:                return rv;
0227:            }
0228:
0229:            /**
0230:             * Construct a new container resource, as a copy of another
0231:             * 
0232:             * @param other
0233:             *        The other contianer to copy.
0234:             * @return The new container resource.
0235:             */
0236:            public Edit newContainerEdit(Entity other) {
0237:                BaseDiscussionChannelEdit rv = new BaseDiscussionChannelEdit(
0238:                        (MessageChannel) other);
0239:                rv.activate();
0240:                return rv;
0241:            }
0242:
0243:            /**
0244:             * Construct a new rsource given just an id.
0245:             * 
0246:             * @param container
0247:             *        The Resource that is the container for the new resource (may be null).
0248:             * @param id
0249:             *        The id for the new object.
0250:             * @param others
0251:             *        (options) array of objects to load into the Resource's fields.
0252:             * @return The new resource.
0253:             */
0254:            public Edit newResourceEdit(Entity container, String id,
0255:                    Object[] others) {
0256:                BaseDiscussionMessageEdit rv = new BaseDiscussionMessageEdit(
0257:                        (MessageChannel) container, id);
0258:                rv.activate();
0259:                return rv;
0260:            }
0261:
0262:            /**
0263:             * Construct a new resource, from an XML element.
0264:             * 
0265:             * @param container
0266:             *        The Resource that is the container for the new resource (may be null).
0267:             * @param element
0268:             *        The XML.
0269:             * @return The new resource from the XML.
0270:             */
0271:            public Edit newResourceEdit(Entity container, Element element) {
0272:                BaseDiscussionMessageEdit rv = new BaseDiscussionMessageEdit(
0273:                        (MessageChannel) container, element);
0274:                rv.activate();
0275:                return rv;
0276:            }
0277:
0278:            /**
0279:             * Construct a new resource from another resource of the same type.
0280:             * 
0281:             * @param container
0282:             *        The Resource that is the container for the new resource (may be null).
0283:             * @param other
0284:             *        The other resource.
0285:             * @return The new resource as a copy of the other.
0286:             */
0287:            public Edit newResourceEdit(Entity container, Entity other) {
0288:                BaseDiscussionMessageEdit rv = new BaseDiscussionMessageEdit(
0289:                        (MessageChannel) container, (Message) other);
0290:                rv.activate();
0291:                return rv;
0292:            }
0293:
0294:            /**
0295:             * Collect the fields that need to be stored outside the XML (for the resource).
0296:             * 
0297:             * @return An array of field values to store in the record outside the XML (for the resource).
0298:             */
0299:            public Object[] storageFields(Entity r) {
0300:                Object[] rv = new Object[6];
0301:                rv[0] = ((Message) r).getHeader().getDate();
0302:                rv[1] = ((Message) r).getHeader().getFrom().getId();
0303:                rv[2] = ((DiscussionMessage) r).getDiscussionHeader()
0304:                        .getDraft() ? "1" : "0";
0305:                rv[3] = r.getProperties().getProperty(
0306:                        ResourceProperties.PROP_PUBVIEW) == null ? "0" : "1";
0307:                rv[4] = ((DiscussionMessage) r).getDiscussionHeader()
0308:                        .getCategory();
0309:                rv[5] = ((DiscussionMessage) r).getDiscussionHeader()
0310:                        .getReplyTo();
0311:                if (rv[5] == null)
0312:                    rv[5] = "";
0313:
0314:                return rv;
0315:            }
0316:
0317:            /**
0318:             * Check if this resource is in draft mode.
0319:             * 
0320:             * @param r
0321:             *        The resource.
0322:             * @return true if the resource is in draft mode, false if not.
0323:             */
0324:            public boolean isDraft(Entity r) {
0325:                return ((DiscussionMessage) r).getDiscussionHeader().getDraft();
0326:            }
0327:
0328:            /**
0329:             * Access the resource owner user id.
0330:             * 
0331:             * @param r
0332:             *        The resource.
0333:             * @return The resource owner user id.
0334:             */
0335:            public String getOwnerId(Entity r) {
0336:                return ((Message) r).getHeader().getFrom().getId();
0337:            }
0338:
0339:            /**
0340:             * Access the resource date.
0341:             * 
0342:             * @param r
0343:             *        The resource.
0344:             * @return The resource date.
0345:             */
0346:            public Time getDate(Entity r) {
0347:                return ((Message) r).getHeader().getDate();
0348:            }
0349:
0350:            /**********************************************************************************************************************************************************************************************************************************************************
0351:             * Abstractions, etc. satisfied
0352:             *********************************************************************************************************************************************************************************************************************************************************/
0353:
0354:            /**
0355:             * Report the Service API name being implemented.
0356:             */
0357:            protected String serviceName() {
0358:                return DiscussionService.class.getName();
0359:            }
0360:
0361:            /**
0362:             * Construct a new message header from XML in a DOM element.
0363:             * 
0364:             * @param id
0365:             *        The message Id.
0366:             * @return The new message header.
0367:             */
0368:            protected MessageHeaderEdit newMessageHeader(Message msg, String id) {
0369:                return new BaseDiscussionMessageHeaderEdit(msg, id);
0370:
0371:            } // newMessageHeader
0372:
0373:            /**
0374:             * Construct a new message header from XML in a DOM element.
0375:             * 
0376:             * @param el
0377:             *        The XML DOM element that has the header information.
0378:             * @return The new message header.
0379:             */
0380:            protected MessageHeaderEdit newMessageHeader(Message msg, Element el) {
0381:                return new BaseDiscussionMessageHeaderEdit(msg, el);
0382:
0383:            } // newMessageHeader
0384:
0385:            /**
0386:             * Construct a new message header as a copy of another.
0387:             * 
0388:             * @param other
0389:             *        The other header to copy.
0390:             * @return The new message header.
0391:             */
0392:            protected MessageHeaderEdit newMessageHeader(Message msg,
0393:                    MessageHeader other) {
0394:                return new BaseDiscussionMessageHeaderEdit(msg, other);
0395:
0396:            } // newMessageHeader
0397:
0398:            /**
0399:             * Form a tracking event string based on a security function string.
0400:             * 
0401:             * @param secure
0402:             *        The security function string.
0403:             * @return The event tracking string.
0404:             */
0405:            protected String eventId(String secure) {
0406:                return "disc." + secure;
0407:
0408:            } // eventId
0409:
0410:            /**
0411:             * Return the reference rooot for use in resource references and urls.
0412:             * 
0413:             * @return The reference rooot for use in resource references and urls.
0414:             */
0415:            protected String getReferenceRoot() {
0416:                return REFERENCE_ROOT;
0417:
0418:            } // getReferenceRoot
0419:
0420:            /**
0421:             * {@inheritDoc}
0422:             */
0423:            public boolean parseEntityReference(String reference, Reference ref) {
0424:                if (reference.startsWith(REFERENCE_ROOT)) {
0425:                    String[] parts = StringUtil.split(reference,
0426:                            Entity.SEPARATOR);
0427:
0428:                    String id = null;
0429:                    String subType = null;
0430:                    String context = null;
0431:                    String container = null;
0432:
0433:                    // the first part will be null, then next the service, the third will be "msg" or "channel"
0434:                    if (parts.length > 2) {
0435:                        subType = parts[2];
0436:                        if (REF_TYPE_CHANNEL.equals(subType)) {
0437:                            // next is the context id
0438:                            if (parts.length > 3) {
0439:                                context = parts[3];
0440:
0441:                                // next is the channel id
0442:                                if (parts.length > 4) {
0443:                                    id = parts[4];
0444:                                }
0445:                            }
0446:                        } else if (REF_TYPE_MESSAGE.equals(subType)) {
0447:                            // next three parts are context, channel (container) and mesage id
0448:                            if (parts.length > 5) {
0449:                                context = parts[3];
0450:                                container = parts[4];
0451:                                id = parts[5];
0452:                            }
0453:                        } else
0454:                            M_log.warn("parse(): unknown message subtype: "
0455:                                    + subType + " in ref: " + reference);
0456:                    }
0457:
0458:                    ref.set(APPLICATION_ID, subType, id, container, context);
0459:
0460:                    return true;
0461:                }
0462:
0463:                return false;
0464:            }
0465:
0466:            /**
0467:             * {@inheritDoc}
0468:             */
0469:            public void contextCreated(String context, boolean toolPlacement) {
0470:                if (toolPlacement)
0471:                    enableMessageChannel(context);
0472:            }
0473:
0474:            /**
0475:             * {@inheritDoc}
0476:             */
0477:            public void contextUpdated(String context, boolean toolPlacement) {
0478:                if (toolPlacement)
0479:                    enableMessageChannel(context);
0480:            }
0481:
0482:            /**
0483:             * {@inheritDoc}
0484:             */
0485:            public void contextDeleted(String context, boolean toolPlacement) {
0486:                disableMessageChannel(context);
0487:            }
0488:
0489:            /**
0490:             * {@inheritDoc}
0491:             */
0492:            public String[] myToolIds() {
0493:                String[] toolIds = { "sakai.discussion" };
0494:                return toolIds;
0495:            }
0496:
0497:            /**********************************************************************************************************************************************************************************************************************************************************
0498:             * DiscussionService implementation
0499:             *********************************************************************************************************************************************************************************************************************************************************/
0500:
0501:            /**
0502:             * Return a specific discussion channel.
0503:             * 
0504:             * @param ref
0505:             *        The channel reference.
0506:             * @return the DiscussionChannel that has the specified name.
0507:             * @exception IdUnusedException
0508:             *            If this name is not defined for a discussion channel.
0509:             * @exception PermissionException
0510:             *            If the user does not have any permissions to the channel.
0511:             */
0512:            public DiscussionChannel getDiscussionChannel(String ref)
0513:                    throws IdUnusedException, PermissionException {
0514:                return (DiscussionChannel) getChannel(ref);
0515:
0516:            } // getDiscussionChannel
0517:
0518:            /**
0519:             * Add a new discussion channel.
0520:             * 
0521:             * @param ref
0522:             *        The channel reference.
0523:             * @return The newly created channel.
0524:             * @exception IdUsedException
0525:             *            if the id is not unique.
0526:             * @exception IdInvalidException
0527:             *            if the id is not made up of valid characters.
0528:             * @exception PermissionException
0529:             *            if the user does not have permission to add a channel.
0530:             */
0531:            public DiscussionChannelEdit addDiscussionChannel(String ref)
0532:                    throws IdUsedException, IdInvalidException,
0533:                    PermissionException {
0534:                return (DiscussionChannelEdit) addChannel(ref);
0535:
0536:            } // addDiscussionChannel
0537:
0538:            /**
0539:             * {@inheritDoc}
0540:             */
0541:            protected void parseMergeChannelExtra(Element element3,
0542:                    String channelRef) {
0543:                // pick up the discussion channel categories
0544:                if (element3.getTagName().equals("categories")) {
0545:                    NodeList children4 = element3.getChildNodes();
0546:                    final int length4 = children4.getLength();
0547:                    for (int i4 = 0; i4 < length4; i4++) {
0548:                        Node child4 = children4.item(i4);
0549:                        if (child4.getNodeType() == Node.ELEMENT_NODE) {
0550:                            Element element4 = (Element) child4;
0551:                            if (element4.getTagName().equals("category")) {
0552:                                try {
0553:                                    MessageChannelEdit c = editChannel(channelRef);
0554:                                    String category = element4
0555:                                            .getAttribute("name");
0556:                                    commitChannel(c);
0557:                                    ((DiscussionChannel) c)
0558:                                            .addCategory(category);
0559:                                } catch (Exception e) {
0560:                                    M_log.warn("parseMergeChannelExtra: "
0561:                                            + e.toString());
0562:                                }
0563:                            }
0564:                        }
0565:                    }
0566:                }
0567:            }
0568:
0569:            /**
0570:             * {@inheritDoc}
0571:             */
0572:            public String archive(String siteId, Document doc, Stack stack,
0573:                    String archivePath, List attachments) {
0574:                // prepare the buffer for the results log
0575:                StringBuffer results = new StringBuffer();
0576:
0577:                // start with an element with our very own (service) name
0578:                Element element = doc.createElement(serviceName());
0579:                ((Element) stack.peek()).appendChild(element);
0580:                stack.push(element);
0581:
0582:                // get the channel associated with this site
0583:                String channelRef = channelReference(siteId,
0584:                        SiteService.MAIN_CONTAINER);
0585:
0586:                results.append("archiving " + getLabel() + " channel "
0587:                        + channelRef + ".\n");
0588:
0589:                try {
0590:                    // do the channel
0591:                    MessageChannel channel = getChannel(channelRef);
0592:                    Element containerElement = channel.toXml(doc, stack);
0593:                    stack.push(containerElement);
0594:
0595:                    // do the messages in the channel
0596:                    Iterator messages = channel.getMessages(null, true)
0597:                            .iterator();
0598:                    while (messages.hasNext()) {
0599:                        DiscussionMessage msg = (DiscussionMessage) messages
0600:                                .next();
0601:                        Element el = msg.toXml(doc, stack);
0602:
0603:                        int depth = msg.getReplyToDepth();
0604:                        NodeList children2 = el.getChildNodes();
0605:                        int length2 = children2.getLength();
0606:                        for (int i2 = 0; i2 < length2; i2++) {
0607:                            Node child2 = children2.item(i2);
0608:                            if (child2.getNodeType() == Node.ELEMENT_NODE) {
0609:                                Element element2 = (Element) child2;
0610:
0611:                                // get the "calendar" child
0612:                                if (element2.getTagName().equals("header")) {
0613:                                    element2.setAttribute("depth",
0614:                                            (new Integer(depth)).toString());
0615:                                }
0616:                            } // if
0617:                        } // for
0618:
0619:                        // collect message attachments
0620:                        MessageHeader header = msg.getHeader();
0621:                        List atts = header.getAttachments();
0622:                        for (int i = 0; i < atts.size(); i++) {
0623:                            Reference ref = (Reference) atts.get(i);
0624:                            // if it's in the attachment area, and not already in the list
0625:                            if ((ref.getReference()
0626:                                    .startsWith("/content/attachment/"))
0627:                                    && (!attachments.contains(ref))) {
0628:                                attachments.add(ref);
0629:                            }
0630:                        }
0631:                    }
0632:
0633:                    archiveSynopticOptions(siteId, doc, element);
0634:
0635:                    stack.pop();
0636:                } catch (Exception any) {
0637:                    M_log
0638:                            .warn("archve: exception archiving messages for service: "
0639:                                    + serviceName() + " channel: " + channelRef);
0640:                }
0641:
0642:                stack.pop();
0643:
0644:                return results.toString();
0645:            } // archive
0646:
0647:            /**********************************************************************************************************************************************************************************************************************************************************
0648:             * ResourceService implementation
0649:             *********************************************************************************************************************************************************************************************************************************************************/
0650:
0651:            /**
0652:             * {@inheritDoc}
0653:             */
0654:            public String getLabel() {
0655:                return "discussion";
0656:            }
0657:
0658:            /**********************************************************************************************************************************************************************************************************************************************************
0659:             * getSummaryFromHeader implementation
0660:             *********************************************************************************************************************************************************************************************************************************************************/
0661:            protected String getSummaryFromHeader(Message item,
0662:                    MessageHeader header) {
0663:                String newText;
0664:                if (header instanceof  DiscussionMessageHeader) {
0665:                    DiscussionMessageHeader hdr = (DiscussionMessageHeader) header;
0666:                    newText = hdr.getSubject();
0667:                } else {
0668:                    newText = item.getBody();
0669:                    if (newText.length() > 50)
0670:                        newText = newText.substring(1, 49);
0671:                }
0672:                newText = newText + ", " + header.getFrom().getDisplayName()
0673:                        + ", " + header.getDate().toStringLocalFull();
0674:                return newText;
0675:            }
0676:
0677:            /**
0678:             * {@inheritDoc}
0679:             */
0680:            public void transferCopyEntities(String fromContext,
0681:                    String toContext, List resourceIds) {
0682:                // get the channel associated with this site
0683:                String oChannelRef = channelReference(fromContext,
0684:                        SiteService.MAIN_CONTAINER);
0685:                DiscussionChannel oChannel = null;
0686:                try {
0687:                    oChannel = getDiscussionChannel(oChannelRef);
0688:
0689:                    // the "to" DiscussionMessage channel
0690:                    DiscussionChannel nChannel = null;
0691:                    String nChannelRef = channelReference(toContext,
0692:                            SiteService.MAIN_CONTAINER);
0693:                    try {
0694:                        nChannel = (DiscussionChannel) getChannel(nChannelRef);
0695:                    } catch (IdUnusedException e) {
0696:                        try {
0697:                            commitChannel(addDiscussionChannel(nChannelRef));
0698:
0699:                            try {
0700:                                nChannel = (DiscussionChannel) getChannel(nChannelRef);
0701:                            } catch (IdUnusedException eee) {
0702:                                // ignore
0703:                            }
0704:                        } catch (Exception ee) {
0705:                            // ignore
0706:                        }
0707:                    }
0708:
0709:                    if (nChannel != null) {
0710:                        // categories
0711:                        List oCategories = oChannel.getCategories(true);
0712:
0713:                        for (Iterator it = oCategories.iterator(); it.hasNext();) {
0714:                            String category = (String) it.next();
0715:
0716:                            nChannel.addCategory(category);
0717:
0718:                            // only importing topic messages and mark them as draft
0719:                            Iterator oMessageList = oChannel
0720:                                    .getTopics(category);
0721:                            DiscussionMessage oMessage = null;
0722:                            DiscussionMessageHeader oMessageHeader = null;
0723:                            DiscussionMessageEdit nMessage = null;
0724:                            for (; oMessageList.hasNext();) {
0725:                                // the "from" message
0726:                                oMessage = (DiscussionMessage) oMessageList
0727:                                        .next();
0728:                                oMessageHeader = oMessage.getDiscussionHeader();
0729:                                ResourceProperties oProperties = oMessage
0730:                                        .getProperties();
0731:
0732:                                // the "to" message
0733:                                nMessage = (DiscussionMessageEdit) nChannel
0734:                                        .addMessage();
0735:                                nMessage.setBody(oMessage.getBody());
0736:                                DiscussionMessageHeaderEdit nMessageHeader = nMessage
0737:                                        .getDiscussionHeaderEdit();
0738:                                nMessageHeader
0739:                                        .setDate(oMessageHeader.getDate());
0740:
0741:                                if ("false"
0742:                                        .equalsIgnoreCase(m_serverConfigurationService
0743:                                                .getString("import.importAsDraft"))) {
0744:                                    nMessageHeader.setDraft(oMessageHeader
0745:                                            .getDraft());
0746:                                } else {
0747:                                    nMessageHeader.setDraft(true);
0748:                                }
0749:
0750:                                try {
0751:                                    nMessageHeader
0752:                                            .setFrom(m_userDirectoryService
0753:                                                    .getUser(m_sessionManager
0754:                                                            .getCurrentSessionUserId()));
0755:                                } catch (UserNotDefinedException e) {
0756:                                    nMessageHeader
0757:                                            .setFrom(m_userDirectoryService
0758:                                                    .getAnonymousUser());
0759:                                }
0760:                                nMessageHeader.setSubject(oMessageHeader
0761:                                        .getSubject());
0762:                                nMessageHeader.setCategory(category);
0763:                                // attachment
0764:                                List oAttachments = oMessageHeader
0765:                                        .getAttachments();
0766:                                List nAttachments = m_entityManager
0767:                                        .newReferenceList();
0768:                                for (int n = 0; n < oAttachments.size(); n++) {
0769:                                    Reference oAttachmentRef = (Reference) oAttachments
0770:                                            .get(n);
0771:                                    String oAttachmentId = ((Reference) oAttachments
0772:                                            .get(n)).getId();
0773:                                    if (oAttachmentId.indexOf(fromContext) != -1) {
0774:                                        // replace old site id with new site id in attachments
0775:                                        String nAttachmentId = oAttachmentId
0776:                                                .replaceAll(fromContext,
0777:                                                        toContext);
0778:                                        try {
0779:                                            ContentResource attachment = ContentHostingService
0780:                                                    .getResource(nAttachmentId);
0781:                                            nAttachments.add(m_entityManager
0782:                                                    .newReference(attachment
0783:                                                            .getReference()));
0784:                                        } catch (IdUnusedException e) {
0785:                                            try {
0786:                                                ContentResource oAttachment = ContentHostingService
0787:                                                        .getResource(oAttachmentId);
0788:                                                try {
0789:                                                    if (ContentHostingService
0790:                                                            .isAttachmentResource(nAttachmentId)) {
0791:                                                        // add the new resource into attachment collection area
0792:                                                        ContentResource attachment = ContentHostingService
0793:                                                                .addAttachmentResource(
0794:                                                                        Validator
0795:                                                                                .escapeResourceName(oAttachment
0796:                                                                                        .getProperties()
0797:                                                                                        .getProperty(
0798:                                                                                                ResourceProperties.PROP_DISPLAY_NAME)),
0799:                                                                        ToolManager
0800:                                                                                .getCurrentPlacement()
0801:                                                                                .getContext(),
0802:                                                                        ToolManager
0803:                                                                                .getTool(
0804:                                                                                        "sakai.discussion")
0805:                                                                                .getTitle(),
0806:                                                                        oAttachment
0807:                                                                                .getContentType(),
0808:                                                                        oAttachment
0809:                                                                                .getContent(),
0810:                                                                        oAttachment
0811:                                                                                .getProperties());
0812:                                                        // add to attachment list
0813:                                                        nAttachments
0814:                                                                .add(m_entityManager
0815:                                                                        .newReference(attachment
0816:                                                                                .getReference()));
0817:                                                    } else {
0818:                                                        // add the new resource into resource area
0819:                                                        ContentResource attachment = ContentHostingService
0820:                                                                .addResource(
0821:                                                                        Validator
0822:                                                                                .escapeResourceName(oAttachment
0823:                                                                                        .getProperties()
0824:                                                                                        .getProperty(
0825:                                                                                                ResourceProperties.PROP_DISPLAY_NAME)),
0826:                                                                        ToolManager
0827:                                                                                .getCurrentPlacement()
0828:                                                                                .getContext(),
0829:                                                                        1,
0830:                                                                        oAttachment
0831:                                                                                .getContentType(),
0832:                                                                        oAttachment
0833:                                                                                .getContent(),
0834:                                                                        oAttachment
0835:                                                                                .getProperties(),
0836:                                                                        NotificationService.NOTI_NONE);
0837:                                                        // add to attachment list
0838:                                                        nAttachments
0839:                                                                .add(m_entityManager
0840:                                                                        .newReference(attachment
0841:                                                                                .getReference()));
0842:                                                    }
0843:                                                } catch (Exception eeAny) {
0844:                                                    // if the new resource cannot be added
0845:                                                    M_log
0846:                                                            .warn("cannot add new attachment with id="
0847:                                                                    + nAttachmentId);
0848:                                                }
0849:                                            } catch (Exception eAny) {
0850:                                                // if cannot find the original attachment, do nothing.
0851:                                                M_log
0852:                                                        .warn("cannot find the original attachment with id="
0853:                                                                + oAttachmentId);
0854:                                            }
0855:                                        } catch (Exception any) {
0856:                                            M_log.warn(any.getMessage());
0857:                                        }
0858:                                    } else {
0859:                                        nAttachments.add(oAttachmentRef);
0860:                                    }
0861:                                }
0862:                                nMessageHeader.replaceAttachments(nAttachments);
0863:                                // properties
0864:                                ResourcePropertiesEdit p = nMessage
0865:                                        .getPropertiesEdit();
0866:                                p.clear();
0867:                                p.addAll(oProperties);
0868:
0869:                                nChannel.commitMessage(nMessage,
0870:                                        NotificationService.NOTI_NONE);
0871:                            } // for
0872:                        } // for
0873:                    } // if
0874:
0875:                    transferSynopticOptions(fromContext, toContext);
0876:                } catch (IdUnusedException e) {
0877:                    M_log.warn("DiscussionChannel " + fromContext
0878:                            + " cannot be found. ");
0879:                } catch (Exception any) {
0880:                    M_log.warn("importResources(): exception in handling "
0881:                            + serviceName() + " : ", any);
0882:                }
0883:
0884:            } // importResources
0885:
0886:            /**********************************************************************************************************************************************************************************************************************************************************
0887:             * DiscussionChannel implementation
0888:             *********************************************************************************************************************************************************************************************************************************************************/
0889:
0890:            public class BaseDiscussionChannelEdit extends
0891:                    BaseMessageChannelEdit implements  DiscussionChannelEdit {
0892:                /** Store categories, each a string. */
0893:                protected List m_categories = new Vector();
0894:
0895:                /**
0896:                 * Construct with a reference.
0897:                 * 
0898:                 * @param ref
0899:                 *        The channel reference.
0900:                 * @param context
0901:                 *        The context in which this channel will live.
0902:                 * @param id
0903:                 *        The unique channel id.
0904:                 */
0905:                public BaseDiscussionChannelEdit(String ref) {
0906:                    super (ref);
0907:
0908:                } // BaseDiscussionChannelEdit
0909:
0910:                /**
0911:                 * Construct as a copy of another message.
0912:                 * 
0913:                 * @param other
0914:                 *        The other message to copy.
0915:                 */
0916:                public BaseDiscussionChannelEdit(MessageChannel other) {
0917:                    super (other);
0918:
0919:                    // add the categories
0920:                    m_categories
0921:                            .addAll(((BaseDiscussionChannelEdit) other).m_categories);
0922:
0923:                } // BaseDiscussionChannelEdit
0924:
0925:                /**
0926:                 * Construct from a channel (and possibly messages) already defined in XML in a DOM tree. The Channel is added to storage.
0927:                 * 
0928:                 * @param el
0929:                 *        The XML DOM element defining the channel.
0930:                 */
0931:                public BaseDiscussionChannelEdit(Element el) {
0932:                    super (el);
0933:
0934:                    // extract the categories from the XML
0935:                    NodeList children = el.getChildNodes();
0936:                    final int length = children.getLength();
0937:                    for (int i = 0; i < length; i++) {
0938:                        Node child = children.item(i);
0939:                        if (child.getNodeType() != Node.ELEMENT_NODE)
0940:                            continue;
0941:                        Element element = (Element) child;
0942:
0943:                        // look for the categories element
0944:                        if (!element.getTagName().equals("categories"))
0945:                            continue;
0946:
0947:                        NodeList categories = element.getChildNodes();
0948:                        for (int j = 0; j < categories.getLength(); j++) {
0949:                            Node category = categories.item(j);
0950:                            if (category.getNodeType() != Node.ELEMENT_NODE)
0951:                                continue;
0952:
0953:                            Element eCategory = (Element) category;
0954:                            if (!eCategory.getTagName().equals("category"))
0955:                                continue;
0956:
0957:                            String cat = eCategory.getAttribute("name");
0958:                            if ((cat == null) || (cat.length() == 0))
0959:                                continue;
0960:
0961:                            // keep this if we don't already have it
0962:                            if (!m_categories.contains(cat))
0963:                                m_categories.add(cat);
0964:                        }
0965:                    }
0966:
0967:                    // Note: remove this once 1.0.6 CHEF is no longer supported.
0968:                    // Look for the property style categories
0969:                    String categories = getProperties().getProperty(
0970:                            ResourceProperties.PROP_DISCUSSION_CATEGORIES);
0971:                    if ((categories != null) && (categories.length() > 0)) {
0972:                        // these used a "," to separate
0973:                        String[] cats = StringUtil.split(categories, ",");
0974:                        for (int i = 0; i < cats.length; i++) {
0975:                            // keep this if we don't already have it
0976:                            if ((cats[i] != null) && (cats[i].length() > 0)
0977:                                    && (!m_categories.contains(cats[i]))) {
0978:                                m_categories.add(cats[i]);
0979:                            }
0980:                        }
0981:
0982:                        // clear the property
0983:                        getPropertiesEdit().removeProperty(
0984:                                ResourceProperties.PROP_DISCUSSION_CATEGORIES);
0985:                    }
0986:
0987:                } // BaseDiscussionChannelEdit
0988:
0989:                /**
0990:                 * Serialize the resource into XML, adding an element to the doc under the top of the stack element.
0991:                 * 
0992:                 * @param doc
0993:                 *        The DOM doc to contain the XML (or null for a string return).
0994:                 * @param stack
0995:                 *        The DOM elements, the top of which is the containing element of the new "resource" element.
0996:                 * @return The newly added element.
0997:                 */
0998:                public Element toXml(Document doc, Stack stack) {
0999:                    // get the basic work done
1000:                    Element channel = super .toXml(doc, stack);
1001:
1002:                    // add categories
1003:                    Element categories = doc.createElement("categories");
1004:                    channel.appendChild(categories);
1005:
1006:                    for (int i = 0; i < m_categories.size(); i++) {
1007:                        Element cElement = doc.createElement("category");
1008:                        categories.appendChild(cElement);
1009:                        cElement.setAttribute("name", (String) m_categories
1010:                                .get(i));
1011:                    }
1012:
1013:                    return channel;
1014:
1015:                } // toXml
1016:
1017:                /**
1018:                 * Return a specific discussion channel message, as specified by message name.
1019:                 * 
1020:                 * @param messageId
1021:                 *        The id of the message to get.
1022:                 * @return the DiscussionMessage that has the specified id.
1023:                 * @exception IdUnusedException
1024:                 *            If this name is not a defined message in this discussion channel.
1025:                 * @exception PermissionException
1026:                 *            If the user does not have any permissions to read the message.
1027:                 */
1028:                public DiscussionMessage getDiscussionMessage(String messageId)
1029:                        throws IdUnusedException, PermissionException {
1030:                    DiscussionMessage msg = (DiscussionMessage) getMessage(messageId);
1031:
1032:                    // filter out drafts not by this user (unless this user is a super user)
1033:                    if ((msg.getDiscussionHeader()).getDraft()
1034:                            && (!SecurityService.isSuperUser())
1035:                            && (!msg.getHeader().getFrom().getId().equals(
1036:                                    SessionManager.getCurrentSessionUserId()))) {
1037:                        throw new PermissionException(SessionManager
1038:                                .getCurrentSessionUserId(), SECURE_READ, msg
1039:                                .getReference());
1040:                    }
1041:
1042:                    return msg;
1043:
1044:                } // getDiscussionMessage
1045:
1046:                /**
1047:                 * @inheritDoc
1048:                 */
1049:                public DiscussionMessage getDiscussionMessageNoException(
1050:                        String messageId) {
1051:                    DiscussionMessage msg = null;
1052:                    try {
1053:                        msg = getDiscussionMessage(messageId);
1054:                    } catch (Exception ignore) {
1055:                    }
1056:
1057:                    return msg;
1058:
1059:                } // getOneMessage
1060:
1061:                /**
1062:                 * Return a list of all or filtered messages in the channel. The order in which the messages will be found in the iteration is by date, oldest first if ascending is true, newest first if ascending is false.
1063:                 * 
1064:                 * @param filter
1065:                 *        A filtering object to accept messages, or null if no filtering is desired.
1066:                 * @param ascending
1067:                 *        Order of messages, ascending if true, descending if false
1068:                 * @return a list on channel Message objects or specializations of Message objects (may be empty).
1069:                 * @exception PermissionException
1070:                 *            if the user does not have read permission to the channel.
1071:                 */
1072:                public List getMessages(Filter filter, boolean ascending)
1073:                        throws PermissionException {
1074:                    // filter out drafts this user cannot see
1075:                    filter = new PrivacyFilter(filter);
1076:
1077:                    return super .getMessages(filter, ascending);
1078:
1079:                } // getMessages
1080:
1081:                /**
1082:                 * A (DiscussionMessageEdit) cover for editMessage. Return a specific channel message, as specified by message name, locked for update. Must commitEdit() to make official, or cancelEdit() when done!
1083:                 * 
1084:                 * @param messageId
1085:                 *        The id of the message to get.
1086:                 * @return the Message that has the specified id.
1087:                 * @exception IdUnusedException
1088:                 *            If this name is not a defined message in this channel.
1089:                 * @exception PermissionException
1090:                 *            If the user does not have any permissions to read the message.
1091:                 * @exception InUseException
1092:                 *            if the current user does not have permission to mess with this user.
1093:                 */
1094:                public DiscussionMessageEdit editDiscussionMessage(
1095:                        String messageId) throws IdUnusedException,
1096:                        PermissionException, InUseException {
1097:                    return (DiscussionMessageEdit) editMessage(messageId);
1098:
1099:                } // editDiscussionMessage
1100:
1101:                /**
1102:                 * check permissions for addMessage() - if the message is a new Topic.
1103:                 * 
1104:                 * @return true if the user is allowed to addMessage(...) for a new Topic, false if not.
1105:                 */
1106:                public boolean allowAddTopicMessage() {
1107:                    // check security (throws if not permitted)
1108:                    return unlockCheck(SECURE_ADD_TOPIC, getReference());
1109:
1110:                } // allowAddTopicMessage
1111:
1112:                /**
1113:                 * check permissions for removing category
1114:                 * 
1115:                 * @return true if the user is allowed to remove category, false if not.
1116:                 */
1117:                public boolean allowRemoveCategory() {
1118:                    // check security (throws if not permitted)
1119:                    return unlockCheck(SECURE_REMOVE_ANY, getReference());
1120:
1121:                } // allowRemoveCategory
1122:
1123:                /**
1124:                 * A (DiscussionMessageEdit) cover for addMessage. Add a new message to this channel. Must commitEdit() to make official, or cancelEdit() when done!
1125:                 * 
1126:                 * @param replyTo
1127:                 *        The message id to which this message is a reply.
1128:                 * @return The newly added message, locked for update.
1129:                 * @exception PermissionException
1130:                 *            If the user does not have write permission to the channel.
1131:                 */
1132:                public DiscussionMessageEdit addDiscussionMessage(String replyTo)
1133:                        throws PermissionException {
1134:                    // reject if not permitted to post a new Topic, if this is a new Topic
1135:                    // (if it has a null or blank replyTo, it's a Topic)
1136:                    if ((replyTo == null) || (replyTo.trim().length() == 0)) {
1137:                        unlock(SECURE_ADD_TOPIC, getReference());
1138:                    }
1139:
1140:                    DiscussionMessageEdit edit = (DiscussionMessageEdit) addMessage();
1141:                    edit.getDiscussionHeaderEdit().setReplyTo(replyTo);
1142:
1143:                    return edit;
1144:
1145:                } // addDiscussionMessage
1146:
1147:                /**
1148:                 * A (DiscussionMessage) cover for addMessage to add a new message to this channel.
1149:                 * 
1150:                 * @param category
1151:                 *        The message header category.
1152:                 * @param subject
1153:                 *        The message header subject.
1154:                 * @param draft
1155:                 *        The message header draft setting.
1156:                 * @param replyTo
1157:                 *        The message header message id to which this is a reply.
1158:                 * @param attachments
1159:                 *        The message header attachments, a vector of Reference objects.
1160:                 * @param body
1161:                 *        The message body.
1162:                 * @return The newly added message.
1163:                 * @exception PermissionException
1164:                 *            If the user does not have write permission to the channel.
1165:                 */
1166:                public DiscussionMessage addDiscussionMessage(String category,
1167:                        String subject, boolean draft, String replyTo,
1168:                        List attachments, String body)
1169:                        throws PermissionException {
1170:                    DiscussionMessageEdit edit = (DiscussionMessageEdit) addMessage();
1171:                    DiscussionMessageHeaderEdit header = edit
1172:                            .getDiscussionHeaderEdit();
1173:                    edit.setBody(body);
1174:                    header.replaceAttachments(attachments);
1175:                    header.setSubject(subject);
1176:                    header.setDraft(draft);
1177:                    header.setReplyTo(replyTo);
1178:                    header.setCategory(category);
1179:
1180:                    commitMessage(edit);
1181:
1182:                    return edit;
1183:
1184:                } // addDiscussionMessage
1185:
1186:                /**
1187:                 * {@inheritDoc}
1188:                 */
1189:                public void setCategories(List categories) {
1190:                    m_categories = categories;
1191:
1192:                } // setCategories
1193:
1194:                /**
1195:                 * {@inheritDoc}
1196:                 */
1197:                public List getCategories(boolean scanMessages) {
1198:                    Set categories = new HashSet();
1199:                    Vector rv = new Vector();
1200:
1201:                    // start with those stored in the category
1202:                    categories.addAll(m_categories);
1203:
1204:                    // add in the category from each message in the channel if requested
1205:                    if (scanMessages) {
1206:                        Iterator it = findMessages().iterator();
1207:                        while (it.hasNext()) {
1208:                            DiscussionMessage msg = (DiscussionMessage) it
1209:                                    .next();
1210:                            categories.add(msg.getDiscussionHeader()
1211:                                    .getCategory());
1212:                        }
1213:                    }
1214:
1215:                    rv.addAll(categories);
1216:                    return rv;
1217:
1218:                } // getCategories
1219:
1220:                /**
1221:                 * Add a new category for this channel.
1222:                 * 
1223:                 * @param category
1224:                 *        The new category string to add.
1225:                 * @return true if the category was new, false if it is already there.
1226:                 * @exception PermissionException
1227:                 *            If the user does not have write permission to the channel.
1228:                 */
1229:                public boolean addCategory(String category)
1230:                        throws PermissionException, InUseException {
1231:
1232:                    if ((category != null) && (category.length() > 0)
1233:                            && (!m_categories.contains(category))) {
1234:                        // in-storage modification
1235:                        DiscussionChannelEdit e = (DiscussionChannelEdit) m_storage
1236:                                .editChannel(this .getReference());
1237:
1238:                        if (e != null) {
1239:                            List l = e.getCategories(true);
1240:                            l.add(category);
1241:                            e.setCategories(l);
1242:                            m_storage.commitChannel(e);
1243:
1244:                            ((BaseDiscussionChannelEdit) e)
1245:                                    .setEvent(SECURE_ADD_CATEGORY);
1246:
1247:                            // track event (no notification)
1248:                            Event event = EventTrackingService.newEvent(
1249:                                    eventId(((BaseDiscussionChannelEdit) e)
1250:                                            .getEvent()), e.getReference(),
1251:                                    true, NotificationService.NOTI_NONE);
1252:                            EventTrackingService.post(event);
1253:                            // channel notification
1254:                            notify(event);
1255:                            // close the edit object
1256:                            ((BaseDiscussionChannelEdit) e).closeEdit();
1257:
1258:                            return true;
1259:                        } else {
1260:                            throw new InUseException(this .getReference());
1261:                        }
1262:                    }
1263:
1264:                    return false;
1265:
1266:                } // addCategory
1267:
1268:                /**
1269:                 * Remove a category and its related messages for this channel.
1270:                 * 
1271:                 * @param category
1272:                 *        The category string to be removed.
1273:                 * @return true if the category can be removed, false if not.
1274:                 * @exception PermissionException
1275:                 *            If the user does not have write permission to the channel.
1276:                 */
1277:                public boolean removeCategory(String category)
1278:                        throws InUseException, PermissionException {
1279:                    unlock(SECURE_REMOVE_ANY, getReference());
1280:                    try {
1281:                        DiscussionChannelEdit e = (DiscussionChannelEdit) m_storage
1282:                                .editChannel(this .getReference());
1283:
1284:                        if (e != null) {
1285:                            List l = e.getCategories(true);
1286:                            if ((category != null) && (category.length() > 0)
1287:                                    && (l.contains(category))) {
1288:                                // delete all the messages in the category
1289:                                Iterator messages = m_storage.getMessages(e)
1290:                                        .iterator();
1291:                                while (messages.hasNext()) {
1292:                                    DiscussionMessage m = (DiscussionMessage) messages
1293:                                            .next();
1294:                                    if (m.getDiscussionHeader().getCategory()
1295:                                            .equals(category)) {
1296:                                        e.removeMessage(m.getId());
1297:                                    }
1298:                                }
1299:
1300:                                l.remove(category);
1301:                                e.setCategories(l);
1302:
1303:                                m_storage.commitChannel(e);
1304:
1305:                                // track event (no notification)
1306:
1307:                                ((BaseDiscussionChannelEdit) e)
1308:                                        .setEvent(SECURE_REMOVE_CATEGORY);
1309:
1310:                                Event event = EventTrackingService.newEvent(
1311:                                        eventId(((BaseDiscussionChannelEdit) e)
1312:                                                .getEvent()), e.getReference(),
1313:                                        true, NotificationService.NOTI_NONE);
1314:                                EventTrackingService.post(event);
1315:                                // channel notification
1316:                                notify(event);
1317:
1318:                                // close the edit object
1319:                                ((BaseDiscussionChannelEdit) e).closeEdit();
1320:                                return true;
1321:                            } else {
1322:                                // close the edit object
1323:                                m_storage.commitChannel(e);
1324:                                ((BaseDiscussionChannelEdit) e).closeEdit();
1325:                                return false;
1326:                            }
1327:                        } else {
1328:                            throw new InUseException(this .getReference());
1329:                        }
1330:                    } catch (Exception e) {
1331:                    }
1332:
1333:                    return false;
1334:
1335:                } // removeCategory
1336:
1337:                /**
1338:                 * Return an Iterator on the DiscussionMessages that are "topics", i.e. are not a response to any other message. Note: use DiscussionMessage.getReplies() to get the direct replies to any specific message.
1339:                 * 
1340:                 * @param category
1341:                 *        Filter the responses to messages in just this category (optional, may be null).
1342:                 * @return an Iterator on the DiscussionMessages that are "topics", i.e. are not a response to any other message.
1343:                 */
1344:                public Iterator getTopics(String category) {
1345:                    // TODO: storage interface to get this without filtering
1346:                    final String catToMatch = category;
1347:                    Filter filter = new Filter() {
1348:                        public boolean accept(Object o) {
1349:                            DiscussionMessage message = (DiscussionMessage) o;
1350:                            if ((message.getDiscussionHeader().getReplyTo()
1351:                                    .length() == 0)
1352:                                    && ((catToMatch == null)
1353:                                            || (catToMatch.length() == 0) || (catToMatch
1354:                                            .equals(((DiscussionMessageHeader) message
1355:                                                    .getHeader()).getCategory())))
1356:                                    && ((!message.getDiscussionHeader()
1357:                                            .getDraft())
1358:                                            || (SecurityService.isSuperUser()) || (message
1359:                                            .getHeader().getFrom().getId()
1360:                                            .equals(SessionManager
1361:                                                    .getCurrentSessionUserId())))) {
1362:                                return true;
1363:                            }
1364:                            return false;
1365:                        }
1366:                    };
1367:
1368:                    return findFilterMessages(filter, true).iterator();
1369:
1370:                } // getTopics
1371:
1372:                /**
1373:                 * {@inheritDoc}
1374:                 */
1375:                public List getTopicMsgIds(String category) {
1376:                    // TODO: storage interface so get just the ids!
1377:                    final String catToMatch = category;
1378:                    Filter filter = new Filter() {
1379:                        public boolean accept(Object o) {
1380:                            DiscussionMessage message = (DiscussionMessage) o;
1381:                            if ((message.getDiscussionHeader().getReplyTo()
1382:                                    .length() == 0)
1383:                                    && ((catToMatch == null)
1384:                                            || (catToMatch.length() == 0) || (catToMatch
1385:                                            .equals(((DiscussionMessageHeader) message
1386:                                                    .getHeader()).getCategory())))
1387:                                    && ((!message.getDiscussionHeader()
1388:                                            .getDraft())
1389:                                            || (SecurityService.isSuperUser()) || (message
1390:                                            .getHeader().getFrom().getId()
1391:                                            .equals(SessionManager
1392:                                                    .getCurrentSessionUserId())))) {
1393:                                return true;
1394:                            }
1395:                            return false;
1396:                        }
1397:                    };
1398:
1399:                    List found = findFilterMessages(filter, true);
1400:                    Vector rv = new Vector();
1401:                    for (Iterator i = found.iterator(); i.hasNext();) {
1402:                        Message msg = (Message) i.next();
1403:                        rv.add(msg.getId());
1404:                    }
1405:
1406:                    return rv;
1407:                }
1408:
1409:                /**
1410:                 * Return an iterator on the DiscussionMessages that are in the response thread(s) to the specified iteration of messages. They will be returned in depth first order.
1411:                 * 
1412:                 * @param topLevel
1413:                 *        The iterator of messages to which those returned are some depth of response.
1414:                 * @return an iterator on the DiscussionMessages that are in the response threads to the specified iteration of messages, in depth first order (may be empty).
1415:                 */
1416:                protected Iterator threadIterator(Iterator topLevel) {
1417:                    // start the depth iteration stack with the topics of the channel
1418:                    final Stack stack = new Stack();
1419:                    stack.push(topLevel);
1420:
1421:                    return new Iterator() {
1422:                        // if we found one in hasNext(), store it here till the next()
1423:                        private Object m_next = null;
1424:
1425:                        // the depth stack of iterators
1426:                        private Stack m_stack = stack;
1427:
1428:                        // messages already returned
1429:                        private Set m_alreadyReturned = new HashSet();
1430:
1431:                        public Object next() {
1432:                            // make sure hasNext has been called
1433:                            hasNext();
1434:
1435:                            if (m_next == null)
1436:                                throw new NoSuchElementException();
1437:
1438:                            // consume the next
1439:                            Object rv = m_next;
1440:                            m_next = null;
1441:
1442:                            // keep track of what we have already returned to avoid looping
1443:                            m_alreadyReturned.add(rv);
1444:
1445:                            return rv;
1446:
1447:                        } // next
1448:
1449:                        public boolean hasNext() {
1450:                            // if known next not yet used, we have next
1451:                            if (m_next != null)
1452:                                return true;
1453:
1454:                            // clear off completed iterators from the stack
1455:                            while ((!m_stack.empty())
1456:                                    && (!((Iterator) m_stack.peek()).hasNext())) {
1457:                                m_stack.pop();
1458:                            }
1459:
1460:                            // if the stack is now empty, we have no next
1461:                            if (m_stack.empty()) {
1462:                                return false;
1463:                            }
1464:
1465:                            // setup the next from the stack
1466:                            m_next = ((Iterator) m_stack.peek()).next();
1467:
1468:                            // if this next has replies, push an iterator of them in the stack
1469:                            // ... but don't do it if we've alread returned this message, else we might get a loop!
1470:                            if (!m_alreadyReturned.contains(m_next)) {
1471:                                Iterator replies = ((DiscussionMessage) m_next)
1472:                                        .getReplies();
1473:                                if (replies.hasNext()) {
1474:                                    m_stack.push(replies);
1475:                                }
1476:                            }
1477:
1478:                            return true;
1479:
1480:                        } // hasNext
1481:
1482:                        public void remove() {
1483:                            throw new UnsupportedOperationException();
1484:                        }
1485:
1486:                    }; // Iterator
1487:
1488:                } // threadIterator
1489:
1490:                /**
1491:                 * Return an iterator on the DiscussionMessages that are in the response thread to the specified message. They will be returned in depth first order.
1492:                 * 
1493:                 * @param message
1494:                 *        The message to which those returned are some depth of response.
1495:                 * @return an iterator on the DiscussionMessages that are in the response thread to the specified topic messages, in depth first order (may be empty).
1496:                 */
1497:                public Iterator getThread(DiscussionMessage message) {
1498:                    // the top level of the threading is the replies to the specified message
1499:                    Iterator topLevel = message.getReplies();
1500:                    return threadIterator(topLevel);
1501:
1502:                } // getThread
1503:
1504:                /**
1505:                 * Return an iterator on all messages in thread - depth first order.
1506:                 * 
1507:                 * @param category
1508:                 *        Filter the responses to messages in just this category (optional, may be null).
1509:                 * @return an iterator on all messages in thread - depth first order (may be empty).
1510:                 */
1511:                public Iterator getThreads(String category) {
1512:                    // the top level of the threading is the topics that are in category
1513:                    Iterator topLevel = getTopics(category);
1514:                    return threadIterator(topLevel);
1515:
1516:                } // getThreads
1517:
1518:                /**
1519:                 * Access the most recent reply to the thread descending from this message, if any.
1520:                 * 
1521:                 * @param message
1522:                 *        The message that forms the top of a thread.
1523:                 * @return the most recent DiscussionMessage reply to this thread, or null if there are no replies.
1524:                 */
1525:                public DiscussionMessage getThreadLatestReply(
1526:                        DiscussionMessage message) {
1527:                    DiscussionMessage latest = null;
1528:                    Iterator replies = getThread(message);
1529:                    while (replies.hasNext()) {
1530:                        if (latest == null) {
1531:                            latest = (DiscussionMessage) replies.next();
1532:                        } else {
1533:                            DiscussionMessage test = (DiscussionMessage) replies
1534:                                    .next();
1535:                            if (test.getHeader().getDate().after(
1536:                                    latest.getHeader().getDate())) {
1537:                                latest = test;
1538:                            }
1539:                        }
1540:                    }
1541:
1542:                    return latest;
1543:
1544:                } // getThreadLatestReply
1545:
1546:                /**
1547:                 * Count the number of replies to this thread (i.e. the size of the getThread() iterator).
1548:                 * 
1549:                 * @param message
1550:                 *        The message that forms the top of a thread.
1551:                 * @return the number of replies to this thread.
1552:                 */
1553:                public int getThreadNumberOfReplies(DiscussionMessage message) {
1554:                    int count = 0;
1555:                    Iterator replies = getThread(message);
1556:                    while (replies.hasNext()) {
1557:                        replies.next();
1558:                        count++;
1559:                    }
1560:
1561:                    return count;
1562:
1563:                } // getThreadNumberOfReplies
1564:
1565:            } // class BaseDiscussionChannelEdit
1566:
1567:            /**********************************************************************************************************************************************************************************************************************************************************
1568:             * DiscussionMessage implementation
1569:             *********************************************************************************************************************************************************************************************************************************************************/
1570:
1571:            public class BaseDiscussionMessageEdit extends BaseMessageEdit
1572:                    implements  DiscussionMessageEdit {
1573:                /**
1574:                 * Construct.
1575:                 * 
1576:                 * @param channel
1577:                 *        The channel in which this message lives.
1578:                 * @param id
1579:                 *        The message id.
1580:                 */
1581:                public BaseDiscussionMessageEdit(MessageChannel channel,
1582:                        String id) {
1583:                    super (channel, id);
1584:
1585:                } // BaseDiscussionMessageEdit
1586:
1587:                /**
1588:                 * Construct as a copy of another message.
1589:                 * 
1590:                 * @param other
1591:                 *        The other message to copy.
1592:                 */
1593:                public BaseDiscussionMessageEdit(MessageChannel channel,
1594:                        Message other) {
1595:                    super (channel, other);
1596:
1597:                } // BaseDiscussionMessageEdit
1598:
1599:                /**
1600:                 * Construct from an existing definition, in xml.
1601:                 * 
1602:                 * @param channel
1603:                 *        The channel in which this message lives.
1604:                 * @param el
1605:                 *        The message in XML in a DOM element.
1606:                 */
1607:                public BaseDiscussionMessageEdit(MessageChannel channel,
1608:                        Element el) {
1609:                    super (channel, el);
1610:
1611:                } // BaseDiscussionMessageEdit
1612:
1613:                /**
1614:                 * Access the discussion message header.
1615:                 * 
1616:                 * @return The discussion message header.
1617:                 */
1618:                public DiscussionMessageHeader getDiscussionHeader() {
1619:                    return (DiscussionMessageHeader) getHeader();
1620:
1621:                } // getDiscussionHeader
1622:
1623:                /**
1624:                 * Access the discussion message header.
1625:                 * 
1626:                 * @return The discussion message header.
1627:                 */
1628:                public DiscussionMessageHeaderEdit getDiscussionHeaderEdit() {
1629:                    return (DiscussionMessageHeaderEdit) getHeader();
1630:
1631:                } // getDiscussionHeaderEdit
1632:
1633:                /**
1634:                 * Return an array of messages that are a reply to this message.
1635:                 * 
1636:                 * @return an array of DiscussionMessage objects that are replies to this message (may be null).
1637:                 */
1638:                public Iterator getReplies() {
1639:                    // compare others' replyTo to my local id
1640:                    final String id = getId();
1641:
1642:                    Filter filter = new Filter() {
1643:                        public boolean accept(Object o) {
1644:                            DiscussionMessage message = (DiscussionMessage) o;
1645:                            if ((message.getDiscussionHeader().getReplyTo()
1646:                                    .equals(id))
1647:                                    && ((!message.getDiscussionHeader()
1648:                                            .getDraft())
1649:                                            || (SecurityService.isSuperUser()) || (message
1650:                                            .getHeader().getFrom().getId()
1651:                                            .equals(SessionManager
1652:                                                    .getCurrentSessionUserId())))) {
1653:                                return true;
1654:                            }
1655:                            return false;
1656:                        }
1657:                    };
1658:
1659:                    // ask m_channel for a filtered message iterator
1660:                    return ((BaseMessageChannelEdit) m_channel)
1661:                            .findFilterMessages(filter, true).iterator();
1662:
1663:                } // getReplies
1664:
1665:                /**
1666:                 * Are there any replys to this message?
1667:                 * 
1668:                 * @return true if there are replies to this message, false if now.
1669:                 */
1670:                public boolean hasReplies() {
1671:                    return getReplies().hasNext();
1672:
1673:                } // hasReplies
1674:
1675:                /**
1676:                 * Return the depth of replyTo value for this message. Messages that are not a reply to any other message have depth = 0. If the message is a reply to a message, this message's depth is the replyTo's depth + 1.
1677:                 * 
1678:                 * @return The depth of replyTo value for this message.
1679:                 */
1680:                public int getReplyToDepth() {
1681:                    return getReplyToDepth(new HashSet());
1682:
1683:                } // getReplyToDepth
1684:
1685:                /**
1686:                 * Return the depth of replyTo value for this message. Messages that are not a reply to any other message have depth = 0.
1687:                 * 
1688:                 * @param messages
1689:                 *        A set of messages seen so far in the response chain. If the message is a reply to a message, this message's depth is the replyTo's depth + 1.
1690:                 * @return The depth of replyTo value for this message.
1691:                 */
1692:                protected int getReplyToDepth(HashSet messages) {
1693:                    // if not a reply to, return 0
1694:                    if (getDiscussionHeader().getReplyTo().length() == 0) {
1695:                        return 0;
1696:                    }
1697:
1698:                    // if I am alreay in the reply chain due to some sort of looping, stop here!
1699:                    if (messages.contains(this )) {
1700:                        M_log.warn("getReplyToDepth(): looping found: "
1701:                                + getId());
1702:                        return 0;
1703:                    }
1704:
1705:                    try {
1706:                        // add this message to the set of those in the reply chain
1707:                        messages.add(this );
1708:
1709:                        // if a reply to, add one to the replyTo's depth
1710:                        BaseDiscussionMessageEdit replyTo = (BaseDiscussionMessageEdit) ((DiscussionChannel) m_channel)
1711:                                .getDiscussionMessage(getDiscussionHeader()
1712:                                        .getReplyTo());
1713:                        return replyTo.getReplyToDepth(messages) + 1;
1714:                    } catch (IdUnusedException e) {
1715:                        M_log.warn("getReplyToDepth(): exception: "
1716:                                + e.toString());
1717:                        return 0;
1718:                    } catch (PermissionException e) {
1719:                        M_log.warn("getReplyToDepth(): exception: "
1720:                                + e.toString());
1721:                        return 0;
1722:                    }
1723:
1724:                } // getReplyToDepth
1725:
1726:                /**
1727:                 * Access the most recent reply to this message, if any.
1728:                 * 
1729:                 * @return the most recent DiscussionMessage reply to this message, or null if there are no replies.
1730:                 */
1731:                public DiscussionMessage getLatestReply() {
1732:                    DiscussionMessage latest = null;
1733:                    Iterator replies = getReplies();
1734:                    while (replies.hasNext()) {
1735:                        latest = (DiscussionMessage) replies.next();
1736:                    }
1737:
1738:                    return latest;
1739:
1740:                } // getLatestReply
1741:
1742:                /**
1743:                 * Count the number of replies to this message (i.e. the size of the getReplies iterator).
1744:                 * 
1745:                 * @return the number of replies to this message.
1746:                 */
1747:                public int getNumberOfReplies() {
1748:                    int count = 0;
1749:                    Iterator replies = getReplies();
1750:                    while (replies.hasNext()) {
1751:                        replies.next();
1752:                        count++;
1753:                    }
1754:
1755:                    return count;
1756:
1757:                } // getNumberOfReplies
1758:
1759:            } // class BasicDiscussionMessageEdit
1760:
1761:            /**********************************************************************************************************************************************************************************************************************************************************
1762:             * DiscussionMessageHeaderEdit implementation
1763:             *********************************************************************************************************************************************************************************************************************************************************/
1764:
1765:            public class BaseDiscussionMessageHeaderEdit extends
1766:                    BaseMessageHeaderEdit implements 
1767:                    DiscussionMessageHeaderEdit {
1768:                /** The subject for the discussion. */
1769:                protected String m_subject = null;
1770:
1771:                /** The category for the discussion message. */
1772:                protected String m_category = null;
1773:
1774:                /** The message id to which this message is a reply to (message id string). */
1775:                protected String m_replyTo = null;
1776:
1777:                /**
1778:                 * Construct.
1779:                 * 
1780:                 * @param id
1781:                 *        The unique (within the channel) message id.
1782:                 * @param from
1783:                 *        The User who sent the message to the channel.
1784:                 * @param attachments
1785:                 *        The message header attachments, a vector of Reference objects.
1786:                 */
1787:                public BaseDiscussionMessageHeaderEdit(Message msg, String id) {
1788:                    super (msg, id);
1789:
1790:                } // BaseDiscussionMessageHeaderEdit
1791:
1792:                /**
1793:                 * Construct, from an already existing XML DOM element.
1794:                 * 
1795:                 * @param el
1796:                 *        The header in XML in a DOM element.
1797:                 */
1798:                public BaseDiscussionMessageHeaderEdit(Message msg, Element el) {
1799:                    super (msg, el);
1800:
1801:                    // now extract the subject, draft, category and replyTo
1802:                    m_subject = el.getAttribute("subject");
1803:                    m_category = el.getAttribute("category");
1804:                    m_replyTo = el.getAttribute("replyTo");
1805:
1806:                } // BaseDiscussionMessageHeaderEdit
1807:
1808:                /**
1809:                 * Construct as a copy of another header.
1810:                 * 
1811:                 * @param other
1812:                 *        The other message header to copy.
1813:                 */
1814:                public BaseDiscussionMessageHeaderEdit(Message msg,
1815:                        MessageHeader other) {
1816:                    super (msg, other);
1817:
1818:                    m_subject = ((DiscussionMessageHeader) other).getSubject();
1819:                    m_category = ((DiscussionMessageHeader) other)
1820:                            .getCategory();
1821:                    m_replyTo = ((DiscussionMessageHeader) other).getReplyTo();
1822:
1823:                } // BaseDiscussionMessageHeaderEdit
1824:
1825:                /**
1826:                 * Access the subject of the discussion.
1827:                 * 
1828:                 * @return The subject of the discussion.
1829:                 */
1830:                public String getSubject() {
1831:                    return ((m_subject == null) ? "" : m_subject);
1832:
1833:                } // getSubject
1834:
1835:                /**
1836:                 * Set the subject of the discussion.
1837:                 * 
1838:                 * @param subject
1839:                 *        The subject of the discussion.
1840:                 */
1841:                public void setSubject(String subject) {
1842:                    if (StringUtil.different(subject, m_subject)) {
1843:                        m_subject = subject;
1844:                    }
1845:
1846:                } // setSubject
1847:
1848:                /**
1849:                 * Access the category of the discussion.
1850:                 * 
1851:                 * @return The category of the discussion.
1852:                 */
1853:                public String getCategory() {
1854:                    return ((m_category == null) ? "" : m_category);
1855:
1856:                } // getCategory
1857:
1858:                /**
1859:                 * Set the category of the discussion.
1860:                 * 
1861:                 * @param category
1862:                 *        The category of the discussion.
1863:                 */
1864:                public void setCategory(String category) {
1865:                    if (StringUtil.different(category, m_category)) {
1866:                        m_category = category;
1867:                    }
1868:
1869:                } // setCategory
1870:
1871:                /**
1872:                 * Access the local or resource id of the message this one is a reply to, used in threading.
1873:                 * 
1874:                 * @return The id of the message this one is a reply to, used in threading, or null if none.
1875:                 */
1876:                public String getReplyTo() {
1877:                    return ((m_replyTo == null) ? "" : m_replyTo);
1878:
1879:                } // getReplyTo
1880:
1881:                /**
1882:                 * Set the local or resource id of the message this one is a reply to, used in threading.
1883:                 * 
1884:                 * @param id
1885:                 *        The local or resource id of the message this one is a reply to, used in threading.
1886:                 */
1887:                public void setReplyTo(String id) {
1888:                    if (StringUtil.different(id, m_replyTo)) {
1889:                        m_replyTo = id;
1890:                    }
1891:
1892:                } // setReplyTo
1893:
1894:                /**
1895:                 * Serialize the resource into XML, adding an element to the doc under the top of the stack element.
1896:                 * 
1897:                 * @param doc
1898:                 *        The DOM doc to contain the XML (or null for a string return).
1899:                 * @param stack
1900:                 *        The DOM elements, the top of which is the containing element of the new "resource" element.
1901:                 * @return The newly added element.
1902:                 */
1903:                public Element toXml(Document doc, Stack stack) {
1904:                    // get the basic work done
1905:                    Element header = super .toXml(doc, stack);
1906:
1907:                    // add draft, subject
1908:                    header.setAttribute("subject", getSubject());
1909:                    header.setAttribute("draft", new Boolean(getDraft())
1910:                            .toString());
1911:                    header.setAttribute("category", getCategory());
1912:                    header.setAttribute("replyTo", getReplyTo());
1913:
1914:                    return header;
1915:
1916:                } // toXml
1917:
1918:            } // BaseDiscussionMessageHeader
1919:
1920:            /**
1921:             * A filter that will reject discussion message drafts not from the current user, and otherwise use another filter, if defined, for acceptance.
1922:             */
1923:            protected class PrivacyFilter implements  Filter {
1924:                /** The other filter to check with. May be null. */
1925:                protected Filter m_filter = null;
1926:
1927:                /**
1928:                 * Construct
1929:                 * 
1930:                 * @param filter
1931:                 *        The other filter we check with.
1932:                 */
1933:                public PrivacyFilter(Filter filter) {
1934:                    m_filter = filter;
1935:
1936:                } // PrivacyFilter
1937:
1938:                /**
1939:                 * Does this object satisfy the criteria of the filter?
1940:                 * 
1941:                 * @return true if the object is accepted by the filter, false if not.
1942:                 */
1943:                public boolean accept(Object o) {
1944:                    // first if o is a discussion message that's a draft from another user, reject it
1945:                    if (o instanceof  DiscussionMessage) {
1946:                        DiscussionMessage msg = (DiscussionMessage) o;
1947:
1948:                        if ((msg.getDiscussionHeader()).getDraft()
1949:                                && (!SecurityService.isSuperUser())
1950:                                && (!msg.getHeader().getFrom().getId().equals(
1951:                                        SessionManager
1952:                                                .getCurrentSessionUserId()))) {
1953:                            return false;
1954:                        }
1955:                    }
1956:
1957:                    // now, use the real filter, if present
1958:                    if (m_filter != null)
1959:                        return m_filter.accept(o);
1960:
1961:                    return true;
1962:
1963:                } // accept
1964:
1965:            } // PrivacyFilter
1966:
1967:        } // BaseDiscussionService
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.