Source Code Cross Referenced for AnnouncementAction.java in  » ERP-CRM-Financial » sakai » org » sakaiproject » announcement » tool » 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.announcement.tool 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /**********************************************************************************
0002:         * $URL: https://source.sakaiproject.org/svn/announcement/tags/sakai_2-4-1/announcement-tool/tool/src/java/org/sakaiproject/announcement/tool/AnnouncementAction.java $
0003:         * $Id: AnnouncementAction.java 22950 2007-03-19 17:50:17Z josrodri@iupui.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.announcement.tool;
0021:
0022:        import java.util.ArrayList;
0023:        import java.util.Arrays;
0024:        import java.util.Collection;
0025:        import java.util.Collections;
0026:        import java.util.Comparator;
0027:        import java.util.Iterator;
0028:        import java.util.List;
0029:        import java.util.Map;
0030:        import java.util.NoSuchElementException;
0031:        import java.util.Properties;
0032:        import java.util.Stack;
0033:        import java.util.Vector;
0034:
0035:        import org.sakaiproject.announcement.api.AnnouncementChannel;
0036:        import org.sakaiproject.announcement.api.AnnouncementChannelEdit;
0037:        import org.sakaiproject.announcement.api.AnnouncementMessage;
0038:        import org.sakaiproject.announcement.api.AnnouncementMessageEdit;
0039:        import org.sakaiproject.announcement.api.AnnouncementMessageHeader;
0040:        import org.sakaiproject.announcement.api.AnnouncementMessageHeaderEdit;
0041:        import org.sakaiproject.announcement.cover.AnnouncementService;
0042:        import org.sakaiproject.authz.api.PermissionsHelper;
0043:        import org.sakaiproject.authz.cover.SecurityService;
0044:        import org.sakaiproject.cheftool.Context;
0045:        import org.sakaiproject.cheftool.ControllerState;
0046:        import org.sakaiproject.cheftool.JetspeedRunData;
0047:        import org.sakaiproject.cheftool.PagedResourceActionII;
0048:        import org.sakaiproject.cheftool.RunData;
0049:        import org.sakaiproject.cheftool.VelocityPortlet;
0050:        import org.sakaiproject.cheftool.api.Menu;
0051:        import org.sakaiproject.cheftool.api.MenuItem;
0052:        import org.sakaiproject.cheftool.menu.MenuDivider;
0053:        import org.sakaiproject.cheftool.menu.MenuEntry;
0054:        import org.sakaiproject.cheftool.menu.MenuImpl;
0055:        import org.sakaiproject.component.cover.ServerConfigurationService;
0056:        import org.sakaiproject.content.api.FilePickerHelper;
0057:        import org.sakaiproject.content.cover.ContentHostingService;
0058:        import org.sakaiproject.content.cover.ContentTypeImageService;
0059:        import org.sakaiproject.entity.api.EntityPropertyNotDefinedException;
0060:        import org.sakaiproject.entity.api.EntityPropertyTypeException;
0061:        import org.sakaiproject.entity.api.Reference;
0062:        import org.sakaiproject.entity.api.ResourceProperties;
0063:        import org.sakaiproject.entity.cover.EntityManager;
0064:        import org.sakaiproject.event.api.NotificationService;
0065:        import org.sakaiproject.event.api.SessionState;
0066:        import org.sakaiproject.exception.IdInvalidException;
0067:        import org.sakaiproject.exception.IdUnusedException;
0068:        import org.sakaiproject.exception.IdUsedException;
0069:        import org.sakaiproject.exception.InUseException;
0070:        import org.sakaiproject.exception.PermissionException;
0071:        import org.sakaiproject.javax.Filter;
0072:        import org.sakaiproject.javax.PagingPosition;
0073:        import org.sakaiproject.message.api.Message;
0074:        import org.sakaiproject.message.api.MessageHeader;
0075:        import org.sakaiproject.site.api.Group;
0076:        import org.sakaiproject.site.api.Site;
0077:        import org.sakaiproject.site.cover.SiteService;
0078:        import org.sakaiproject.time.api.Time;
0079:        import org.sakaiproject.time.cover.TimeService;
0080:        import org.sakaiproject.tool.api.Placement;
0081:        import org.sakaiproject.tool.api.Tool;
0082:        import org.sakaiproject.tool.cover.SessionManager;
0083:        import org.sakaiproject.tool.cover.ToolManager;
0084:        import org.sakaiproject.user.cover.UserDirectoryService;
0085:        import org.sakaiproject.util.FormattedText;
0086:        import org.sakaiproject.util.MergedList;
0087:        import org.sakaiproject.util.MergedListEntryProviderBase;
0088:        import org.sakaiproject.util.MergedListEntryProviderFixedListWrapper;
0089:        import org.sakaiproject.util.ParameterParser;
0090:        import org.sakaiproject.util.ResourceLoader;
0091:        import org.sakaiproject.util.SortedIterator;
0092:        import org.sakaiproject.util.StringUtil;
0093:        import org.w3c.dom.Document;
0094:        import org.w3c.dom.Element;
0095:
0096:        /**
0097:         * AnnouncementAction is an implementation of Announcement service, which provides the complete function of announcements. User could check the announcements, create own new and manage all the announcement items, under certain permission check.
0098:         */
0099:        public class AnnouncementAction extends PagedResourceActionII {
0100:            /** Resource bundle using current language locale */
0101:            private static ResourceLoader rb = new ResourceLoader(
0102:                    "announcement");
0103:
0104:            private static final String CONTEXT_ENABLED_MENU_ITEM_EXISTS = "EnabledMenuItemExists";
0105:
0106:            private static final String CONTEXT_ENABLE_ITEM_CHECKBOXES = "EnableItemCheckBoxes";
0107:
0108:            private static final String ENABLED_MENU_ITEM_EXISTS = CONTEXT_ENABLED_MENU_ITEM_EXISTS;
0109:
0110:            private static final String NOT_SELECTED_FOR_REVISE_STATUS = "noSelectedForRevise";
0111:
0112:            private static final String FINISH_DELETING_STATUS = "FinishDeleting";
0113:
0114:            private static final String DELETE_ANNOUNCEMENT_STATUS = "deleteAnnouncement";
0115:
0116:            private static final String POST_STATUS = "post";
0117:
0118:            private static final String CANCEL_STATUS = "cancel";
0119:
0120:            private static final String MERGE_STATUS = "merge";
0121:
0122:            private static final String OPTIONS_STATUS = "options";
0123:
0124:            private static final String SSTATE_NOTI_VALUE = "noti_value";
0125:
0126:            private static final String SSTATE_PUBLICVIEW_VALUE = "public_view_value";
0127:
0128:            private static final String SORT_DATE = "date";
0129:
0130:            private static final String SORT_RELEASEDATE = "releasedate";
0131:
0132:            private static final String SORT_RETRACTDATE = "retractdate";
0133:
0134:            private static final String SORT_PUBLIC = "public";
0135:
0136:            private static final String SORT_FROM = "from";
0137:
0138:            private static final String SORT_SUBJECT = "subject";
0139:
0140:            private static final String SORT_CHANNEL = "channel";
0141:
0142:            private static final String SORT_FOR = "for";
0143:
0144:            private static final String SORT_GROUPTITLE = "grouptitle";
0145:
0146:            private static final String SORT_GROUPDESCRIPTION = "groupdescription";
0147:
0148:            private static final String CONTEXT_VAR_DISPLAY_OPTIONS = "displayOptions";
0149:
0150:            private static final String VELOCITY_DISPLAY_OPTIONS = CONTEXT_VAR_DISPLAY_OPTIONS;
0151:
0152:            private static final String PERMISSIONS_BUTTON_HANDLER = "doPermissions";
0153:
0154:            private static final String MERGE_BUTTON_HANDLER = "doMerge";
0155:
0156:            private static final String SSTATE_ATTRIBUTE_MERGED_CHANNELS = "mergedChannels";
0157:
0158:            private static final String VELOCITY_MERGED_CHANNEL_LIST = "mergedAnnouncementsCollection";
0159:
0160:            /** state attribute names. */
0161:            private static final String STATE_CHANNEL_REF = "channelId";
0162:
0163:            private static final String STATE_CHANNEL_PUBVIEW = "channelPubView";
0164:
0165:            private static final String PORTLET_CONFIG_PARM_NON_MERGED_CHANNELS = "nonMergedAnnouncementChannels";
0166:
0167:            private static final String PORTLET_CONFIG_PARM_MERGED_CHANNELS = "mergedAnnouncementChannels";
0168:
0169:            public static final String STATE_MESSAGE = "message";
0170:
0171:            public static final String STATE_MESSAGES = "pagedMessages";
0172:
0173:            protected static final String STATE_INITED = "annc.state.inited";
0174:
0175:            private static final String STATE_CURRENT_SORTED_BY = "session.state.sorted.by";
0176:
0177:            private static final String STATE_CURRENT_SORT_ASC = "session.state.sort.asc";
0178:
0179:            private static final String STATE_SELECTED_VIEW = "state.selected.view";
0180:
0181:            private static final String SC_TRUE = "true";
0182:
0183:            private static final String SC_FALSE = "false";
0184:
0185:            private static final String PUBLIC_DISPLAY_DISABLE_BOOLEAN = "publicDisplayBoolean";
0186:
0187:            private static final String VIEW_MODE_ALL = "view.all";
0188:            private static final String VIEW_MODE_PUBLIC = "view.public";
0189:            private static final String VIEW_MODE_BYGROUP = "view.bygroup";
0190:            private static final String VIEW_MODE_MYGROUPS = "view.mygroups";
0191:
0192:            // hours * minutes * seconds * milliseconds
0193:            private static final long MILLISECONDS_IN_DAY = (24 * 60 * 60 * 1000);
0194:            private static final long FUTURE_DAYS = 30;
0195:
0196:            private static final String RELEASE_DATE = "releaseDate";
0197:            private static final String RETRACT_DATE = "retractDate";
0198:            private static final String HIDDEN = "hidden";
0199:            private static final String SPECIFY_DATES = "specify";
0200:
0201:            private static final String SYNOPTIC_ANNOUNCEMENT_TOOL = "sakai.synoptic.announcement";
0202:
0203:            private static final String UPDATE_PERMISSIONS = "site.upd";
0204:
0205:            /**
0206:             * Used by callback to convert channel references to channels.
0207:             */
0208:            private final class AnnouncementReferenceToChannelConverter
0209:                    implements 
0210:                    MergedListEntryProviderFixedListWrapper.ReferenceToChannelConverter {
0211:                public Object getChannel(String channelReference) {
0212:                    try {
0213:                        return AnnouncementService
0214:                                .getAnnouncementChannel(channelReference);
0215:                    } catch (IdUnusedException e) {
0216:                        return null;
0217:                    } catch (PermissionException e) {
0218:                        return null;
0219:                    }
0220:                }
0221:            }
0222:
0223:            /*
0224:             * Callback class so that we can form references in a generic way.
0225:             */
0226:            private final class AnnouncementChannelReferenceMaker implements 
0227:                    MergedList.ChannelReferenceMaker {
0228:                public String makeReference(String siteId) {
0229:                    return AnnouncementService.channelReference(siteId,
0230:                            SiteService.MAIN_CONTAINER);
0231:                }
0232:            }
0233:
0234:            /**
0235:             * Used to provide a interface to the MergedList class that is shared with the calendar action.
0236:             */
0237:            class EntryProvider extends MergedListEntryProviderBase {
0238:                /*
0239:                 * (non-Javadoc)
0240:                 * 
0241:                 * @see org.sakaiproject.util.MergedListEntryProviderBase#makeReference(java.lang.String)
0242:                 */
0243:                public Object makeObjectFromSiteId(String id) {
0244:                    String channelReference = AnnouncementService
0245:                            .channelReference(id, SiteService.MAIN_CONTAINER);
0246:                    Object channel = null;
0247:
0248:                    if (channelReference != null) {
0249:                        try {
0250:                            channel = AnnouncementService
0251:                                    .getChannel(channelReference);
0252:                        } catch (IdUnusedException e) {
0253:                            // The channel isn't there.
0254:                        } catch (PermissionException e) {
0255:                            // We can't see the channel
0256:                        }
0257:                    }
0258:
0259:                    return channel;
0260:                }
0261:
0262:                /*
0263:                 * (non-Javadoc)
0264:                 * 
0265:                 * @see org.chefproject.actions.MergedEntryList.EntryProvider#allowGet(java.lang.Object)
0266:                 */
0267:                public boolean allowGet(String ref) {
0268:                    return AnnouncementService.allowGetChannel(ref);
0269:                }
0270:
0271:                /*
0272:                 * (non-Javadoc)
0273:                 * 
0274:                 * @see org.chefproject.actions.MergedEntryList.EntryProvider#getContext(java.lang.Object)
0275:                 */
0276:                public String getContext(Object obj) {
0277:                    if (obj == null) {
0278:                        return "";
0279:                    }
0280:
0281:                    AnnouncementChannel channel = (AnnouncementChannel) obj;
0282:                    return channel.getContext();
0283:                }
0284:
0285:                /*
0286:                 * (non-Javadoc)
0287:                 * 
0288:                 * @see org.chefproject.actions.MergedEntryList.EntryProvider#getReference(java.lang.Object)
0289:                 */
0290:                public String getReference(Object obj) {
0291:                    if (obj == null) {
0292:                        return "";
0293:                    }
0294:
0295:                    AnnouncementChannel channel = (AnnouncementChannel) obj;
0296:                    return channel.getReference();
0297:                }
0298:
0299:                /*
0300:                 * (non-Javadoc)
0301:                 * 
0302:                 * @see org.chefproject.actions.MergedEntryList.EntryProvider#getProperties(java.lang.Object)
0303:                 */
0304:                public ResourceProperties getProperties(Object obj) {
0305:                    if (obj == null) {
0306:                        return null;
0307:                    }
0308:
0309:                    AnnouncementChannel channel = (AnnouncementChannel) obj;
0310:                    return channel.getProperties();
0311:                }
0312:
0313:            }
0314:
0315:            /**
0316:             * Decorator for the "Message" class. It adds various properties to the decorated real Announcement message.
0317:             */
0318:            static public class AnnouncementWrapper implements 
0319:                    AnnouncementMessage {
0320:                private boolean enforceMaxNumberOfChars;
0321:
0322:                private AnnouncementMessage announcementMesssage;
0323:
0324:                private boolean editable;
0325:
0326:                private String channelDisplayName;
0327:
0328:                private int maxNumberOfChars;
0329:
0330:                private String range;
0331:
0332:                public AnnouncementMessage getMessage() {
0333:                    return this .announcementMesssage;
0334:                }
0335:
0336:                /**
0337:                 * Constructor
0338:                 * 
0339:                 * @param message
0340:                 *        The message to be wrapped.
0341:                 * @param currentChannel
0342:                 *        The channel in which the message is contained.
0343:                 * @param hostingChannel
0344:                 *        The channel into which the message is being merged.
0345:                 * @param maxNumberOfChars
0346:                 *        The maximum number of characters that will be returned by getTrimmedBody().
0347:                 */
0348:                public AnnouncementWrapper(AnnouncementMessage message,
0349:                        AnnouncementChannel currentChannel,
0350:                        AnnouncementChannel hostingChannel,
0351:                        AnnouncementActionState.DisplayOptions options,
0352:                        String range) {
0353:                    this .maxNumberOfChars = options
0354:                            .getNumberOfCharsPerAnnouncement();
0355:                    this .enforceMaxNumberOfChars = options
0356:                            .isEnforceNumberOfCharsPerAnnouncement();
0357:                    this .announcementMesssage = message;
0358:
0359:                    // This message is editable only if the site matches.
0360:                    this .editable = currentChannel.getReference().equals(
0361:                            hostingChannel.getReference());
0362:
0363:                    Site site = null;
0364:
0365:                    try {
0366:                        site = SiteService.getSite(currentChannel.getContext());
0367:                    } catch (IdUnusedException e) {
0368:                        // No site available.
0369:                    }
0370:
0371:                    if (site != null) {
0372:                        this .channelDisplayName = site.getTitle();
0373:                    } else {
0374:                        this .channelDisplayName = "";
0375:                    }
0376:
0377:                    if (range != null) {
0378:                        this .range = range;
0379:                    }
0380:                }
0381:
0382:                /**
0383:                 * Constructor
0384:                 * 
0385:                 * @param announcementWrapper
0386:                 *        The message to be wrapped.
0387:                 */
0388:                public AnnouncementWrapper(AnnouncementWrapper mWrapper) {
0389:                    this .maxNumberOfChars = mWrapper.maxNumberOfChars;
0390:                    this .enforceMaxNumberOfChars = mWrapper.enforceMaxNumberOfChars;
0391:                    this .announcementMesssage = mWrapper.getMessage();
0392:
0393:                    this .channelDisplayName = mWrapper.channelDisplayName;
0394:                    this .range = mWrapper.range;
0395:                }
0396:
0397:                /**
0398:                 * See if the given message was posted in the last N days, where N is the value of the maxDaysInPast parameter.
0399:                 */
0400:                private static boolean isMessageWithinLastNDays(
0401:                        AnnouncementMessage message, int maxDaysInPast) {
0402:                    long currentTime = TimeService.newTime().getTime();
0403:
0404:                    long timeDeltaMSeconds = currentTime
0405:                            - message.getHeader().getDate().getTime();
0406:
0407:                    long numDays = timeDeltaMSeconds / MILLISECONDS_IN_DAY;
0408:
0409:                    return (numDays <= maxDaysInPast);
0410:                }
0411:
0412:                /*
0413:                 * (non-Javadoc)
0414:                 * 
0415:                 * @see org.chefproject.core.Message#getHeader()
0416:                 */
0417:                public MessageHeader getHeader() {
0418:                    return announcementMesssage.getHeader();
0419:                }
0420:
0421:                /*
0422:                 * (non-Javadoc)
0423:                 * 
0424:                 * @see org.chefproject.core.Message#getBody()
0425:                 */
0426:                public String getBody() {
0427:                    return announcementMesssage.getBody();
0428:                }
0429:
0430:                /*
0431:                 * (non-Javadoc)
0432:                 * 
0433:                 * @see org.chefproject.core.Message#getBody()
0434:                 */
0435:                public String getTrimmedBody() {
0436:                    if (this .enforceMaxNumberOfChars) {
0437:                        // trim the body, as formatted text
0438:                        String body = announcementMesssage.getBody();
0439:                        StringBuffer buf = new StringBuffer();
0440:                        body = FormattedText
0441:                                .escapeHtmlFormattedTextSupressNewlines(body);
0442:                        boolean didTrim = FormattedText.trimFormattedText(body,
0443:                                this .maxNumberOfChars, buf);
0444:                        if (didTrim) {
0445:                            if (buf.toString().length() != 0) {
0446:                                buf.append("...");
0447:                            }
0448:                        }
0449:
0450:                        return buf.toString();
0451:                    } else {
0452:                        return announcementMesssage.getBody();
0453:                    }
0454:                }
0455:
0456:                /*
0457:                 * (non-Javadoc)
0458:                 * 
0459:                 * @see org.chefproject.core.Resource#getUrl()
0460:                 */
0461:                public String getUrl() {
0462:                    return announcementMesssage.getUrl();
0463:                }
0464:
0465:                /*
0466:                 * (non-Javadoc)
0467:                 * 
0468:                 * @see org.chefproject.core.Resource#getReference()
0469:                 */
0470:                public String getReference() {
0471:                    return announcementMesssage.getReference();
0472:                }
0473:
0474:                /**
0475:                 * @inheritDoc
0476:                 */
0477:                public String getReference(String rootProperty) {
0478:                    return getReference();
0479:                }
0480:
0481:                /**
0482:                 * @inheritDoc
0483:                 */
0484:                public String getUrl(String rootProperty) {
0485:                    return getUrl();
0486:                }
0487:
0488:                /*
0489:                 * (non-Javadoc)
0490:                 * 
0491:                 * @see org.chefproject.core.Resource#getId()
0492:                 */
0493:                public String getId() {
0494:                    return announcementMesssage.getId();
0495:                }
0496:
0497:                /*
0498:                 * (non-Javadoc)
0499:                 * 
0500:                 * @see org.chefproject.core.Resource#getProperties()
0501:                 */
0502:                public ResourceProperties getProperties() {
0503:                    return announcementMesssage.getProperties();
0504:                }
0505:
0506:                /**
0507:                 * returns the range string
0508:                 * 
0509:                 * @return
0510:                 */
0511:                public String getRange() {
0512:                    return range;
0513:                }
0514:
0515:                /**
0516:                 * Set the range string
0517:                 * 
0518:                 * @return
0519:                 */
0520:                public void setRange(String range) {
0521:                    this .range = range;
0522:                }
0523:
0524:                /*
0525:                 * (non-Javadoc)
0526:                 * 
0527:                 * @see org.chefproject.core.Resource#toXml(org.w3c.dom.Document, java.util.Stack)
0528:                 */
0529:                public Element toXml(Document doc, Stack stack) {
0530:                    return announcementMesssage.toXml(doc, stack);
0531:                }
0532:
0533:                /*
0534:                 * (non-Javadoc)
0535:                 * 
0536:                 * @see java.lang.Comparable#compareTo(java.lang.Object)
0537:                 */
0538:                public int compareTo(Object arg0) {
0539:                    return announcementMesssage.compareTo(arg0);
0540:                }
0541:
0542:                /**
0543:                 * Returns true if the message is editable.
0544:                 */
0545:                public boolean isEditable() {
0546:                    return editable;
0547:                }
0548:
0549:                /**
0550:                 * Returns the string that is used to show the channel to the user.
0551:                 */
0552:                public String getChannelDisplayName() {
0553:                    return channelDisplayName;
0554:                }
0555:
0556:                /*
0557:                 * (non-Javadoc)
0558:                 * 
0559:                 * @see org.chefproject.core.AnnouncementMessage#getAnnouncementHeader()
0560:                 */
0561:                public AnnouncementMessageHeader getAnnouncementHeader() {
0562:                    return announcementMesssage.getAnnouncementHeader();
0563:                }
0564:
0565:                /**
0566:                 * Constructs a list of wrapped/decorated AnnouncementMessages when given a list of unwrapped/undecorated AnnouncementMessages.
0567:                 * 
0568:                 * @param messages
0569:                 *        The list of messages.
0570:                 * @param currentChannel
0571:                 *        The current channel being processed.
0572:                 * @param hostingChannel
0573:                 *        The default channel of the page into which this list is being merged.
0574:                 * @param maxNumberOfDaysInThePast
0575:                 *        Messages over this limit will not be included in the list.
0576:                 * @param maxCharsPerAnnouncement
0577:                 *        The maximum number of characters that will be returned when getTrimmedBody() is called.
0578:                 */
0579:                static private List wrapList(List messages,
0580:                        AnnouncementChannel currentChannel,
0581:                        AnnouncementChannel hostingChannel,
0582:                        AnnouncementActionState.DisplayOptions options) {
0583:                    int maxNumberOfDaysInThePast = options
0584:                            .getNumberOfDaysInThePast();
0585:
0586:                    List messageList = new ArrayList();
0587:
0588:                    Iterator it = messages.iterator();
0589:
0590:                    while (it.hasNext()) {
0591:                        AnnouncementMessage message = (AnnouncementMessage) it
0592:                                .next();
0593:
0594:                        // See if the message falls within the filter window.
0595:                        if (options.isEnforceNumberOfDaysInThePastLimit()
0596:                                && !isMessageWithinLastNDays(message,
0597:                                        maxNumberOfDaysInThePast)) {
0598:                            continue;
0599:                        }
0600:
0601:                        messageList.add(new AnnouncementWrapper(message,
0602:                                currentChannel, hostingChannel, options,
0603:                                getAnnouncementRange(message)));
0604:                    }
0605:
0606:                    return messageList;
0607:                }
0608:
0609:            }
0610:
0611:            /**
0612:             * get announcement range information
0613:             */
0614:            private static String getAnnouncementRange(AnnouncementMessage a) {
0615:                if (a.getProperties().getProperty(
0616:                        ResourceProperties.PROP_PUBVIEW) != null
0617:                        && a.getProperties().getProperty(
0618:                                ResourceProperties.PROP_PUBVIEW).equals(
0619:                                Boolean.TRUE.toString())) {
0620:                    return rb.getString("gen.public");
0621:                } else if (a.getAnnouncementHeader().getAccess().equals(
0622:                        MessageHeader.MessageAccess.CHANNEL)) {
0623:                    return rb.getString("range.allgroups");
0624:                } else {
0625:                    int count = 0;
0626:                    String allGroupString = "";
0627:                    try {
0628:                        Site site = SiteService.getSite(EntityManager
0629:                                .newReference(a.getReference()).getContext());
0630:                        for (Iterator i = a.getAnnouncementHeader().getGroups()
0631:                                .iterator(); i.hasNext();) {
0632:                            Group aGroup = site.getGroup((String) i.next());
0633:                            if (aGroup != null) {
0634:                                count++;
0635:                                if (count > 1) {
0636:                                    allGroupString = allGroupString
0637:                                            .concat(", ").concat(
0638:                                                    aGroup.getTitle());
0639:                                } else {
0640:                                    allGroupString = aGroup.getTitle();
0641:                                }
0642:                            }
0643:                        }
0644:                    } catch (IdUnusedException e) {
0645:                        // No site available.
0646:                    }
0647:                    return allGroupString;
0648:                }
0649:            }
0650:
0651:            /**
0652:             * Enable or disable the observer
0653:             * 
0654:             * @param enable
0655:             *        if true, the observer is enabled, if false, it is disabled
0656:             */
0657:            protected void enableObserver(SessionState sstate, boolean enable) {
0658:                if (enable) {
0659:                    enableObservers(sstate);
0660:                } else {
0661:                    disableObservers(sstate);
0662:                }
0663:            }
0664:
0665:            /**
0666:             * See if the current tab is the workspace tab.
0667:             * 
0668:             * @return true if we are currently on the "My Workspace" tab.
0669:             */
0670:            private boolean isOnWorkspaceTab() {
0671:                // TODO: this is such a bad question... workspace? tab? revisit this. -ggolden
0672:                // return false;
0673:                // // we'll really answer the question - is the current request's site a user site, and not the ~admin user's site.
0674:                String siteId = ToolManager.getCurrentPlacement().getContext();
0675:                if (SiteService.getUserSiteId("admin").equals(siteId))
0676:                    return false;
0677:                return SiteService.isUserSite(siteId);
0678:            }
0679:
0680:            /**
0681:             * Build the context for showing merged view
0682:             */
0683:            public String buildMergeContext(VelocityPortlet portlet,
0684:                    Context context, RunData runData,
0685:                    AnnouncementActionState state, SessionState sstate) {
0686:
0687:                if (Log.getLogger("chef").isDebugEnabled())
0688:                    Log.debug("chef",
0689:                            "buildMergedCalendarContext has been reached");
0690:
0691:                MergedList mergedAnnouncementList = new MergedList();
0692:
0693:                mergedAnnouncementList
0694:                        .loadChannelsFromDelimitedString(
0695:                                isOnWorkspaceTab(),
0696:                                new EntryProvider(),
0697:                                StringUtil.trimToZero(SessionManager
0698:                                        .getCurrentSessionUserId()),
0699:                                mergedAnnouncementList
0700:                                        .getChannelReferenceArrayFromDelimitedString(
0701:                                                state.getChannelId(),
0702:                                                portlet
0703:                                                        .getPortletConfig()
0704:                                                        .getInitParameter(
0705:                                                                getPortletConfigParameterNameForLoadOnly(portlet))),
0706:                                SecurityService.isSuperUser(), ToolManager
0707:                                        .getCurrentPlacement().getContext());
0708:
0709:                // Place this object in the context so that the velocity template
0710:                // can get at it.
0711:                context.put(VELOCITY_MERGED_CHANNEL_LIST,
0712:                        mergedAnnouncementList);
0713:                context.put("tlang", rb);
0714:                sstate.setAttribute(SSTATE_ATTRIBUTE_MERGED_CHANNELS,
0715:                        mergedAnnouncementList);
0716:
0717:                String template = (String) getContext(runData).get("template");
0718:                return template + "-merge";
0719:            }
0720:
0721:            /**
0722:             * This is a cover to return the right config parameter name, regardless of whether the parameter is using an older, deprecated name or the newer version.
0723:             */
0724:            private String getPortletConfigParameterNameForLoadOnly(
0725:                    VelocityPortlet portlet) {
0726:                // Check to see if the older non-merged parameter is present.
0727:                // This is really the "merged" parameter, but it was incorrectly
0728:                // named. This is for backward compatibility.
0729:                String configParameter = StringUtil.trimToNull(portlet
0730:                        .getPortletConfig().getInitParameter(
0731:                                PORTLET_CONFIG_PARM_NON_MERGED_CHANNELS));
0732:                String configParameterName = configParameter != null ? PORTLET_CONFIG_PARM_NON_MERGED_CHANNELS
0733:                        : PORTLET_CONFIG_PARM_MERGED_CHANNELS;
0734:                return configParameterName;
0735:            }
0736:
0737:            /**
0738:             * Default is to use when Portal starts up
0739:             */
0740:            public String buildMainPanelContext(VelocityPortlet portlet,
0741:                    Context context, RunData rundata, SessionState sstate) {
0742:                // retrieve the state from state object
0743:                AnnouncementActionState state = (AnnouncementActionState) getState(
0744:                        portlet, rundata, AnnouncementActionState.class);
0745:
0746:                // load the saved option data
0747:                Placement placement = ToolManager.getCurrentPlacement();
0748:                if (placement != null) {
0749:                    Properties props = placement.getPlacementConfig();
0750:                    if (props.isEmpty())
0751:                        props = placement.getConfig();
0752:                    AnnouncementActionState.DisplayOptions disOptions = state
0753:                            .getDisplayOptions();
0754:                    disOptions.loadProperties(props);
0755:                    context.put(VELOCITY_DISPLAY_OPTIONS, disOptions);
0756:                } else {
0757:                    // Put our display options in the context so
0758:                    // that we can modify our list display accordingly
0759:                    context.put(VELOCITY_DISPLAY_OPTIONS, state
0760:                            .getDisplayOptions());
0761:                }
0762:
0763:                String template = (String) getContext(rundata).get("template");
0764:
0765:                // group realted variables
0766:                context.put("channelAccess",
0767:                        MessageHeader.MessageAccess.CHANNEL);
0768:                context.put("groupAccess", MessageHeader.MessageAccess.GROUPED);
0769:                // ********* for site column display ********
0770:                Site site = null;
0771:                try {
0772:                    site = SiteService.getSite(ToolManager
0773:                            .getCurrentPlacement().getContext());
0774:                    context.put("site", site);
0775:                } catch (IdUnusedException e) {
0776:                    // No site available.
0777:                } catch (NullPointerException e) {
0778:                }
0779:
0780:                // get the current channel ID from state object or prolet initial parameter
0781:                String channelId = state.getChannelId();
0782:                if (channelId == null) {
0783:                    // try the portlet parameter
0784:                    channelId = StringUtil.trimToNull(portlet
0785:                            .getPortletConfig().getInitParameter("channel"));
0786:                    if (channelId == null) {
0787:                        // form based on the request's site's "main" channel
0788:                        channelId = AnnouncementService.channelReference(
0789:                                ToolManager.getCurrentPlacement().getContext(),
0790:                                SiteService.MAIN_CONTAINER);
0791:                    }
0792:
0793:                    // let the state object have the current channel id
0794:                    state.setChannelId(channelId);
0795:                    state.setIsListVM(true);
0796:                }
0797:                // context.put("channel_id", ((channelId == null) ? "Now null" : channelId));
0798:                context.put("channel_id", ((channelId == null) ? rb
0799:                        .getString("java.nownull") : channelId));
0800:
0801:                // set if we have notification enabled
0802:                context.put("notification", Boolean
0803:                        .valueOf(notificationEnabled(state)));
0804:
0805:                // find the channel and channel information through the service
0806:                AnnouncementChannel channel = null;
0807:
0808:                boolean menu_new = true;
0809:                boolean menu_delete = true;
0810:                boolean menu_revise = true;
0811:
0812:                try {
0813:                    if (AnnouncementService.allowGetChannel(channelId)
0814:                            && isOkayToDisplayMessageMenu(state)) {
0815:                        // get the channel name throught announcement service API
0816:                        channel = AnnouncementService
0817:                                .getAnnouncementChannel(channelId);
0818:
0819:                        if (channel.allowGetMessages()
0820:                                && !state.getCurrentSortedBy().equals(
0821:                                        SORT_GROUPTITLE)
0822:                                && !state.getCurrentSortedBy().equals(
0823:                                        SORT_GROUPDESCRIPTION)) {
0824:                            // this checks for any possibility of an add, channel or any site group
0825:                            menu_new = channel.allowAddMessage();
0826:
0827:                            List messages = null;
0828:
0829:                            String view = (String) sstate
0830:                                    .getAttribute(STATE_SELECTED_VIEW);
0831:
0832:                            if (view != null) {
0833:                                if (view.equals(VIEW_MODE_ALL)) {
0834:                                    messages = getMessages(channel, null, true,
0835:                                            state, portlet);
0836:                                } else if (view.equals(VIEW_MODE_BYGROUP)) {
0837:                                    messages = getMessagesByGroups(site,
0838:                                            channel, null, true, state, portlet);
0839:                                } else if (view.equals(VIEW_MODE_PUBLIC)) {
0840:                                    messages = getMessagesPublic(site, channel,
0841:                                            null, true, state, portlet);
0842:                                }
0843:                            } else {
0844:                                messages = getMessages(channel, null, true,
0845:                                        state, portlet);
0846:                            }
0847:
0848:                            sstate.setAttribute("messages", messages);
0849:                            messages = prepPage(sstate);
0850:                            sstate.setAttribute(STATE_MESSAGES, messages);
0851:
0852:                            menu_delete = false;
0853:                            for (int i = 0; i < messages.size(); i++) {
0854:                                AnnouncementWrapper message = (AnnouncementWrapper) messages
0855:                                        .get(i);
0856:
0857:                                // If any message is allowed to be removed
0858:                                // Also check to see if the AnnouncementWrapper object thinks
0859:                                // that this message is editable from the default site.
0860:                                if (message.editable
0861:                                        && channel.allowRemoveMessage(message)) {
0862:                                    menu_delete = true;
0863:                                    break;
0864:                                }
0865:                            }
0866:
0867:                            menu_revise = false;
0868:                            for (int i = 0; i < messages.size(); i++) {
0869:                                // if any message is allowed to be edited
0870:                                if (channel
0871:                                        .allowEditMessage(((Message) messages
0872:                                                .get(i)).getId())) {
0873:                                    menu_revise = true;
0874:                                    break;
0875:                                }
0876:                            }
0877:                        } else
0878:                        // if the messages in this channel are not allow to be accessed
0879:                        {
0880:                            menu_new = channel.allowAddMessage();
0881:                            menu_revise = false;
0882:                            menu_delete = false;
0883:                        } // if-else
0884:                    } else
0885:                    // if the channel is not allowed to access
0886:                    {
0887:                        menu_new = false;
0888:                        menu_revise = false;
0889:                        menu_delete = false;
0890:                    }
0891:                } catch (PermissionException error) {
0892:                    if (Log.getLogger("chef").isDebugEnabled())
0893:                        Log.debug("chef", this 
0894:                                + "inside .buildNormalContext(): " + error);
0895:                } catch (IdUnusedException error) {
0896:                    if (AnnouncementService.allowAddChannel(channelId)) {
0897:                        try {
0898:                            AnnouncementChannelEdit edit = AnnouncementService
0899:                                    .addAnnouncementChannel(channelId);
0900:                            AnnouncementService.commitChannel(edit);
0901:                            channel = edit;
0902:                        } catch (IdUsedException err) {
0903:                            if (Log.getLogger("chef").isDebugEnabled())
0904:                                Log.debug("chef", this 
0905:                                        + "inside .buildNormalContext(): "
0906:                                        + err);
0907:                        } catch (IdInvalidException err) {
0908:                        } catch (PermissionException err) {
0909:                        }
0910:                        menu_new = channel.allowAddMessage();
0911:                        menu_revise = false;
0912:                        menu_delete = false;
0913:                    } else {
0914:                        menu_new = false;
0915:                        menu_revise = false;
0916:                        menu_delete = false;
0917:                    } // if-else
0918:                } // try-catch
0919:
0920:                // check the state status to decide which vm to render
0921:                String statusName = state.getStatus();
0922:
0923:                AnnouncementActionState.DisplayOptions displayOptions = state
0924:                        .getDisplayOptions();
0925:
0926:                buildMenu(portlet, context, rundata, state, menu_new,
0927:                        menu_delete, menu_revise, this 
0928:                                .isOkToShowMergeButton(statusName), this 
0929:                                .isOkToShowPermissionsButton(statusName), this 
0930:                                .isOkToShowOptionsButton(statusName),
0931:                        displayOptions);
0932:
0933:                // added by zqian for toolbar
0934:                context.put("allow_new", Boolean.valueOf(menu_new));
0935:                context.put("allow_delete", Boolean.valueOf(menu_delete));
0936:                context.put("allow_revise", Boolean.valueOf(menu_revise));
0937:
0938:                if (statusName != null) {
0939:                    template = getTemplate(portlet, context, rundata, sstate,
0940:                            state, template);
0941:                }
0942:
0943:                if (channel != null) {
0944:                    // ********* for sorting *********
0945:                    if (channel.allowGetMessages()
0946:                            && isOkayToDisplayMessageMenu(state)) {
0947:                        String currentSortedBy = state.getCurrentSortedBy();
0948:                        context.put("currentSortedBy", currentSortedBy);
0949:                        if (state.getCurrentSortAsc())
0950:                            context.put("currentSortAsc", "true");
0951:                        else
0952:                            context.put("currentSortAsc", "false");
0953:
0954:                        if (currentSortedBy != null
0955:                                && !currentSortedBy.equals(SORT_GROUPTITLE)
0956:                                && !currentSortedBy
0957:                                        .equals(SORT_GROUPDESCRIPTION)) {
0958:                            // sort in announcement list view
0959:                            buildSortedContext(portlet, context, rundata,
0960:                                    sstate);
0961:                        }
0962:
0963:                    } // if allowGetMessages()
0964:                }
0965:
0966:                context.put("service", AnnouncementService.getInstance());
0967:                context.put("entityManager", EntityManager.getInstance());
0968:                context.put("timeservice", TimeService.getInstance());
0969:
0970:                // ********* for site column display ********
0971:
0972:                context.put("isOnWorkspaceTab", (isOnWorkspaceTab() ? "true"
0973:                        : "false"));
0974:
0975:                context.put("channel", channel);
0976:
0977:                final Tool tool = ToolManager.getCurrentTool();
0978:                final String toolId = tool.getId();
0979:                context.put("toolId", toolId);
0980:
0981:                if (channel != null) {
0982:                    // show all the groups in this channal that user has get message in
0983:                    Collection groups = channel.getGroupsAllowGetMessage();
0984:                    if (groups != null && groups.size() > 0) {
0985:                        context.put("groups", groups);
0986:                    }
0987:                }
0988:
0989:                if (sstate.getAttribute(STATE_SELECTED_VIEW) != null) {
0990:                    context.put("view", sstate
0991:                            .getAttribute(STATE_SELECTED_VIEW));
0992:                }
0993:
0994:                // inform the observing courier that we just updated the page...
0995:                // if there are pending requests to do so they can be cleared
0996:                justDelivered(sstate);
0997:
0998:                return template;
0999:
1000:            } // buildMainPanelContext
1001:
1002:            public void buildSortedContext(VelocityPortlet portlet,
1003:                    Context context, RunData rundata, SessionState sstate) {
1004:                Vector drafts = new Vector();
1005:                Vector nonDrafts = new Vector();
1006:                Vector showMessagesList = new Vector();
1007:
1008:                List messages = prepPage(sstate);
1009:                for (int i = 0; i < messages.size(); i++) {
1010:                    final AnnouncementMessage m = (AnnouncementMessage) messages
1011:                            .get(i);
1012:
1013:                    if (m.getAnnouncementHeader().getDraft()) {
1014:                        drafts.addElement(m);
1015:                    } else {
1016:                        nonDrafts.add(m);
1017:                    }
1018:                }
1019:
1020:                AnnouncementActionState state = (AnnouncementActionState) getState(
1021:                        portlet, rundata, AnnouncementActionState.class);
1022:
1023:                SortedIterator sortedDraftIterator = new SortedIterator(drafts
1024:                        .iterator(), new AnnouncementComparator(state
1025:                        .getCurrentSortedBy(), state.getCurrentSortAsc()));
1026:                SortedIterator sortedNonDraftIterator = new SortedIterator(
1027:                        nonDrafts.iterator(), new AnnouncementComparator(state
1028:                                .getCurrentSortedBy(), state
1029:                                .getCurrentSortAsc()));
1030:
1031:                if (state.getCurrentSortAsc()) {
1032:                    while (sortedDraftIterator.hasNext())
1033:                        showMessagesList
1034:                                .add((AnnouncementMessage) sortedDraftIterator
1035:                                        .next());
1036:
1037:                    while (sortedNonDraftIterator.hasNext())
1038:                        showMessagesList
1039:                                .add((AnnouncementMessage) sortedNonDraftIterator
1040:                                        .next());
1041:                } else {
1042:                    while (sortedDraftIterator.hasNext())
1043:                        showMessagesList
1044:                                .add((AnnouncementMessage) sortedDraftIterator
1045:                                        .next());
1046:
1047:                    while (sortedNonDraftIterator.hasNext())
1048:                        showMessagesList
1049:                                .add((AnnouncementMessage) sortedNonDraftIterator
1050:                                        .next());
1051:                }
1052:
1053:                context.put("showMessagesList", showMessagesList.iterator());
1054:                context.put("showMessagesList2", showMessagesList.iterator());
1055:                context.put("messageListVector", showMessagesList);
1056:
1057:                context.put("totalPageNumber", sstate
1058:                        .getAttribute(STATE_TOTAL_PAGENUMBER));
1059:                context.put("formPageNumber", FORM_PAGE_NUMBER);
1060:                context.put("prev_page_exists", sstate
1061:                        .getAttribute(STATE_PREV_PAGE_EXISTS));
1062:                context.put("next_page_exists", sstate
1063:                        .getAttribute(STATE_NEXT_PAGE_EXISTS));
1064:                context.put("current_page", sstate
1065:                        .getAttribute(STATE_CURRENT_PAGE));
1066:                pagingInfoToContext(sstate, context);
1067:
1068:                // context.put("jsfutil", JsfUtil.this);
1069:
1070:            } // buildSortedContext
1071:
1072:            public String getTemplate(VelocityPortlet portlet, Context context,
1073:                    RunData rundata, SessionState sstate,
1074:                    AnnouncementActionState state, String value) {
1075:                String template = value;
1076:                String statusName = state.getStatus();
1077:
1078:                if (statusName.equals(DELETE_ANNOUNCEMENT_STATUS)) {
1079:                    template = buildDeleteAnnouncementContext(portlet, context,
1080:                            rundata, state);
1081:                } else if (statusName.equals("showMetadata")) {
1082:                    template = buildShowMetadataContext(portlet, context,
1083:                            rundata, state, sstate);
1084:                } else if ((statusName.equals("goToReviseAnnouncement"))
1085:                        || (statusName.equals("backToReviseAnnouncement"))
1086:                        || (statusName.equals("new"))
1087:                        || (statusName.equals("stayAtRevise"))) {
1088:                    template = buildReviseAnnouncementContext(portlet, context,
1089:                            rundata, state, sstate);
1090:                } else if (statusName.equals("revisePreviw")) {
1091:                    template = buildPreviewContext(portlet, context, rundata,
1092:                            state);
1093:                } else if ((statusName.equals(CANCEL_STATUS))
1094:                        || (statusName.equals(POST_STATUS))
1095:                        || (statusName.equals("FinishDeleting"))) {
1096:                    template = buildCancelContext(portlet, context, rundata,
1097:                            state);
1098:                } else if (statusName.equals("noSelectedForDeletion")
1099:                        || (statusName.equals(NOT_SELECTED_FOR_REVISE_STATUS))) {
1100:                    // addAlert(sstate, "You have to select the announcement first!");
1101:                    addAlert(sstate, rb.getString("java.alert.youhave"));
1102:                } else if (statusName.equals("moreThanOneSelectedForRevise")) {
1103:                    // addAlert(sstate, "Please choose only one announcement at a time to revise!");
1104:                    addAlert(sstate, rb.getString("java.alert.pleasechoose"));
1105:                } else if (statusName.equals("noPermissionToRevise")) {
1106:                    // addAlert(sstate, "You don't have permission to revise this announcement!");
1107:                    addAlert(sstate, rb.getString("java.alert.youdont"));
1108:                } else if (statusName.equals(MERGE_STATUS)) {
1109:                    template = buildMergeContext(portlet, context, rundata,
1110:                            state, sstate);
1111:                } else if (statusName.equals(OPTIONS_STATUS)) {
1112:                    template = buildOptionsPanelContext(portlet, context,
1113:                            rundata, sstate);
1114:                }
1115:                return template;
1116:
1117:            } // getTemplate
1118:
1119:            /**
1120:             * Setup for the options panel.
1121:             */
1122:            public String buildOptionsPanelContext(VelocityPortlet portlet,
1123:                    Context context, RunData runData, SessionState state) {
1124:                // retrieve the state from state object
1125:                AnnouncementActionState actionState = (AnnouncementActionState) getState(
1126:                        portlet, runData, AnnouncementActionState.class);
1127:                context.put(CONTEXT_VAR_DISPLAY_OPTIONS, actionState
1128:                        .getDisplayOptions());
1129:
1130:                String channelId = actionState.getChannelId();
1131:                Reference channelRef = EntityManager.newReference(channelId);
1132:                context.put("description", rb.getString("java.setting")// "Setting options for Announcements in worksite "
1133:                        + SiteService.getSiteDisplay(channelRef.getContext()));
1134:
1135:                // pick the "-customize" template based on the standard template name
1136:                String template = (String) getContext(runData).get("template");
1137:                return template + "-customize";
1138:                // return template + rb.getString("java.customize");
1139:
1140:            } // buildOptionsPanelContext
1141:
1142:            /**
1143:             * Returns true if it is okay to display the revise/delete/etc. menu buttons.
1144:             */
1145:            private boolean isOkayToDisplayMessageMenu(
1146:                    AnnouncementActionState state) {
1147:                String selectedMessageReference = state.getMessageReference();
1148:
1149:                // If we're in the list state or if there is otherwise no message selected,
1150:                // return true.
1151:                if (state.getStatus() == null
1152:                        || state.getStatus().equals(CANCEL_STATUS)
1153:                        || selectedMessageReference == null
1154:                        || selectedMessageReference.length() == 0) {
1155:                    return true;
1156:                }
1157:                if (state.getStatus().equals(MERGE_STATUS)) {
1158:                    return false;
1159:                } else {
1160:                    String channelID = getChannelIdFromReference(selectedMessageReference);
1161:
1162:                    boolean selectedMessageMatchesDefaultChannel = state
1163:                            .getChannelId().equals(channelID);
1164:
1165:                    return selectedMessageMatchesDefaultChannel;
1166:                }
1167:            }
1168:
1169:            /**
1170:             * Returns true if it is ok to show the options button in the toolbar.
1171:             */
1172:            private boolean isOkToShowOptionsButton(String statusName) {
1173:                if (SiteService.allowUpdateSite(ToolManager
1174:                        .getCurrentPlacement().getContext())
1175:                        && !isOnWorkspaceTab()) {
1176:                    return (statusName == null
1177:                            || statusName.equals(CANCEL_STATUS)
1178:                            || statusName.equals(POST_STATUS)
1179:                            || statusName.equals(DELETE_ANNOUNCEMENT_STATUS)
1180:                            || statusName.equals(FINISH_DELETING_STATUS)
1181:                            || statusName.equals("noSelectedForDeletion") || statusName
1182:                            .equals(NOT_SELECTED_FOR_REVISE_STATUS));
1183:                } else {
1184:                    return false;
1185:                }
1186:            }
1187:
1188:            /*
1189:             * what i've done to make this tool automaticlly updated includes some corresponding imports in buildMail, tell observer just the page is just refreshed in the do() functions related to show the list, enable the obeserver in other do() functions
1190:             * related to not show the list, disable the obeserver in the do(), define the session sstate object, and protlet. add initState add updateObservationOfChannel() add state attribute STATE_CHANNEL_REF
1191:             */
1192:
1193:            /**
1194:             * Returns true if it is okay to show the merge button in the menu.
1195:             */
1196:            private boolean isOkToShowMergeButton(String statusName) {
1197:                String displayMerge = ServerConfigurationService.getString(
1198:                        "announcement.merge.display", "1");
1199:
1200:                if (displayMerge != null && !displayMerge.equals("1"))
1201:                    return false;
1202:
1203:                if (SiteService.allowUpdateSite(ToolManager
1204:                        .getCurrentPlacement().getContext())
1205:                        && !isOnWorkspaceTab()) {
1206:                    return (statusName == null
1207:                            || statusName.equals(CANCEL_STATUS)
1208:                            || statusName.equals(POST_STATUS)
1209:                            || statusName.equals(DELETE_ANNOUNCEMENT_STATUS)
1210:                            || statusName.equals(FINISH_DELETING_STATUS)
1211:                            || statusName.equals("noSelectedForDeletion") || statusName
1212:                            .equals(NOT_SELECTED_FOR_REVISE_STATUS));
1213:                } else {
1214:                    return false;
1215:                }
1216:            }
1217:
1218:            /**
1219:             * Returns true if it is okay to show the permissions button in the menu.
1220:             */
1221:            private boolean isOkToShowPermissionsButton(String statusName) {
1222:                if (SiteService.allowUpdateSite(ToolManager
1223:                        .getCurrentPlacement().getContext())) {
1224:                    return (statusName == null
1225:                            || statusName.equals(CANCEL_STATUS)
1226:                            || statusName.equals(POST_STATUS)
1227:                            || statusName.equals(DELETE_ANNOUNCEMENT_STATUS)
1228:                            || statusName.equals(FINISH_DELETING_STATUS)
1229:                            || statusName.equals("noSelectedForDeletion") || statusName
1230:                            .equals(NOT_SELECTED_FOR_REVISE_STATUS));
1231:                } else {
1232:                    return false;
1233:                }
1234:            }
1235:
1236:            /**
1237:             * This should be the single point for getting lists of announcements in this action. It collects together all the announcements and wraps the real announcements in a decorator object that adds extra properties for use in the VM template.
1238:             * 
1239:             * @throws PermissionException
1240:             */
1241:            private List getMessages(AnnouncementChannel defaultChannel,
1242:                    Filter filter, boolean ascending,
1243:                    AnnouncementActionState state, VelocityPortlet portlet)
1244:                    throws PermissionException {
1245:                List messageList = new ArrayList();
1246:
1247:                MergedList mergedAnnouncementList = new MergedList();
1248:
1249:                // TODO - MERGE FIX
1250:                String[] channelArrayFromConfigParameterValue = null;
1251:
1252:                // Figure out the list of channel references that we'll be using.
1253:                // If we're on the workspace tab, we get everything.
1254:                // Don't do this if we're the super-user, since we'd be
1255:                // overwhelmed.
1256:                if (isOnWorkspaceTab() && !SecurityService.isSuperUser()) {
1257:                    channelArrayFromConfigParameterValue = mergedAnnouncementList
1258:                            .getAllPermittedChannels(new AnnouncementChannelReferenceMaker());
1259:                } else {
1260:                    channelArrayFromConfigParameterValue = mergedAnnouncementList
1261:                            .getChannelReferenceArrayFromDelimitedString(
1262:                                    state.getChannelId(),
1263:                                    portlet
1264:                                            .getPortletConfig()
1265:                                            .getInitParameter(
1266:                                                    getPortletConfigParameterNameForLoadOnly(portlet)));
1267:                }
1268:
1269:                mergedAnnouncementList.loadChannelsFromDelimitedString(
1270:                        isOnWorkspaceTab(),
1271:                        new MergedListEntryProviderFixedListWrapper(
1272:                                new EntryProvider(), state.getChannelId(),
1273:                                channelArrayFromConfigParameterValue,
1274:                                new AnnouncementReferenceToChannelConverter()),
1275:                        StringUtil.trimToZero(SessionManager
1276:                                .getCurrentSessionUserId()),
1277:                        channelArrayFromConfigParameterValue, SecurityService
1278:                                .isSuperUser(), ToolManager
1279:                                .getCurrentPlacement().getContext());
1280:
1281:                Iterator channelsIt = mergedAnnouncementList.iterator();
1282:
1283:                while (channelsIt.hasNext()) {
1284:                    MergedList.MergedEntry curEntry = (MergedList.MergedEntry) channelsIt
1285:                            .next();
1286:
1287:                    // If this entry should not be merged, skip to the next one.
1288:                    if (!curEntry.isMerged()) {
1289:                        continue;
1290:                    }
1291:
1292:                    AnnouncementChannel curChannel = null;
1293:                    try {
1294:                        curChannel = (AnnouncementChannel) AnnouncementService
1295:                                .getChannel(curEntry.getReference());
1296:                    } catch (IdUnusedException e) {
1297:                        Log.debug("chef", this  + "getMessages()" + e);
1298:                    } catch (PermissionException e) {
1299:                        Log.debug("chef", this  + "getMessages()" + e);
1300:                    }
1301:
1302:                    if (curChannel != null) {
1303:                        if (AnnouncementService.allowGetChannel(curChannel
1304:                                .getReference())) {
1305:                            messageList.addAll(AnnouncementWrapper.wrapList(
1306:                                    curChannel.getMessages(filter, ascending),
1307:                                    curChannel, defaultChannel, state
1308:                                            .getDisplayOptions()));
1309:                        }
1310:                    }
1311:                }
1312:
1313:                // Do an overall sort. We couldn't do this earlier since each merged channel
1314:                Collections.sort(messageList);
1315:
1316:                // Reverse if we're not ascending.
1317:                if (!ascending) {
1318:                    Collections.reverse(messageList);
1319:                }
1320:
1321:                // Apply any necessary list truncation.
1322:                messageList = getViewableMessages(messageList, ToolManager
1323:                        .getCurrentPlacement().getContext());
1324:
1325:                messageList = trimListToMaxNumberOfAnnouncements(messageList,
1326:                        state.getDisplayOptions());
1327:
1328:                return messageList;
1329:            }
1330:
1331:            /**
1332:             * This get the whole list of announcement, find their groups, and list them based on group attribute
1333:             * 
1334:             * @throws PermissionException
1335:             */
1336:            private List getMessagesByGroups(Site site,
1337:                    AnnouncementChannel defaultChannel, Filter filter,
1338:                    boolean ascending, AnnouncementActionState state,
1339:                    VelocityPortlet portlet) throws PermissionException {
1340:                List messageList = getMessages(defaultChannel, filter,
1341:                        ascending, state, portlet);
1342:                List rv = new Vector();
1343:
1344:                for (int i = 0; i < messageList.size(); i++) {
1345:                    AnnouncementWrapper aMessage = (AnnouncementWrapper) messageList
1346:                            .get(i);
1347:                    String pubview = aMessage.getProperties().getProperty(
1348:                            ResourceProperties.PROP_PUBVIEW);
1349:                    if (pubview != null
1350:                            && Boolean.valueOf(pubview).booleanValue()) {
1351:                        // public announcements
1352:                        aMessage.setRange(rb.getString("range.public"));
1353:                        rv.add(new AnnouncementWrapper(aMessage));
1354:                    } else {
1355:                        if (aMessage.getAnnouncementHeader().getAccess()
1356:                                .equals(MessageHeader.MessageAccess.CHANNEL)) {
1357:                            // site announcements
1358:                            aMessage.setRange(rb.getString("range.allgroups"));
1359:                            rv.add(new AnnouncementWrapper(aMessage));
1360:                        } else {
1361:                            for (Iterator k = aMessage.getAnnouncementHeader()
1362:                                    .getGroups().iterator(); k.hasNext();) {
1363:                                // announcement by group
1364:                                AnnouncementWrapper m = new AnnouncementWrapper(
1365:                                        aMessage);
1366:                                m.setRange(site.getGroup((String) k.next())
1367:                                        .getTitle());
1368:                                rv.add(m);
1369:                            }
1370:                        }
1371:
1372:                    }
1373:                }
1374:
1375:                return rv;
1376:
1377:            } // getMessagesByGroups
1378:
1379:            /**
1380:             * This get the whole list of announcement, find their groups, and list them based on group attribute
1381:             * 
1382:             * @throws PermissionException
1383:             */
1384:            private List getMessagesPublic(Site site,
1385:                    AnnouncementChannel defaultChannel, Filter filter,
1386:                    boolean ascending, AnnouncementActionState state,
1387:                    VelocityPortlet portlet) throws PermissionException {
1388:                List messageList = getMessages(defaultChannel, filter,
1389:                        ascending, state, portlet);
1390:                List rv = new Vector();
1391:
1392:                for (int i = 0; i < messageList.size(); i++) {
1393:                    AnnouncementMessage aMessage = (AnnouncementMessage) messageList
1394:                            .get(i);
1395:                    String pubview = aMessage.getProperties().getProperty(
1396:                            ResourceProperties.PROP_PUBVIEW);
1397:                    if (pubview != null
1398:                            && Boolean.valueOf(pubview).booleanValue()) {
1399:                        // public announcements
1400:                        rv.add(aMessage);
1401:                    }
1402:                }
1403:
1404:                return rv;
1405:
1406:            } // getMessagesPublic
1407:
1408:            /**
1409:             * This will limit the maximum number of announcements that is shown.
1410:             */
1411:            private List trimListToMaxNumberOfAnnouncements(List messageList,
1412:                    AnnouncementActionState.DisplayOptions options) {
1413:                if (options.isEnforceNumberOfAnnouncementsLimit()) {
1414:                    int numberOfAnnouncements = options
1415:                            .getNumberOfAnnouncements();
1416:                    ArrayList destList = new ArrayList();
1417:
1418:                    // We need to go backwards through the list, limiting it to the number
1419:                    // of announcements that we're allowed to display.
1420:                    for (int i = messageList.size() - 1, curAnnouncementCount = 0; i >= 0
1421:                            && curAnnouncementCount < numberOfAnnouncements; i--) {
1422:                        AnnouncementMessage message = (AnnouncementMessage) messageList
1423:                                .get(i);
1424:
1425:                        destList.add(message);
1426:
1427:                        curAnnouncementCount++;
1428:                    }
1429:
1430:                    return destList;
1431:                } else {
1432:                    return messageList;
1433:                }
1434:            }
1435:
1436:            /**
1437:             * Filters out messages based on hidden property and release/retract dates.
1438:             * Only use hidden if in synoptic tool.
1439:             * 
1440:             * @param messageList
1441:             * 			The unfiltered message list
1442:             * 
1443:             * @return
1444:             * 			List of messsage this user is able to view
1445:             */
1446:            private List getViewableMessages(List messageList, String siteId) {
1447:                final List filteredMessages = new ArrayList();
1448:
1449:                for (Iterator messIter = messageList.iterator(); messIter
1450:                        .hasNext();) {
1451:                    final AnnouncementMessage message = (AnnouncementMessage) messIter
1452:                            .next();
1453:
1454:                    // for synoptic tool or if in MyWorkspace, 
1455:                    // only display if not hidden AND
1456:                    // between release and retract dates (if set)
1457:                    if (isSynopticTool() || isOnWorkspaceTab()) {
1458:                        if (!isHidden(message) && isViewable(message)) {
1459:                            filteredMessages.add(message);
1460:                        }
1461:                    } else {
1462:                        // on main page, if hidden but user has hidden permission
1463:                        // then display. Otherwise, if between release/retract dates
1464:                        // or they are not set
1465:                        if (isHidden(message)) {
1466:                            if (canViewHidden(message, siteId)) {
1467:                                filteredMessages.add(message);
1468:                            }
1469:                        } else if (isViewable(message)) {
1470:                            filteredMessages.add(message);
1471:                        } else if (canViewHidden(message, siteId)) {
1472:                            filteredMessages.add(message);
1473:                        }
1474:                    }
1475:                }
1476:
1477:                return filteredMessages;
1478:            }
1479:
1480:            /**
1481:             * Returns true if the tool with the id passed in exists in the
1482:             * current site.
1483:             * 
1484:             * @param toolId
1485:             * 			The tool id to search for.
1486:             * 
1487:             * @return
1488:             * 			TRUE if tool exists, FALSE otherwise.
1489:             */
1490:            private boolean isSynopticTool() {
1491:                String curToolId = ToolManager.getCurrentTool().getId();
1492:
1493:                if (SYNOPTIC_ANNOUNCEMENT_TOOL.equals(curToolId)) {
1494:                    return true;
1495:                }
1496:
1497:                return false;
1498:            }
1499:
1500:            /**
1501:             * Determines if use has draft (UI: hidden) permission or site.upd
1502:             * If so, they will be able to view messages that are hidden
1503:             */
1504:            private boolean canViewHidden(AnnouncementMessage msg, String siteId) {
1505:                final boolean b = SecurityService.unlock(
1506:                        AnnouncementService.SECURE_READ_DRAFT, msg
1507:                                .getReference())
1508:                        || SecurityService.unlock(UPDATE_PERMISSIONS, "/site/"
1509:                                + siteId);
1510:                return b;
1511:            }
1512:
1513:            /**
1514:             * Determine if message is hidden (draft property set)
1515:             */
1516:            private boolean isHidden(AnnouncementMessage message) {
1517:                return message.getHeader().getDraft();
1518:                /*		final ResourceProperties messageProps = message.getProperties();
1519:                
1520:                 boolean hidden = false;
1521:                 try 
1522:                 {	hidden = messageProps.getBooleanProperty(HIDDEN);
1523:                 } 
1524:                 catch (Exception e) 
1525:                 {
1526:                 // Just means property not set, so continue
1527:                 } 
1528:                
1529:                 return hidden;
1530:                 */
1531:            }
1532:
1533:            /**
1534:             * Determine if message viewable based on release/retract dates (if set)
1535:             */
1536:            private boolean isViewable(AnnouncementMessage message) {
1537:                final ResourceProperties messageProps = message.getProperties();
1538:
1539:                final Time now = TimeService.newTime();
1540:                try {
1541:                    final Time releaseDate = message.getProperties()
1542:                            .getTimeProperty(RELEASE_DATE);
1543:
1544:                    if (now.before(releaseDate)) {
1545:                        return false;
1546:                    }
1547:                } catch (Exception e) {
1548:                    // Just not using/set Release Date
1549:                }
1550:
1551:                try {
1552:                    final Time retractDate = message.getProperties()
1553:                            .getTimeProperty(RETRACT_DATE);
1554:
1555:                    if (now.after(retractDate)) {
1556:                        return false;
1557:                    }
1558:                } catch (Exception e) {
1559:                    // Just not using/set Retract Date
1560:                }
1561:
1562:                return true;
1563:            }
1564:
1565:            /**
1566:             * Build the context for preview an attachment
1567:             */
1568:            protected String buildPreviewContext(VelocityPortlet portlet,
1569:                    Context context, RunData rundata,
1570:                    AnnouncementActionState state) {
1571:                context.put("conService", ContentHostingService.getInstance());
1572:
1573:                // to get the content Type Image Service
1574:                context.put("contentTypeImageService", ContentTypeImageService
1575:                        .getInstance());
1576:
1577:                final String subject = state.getTempSubject();
1578:                final String body = state.getTempBody();
1579:                final Time tempReleaseDate = state.getTempReleaseDate();
1580:                final Time tempRetractDate = state.getTempRetractDate();
1581:                context.put("subject", subject);
1582:                context.put("body", body);
1583:                context.put("user", UserDirectoryService.getCurrentUser());
1584:
1585:                // Set date
1586:                AnnouncementMessageEdit edit = state.getEdit();
1587:
1588:                if (tempReleaseDate != null) {
1589:                    context.put("date", tempReleaseDate);
1590:                } else {
1591:                    Time releaseDate = null;
1592:                    try {
1593:                        releaseDate = edit.getProperties().getTimeProperty(
1594:                                RELEASE_DATE);
1595:                        context.put("date", releaseDate);
1596:                    } catch (Exception e) {
1597:                        // not set so set switch appropriately
1598:                        context.put("date", TimeService.newTime());
1599:                    }
1600:                }
1601:
1602:                List attachments = state.getAttachments();
1603:                context.put("attachments", attachments);
1604:
1605:                String peid = ((JetspeedRunData) rundata).getJs_peid();
1606:                SessionState sstate = ((JetspeedRunData) rundata)
1607:                        .getPortletSessionState(peid);
1608:
1609:                // output the public view options
1610:                boolean pubview = Boolean.valueOf(
1611:                        (String) sstate.getAttribute(SSTATE_PUBLICVIEW_VALUE))
1612:                        .booleanValue();
1613:                if (pubview)
1614:                    context.put("IsPubView", rb.getString("java.yes"));// "Yes");
1615:                else
1616:                    context.put("IsPubView", rb.getString("java.no"));// "No");
1617:
1618:                if (edit == null)
1619:                    context.put(HIDDEN, false);
1620:                else {
1621:                    final boolean hidden = edit.getHeader().getDraft();
1622:                    context.put(HIDDEN, hidden);
1623:                }
1624:
1625:                // output the notification options
1626:                String notification = (String) sstate
1627:                        .getAttribute(SSTATE_NOTI_VALUE);
1628:                ;
1629:                if ("r".equals(notification)) {
1630:                    context.put("noti", rb.getString("java.NOTI_REQUIRED"));
1631:                } else if ("n".equals(notification)) {
1632:                    context.put("noti", rb.getString("java.NOTI_NONE"));
1633:                } else {
1634:                    context.put("noti", rb.getString("java.NOTI_OPTIONAL"));
1635:                }
1636:
1637:                // pick the "browse" template based on the standard template name
1638:                String template = (String) getContext(rundata).get("template");
1639:                return template + "-preview";
1640:
1641:            } // buildPreviewContext
1642:
1643:            /**
1644:             * Build the context for revising the announcement
1645:             */
1646:            protected String buildReviseAnnouncementContext(
1647:                    VelocityPortlet portlet, Context context, RunData rundata,
1648:                    AnnouncementActionState state, SessionState sstate) {
1649:                context.put("service", ContentHostingService.getInstance());
1650:
1651:                // to get the content Type Image Service
1652:                context.put("contentTypeImageService", ContentTypeImageService
1653:                        .getInstance());
1654:
1655:                final String channelId = state.getChannelId();
1656:
1657:                // find the channel and channel information through the service
1658:                AnnouncementChannel channel = null;
1659:                try {
1660:                    if (channelId != null
1661:                            && AnnouncementService.allowGetChannel(channelId)) {
1662:                        // get the channel name throught announcement service API
1663:                        channel = AnnouncementService
1664:                                .getAnnouncementChannel(channelId);
1665:
1666:                        context.put("allowAddChannelMessage", new Boolean(
1667:                                channel.allowAddChannelMessage()));
1668:
1669:                        String announceTo = state.getTempAnnounceTo();
1670:                        if (announceTo != null && announceTo.length() != 0) {
1671:                            context.put("announceTo", announceTo);
1672:                        } else {
1673:                            if (state.getIsNewAnnouncement()) {
1674:                                if (channel.allowAddChannelMessage()) {
1675:                                    // default to make site selection
1676:                                    context.put("announceTo", "site");
1677:                                } else if (channel.getGroupsAllowAddMessage()
1678:                                        .size() > 0) {
1679:                                    // to group otherwise
1680:                                    context.put("announceTo", "groups");
1681:                                }
1682:                            }
1683:                        }
1684:                        AnnouncementMessageEdit edit = state.getEdit();
1685:
1686:                        // Get/set release information
1687:                        Time releaseDate = null;
1688:                        try {
1689:                            releaseDate = edit.getProperties().getTimeProperty(
1690:                                    RELEASE_DATE);
1691:                            context
1692:                                    .put("useReleaseDate", Boolean
1693:                                            .valueOf(true));
1694:                        } catch (Exception e) {
1695:                            // Set inital release date to creation date
1696:                            releaseDate = edit.getHeader().getDate();
1697:                        }
1698:
1699:                        context.put(RELEASE_DATE, releaseDate);
1700:
1701:                        // Get/set retract information
1702:                        Time retractDate = null;
1703:                        try {
1704:                            retractDate = edit.getProperties().getTimeProperty(
1705:                                    RETRACT_DATE);
1706:                            context
1707:                                    .put("useRetractDate", Boolean
1708:                                            .valueOf(true));
1709:                        } catch (Exception e) {
1710:                            // Set inital retract date to approx 2 months from today
1711:                            final long futureTimeLong = TimeService.newTime()
1712:                                    .getTime()
1713:                                    + MILLISECONDS_IN_DAY * FUTURE_DAYS;
1714:                            retractDate = TimeService.newTime(futureTimeLong);
1715:                        }
1716:
1717:                        context.put(RETRACT_DATE, retractDate);
1718:
1719:                        // group list which user can remove message from
1720:                        // TODO: this is almost right (see chef_announcements-revise.vm)... ideally, we would let the check groups that they can add to,
1721:                        // and uncheck groups they can remove from... only matters if the user does not have both add and remove -ggolden
1722:                        final boolean own = edit == null ? true : edit
1723:                                .getHeader().getFrom().getId().equals(
1724:                                        SessionManager
1725:                                                .getCurrentSessionUserId());
1726:                        Collection groups = channel
1727:                                .getGroupsAllowRemoveMessage(own);
1728:                        context.put("allowedRemoveGroups", groups);
1729:
1730:                        // group list which user can add message to
1731:                        groups = channel.getGroupsAllowAddMessage();
1732:
1733:                        // add to these any groups that the message already has
1734:                        if (edit != null) {
1735:                            final Collection otherGroups = edit.getHeader()
1736:                                    .getGroupObjects();
1737:                            for (Iterator i = otherGroups.iterator(); i
1738:                                    .hasNext();) {
1739:                                Group g = (Group) i.next();
1740:
1741:                                if (!groups.contains(g)) {
1742:                                    groups.add(g);
1743:                                }
1744:                            }
1745:                        }
1746:
1747:                        if (groups.size() > 0) {
1748:                            String sort = (String) sstate
1749:                                    .getAttribute(STATE_CURRENT_SORTED_BY);
1750:                            boolean asc = sstate
1751:                                    .getAttribute(STATE_CURRENT_SORT_ASC) != null ? ((Boolean) sstate
1752:                                    .getAttribute(STATE_CURRENT_SORT_ASC))
1753:                                    .booleanValue()
1754:                                    : true;
1755:                            if (sort == null
1756:                                    || (!sort.equals(SORT_GROUPTITLE) && !sort
1757:                                            .equals(SORT_GROUPDESCRIPTION))) {
1758:                                sort = SORT_GROUPTITLE;
1759:                                sstate.setAttribute(STATE_CURRENT_SORTED_BY,
1760:                                        sort);
1761:                                state.setCurrentSortedBy(sort);
1762:                                state.setCurrentSortAsc(Boolean.TRUE
1763:                                        .booleanValue());
1764:                            }
1765:                            Collection sortedGroups = new Vector();
1766:                            for (Iterator i = new SortedIterator(groups
1767:                                    .iterator(), new AnnouncementComparator(
1768:                                    sort, asc)); i.hasNext();) {
1769:                                sortedGroups.add(i.next());
1770:                            }
1771:                            context.put("groups", sortedGroups);
1772:                        }
1773:                    }
1774:                } catch (Exception ignore) {
1775:                }
1776:
1777:                List attachments = state.getAttachments();
1778:
1779:                // if this a new annoucement, get the subject and body from temparory record
1780:                if (state.getIsNewAnnouncement()) {
1781:                    context.put("new", "true");
1782:                    context.put("tempSubject", state.getTempSubject());
1783:                    context.put("tempBody", state.getTempBody());
1784:
1785:                    // default pubview
1786:                    context
1787:                            .put(
1788:                                    "pubviewset",
1789:                                    ((sstate
1790:                                            .getAttribute(STATE_CHANNEL_PUBVIEW) == null) ? Boolean.FALSE
1791:                                            : Boolean.TRUE));
1792:
1793:                    // output the sstate saved public view options
1794:                    final boolean pubview = Boolean.valueOf(
1795:                            (String) sstate
1796:                                    .getAttribute(SSTATE_PUBLICVIEW_VALUE))
1797:                            .booleanValue();
1798:                    if (pubview)
1799:                        context.put("pubview", Boolean.TRUE);
1800:                    else
1801:                        context.put("pubview", Boolean.FALSE);
1802:
1803:                    // Set inital release date to today
1804:                    final Time currentTime = TimeService.newTime();
1805:                    context.put(RELEASE_DATE, currentTime);
1806:
1807:                    // Set inital retract date to 60 days from now
1808:                    final long futureTimeLong = currentTime.getTime()
1809:                            + MILLISECONDS_IN_DAY * FUTURE_DAYS;
1810:                    final Time futureTime = TimeService.newTime(futureTimeLong);
1811:
1812:                    context.put(RETRACT_DATE, futureTime);
1813:
1814:                    // output the notification options
1815:                    String notification = (String) sstate
1816:                            .getAttribute(SSTATE_NOTI_VALUE);
1817:                    // "r", "o" or "n"
1818:                    context.put("noti", notification);
1819:
1820:                }
1821:                // if this is an existing one
1822:                else if (state.getStatus().equals("goToReviseAnnouncement")) {
1823:                    // to determine if release/retract dates have been specified
1824:                    // so correct checkbox is selected
1825:                    boolean specify = false;
1826:
1827:                    // get the message object through service
1828:                    context.put("new", "false");
1829:                    // get the message object through service
1830:                    // AnnouncementMessage message = channel.getAnnouncementMessage( messageId );
1831:                    // context.put("message", message);
1832:
1833:                    AnnouncementMessageEdit edit = state.getEdit();
1834:                    context.put("message", edit);
1835:
1836:                    // find out about pubview
1837:                    context
1838:                            .put(
1839:                                    "pubviewset",
1840:                                    ((sstate
1841:                                            .getAttribute(STATE_CHANNEL_PUBVIEW) == null) ? Boolean.FALSE
1842:                                            : Boolean.TRUE));
1843:                    context.put("pubview", Boolean
1844:                            .valueOf(edit.getProperties().getProperty(
1845:                                    ResourceProperties.PROP_PUBVIEW) != null));
1846:
1847:                    // Get/set release information
1848:                    Time releaseDate = null;
1849:                    try {
1850:                        releaseDate = edit.getProperties().getTimeProperty(
1851:                                RELEASE_DATE);
1852:
1853:                        context.put("useReleaseDate", Boolean.valueOf(true));
1854:                        specify = true;
1855:                    } catch (Exception e) {
1856:                        // Set inital release date to creation date
1857:                        releaseDate = edit.getHeader().getDate();
1858:                    }
1859:
1860:                    context.put(RELEASE_DATE, releaseDate);
1861:
1862:                    // Get/set retract information
1863:                    Time retractDate = null;
1864:                    try {
1865:                        retractDate = edit.getProperties().getTimeProperty(
1866:                                RETRACT_DATE);
1867:
1868:                        context.put("useRetractDate", Boolean.valueOf(true));
1869:                        specify = true;
1870:                    } catch (Exception e) {
1871:                        // Set inital retract date to approx 2 months from today
1872:                        final long futureTimeLong = TimeService.newTime()
1873:                                .getTime()
1874:                                + MILLISECONDS_IN_DAY * FUTURE_DAYS;
1875:                        retractDate = TimeService.newTime(futureTimeLong);
1876:                    }
1877:
1878:                    context.put(RETRACT_DATE, retractDate);
1879:
1880:                    context.put(SPECIFY_DATES, specify);
1881:                    context.put(HIDDEN, edit.getHeader().getDraft());
1882:                    // there is no chance to get the notification setting at this point
1883:                } else
1884:                // if state is "backToRevise"
1885:                {
1886:                    context.put("new", "true");
1887:                    context.put("tempSubject", state.getTempSubject());
1888:                    context.put("tempBody", state.getTempBody());
1889:
1890:                    final boolean pubview = Boolean.valueOf(
1891:                            (String) sstate
1892:                                    .getAttribute(SSTATE_PUBLICVIEW_VALUE))
1893:                            .booleanValue();
1894:                    if (pubview)
1895:                        context.put("pubview", Boolean.TRUE);
1896:                    else
1897:                        context.put("pubview", Boolean.FALSE);
1898:
1899:                    // output the notification options
1900:                    String notification = (String) sstate
1901:                            .getAttribute(SSTATE_NOTI_VALUE);
1902:                    ;
1903:                    // "r", "o" or "n"
1904:                    context.put("noti", notification);
1905:                }
1906:
1907:                context.put("attachments", attachments);
1908:                context.put("newAnn", (state.getIsNewAnnouncement()) ? "true"
1909:                        : "else");
1910:
1911:                context
1912:                        .put("announceToGroups", state
1913:                                .getTempAnnounceToGroups());
1914:
1915:                context.put("publicDisable", sstate
1916:                        .getAttribute(PUBLIC_DISPLAY_DISABLE_BOOLEAN));
1917:
1918:                String template = (String) getContext(rundata).get("template");
1919:                return template + "-revise";
1920:
1921:            } // buildReviseAnnouncementContext
1922:
1923:            /**
1924:             * Build the context for viewing announcement content
1925:             */
1926:            protected String buildShowMetadataContext(VelocityPortlet portlet,
1927:                    Context context, RunData rundata,
1928:                    AnnouncementActionState state, SessionState sstate) {
1929:                context.put("conService", ContentHostingService.getInstance());
1930:
1931:                // to get the content Type Image Service
1932:                context.put("contentTypeImageService", ContentTypeImageService
1933:                        .getInstance());
1934:
1935:                // get the channel and message id information from state object
1936:                String messageReference = state.getMessageReference();
1937:
1938:                // get the message object through service
1939:                try {
1940:                    // get the channel id throught announcement service
1941:                    AnnouncementChannel channel = AnnouncementService
1942:                            .getAnnouncementChannel(this 
1943:                                    .getChannelIdFromReference(messageReference));
1944:
1945:                    // get the message object through service
1946:                    AnnouncementMessage message = channel
1947:                            .getAnnouncementMessage(this 
1948:                                    .getMessageIDFromReference(messageReference));
1949:
1950:                    // put release date into context if set. otherwise, put current date
1951:                    try {
1952:                        Time releaseDate = message.getProperties()
1953:                                .getTimeProperty(RELEASE_DATE);
1954:
1955:                        context.put("date", releaseDate);
1956:                    } catch (Exception e) {
1957:                        // no release date, put in current time
1958:                        context.put("date", TimeService.newTime());
1959:                    }
1960:
1961:                    context.put("message", message);
1962:
1963:                    // find out about pubview
1964:                    context
1965:                            .put(
1966:                                    "pubviewset",
1967:                                    ((sstate
1968:                                            .getAttribute(STATE_CHANNEL_PUBVIEW) == null) ? Boolean.FALSE
1969:                                            : Boolean.TRUE));
1970:                    context.put("pubview", Boolean.valueOf(message
1971:                            .getProperties().getProperty(
1972:                                    ResourceProperties.PROP_PUBVIEW) != null));
1973:
1974:                    // show all the groups in this channal that user has get message in
1975:                    Collection groups = channel.getGroupsAllowGetMessage();
1976:                    if (groups != null) {
1977:                        context.put("range", getAnnouncementRange(message));
1978:                    }
1979:
1980:                    boolean menu_new = channel.allowAddMessage();
1981:                    boolean menu_delete = channel.allowRemoveMessage(message);
1982:                    boolean menu_revise = channel.allowEditMessage(message
1983:                            .getId());
1984:
1985:                    // Check to see if we can display an enabled menu.
1986:                    // We're currently not allowing modification of
1987:                    // announcements if they are not from this site.
1988:                    if (!this .isOkayToDisplayMessageMenu(state)) {
1989:                        menu_new = menu_delete = menu_revise = false;
1990:                    }
1991:
1992:                    // check the state status to decide which vm to render
1993:                    String statusName = state.getStatus();
1994:
1995:                    AnnouncementActionState.DisplayOptions displayOptions = state
1996:                            .getDisplayOptions();
1997:
1998:                    buildMenu(portlet, context, rundata, state, menu_new,
1999:                            menu_delete, menu_revise, this 
2000:                                    .isOkToShowMergeButton(statusName), this 
2001:                                    .isOkToShowPermissionsButton(statusName),
2002:                            this .isOkToShowOptionsButton(statusName),
2003:                            displayOptions);
2004:
2005:                    context.put("allow_new", Boolean.valueOf(menu_new));
2006:                    context.put("allow_delete", Boolean.valueOf(menu_delete));
2007:                    context.put("allow_revise", Boolean.valueOf(menu_revise));
2008:
2009:                    // navigation bar display control
2010:                    List msgs = (List) sstate.getAttribute(STATE_MESSAGES);
2011:                    for (int i = 0; i < msgs.size(); i++) {
2012:                        if (((AnnouncementWrapper) msgs.get(i)).getId().equals(
2013:                                message.getId())) {
2014:                            boolean goPT = false;
2015:                            boolean goNT = false;
2016:                            if ((i - 1) >= 0) {
2017:                                goPT = true;
2018:                                context.put("prevMsg", msgs.get(i - 1));
2019:                            }
2020:                            if ((i + 1) < msgs.size()) {
2021:                                goNT = true;
2022:                                context.put("nextMsg", msgs.get(i + 1));
2023:                            }
2024:                            context.put("goPTButton", new Boolean(goPT));
2025:                            context.put("goNTButton", new Boolean(goNT));
2026:                        }
2027:                    }
2028:                } catch (IdUnusedException e) {
2029:                    if (Log.getLogger("chef").isDebugEnabled())
2030:                        Log.debug("chef", this  + "buildShowMetadataContext()"
2031:                                + e);
2032:                } catch (PermissionException e) {
2033:                    if (Log.getLogger("chef").isDebugEnabled())
2034:                        Log.debug("chef", this  + "buildShowMetadataContext()"
2035:                                + e);
2036:                    addAlert(sstate, rb.getString("java.youmess")// "You don't have permissions to access the message(s) - "
2037:                            + e.toString());
2038:                }
2039:
2040:                String template = (String) getContext(rundata).get("template");
2041:                return template + "-metadata";
2042:
2043:            }
2044:
2045:            /*
2046:             * Update the current message reference in the state object @param direction If going to previous message, -1; to next one, 1.
2047:             */
2048:            private void indexMessage(RunData rundata, Context context,
2049:                    int direction) {
2050:                SessionState sstate = ((JetspeedRunData) rundata)
2051:                        .getPortletSessionState(((JetspeedRunData) rundata)
2052:                                .getJs_peid());
2053:
2054:                // retrieve the state from state object
2055:                AnnouncementActionState state = (AnnouncementActionState) getState(
2056:                        context, rundata, AnnouncementActionState.class);
2057:
2058:                // get the channel and message id information from state object
2059:                String messageReference = state.getMessageReference();
2060:
2061:                // get the message object through service
2062:                try {
2063:                    // get the channel id throught announcement service
2064:                    AnnouncementChannel channel = AnnouncementService
2065:                            .getAnnouncementChannel(this 
2066:                                    .getChannelIdFromReference(messageReference));
2067:
2068:                    // get the message object through service
2069:                    AnnouncementMessage message = channel
2070:                            .getAnnouncementMessage(this 
2071:                                    .getMessageIDFromReference(messageReference));
2072:
2073:                    List msgs = (List) sstate.getAttribute(STATE_MESSAGES);
2074:                    for (int i = 0; i < msgs.size(); i++) {
2075:                        if (((AnnouncementWrapper) msgs.get(i)).getId().equals(
2076:                                message.getId())) {
2077:                            int index = i;
2078:                            // moving to the next message in the list
2079:                            if (direction == 1) {
2080:                                if ((index != -1)
2081:                                        && ((index + 1) < msgs.size())) {
2082:                                    AnnouncementWrapper next = (AnnouncementWrapper) (msgs
2083:                                            .get(index + 1));
2084:                                    state.setMessageReference(next
2085:                                            .getReference());
2086:                                }
2087:                            }
2088:                            // moving to the previous message in the list
2089:                            else if (direction == -1) {
2090:                                if ((index != -1) && ((index - 1) >= 0)) {
2091:                                    AnnouncementWrapper prev = (AnnouncementWrapper) (msgs
2092:                                            .get(index - 1));
2093:                                    state.setMessageReference(prev
2094:                                            .getReference());
2095:                                }
2096:                            }
2097:                        }
2098:                    }
2099:                } catch (IdUnusedException e) {
2100:                    addAlert(sstate, rb.getString("java.alert.cannotfindann"));
2101:                } catch (PermissionException e) {
2102:                    addAlert(sstate, rb.getString("java.alert.youacc"));
2103:                }
2104:            }
2105:
2106:            /**
2107:             * Responding to the request of going to next message
2108:             */
2109:            public void doNext_message(RunData rundata, Context context) {
2110:                indexMessage(rundata, context, 1);
2111:
2112:            } // doNext_message
2113:
2114:            /**
2115:             * Responding to the request of going to previous message
2116:             */
2117:            public void doPrev_message(RunData rundata, Context context) {
2118:                indexMessage(rundata, context, -1);
2119:
2120:            } // doPrev_message
2121:
2122:            /**
2123:             * Get the message id from a message reference.
2124:             */
2125:            private String getMessageIDFromReference(String messageReference) {
2126:                // "crack" the reference (a.k.a dereference, i.e. make a Reference)
2127:                // and get the event id and channel reference
2128:                Reference ref = EntityManager.newReference(messageReference);
2129:                return ref.getId();
2130:            }
2131:
2132:            /**
2133:             * Get the channel id from a message reference.
2134:             */
2135:            private String getChannelIdFromReference(String messageReference) {
2136:                // "crack" the reference (a.k.a dereference, i.e. make a Reference)
2137:                // and get the event id and channel reference
2138:                Reference ref = EntityManager.newReference(messageReference);
2139:                String channelId = AnnouncementService.channelReference(ref
2140:                        .getContext(), ref.getContainer());
2141:                return channelId;
2142:            } // getChannelIdFromReference
2143:
2144:            /**
2145:             * corresponding to chef_announcements doShowMetadata
2146:             * 
2147:             * @param itemId
2148:             *        The string used to record the announcement id
2149:             */
2150:            public void doShowmetadata(RunData rundata, Context context) {
2151:                // retrieve the state from state object
2152:                AnnouncementActionState state = (AnnouncementActionState) getState(
2153:                        context, rundata, AnnouncementActionState.class);
2154:
2155:                String peid = ((JetspeedRunData) rundata).getJs_peid();
2156:                SessionState sstate = ((JetspeedRunData) rundata)
2157:                        .getPortletSessionState(peid);
2158:
2159:                String itemReference = rundata.getParameters().getString(
2160:                        "itemReference");
2161:                state.setMessageReference(itemReference);
2162:
2163:                state.setIsListVM(false);
2164:                state.setIsNewAnnouncement(false);
2165:                state.setStatus("showMetadata");
2166:
2167:                // disable auto-updates while in view mode
2168:                disableObservers(sstate);
2169:
2170:            } // doShowMetadata
2171:
2172:            /**
2173:             * Build the context for cancelling the operation and going back to list view
2174:             */
2175:            protected String buildCancelContext(VelocityPortlet portlet,
2176:                    Context context, RunData rundata,
2177:                    AnnouncementActionState state) {
2178:                // buildNormalContext(portlet, context, rundata);
2179:
2180:                String template = (String) getContext(rundata).get("template");
2181:                return template;
2182:
2183:            } // buildCancelContext
2184:
2185:            /**
2186:             * Build the context for asking for the delete confirmation
2187:             */
2188:            protected String buildDeleteAnnouncementContext(
2189:                    VelocityPortlet portlet, Context context, RunData rundata,
2190:                    AnnouncementActionState state) {
2191:                Vector v = state.getDelete_messages();
2192:                if (v == null)
2193:                    v = new Vector();
2194:                context.put("delete_messages", v.iterator());
2195:
2196:                try {
2197:                    Site site = SiteService.getSite(ToolManager
2198:                            .getCurrentPlacement().getContext());
2199:                    context.put("site", site);
2200:                } catch (IdUnusedException e) {
2201:                    // No site available.
2202:                } catch (NullPointerException e) {
2203:                }
2204:                context.put("channelAccess",
2205:                        MessageHeader.MessageAccess.CHANNEL);
2206:
2207:                String template = (String) getContext(rundata).get("template");
2208:                return template + "-delete";
2209:
2210:            } // buildDeleteAnnouncementContext
2211:
2212:            /**
2213:             * Action is to use when doNewannouncement requested, corresponding to chef_announcements menu "New..."
2214:             */
2215:            public void doNewannouncement(RunData rundata, Context context) {
2216:                // retrieve the state from state object
2217:                AnnouncementActionState state = (AnnouncementActionState) getState(
2218:                        context, rundata, AnnouncementActionState.class);
2219:
2220:                String peid = ((JetspeedRunData) rundata).getJs_peid();
2221:                SessionState sstate = ((JetspeedRunData) rundata)
2222:                        .getPortletSessionState(peid);
2223:
2224:                state.setIsListVM(false);
2225:                state.setAttachments(null);
2226:                state.setSelectedAttachments(null);
2227:                state.setDeleteMessages(null);
2228:                state.setIsNewAnnouncement(true);
2229:                state.setTempBody("");
2230:                state.setTempSubject("");
2231:                state.setStatus("new");
2232:
2233:                sstate.setAttribute(AnnouncementAction.SSTATE_PUBLICVIEW_VALUE,
2234:                        null);
2235:                sstate.setAttribute(AnnouncementAction.SSTATE_NOTI_VALUE, null);
2236:
2237:                // disable auto-updates while in view mode
2238:                disableObservers(sstate);
2239:
2240:            } // doNewannouncement
2241:
2242:            /**
2243:             * Dispatcher function for various actions on add/revise announcement page
2244:             */
2245:            public void doAnnouncement_form(RunData data, Context context) {
2246:
2247:                ParameterParser params = data.getParameters();
2248:
2249:                String option = (String) params.getString("option");
2250:                if (option != null) {
2251:                    if (option.equals("post")) {
2252:                        // post announcement
2253:                        readAnnouncementForm(data, context, true);
2254:                        doPost(data, context);
2255:                    } else if (option.equals("preview")) {
2256:                        // preview announcement
2257:                        readAnnouncementForm(data, context, true);
2258:                        doRevisepreview(data, context);
2259:                    } else if (option.equals("save")) {
2260:                        // save announcement as draft
2261:                        readAnnouncementForm(data, context, true);
2262:                        doSavedraft(data, context);
2263:                    } else if (option.equals("cancel")) {
2264:                        // cancel
2265:                        doCancel(data, context);
2266:                    } else if (option.equals("attach")) {
2267:                        // attach
2268:                        readAnnouncementForm(data, context, false);
2269:                        doAttachments(data, context);
2270:                    } else if (option.equals("sortbygrouptitle")) {
2271:                        // sort group by title
2272:                        readAnnouncementForm(data, context, false);
2273:                        doSortbygrouptitle(data, context);
2274:                    } else if (option.equals("sortbygroupdescription")) {
2275:                        // sort group by description
2276:                        readAnnouncementForm(data, context, false);
2277:                        doSortbygroupdescription(data, context);
2278:                    }
2279:                }
2280:            } // doAnnouncement_form
2281:
2282:            /**
2283:             * Read user inputs in announcement form
2284:             * 
2285:             * @param data
2286:             * @param checkForm
2287:             *        need to check form data or not
2288:             */
2289:            protected void readAnnouncementForm(RunData rundata,
2290:                    Context context, boolean checkForm) {
2291:                // retrieve the state from state object
2292:                final AnnouncementActionState state = (AnnouncementActionState) getState(
2293:                        context, rundata, AnnouncementActionState.class);
2294:
2295:                final String peid = ((JetspeedRunData) rundata).getJs_peid();
2296:                final SessionState sstate = ((JetspeedRunData) rundata)
2297:                        .getPortletSessionState(peid);
2298:                final ParameterParser params = rundata.getParameters();
2299:
2300:                // *** make sure the subject and body won't be empty
2301:                // read in the subject input from announcements-new.vm
2302:                final String subject = params.getString("subject");
2303:                // read in the body input
2304:                String body = params.getString("body");
2305:                body = processFormattedTextFromBrowser(sstate, body);
2306:
2307:                state.setTempSubject(subject);
2308:                state.setTempBody(body);
2309:
2310:                if (checkForm) {
2311:                    if (subject.length() == 0) {
2312:                        // addAlert(sstate, "You need to fill in the subject!");
2313:                        addAlert(sstate, rb.getString("java.alert.youneed"));
2314:                    } else if (body.length() == 0) {
2315:                        addAlert(sstate, rb.getString("java.alert.youfill"));// "You need to fill in the body of the announcement!");
2316:                    }
2317:                }
2318:
2319:                final String specify = params.getString(HIDDEN);
2320:                final boolean use_start_date = params
2321:                        .getBoolean("use_start_date");
2322:                final boolean use_end_date = params.getBoolean("use_end_date");
2323:
2324:                // if user selected specify dates but then did not check a checkbox
2325:                // in order to do so, return an alert
2326:                if (checkForm) {
2327:                    if (specify.equals("specify")
2328:                            && !(use_start_date || use_end_date)) {
2329:                        addAlert(sstate, rb.getString("java.alert.nodates"));
2330:                    }
2331:                }
2332:
2333:                Time releaseDate = null;
2334:                Time retractDate = null;
2335:
2336:                if (use_start_date && SPECIFY_DATES.equals(specify)) {
2337:                    int begin_year = params.getInt("release_year");
2338:                    int begin_month = params.getInt("release_month");
2339:                    int begin_day = params.getInt("release_day");
2340:                    int begin_hour = params.getInt("release_hour");
2341:                    int begin_min = params.getInt("release_min");
2342:                    String release_ampm = params.getString("release_ampm");
2343:                    if ("pm".equals(release_ampm)) {
2344:                        begin_hour += 12;
2345:                    } else if (begin_hour == 12) {
2346:                        begin_hour = 0;
2347:                    }
2348:                    releaseDate = TimeService
2349:                            .newTimeLocal(begin_year, begin_month, begin_day,
2350:                                    begin_hour, begin_min, 0, 0);
2351:
2352:                    state.setTempReleaseDate(releaseDate);
2353:                } else {
2354:                    state.setTempReleaseDate(null);
2355:                }
2356:
2357:                if (use_end_date && SPECIFY_DATES.equals(specify)) {
2358:                    int end_year = params.getInt("retract_year");
2359:                    int end_month = params.getInt("retract_month");
2360:                    int end_day = params.getInt("retract_day");
2361:                    int end_hour = params.getInt("retract_hour");
2362:                    int end_min = params.getInt("retract_min");
2363:                    String retract_ampm = params.getString("retract_ampm");
2364:                    if ("pm".equals(retract_ampm)) {
2365:                        end_hour += 12;
2366:                    } else if (end_hour == 12) {
2367:                        end_hour = 0;
2368:                    }
2369:                    retractDate = TimeService.newTimeLocal(end_year, end_month,
2370:                            end_day, end_hour, end_min, 0, 0);
2371:
2372:                    state.setTempRetractDate(retractDate);
2373:                } else {
2374:                    state.setTempRetractDate(null);
2375:                }
2376:
2377:                if (checkForm) {
2378:                    if ((use_start_date && use_end_date)
2379:                            && retractDate.before(releaseDate)) {
2380:                        addAlert(sstate, rb.getString("java.alert.baddates"));
2381:                    }
2382:                }
2383:                // set hidden property just in case saved
2384:                state.setTempHidden(params.getBoolean(HIDDEN));
2385:
2386:                // announce to public?
2387:                String announceTo = params.getString("announceTo");
2388:                state.setTempAnnounceTo(announceTo);
2389:                if (announceTo.equals("groups")) {
2390:                    String[] groupChoice = params.getStrings("selectedGroups");
2391:                    if (groupChoice != null) {
2392:                        state.setTempAnnounceToGroups(new ArrayList(Arrays
2393:                                .asList(groupChoice)));
2394:                    }
2395:
2396:                    if (groupChoice == null || groupChoice.length == 0) {
2397:                        state.setTempAnnounceToGroups(null);
2398:                        if (checkForm) {
2399:                            addAlert(sstate, rb
2400:                                    .getString("java.alert.youchoosegroup"));
2401:                        }
2402:                    }
2403:                } else {
2404:                    state.setTempAnnounceToGroups(null);
2405:                }
2406:
2407:                // read the public view setting and save it in session state
2408:                String publicView = params.getString("pubview");
2409:                if (publicView == null)
2410:                    publicView = "false";
2411:                sstate.setAttribute(AnnouncementAction.SSTATE_PUBLICVIEW_VALUE,
2412:                        publicView);
2413:
2414:                // read the notification options & save it in session state
2415:                String notification = rundata.getParameters().getString(
2416:                        "notify");
2417:                sstate.setAttribute(AnnouncementAction.SSTATE_NOTI_VALUE,
2418:                        notification);
2419:
2420:            } // readAnnouncementForm
2421:
2422:            /**
2423:             * Action is to use when doPost requested, corresponding to chef_announcements-revise or -preview "eventSubmit_doPost"
2424:             */
2425:            public void doPost(RunData rundata, Context context) {
2426:                postOrSaveDraft(rundata, context, true);
2427:            } // doPost
2428:
2429:            /**
2430:             * post or save draft of a message?
2431:             */
2432:            protected void postOrSaveDraft(RunData rundata, Context context,
2433:                    boolean post) {
2434:                // retrieve the state from state object
2435:                AnnouncementActionState state = (AnnouncementActionState) getState(
2436:                        context, rundata, AnnouncementActionState.class);
2437:
2438:                final String peid = ((JetspeedRunData) rundata).getJs_peid();
2439:                final SessionState sstate = ((JetspeedRunData) rundata)
2440:                        .getPortletSessionState(peid);
2441:
2442:                // get the channel and message id information from state object
2443:                final String channelId = state.getChannelId();
2444:
2445:                // these are values that will be have been set if coming
2446:                // from Preview
2447:                final String subject = state.getTempSubject();
2448:                final String body = state.getTempBody();
2449:                final Time tempReleaseDate = state.getTempReleaseDate();
2450:                final Time tempRetractDate = state.getTempRetractDate();
2451:                final Boolean tempHidden = state.getTempHidden();
2452:
2453:                // announce to public?
2454:                final String announceTo = state.getTempAnnounceTo();
2455:
2456:                // there is any error message caused by empty subject or body
2457:                if (sstate.getAttribute(STATE_MESSAGE) != null) {
2458:                    state.setIsListVM(false);
2459:                    state.setStatus("stayAtRevise");
2460:
2461:                    // disable auto-updates while in view mode
2462:                    disableObservers(sstate);
2463:                } else {
2464:
2465:                    // read the notification options
2466:                    String notification = (String) sstate
2467:                            .getAttribute(AnnouncementAction.SSTATE_NOTI_VALUE);
2468:
2469:                    int noti = NotificationService.NOTI_OPTIONAL;
2470:                    if ("r".equals(notification)) {
2471:                        noti = NotificationService.NOTI_REQUIRED;
2472:                    } else if ("n".equals(notification)) {
2473:                        noti = NotificationService.NOTI_NONE;
2474:                    }
2475:
2476:                    try {
2477:                        AnnouncementChannel channel = null;
2478:                        AnnouncementMessageEdit msg = null;
2479:
2480:                        // if a new created announcement to be posted
2481:                        if (state.getIsNewAnnouncement()) {
2482:                            // get the channel id throught announcement service
2483:                            channel = AnnouncementService
2484:                                    .getAnnouncementChannel(channelId);
2485:                            msg = channel.addAnnouncementMessage();
2486:                        } else {
2487:                            // get the message object through service
2488:                            // AnnouncementMessageEdit msg = channel.editAnnouncementMessage( messageId );
2489:                            msg = state.getEdit();
2490:
2491:                            // get the channel id throught announcement service
2492:                            channel = AnnouncementService
2493:                                    .getAnnouncementChannel(this 
2494:                                            .getChannelIdFromReference(msg
2495:                                                    .getReference()));
2496:                        }
2497:
2498:                        msg.setBody(body);
2499:                        AnnouncementMessageHeaderEdit header = msg
2500:                                .getAnnouncementHeaderEdit();
2501:                        header.setSubject(subject);
2502:                        //				header.setDraft(!post);
2503:                        // v2.4: Hidden in UI becomes Draft 'behind the scenes'
2504:                        header.setDraft(tempHidden);
2505:                        header.replaceAttachments(state.getAttachments());
2506:
2507:                        // values stored here if saving from Add/Revise page
2508:                        ParameterParser params = rundata.getParameters();
2509:
2510:                        // get release/retract dates
2511:                        final String specify = params.getString(HIDDEN);
2512:                        final boolean use_start_date = params
2513:                                .getBoolean("use_start_date");
2514:                        final boolean use_end_date = params
2515:                                .getBoolean("use_end_date");
2516:                        Time releaseDate = null;
2517:                        Time retractDate = null;
2518:
2519:                        if (use_start_date && SPECIFY_DATES.equals("specify")) {
2520:                            int begin_year = params.getInt("release_year");
2521:                            int begin_month = params.getInt("release_month");
2522:                            int begin_day = params.getInt("release_day");
2523:                            int begin_hour = params.getInt("release_hour");
2524:                            int begin_min = params.getInt("release_minute");
2525:                            String release_ampm = params
2526:                                    .getString("release_ampm");
2527:                            if ("pm".equals(release_ampm)) {
2528:                                if (begin_hour < 12) {
2529:                                    begin_hour += 12;
2530:                                } else {
2531:                                    // its noon, no change needed
2532:                                }
2533:                            } else if (begin_hour == 12) {
2534:                                begin_hour = 0;
2535:                            }
2536:
2537:                            releaseDate = TimeService.newTimeLocal(begin_year,
2538:                                    begin_month, begin_day, begin_hour,
2539:                                    begin_min, 0, 0);
2540:
2541:                            // in addition to setting release date property, also set Date to release
2542:                            // date so properly sorted
2543:                            msg.getPropertiesEdit().addProperty(RELEASE_DATE,
2544:                                    releaseDate.toString());
2545:                            header.setDate(releaseDate);
2546:                        } else if (tempReleaseDate != null) // saving from Preview page
2547:                        {
2548:                            // in addition to setting release date property, also set Date to release
2549:                            // date so properly sorted
2550:                            msg.getPropertiesEdit().addProperty(RELEASE_DATE,
2551:                                    tempReleaseDate.toString());
2552:                            header.setDate(tempReleaseDate);
2553:                        } else {
2554:                            // they are not using release date so remove
2555:                            if (msg.getProperties().getProperty(RELEASE_DATE) != null) {
2556:                                msg.getPropertiesEdit().removeProperty(
2557:                                        RELEASE_DATE);
2558:                            }
2559:
2560:                            // since revised, set Date to current date
2561:                            header.setDate(TimeService.newTime());
2562:                        }
2563:
2564:                        if (use_end_date && SPECIFY_DATES.equals(specify)) {
2565:                            int end_year = params.getInt("retract_year");
2566:                            int end_month = params.getInt("retract_month");
2567:                            int end_day = params.getInt("retract_day");
2568:                            int end_hour = params.getInt("retract_hour");
2569:                            int end_min = params.getInt("retract_minute");
2570:                            String retract_ampm = params
2571:                                    .getString("retract_ampm");
2572:                            if ("pm".equals(retract_ampm)) {
2573:                                end_hour += 12;
2574:                            } else if (end_hour == 12) {
2575:                                end_hour = 0;
2576:                            }
2577:                            retractDate = TimeService
2578:                                    .newTimeLocal(end_year, end_month, end_day,
2579:                                            end_hour, end_min, 0, 0);
2580:
2581:                            msg.getPropertiesEdit().addProperty("retractDate",
2582:                                    retractDate.toString());
2583:                        } else if (tempRetractDate != null) {
2584:                            msg.getPropertiesEdit().addProperty(RETRACT_DATE,
2585:                                    tempRetractDate.toString());
2586:                        } else {
2587:                            // they are not using release date so remove
2588:                            if (msg.getProperties().getProperty(RETRACT_DATE) != null) {
2589:                                msg.getPropertiesEdit().removeProperty(
2590:                                        RETRACT_DATE);
2591:                            }
2592:                        }
2593:
2594:                        // announce to?
2595:                        try {
2596:                            Site site = SiteService.getSite(channel
2597:                                    .getContext());
2598:
2599:                            if (announceTo.equals("pubview")
2600:                                    || Boolean
2601:                                            .valueOf(
2602:                                                    (String) sstate
2603:                                                            .getAttribute(AnnouncementAction.SSTATE_PUBLICVIEW_VALUE))
2604:                                            .booleanValue()) // if from the post in preview, get the setting from sstate object
2605:                            {
2606:                                // any setting of this property indicates pubview
2607:                                msg.getPropertiesEdit().addProperty(
2608:                                        ResourceProperties.PROP_PUBVIEW,
2609:                                        Boolean.TRUE.toString());
2610:                                header.clearGroupAccess();
2611:                            } else {
2612:                                // remove the property to indicate no pubview
2613:                                msg.getPropertiesEdit().removeProperty(
2614:                                        ResourceProperties.PROP_PUBVIEW);
2615:                            }
2616:
2617:                            // announce to site?
2618:                            if (announceTo.equals("site")) {
2619:                                header.clearGroupAccess();
2620:                            } else if (announceTo.equals("groups")) {
2621:                                // get the group ids selected
2622:                                Collection groupChoice = state
2623:                                        .getTempAnnounceToGroups();
2624:
2625:                                // make a collection of Group objects
2626:                                Collection groups = new Vector();
2627:                                for (Iterator iGroups = groupChoice.iterator(); iGroups
2628:                                        .hasNext();) {
2629:                                    String groupId = (String) iGroups.next();
2630:                                    groups.add(site.getGroup(groupId));
2631:                                }
2632:
2633:                                // set access
2634:                                header.setGroupAccess(groups);
2635:                            }
2636:                        } catch (PermissionException e) {
2637:                            addAlert(sstate, rb
2638:                                    .getString("java.alert.youpermi")// "You don't have permissions to create this announcement -"
2639:                                    + subject);
2640:
2641:                            state.setIsListVM(false);
2642:                            state.setStatus("stayAtRevise");
2643:
2644:                            // disable auto-updates while in view mode
2645:                            disableObservers(sstate);
2646:                            return;
2647:                        } catch (Exception ignore) {
2648:                            // No site available.
2649:                        }
2650:
2651:                        // save notification level if this is a future notification message
2652:                        Time now = TimeService.newTime();
2653:
2654:                        if (releaseDate != null && now.before(releaseDate)
2655:                                && noti != NotificationService.NOTI_NONE) {
2656:                            msg.getPropertiesEdit().addProperty(
2657:                                    "notificationLevel", notification);
2658:                        }
2659:
2660:                        channel
2661:                                .commitMessage(msg, noti,
2662:                                        "org.sakaiproject.announcement.impl.SiteEmailNotificationAnnc");
2663:
2664:                        if (!state.getIsNewAnnouncement()) {
2665:                            state.setEdit(null);
2666:                        } // if-else
2667:                    } catch (IdUnusedException e) {
2668:                        if (Log.getLogger("chef").isDebugEnabled())
2669:                            Log.debug("chef", this  + "doPost()" + e);
2670:                    } catch (PermissionException e) {
2671:                        if (Log.getLogger("chef").isDebugEnabled())
2672:                            Log.debug("chef", this  + "doPost()" + e);
2673:                        addAlert(sstate, rb.getString("java.alert.youpermi")// "You don't have permissions to create this announcement -"
2674:                                + subject);
2675:                    }
2676:
2677:                    state.setIsListVM(true);
2678:                    state.setAttachments(null);
2679:                    state.setSelectedAttachments(null);
2680:                    state.setDeleteMessages(null);
2681:                    state.setStatus(POST_STATUS);
2682:                    state.setMessageReference("");
2683:                    state.setTempAnnounceTo(null);
2684:                    state.setTempAnnounceToGroups(null);
2685:                    state.setCurrentSortedBy(SORT_DATE);
2686:                    state.setCurrentSortAsc(Boolean.TRUE.booleanValue());
2687:                    sstate.setAttribute(STATE_CURRENT_SORTED_BY, SORT_DATE);
2688:                    sstate.setAttribute(STATE_CURRENT_SORT_ASC, Boolean.TRUE);
2689:
2690:                    // make sure auto-updates are enabled
2691:                    enableObservers(sstate);
2692:                }
2693:            } // postOrSaveDraf
2694:
2695:            /**
2696:             * Action is to use when doPreviewrevise requested from preview status corresponding to chef_announcements-preview "eventSubmit_doPreviewrevise"
2697:             */
2698:            public void doPreviewrevise(RunData rundata, Context context) {
2699:
2700:                // retrieve the state from state object
2701:                AnnouncementActionState state = (AnnouncementActionState) getState(
2702:                        context, rundata, AnnouncementActionState.class);
2703:
2704:                String peid = ((JetspeedRunData) rundata).getJs_peid();
2705:                SessionState sstate = ((JetspeedRunData) rundata)
2706:                        .getPortletSessionState(peid);
2707:
2708:                state.setStatus("backToReviseAnnouncement");
2709:
2710:                // disable auto-updates while in view mode
2711:                disableObservers(sstate);
2712:
2713:            } // doPreviewrevise
2714:
2715:            /**
2716:             * Action is to use when ddoDelete requested, to perform deletion corresponding to chef_announcements-delete "eventSubmit_doDelete"
2717:             */
2718:            public void doDelete(RunData rundata, Context context) {
2719:
2720:                // retrieve the state from state object
2721:                AnnouncementActionState state = (AnnouncementActionState) getState(
2722:                        context, rundata, AnnouncementActionState.class);
2723:
2724:                String peid = ((JetspeedRunData) rundata).getJs_peid();
2725:                SessionState sstate = ((JetspeedRunData) rundata)
2726:                        .getPortletSessionState(peid);
2727:
2728:                // get the messages to be deleted from state object
2729:                Vector v = state.getDelete_messages();
2730:                Iterator delete_messages = v.iterator();
2731:
2732:                while (delete_messages.hasNext()) {
2733:                    try {
2734:                        AnnouncementMessage message = (AnnouncementMessage) delete_messages
2735:                                .next();
2736:
2737:                        // get the channel id throught announcement service
2738:                        AnnouncementChannel channel = AnnouncementService
2739:                                .getAnnouncementChannel(this 
2740:                                        .getChannelIdFromReference(message
2741:                                                .getReference()));
2742:
2743:                        if (channel.allowRemoveMessage(message)) {
2744:                            // remove message from channel
2745:                            AnnouncementMessageEdit edit = channel
2746:                                    .editAnnouncementMessage(message.getId());
2747:                            channel.removeMessage(edit);
2748:
2749:                            // make sure auto-updates are enabled
2750:                            enableObservers(sstate);
2751:                        } else {
2752:                            addAlert(sstate, rb.getString("java.alert.youdel"));
2753:                            // "you don't have permission to delete the messages.");
2754:                        }
2755:                    } catch (IdUnusedException e) {
2756:                        if (Log.getLogger("chef").isDebugEnabled())
2757:                            Log.debug("chef", this  + "doDeleteannouncement()"
2758:                                    + e);
2759:                    } catch (PermissionException e) {
2760:                        if (Log.getLogger("chef").isDebugEnabled())
2761:                            Log.debug("chef", this  + "doDeleteannouncement()"
2762:                                    + e);
2763:                    } catch (NoSuchElementException e) {
2764:                        if (Log.getLogger("chef").isDebugEnabled())
2765:                            Log.debug("chef", this  + "doDeleteannouncement()"
2766:                                    + e);
2767:                    } catch (InUseException e) {
2768:                        if (Log.getLogger("chef").isDebugEnabled())
2769:                            Log.debug("chef", this  + "doPost()" + e);
2770:                        // addAlert(sstate, "this announcement is being edited by someone else");
2771:
2772:                        disableObservers(sstate);
2773:                    }
2774:                }
2775:
2776:                state.setIsListVM(true);
2777:                state.setStatus("FinishDeleting");
2778:
2779:            } // doDelete
2780:
2781:            /**
2782:             * Action is to use when doDeleteannouncement requested, corresponding to chef_announcements or chef_announcements-metadata menu "Delete"
2783:             */
2784:            public void doDeleteannouncement(RunData rundata, Context context) {
2785:                // retrieve the state from state object
2786:                AnnouncementActionState state = (AnnouncementActionState) getState(
2787:                        context, rundata, AnnouncementActionState.class);
2788:
2789:                String peid = ((JetspeedRunData) rundata).getJs_peid();
2790:                SessionState sstate = ((JetspeedRunData) rundata)
2791:                        .getPortletSessionState(peid);
2792:
2793:                // get the channel and message id information from state object
2794:                String messageReference = state.getMessageReference();
2795:
2796:                // if in main screen
2797:                if (state.getIsListVM()) {
2798:                    // then, read in the selected announcment items
2799:                    String[] messageReferences = rundata.getParameters()
2800:                            .getStrings("selectedMembers");
2801:                    if (messageReferences != null) {
2802:                        Vector v = new Vector();
2803:                        for (int i = 0; i < messageReferences.length; i++) {
2804:                            // get the message object through service
2805:                            try {
2806:                                // get the channel id throught announcement service
2807:                                AnnouncementChannel channel = AnnouncementService
2808:                                        .getAnnouncementChannel(this 
2809:                                                .getChannelIdFromReference(messageReferences[i]));
2810:                                // get the message object through service
2811:                                AnnouncementMessage message = channel
2812:                                        .getAnnouncementMessage(this 
2813:                                                .getMessageIDFromReference(messageReferences[i]));
2814:
2815:                                v.addElement(message);
2816:                            } catch (IdUnusedException e) {
2817:                                if (Log.getLogger("chef").isDebugEnabled())
2818:                                    Log.debug("chef", this 
2819:                                            + "doDeleteannouncement()" + e);
2820:                                // addAlert(sstate, e.toString());
2821:                            } catch (PermissionException e) {
2822:                                if (Log.getLogger("chef").isDebugEnabled())
2823:                                    Log.debug("chef", this 
2824:                                            + "doDeleteannouncement()" + e);
2825:                                addAlert(sstate, rb
2826:                                        .getString("java.alert.youdelann")
2827:                                        // "you don't have permissions to delete this announcement -"
2828:                                        + messageReferences[i]);
2829:                            }
2830:                        }
2831:
2832:                        // record the items to be deleted
2833:                        state.setDeleteMessages(v);
2834:                        state.setIsListVM(false);
2835:                        state.setStatus(DELETE_ANNOUNCEMENT_STATUS);
2836:
2837:                        // disable auto-updates while in view mode
2838:                        disableObservers(sstate);
2839:                    } else {
2840:                        state.setIsListVM(true);
2841:                        state.setStatus("noSelectedForDeletion");
2842:
2843:                        // make sure auto-updates are enabled
2844:                        enableObservers(sstate);
2845:                    }
2846:
2847:                }
2848:                // if not in main screen
2849:                else {
2850:                    state.setIsNewAnnouncement(false);
2851:                    Vector v = new Vector();
2852:
2853:                    // get the message object through service
2854:                    try {
2855:                        // get the channel id throught announcement service
2856:                        AnnouncementChannel channel = AnnouncementService
2857:                                .getAnnouncementChannel(this 
2858:                                        .getChannelIdFromReference(messageReference));
2859:                        // get the message object through service
2860:                        AnnouncementMessage message = channel
2861:                                .getAnnouncementMessage(this 
2862:                                        .getMessageIDFromReference(messageReference));
2863:
2864:                        v.addElement(message);
2865:                    } catch (IdUnusedException e) {
2866:                        if (Log.getLogger("chef").isDebugEnabled())
2867:                            Log.debug("chef", this  + "doDeleteannouncement()"
2868:                                    + e);
2869:                        // addAlert(sstate, e.toString());
2870:                    } catch (PermissionException e) {
2871:                        if (Log.getLogger("chef").isDebugEnabled())
2872:                            Log.debug("chef", this  + "doDeleteannouncement()"
2873:                                    + e);
2874:                        addAlert(sstate, rb.getString("java.alert.youdelann2"));
2875:                    }
2876:
2877:                    // state.setDelete_messages(delete_messages);
2878:                    state.setDeleteMessages(v);
2879:
2880:                    state.setIsListVM(false);
2881:                    if (sstate.getAttribute(STATE_MESSAGE) == null) {
2882:                        // add folder sucessful
2883:                        state.setStatus(DELETE_ANNOUNCEMENT_STATUS);
2884:                    }
2885:                }
2886:
2887:                // disable auto-updates while in confirm mode
2888:                disableObservers(sstate);
2889:
2890:            } // doDeleteannouncement
2891:
2892:            /**
2893:             * Action is to use when doDelete_announcement_link requested, corresponding to chef_announcements the link of deleting announcement item
2894:             */
2895:            public void doDelete_announcement_link(RunData rundata,
2896:                    Context context) {
2897:                // retrieve the state from state object
2898:                AnnouncementActionState state = (AnnouncementActionState) getState(
2899:                        context, rundata, AnnouncementActionState.class);
2900:
2901:                String peid = ((JetspeedRunData) rundata).getJs_peid();
2902:                SessionState sstate = ((JetspeedRunData) rundata)
2903:                        .getPortletSessionState(peid);
2904:
2905:                String messageReference = rundata.getParameters().getString(
2906:                        "itemReference");
2907:                state.setMessageReference(messageReference);
2908:
2909:                state.setIsNewAnnouncement(false);
2910:                Vector v = new Vector();
2911:
2912:                // get the message object through service
2913:                try {
2914:                    // get the channel id throught announcement service
2915:                    AnnouncementChannel channel = AnnouncementService
2916:                            .getAnnouncementChannel(this 
2917:                                    .getChannelIdFromReference(messageReference));
2918:                    // get the message object through service
2919:                    AnnouncementMessage message = channel
2920:                            .getAnnouncementMessage(this 
2921:                                    .getMessageIDFromReference(messageReference));
2922:
2923:                    v.addElement(message);
2924:                } catch (IdUnusedException e) {
2925:                    if (Log.getLogger("chef").isDebugEnabled())
2926:                        Log.debug("chef", this  + "doDeleteannouncement()" + e);
2927:                } catch (PermissionException e) {
2928:                    if (Log.getLogger("chef").isDebugEnabled())
2929:                        Log.debug("chef", this  + "doDeleteannouncement()" + e);
2930:                    addAlert(sstate, rb.getString("java.alert.youdelann2"));
2931:                }
2932:
2933:                state.setDeleteMessages(v);
2934:
2935:                if (sstate.getAttribute(STATE_MESSAGE) == null) {
2936:                    state.setStatus(DELETE_ANNOUNCEMENT_STATUS);
2937:                }
2938:            } // doDelete_announcement_link
2939:
2940:            /**
2941:             * Action is to use when doReviseannouncement requested, corresponding to chef_announcements the link of any draft announcement item
2942:             */
2943:            public void doReviseannouncement(RunData rundata, Context context) {
2944:                // retrieve the state from state object
2945:                AnnouncementActionState state = (AnnouncementActionState) getState(
2946:                        context, rundata, AnnouncementActionState.class);
2947:
2948:                String peid = ((JetspeedRunData) rundata).getJs_peid();
2949:                SessionState sstate = ((JetspeedRunData) rundata)
2950:                        .getPortletSessionState(peid);
2951:
2952:                state.setStatus("goToReviseAnnouncement");
2953:
2954:                String messageReference = rundata.getParameters().getString(
2955:                        "itemReference");
2956:                state.setMessageReference(messageReference);
2957:
2958:                // get the message object through service
2959:                try {
2960:                    // get the channel id throught announcement service
2961:                    AnnouncementChannel channel = AnnouncementService
2962:                            .getAnnouncementChannel(this 
2963:                                    .getChannelIdFromReference(messageReference));
2964:                    // get the message object through service
2965:                    // AnnouncementMessage message = channel.getAnnouncementMessage( messageId );
2966:
2967:                    AnnouncementMessageEdit edit = channel
2968:                            .editAnnouncementMessage(this 
2969:                                    .getMessageIDFromReference(messageReference));
2970:                    state.setEdit(edit);
2971:
2972:                    state.setTempAnnounceToGroups(edit.getAnnouncementHeader()
2973:                            .getGroups());
2974:
2975:                    // ReferenceVector attachmentList = (message.getHeader()).getAttachments();
2976:                    List attachmentList = (edit.getHeader()).getAttachments();
2977:                    state.setAttachments(attachmentList);
2978:
2979:                    // disable auto-updates while in confirm mode
2980:                    disableObservers(sstate);
2981:                } catch (IdUnusedException e) {
2982:                    if (Log.getLogger("chef").isDebugEnabled())
2983:                        Log.debug("chef", this  + "announcementRevise" + e);
2984:                    // addAlert(sstate, e.toString());
2985:                } catch (PermissionException e) {
2986:                    if (Log.getLogger("chef").isDebugEnabled())
2987:                        Log.debug("chef", this  + "announcementRevise" + e);
2988:                    state.setStatus("showMetadata");
2989:                } catch (InUseException err) {
2990:                    if (Log.getLogger("chef").isDebugEnabled())
2991:                        Log.debug("chef", this 
2992:                                + "inside .doReviseannouncementfrommenu" + err);
2993:                    addAlert(sstate, rb.getString("java.alert.thisitem"));
2994:                    // "This item is being edited by another user. Please try again later.");
2995:                    state.setStatus("showMetadata");
2996:                }
2997:                state.setIsNewAnnouncement(false);
2998:
2999:            } // doReviseannouncement
3000:
3001:            /**
3002:             * Action is to use when doReviseannouncementfrommenu requested, corresponding to chef_announcements.vm and -metadata.vm menu "Revise"
3003:             */
3004:
3005:            public void doReviseannouncementfrommenu(RunData rundata,
3006:                    Context context) {
3007:
3008:                // retrieve the state from state object
3009:                AnnouncementActionState state = (AnnouncementActionState) getState(
3010:                        context, rundata, AnnouncementActionState.class);
3011:
3012:                String peid = ((JetspeedRunData) rundata).getJs_peid();
3013:                SessionState sstate = ((JetspeedRunData) rundata)
3014:                        .getPortletSessionState(peid);
3015:
3016:                // get the channel and message id information from state object
3017:                String messageReference = state.getMessageReference();
3018:
3019:                // if in main screen
3020:                if (state.getIsListVM()) {
3021:                    // then, read in the selected announcment items
3022:                    String[] messageReferences = rundata.getParameters()
3023:                            .getStrings("selectedMembers");
3024:                    if (messageReferences != null) {
3025:                        if (messageReferences.length > 1) {
3026:                            state.setIsListVM(true);
3027:                            state.setStatus("moreThanOneSelectedForRevise");
3028:
3029:                            // make sure auto-updates are enabled
3030:                            enableObservers(sstate);
3031:
3032:                        } else if (messageReferences.length == 1) {
3033:                            state.setIsListVM(false);
3034:                            state.setMessageReference(messageReferences[0]);
3035:                            state.setStatus("goToReviseAnnouncement");
3036:
3037:                            // get the message object through service
3038:                            try {
3039:                                // get the channel id throught announcement service
3040:                                AnnouncementChannel channel = AnnouncementService
3041:                                        .getAnnouncementChannel(this 
3042:                                                .getChannelIdFromReference(messageReferences[0]));
3043:                                // get the message object through service
3044:                                AnnouncementMessage message = channel
3045:                                        .getAnnouncementMessage(this 
3046:                                                .getMessageIDFromReference(messageReferences[0]));
3047:
3048:                                if (channel.allowEditMessage(message.getId())) {
3049:                                    state.setAttachments(message.getHeader()
3050:                                            .getAttachments());
3051:                                    AnnouncementMessageEdit edit = channel
3052:                                            .editAnnouncementMessage(this 
3053:                                                    .getMessageIDFromReference(messageReferences[0]));
3054:                                    state.setEdit(edit);
3055:                                    state.setTempAnnounceToGroups(edit
3056:                                            .getAnnouncementHeader()
3057:                                            .getGroups());
3058:                                } else {
3059:                                    state.setIsListVM(true);
3060:                                    state.setStatus("noPermissionToRevise");
3061:                                }
3062:                            } catch (IdUnusedException e) {
3063:                                if (Log.getLogger("chef").isDebugEnabled())
3064:                                    Log.debug("chef", this 
3065:                                            + "announcementReviseFromMenu" + e);
3066:                            } catch (PermissionException e) {
3067:                                if (Log.getLogger("chef").isDebugEnabled())
3068:                                    Log.debug("chef", this 
3069:                                            + "announcementReviseFromMenu" + e);
3070:                                addAlert(sstate, rb
3071:                                        .getString("java.alert.youacc")// "You don't have permissions to access the message(s) - "
3072:                                        + e.toString());
3073:                            }
3074:                            // %%% -ggolden catch(InUseException err)
3075:                            catch (InUseException err) {
3076:                                if (Log.getLogger("chef").isDebugEnabled())
3077:                                    Log
3078:                                            .debug(
3079:                                                    "chef",
3080:                                                    this 
3081:                                                            + "inside .doReviseannouncementfrommenu"
3082:                                                            + err);
3083:                                addAlert(sstate, rb
3084:                                        .getString("java.alert.thisis"));// "This item is being edited by another user. Please try again later.");
3085:                                state.setIsListVM(false);
3086:                                state.setStatus("showMetadata");
3087:
3088:                                // make sure auto-updates are enabled
3089:                                disableObservers(sstate);
3090:                            }
3091:                        }
3092:                    } else {
3093:                        state.setIsListVM(true);
3094:                        state.setStatus(NOT_SELECTED_FOR_REVISE_STATUS);
3095:
3096:                        // make sure auto-updates are enabled
3097:                        enableObservers(sstate);
3098:                    }
3099:                }
3100:                // if the user is viewing a certain announcement already
3101:                else {
3102:                    state.setIsListVM(false);
3103:                    state.setStatus("goToReviseAnnouncement");
3104:
3105:                    // get the message object through service
3106:                    try {
3107:                        // get the channel id throught announcement service
3108:                        AnnouncementChannel channel = AnnouncementService
3109:                                .getAnnouncementChannel(this 
3110:                                        .getChannelIdFromReference(messageReference));
3111:                        // get the message object through service
3112:                        AnnouncementMessage message = channel
3113:                                .getAnnouncementMessage(this 
3114:                                        .getMessageIDFromReference(messageReference));
3115:
3116:                        if (channel.allowEditMessage(message.getId())) {
3117:                            AnnouncementMessageEdit edit = channel
3118:                                    .editAnnouncementMessage(this 
3119:                                            .getMessageIDFromReference(messageReference));
3120:                            state.setEdit(edit);
3121:                            state.setAttachments(message.getHeader()
3122:                                    .getAttachments());
3123:                            state.setTempAnnounceToGroups(edit
3124:                                    .getAnnouncementHeader().getGroups());
3125:                        } else {
3126:                            state.setIsListVM(true);
3127:                            state.setStatus("noPermissionToRevise");
3128:                        }
3129:                    } catch (IdUnusedException e) {
3130:                        if (Log.getLogger("chef").isDebugEnabled())
3131:                            Log.debug("chef", this 
3132:                                    + "announcementReviseFromMenu" + e);
3133:                        // addAlert(sstate, e.toString());
3134:                    } catch (PermissionException e) {
3135:                        if (Log.getLogger("chef").isDebugEnabled())
3136:                            Log.debug("chef", this 
3137:                                    + "announcementReviseFromMenu" + e);
3138:                        addAlert(sstate, rb.getString("java.alert.youacc")// "You don't have permissions to access the message(s) - "
3139:                                + e.toString());
3140:                    } catch (InUseException err) {
3141:                        if (Log.getLogger("chef").isDebugEnabled())
3142:                            Log.debug("chef", this 
3143:                                    + "inside .doReviseannouncementfrommenu"
3144:                                    + err);
3145:                        addAlert(sstate, rb.getString("java.alert.thisis"));// "This item is being edited by another user. Please try again later.");
3146:                        state.setIsListVM(false);
3147:                        state.setStatus("showMetadata");
3148:
3149:                        // disable auto-updates while in view mode
3150:                        disableObservers(sstate);
3151:                    }
3152:                }
3153:
3154:                state.setIsNewAnnouncement(false);
3155:            } // doReviseannouncementfrommenu
3156:
3157:            /**
3158:             * Action is to use when doRevisePreview requested, corresponding to chef_announcements-revise "eventSubmit_doRevisePreview" from revise view to preview view
3159:             */
3160:            public void doRevisepreview(RunData rundata, Context context) {
3161:                // retrieve the state from state object
3162:                AnnouncementActionState state = (AnnouncementActionState) getState(
3163:                        context, rundata, AnnouncementActionState.class);
3164:
3165:                String peid = ((JetspeedRunData) rundata).getJs_peid();
3166:                SessionState sstate = ((JetspeedRunData) rundata)
3167:                        .getPortletSessionState(peid);
3168:
3169:                // there is any error message caused by empty subject or boy
3170:                if (sstate.getAttribute(STATE_MESSAGE) != null) {
3171:                    state.setIsListVM(false);
3172:                    state.setStatus("stayAtRevise");
3173:                } else {
3174:                    state.setStatus("revisePreviw");
3175:                } // if-else
3176:
3177:                // disable auto-updates while in view mode
3178:                disableObservers(sstate);
3179:
3180:            } // doRevisepreview
3181:
3182:            public void doAttachments(RunData data, Context context) {
3183:                // get into helper mode with this helper tool
3184:                startHelper(data.getRequest(), "sakai.filepicker");
3185:
3186:                SessionState state = ((JetspeedRunData) data)
3187:                        .getPortletSessionState(((JetspeedRunData) data)
3188:                                .getJs_peid());
3189:                AnnouncementActionState myState = (AnnouncementActionState) getState(
3190:                        context, data, AnnouncementActionState.class);
3191:
3192:                // // setup... we'll use the ResourcesAction's mode
3193:                // state.setAttribute(ResourcesAction.STATE_MODE, ResourcesAction.MODE_HELPER);
3194:                // state.setAttribute(ResourcesAction.STATE_RESOURCES_HELPER_MODE, ResourcesAction.MODE_ATTACHMENT_SELECT);
3195:                // boolean show_other_sites = ServerConfigurationService.getBoolean("resources.show_all_collections.helper", ResourcesAction.SHOW_ALL_SITES_IN_FILE_PICKER);
3196:                // /** This attribute indicates whether "Other Sites" twiggle should show */
3197:                // state.setAttribute(ResourcesAction.STATE_SHOW_ALL_SITES, Boolean.toString(show_other_sites));
3198:                // /** This attribute indicates whether "Other Sites" twiggle should be open */
3199:                // state.setAttribute(ResourcesAction.STATE_SHOW_OTHER_SITES, Boolean.FALSE.toString());
3200:                //		
3201:                // String toolName = ToolManager.getCurrentTool().getTitle();
3202:                // state.setAttribute(ResourcesAction.STATE_ATTACH_TOOL_NAME, toolName);
3203:                //		
3204:                // String subject = myState.getTempSubject();
3205:                // String stateFromText = rb.getString("java.theann");//"the announcement";
3206:                // if (subject != null && subject.length() > 0)
3207:                // {
3208:                // stateFromText = rb.getString("java.ann")//"announcement "
3209:                // + '"' + subject + '"';
3210:                // }
3211:                // state.setAttribute(AttachmentAction.STATE_FROM_TEXT, stateFromText);
3212:                //
3213:                // List attachments = myState.getAttachments();
3214:                // // whether there is alread an attachment //%%%zqian
3215:                // if (attachments.size() > 0)
3216:                // {
3217:                // state.setAttribute(ResourcesAction.STATE_HAS_ATTACHMENT_BEFORE, Boolean.TRUE);
3218:                // }
3219:                // else
3220:                // {
3221:                // state.setAttribute(ResourcesAction.STATE_HAS_ATTACHMENT_BEFORE, Boolean.FALSE);
3222:                // }
3223:
3224:                state.setAttribute(FilePickerHelper.FILE_PICKER_ATTACHMENTS,
3225:                        myState.getAttachments());
3226:
3227:                myState.setStatus("backToReviseAnnouncement");
3228:            } // doAttachments
3229:
3230:            /**
3231:             * Action is to use when doCancel requested, corresponding to chef_announcement "eventSubmit_doCancel"
3232:             */
3233:            public void doCancel(RunData rundata, Context context) {
3234:
3235:                // retrieve the state from state object
3236:                AnnouncementActionState state = (AnnouncementActionState) getState(
3237:                        context, rundata, AnnouncementActionState.class);
3238:
3239:                // Carry out the base class options cancel if we're in the
3240:                // middle of an options page or an merge page
3241:                if (state.getStatus().equals(OPTIONS_STATUS)
3242:                        || state.getStatus().equals(MERGE_STATUS)) {
3243:                    cancelOptions();
3244:                }
3245:
3246:                String peid = ((JetspeedRunData) rundata).getJs_peid();
3247:                SessionState sstate = ((JetspeedRunData) rundata)
3248:                        .getPortletSessionState(peid);
3249:
3250:                state.setIsListVM(true);
3251:                state.setAttachments(null);
3252:                state.setSelectedAttachments(null);
3253:                state.setDeleteMessages(null);
3254:                state.setStatus(CANCEL_STATUS);
3255:                state.setTempAnnounceTo(null);
3256:                state.setTempAnnounceToGroups(null);
3257:                state.setCurrentSortedBy(SORT_DATE);
3258:                state.setCurrentSortAsc(Boolean.TRUE.booleanValue());
3259:                sstate.setAttribute(STATE_CURRENT_SORTED_BY, SORT_DATE);
3260:                sstate.setAttribute(STATE_CURRENT_SORT_ASC, Boolean.TRUE);
3261:
3262:                // we are done with customization... back to the main (list) mode
3263:                sstate.removeAttribute(STATE_MODE);
3264:
3265:                // re-enable auto-updates when going back to list mode
3266:                enableObservers(sstate);
3267:
3268:                try {
3269:                    if (state.getEdit() != null) {
3270:                        // get the channel id throught announcement service
3271:                        AnnouncementChannel channel = AnnouncementService
3272:                                .getAnnouncementChannel(this 
3273:                                        .getChannelIdFromReference(state
3274:                                                .getEdit().getReference()));
3275:
3276:                        channel.cancelMessage(state.getEdit());
3277:                        state.setEdit(null);
3278:                    }
3279:                } catch (IdUnusedException e) {
3280:                    if (Log.getLogger("chef").isDebugEnabled())
3281:                        Log.debug("chef", this  + "doCancel()" + e);
3282:                } catch (PermissionException e) {
3283:                    if (Log.getLogger("chef").isDebugEnabled())
3284:                        Log.debug("chef", this  + "doCancel()" + e);
3285:                }
3286:
3287:                // make sure auto-updates are enabled
3288:                enableObservers(sstate);
3289:
3290:            } // doCancel
3291:
3292:            /**
3293:             * Action is to use when doLinkcancel requested, corresponding to chef_announcement "eventSubmit_doLinkcancel"
3294:             */
3295:            public void doLinkcancel(RunData rundata, Context context) {
3296:
3297:                // retrieve the state from state object
3298:                AnnouncementActionState state = (AnnouncementActionState) getState(
3299:                        context, rundata, AnnouncementActionState.class);
3300:
3301:                String peid = ((JetspeedRunData) rundata).getJs_peid();
3302:                SessionState sstate = ((JetspeedRunData) rundata)
3303:                        .getPortletSessionState(peid);
3304:
3305:                state.setIsListVM(true);
3306:                state.setAttachments(null);
3307:                state.setSelectedAttachments(null);
3308:                state.setDeleteMessages(null);
3309:                state.setStatus(CANCEL_STATUS);
3310:
3311:                // make sure auto-updates are enabled
3312:                enableObservers(sstate);
3313:
3314:            } // doLinkcancel
3315:
3316:            /**
3317:             * Action is to use when doSavedraft requested, corresponding to chef_announcements-preview "eventSubmit_doSavedraft"
3318:             */
3319:            public void doSavedraft(RunData rundata, Context context) {
3320:                postOrSaveDraft(rundata, context, false);
3321:
3322:            } // doSavedraft
3323:
3324:            // ********* starting for sorting *********
3325:
3326:            /**
3327:             * Does initialization of sort parameters in the state.
3328:             */
3329:            private void setupSort(RunData rundata, Context context,
3330:                    String field) {
3331:                // retrieve the state from state object
3332:                AnnouncementActionState state = (AnnouncementActionState) getState(
3333:                        context, rundata, AnnouncementActionState.class);
3334:
3335:                SessionState sstate = ((JetspeedRunData) rundata)
3336:                        .getPortletSessionState(((JetspeedRunData) rundata)
3337:                                .getJs_peid());
3338:                sstate.setAttribute(STATE_CURRENT_SORTED_BY, field);
3339:
3340:                if (state.getCurrentSortedBy().equals(field)) {
3341:                    // current sorting sequence
3342:                    boolean asc = state.getCurrentSortAsc();
3343:
3344:                    // toggle between the ascending and descending sequence
3345:                    if (asc)
3346:                        asc = false;
3347:                    else
3348:                        asc = true;
3349:
3350:                    state.setCurrentSortAsc(asc);
3351:                    sstate.setAttribute(STATE_CURRENT_SORT_ASC,
3352:                            new Boolean(asc));
3353:                } else {
3354:                    // if the messages are not already sorted by subject, set the sort sequence to be ascending
3355:                    state.setCurrentSortedBy(field);
3356:                    state.setCurrentSortAsc(true);
3357:                    sstate.setAttribute(STATE_CURRENT_SORT_ASC, Boolean.TRUE);
3358:                }
3359:            } // setupSort
3360:
3361:            /**
3362:             * Do sort by subject
3363:             */
3364:            public void doSortbysubject(RunData rundata, Context context) {
3365:                if (Log.getLogger("chef").isDebugEnabled())
3366:                    Log.debug("chef",
3367:                            "AnnouncementAction.doSortbysubject get Called");
3368:
3369:                setupSort(rundata, context, SORT_SUBJECT);
3370:            } // doSortbysubject
3371:
3372:            /**
3373:             * Do sort by from - the author
3374:             */
3375:            public void doSortbyfrom(RunData rundata, Context context) {
3376:                if (Log.getLogger("chef").isDebugEnabled())
3377:                    Log.debug("chef",
3378:                            "AnnouncementAction.doSortbyfrom get Called");
3379:
3380:                setupSort(rundata, context, SORT_FROM);
3381:            } // doSortbyfrom
3382:
3383:            /**
3384:             * Do sort by public
3385:             */
3386:            public void doSortbypublic(RunData rundata, Context context) {
3387:                if (Log.getLogger("chef").isDebugEnabled())
3388:                    Log.debug("chef",
3389:                            "AnnouncementAction.doSortbypublic get Called");
3390:
3391:                setupSort(rundata, context, SORT_PUBLIC);
3392:            } // doSortbypublic
3393:
3394:            /**
3395:             * Do sort by the date of the announcement.
3396:             */
3397:            public void doSortbydate(RunData rundata, Context context) {
3398:                if (Log.getLogger("chef").isDebugEnabled())
3399:                    Log.debug("chef",
3400:                            "AnnouncementAction.doSortbydate get Called");
3401:
3402:                setupSort(rundata, context, SORT_DATE);
3403:            } // doSortbydate
3404:
3405:            public void doSortbyreleasedate(RunData rundata, Context context) {
3406:                if (Log.getLogger("chef").isDebugEnabled())
3407:                    Log
3408:                            .debug("chef",
3409:                                    "AnnouncementAction.doSortbyreleasedate get Called");
3410:
3411:                setupSort(rundata, context, SORT_RELEASEDATE);
3412:
3413:            } // doSortbyreleasedate
3414:
3415:            public void doSortbyretractdate(RunData rundata, Context context) {
3416:                if (Log.getLogger("chef").isDebugEnabled())
3417:                    Log
3418:                            .debug("chef",
3419:                                    "AnnouncementAction.doSortbyreleasedate get Called");
3420:
3421:                setupSort(rundata, context, SORT_RETRACTDATE);
3422:
3423:            } // doSortbyreleasedate
3424:
3425:            /**
3426:             * Do sort by the announcement channel name.
3427:             */
3428:            public void doSortbychannel(RunData rundata, Context context) {
3429:                if (Log.getLogger("chef").isDebugEnabled())
3430:                    Log.debug("chef",
3431:                            "AnnouncementAction.doSortbychannel get Called");
3432:
3433:                setupSort(rundata, context, SORT_CHANNEL);
3434:            } // doSortbydate
3435:
3436:            /**
3437:             * Do sort by for - grouop/site/public
3438:             */
3439:            public void doSortbyfor(RunData rundata, Context context) {
3440:                if (Log.getLogger("chef").isDebugEnabled())
3441:                    Log.debug("chef",
3442:                            "AnnouncementAction.doSortbyfrom get Called");
3443:
3444:                setupSort(rundata, context, SORT_FOR);
3445:            } // doSortbyfor
3446:
3447:            /**
3448:             * Do sort by group title
3449:             */
3450:            public void doSortbygrouptitle(RunData rundata, Context context) {
3451:                if (Log.getLogger("chef").isDebugEnabled())
3452:                    Log.debug("chef",
3453:                            "AnnouncementAction.doSortbyfrom get Called");
3454:
3455:                setupSort(rundata, context, SORT_GROUPTITLE);
3456:            } // doSortbygrouptitle
3457:
3458:            /**
3459:             * Do sort by group description
3460:             */
3461:            public void doSortbygroupdescription(RunData rundata,
3462:                    Context context) {
3463:                if (Log.getLogger("chef").isDebugEnabled())
3464:                    Log.debug("chef",
3465:                            "AnnouncementAction.doSortbyfrom get Called");
3466:
3467:                setupSort(rundata, context, SORT_GROUPDESCRIPTION);
3468:            } // doSortbygroupdescription
3469:
3470:            private class AnnouncementComparator implements  Comparator {
3471:                // the criteria
3472:                String m_criteria = null;
3473:
3474:                // the criteria - asc
3475:                boolean m_asc = true;
3476:
3477:                /**
3478:                 * constructor
3479:                 * 
3480:                 * @param criteria
3481:                 *        The sort criteria string
3482:                 * @param asc
3483:                 *        The sort order string. "true" if ascending; "false" otherwise.
3484:                 */
3485:                public AnnouncementComparator(String criteria, boolean asc) {
3486:                    m_criteria = criteria;
3487:                    m_asc = asc;
3488:
3489:                } // constructor
3490:
3491:                /**
3492:                 * implementing the compare function
3493:                 * 
3494:                 * @param o1
3495:                 *        The first object
3496:                 * @param o2
3497:                 *        The second object
3498:                 * @return The compare result. 1 is o1 < o2; -1 otherwise
3499:                 */
3500:                public int compare(Object o1, Object o2) {
3501:                    int result = -1;
3502:
3503:                    if (m_criteria.equals(SORT_SUBJECT)) {
3504:                        // sorted by the discussion message subject
3505:                        result = ((AnnouncementMessage) o1)
3506:                                .getAnnouncementHeader().getSubject()
3507:                                .compareToIgnoreCase(
3508:                                        ((AnnouncementMessage) o2)
3509:                                                .getAnnouncementHeader()
3510:                                                .getSubject());
3511:                    } else if (m_criteria.equals(SORT_DATE)) {
3512:                        // sorted by the discussion message date
3513:                        if (((AnnouncementMessage) o1).getAnnouncementHeader()
3514:                                .getDate().before(
3515:                                        ((AnnouncementMessage) o2)
3516:                                                .getAnnouncementHeader()
3517:                                                .getDate())) {
3518:                            result = -1;
3519:                        } else {
3520:                            result = 1;
3521:                        }
3522:                    } else if (m_criteria.equals(SORT_RELEASEDATE)) {
3523:                        Time o1releaseDate = null;
3524:                        Time o2releaseDate = null;
3525:
3526:                        try {
3527:                            o1releaseDate = ((AnnouncementMessage) o1)
3528:                                    .getProperties().getTimeProperty(
3529:                                            RELEASE_DATE);
3530:                        } catch (Exception e) {
3531:                            // release date not set, go on
3532:                        }
3533:
3534:                        try {
3535:                            o2releaseDate = ((AnnouncementMessage) o2)
3536:                                    .getProperties().getTimeProperty(
3537:                                            RELEASE_DATE);
3538:                        } catch (Exception e) {
3539:                            // release date not set, go on
3540:                        }
3541:
3542:                        if (o1releaseDate != null && o2releaseDate != null) {
3543:                            // sorted by the discussion message date
3544:                            if (o1releaseDate.before(o2releaseDate)) {
3545:                                result = -1;
3546:                            } else {
3547:                                result = 1;
3548:                            }
3549:                        } else if (o1releaseDate == null) {
3550:                            return 1;
3551:                        } else {
3552:                            return -1;
3553:                        }
3554:                    } else if (m_criteria.equals(SORT_RETRACTDATE)) {
3555:                        Time o1retractDate = null;
3556:                        Time o2retractDate = null;
3557:
3558:                        try {
3559:                            o1retractDate = ((AnnouncementMessage) o1)
3560:                                    .getProperties().getTimeProperty(
3561:                                            RETRACT_DATE);
3562:                        } catch (Exception e) {
3563:                            // release date not set, go on
3564:                        }
3565:
3566:                        try {
3567:                            o2retractDate = ((AnnouncementMessage) o2)
3568:                                    .getProperties().getTimeProperty(
3569:                                            RETRACT_DATE);
3570:                        } catch (Exception e) {
3571:                            // release date not set, go on
3572:                        }
3573:
3574:                        if (o1retractDate != null && o2retractDate != null) {
3575:                            // sorted by the discussion message date
3576:                            if (o1retractDate.before(o2retractDate)) {
3577:                                result = -1;
3578:                            } else {
3579:                                result = 1;
3580:                            }
3581:                        } else if (o1retractDate == null) {
3582:                            return 1;
3583:                        } else {
3584:                            return -1;
3585:                        }
3586:                    } else if (m_criteria.equals(SORT_FROM)) {
3587:                        // sorted by the discussion message subject
3588:                        result = ((AnnouncementMessage) o1)
3589:                                .getAnnouncementHeader().getFrom()
3590:                                .getSortName().compareToIgnoreCase(
3591:                                        ((AnnouncementMessage) o2)
3592:                                                .getAnnouncementHeader()
3593:                                                .getFrom().getSortName());
3594:                    } else if (m_criteria.equals(SORT_CHANNEL)) {
3595:                        // sorted by the channel name.
3596:                        result = ((AnnouncementWrapper) o1)
3597:                                .getChannelDisplayName().compareToIgnoreCase(
3598:                                        ((AnnouncementWrapper) o2)
3599:                                                .getChannelDisplayName());
3600:                    } else if (m_criteria.equals(SORT_PUBLIC)) {
3601:                        // sorted by the public view attribute
3602:                        String factor1 = ((AnnouncementMessage) o1)
3603:                                .getProperties().getProperty(
3604:                                        ResourceProperties.PROP_PUBVIEW);
3605:                        if (factor1 == null)
3606:                            factor1 = "false";
3607:                        String factor2 = ((AnnouncementMessage) o2)
3608:                                .getProperties().getProperty(
3609:                                        ResourceProperties.PROP_PUBVIEW);
3610:                        if (factor2 == null)
3611:                            factor2 = "false";
3612:                        result = factor1.compareToIgnoreCase(factor2);
3613:                    } else if (m_criteria.equals(SORT_FOR)) {
3614:                        // sorted by the public view attribute
3615:                        String factor1 = ((AnnouncementWrapper) o1).getRange();
3616:                        String factor2 = ((AnnouncementWrapper) o2).getRange();
3617:                        result = factor1.compareToIgnoreCase(factor2);
3618:                    } else if (m_criteria.equals(SORT_GROUPTITLE)) {
3619:                        // sorted by the group title
3620:                        String factor1 = ((Group) o1).getTitle();
3621:                        String factor2 = ((Group) o2).getTitle();
3622:                        result = factor1.compareToIgnoreCase(factor2);
3623:                    } else if (m_criteria.equals(SORT_GROUPDESCRIPTION)) {
3624:                        // sorted by the group title
3625:                        String factor1 = ((Group) o1).getDescription();
3626:                        String factor2 = ((Group) o2).getDescription();
3627:                        if (factor1 == null) {
3628:                            factor1 = "";
3629:                        }
3630:                        if (factor2 == null) {
3631:                            factor2 = "";
3632:                        }
3633:                        result = factor1.compareToIgnoreCase(factor2);
3634:                    }
3635:
3636:                    // sort ascending or descending
3637:                    if (!m_asc) {
3638:                        result = -result;
3639:                    }
3640:                    return result;
3641:
3642:                } // compare
3643:
3644:            } // AnnouncementComparator
3645:
3646:            // ********* ending for sorting *********
3647:
3648:            /**
3649:             * Action is to parse the function calls
3650:             */
3651:            /*
3652:             * public void doParse_list_announcement(RunData data, Context context) { SessionState state = ((JetspeedRunData)data).getPortletSessionState(((JetspeedRunData)data).getJs_peid()); ParameterParser params = data.getParameters(); String source =
3653:             * params.getString("source"); if (source.equalsIgnoreCase("new")) { // create new announcement doNewannouncement(data, context); } else if (source.equalsIgnoreCase("revise")) { // revise announcement doReviseannouncementfrommenu(data, context); }
3654:             * else if (source.equalsIgnoreCase("delete")) { // delete announcement doDeleteannouncement(data, context); } } // doParse_list_announcement
3655:             */
3656:
3657:            private int seperatorMatrix(boolean a, boolean b, boolean c) {
3658:                int i = 0;
3659:                if (a)
3660:                    i = i + 100;
3661:                if (b)
3662:                    i = i + 10;
3663:                if (c)
3664:                    i = i + 1;
3665:
3666:                if (i == 111)
3667:                    return 11;
3668:                if ((i == 110) || (i == 101))
3669:                    return 10;
3670:                if (i == 11)
3671:                    return 1;
3672:                if ((i == 100) || (i == 10) || (i == 1) || (i == 0))
3673:                    return 0;
3674:                return 11;
3675:            }
3676:
3677:            /**
3678:             * Build the menu.
3679:             */
3680:            private void buildMenu(VelocityPortlet portlet, Context context,
3681:                    RunData rundata, AnnouncementActionState state,
3682:                    boolean menu_new, boolean menu_delete, boolean menu_revise,
3683:                    boolean menu_merge, boolean menu_permissions,
3684:                    boolean menu_options,
3685:                    AnnouncementActionState.DisplayOptions displayOptions) {
3686:                Menu bar = new MenuImpl(portlet, rundata, "AnnouncementAction");
3687:                boolean buttonRequiringCheckboxesPresent = false;
3688:
3689:                if (!displayOptions.isShowOnlyOptionsButton()) {
3690:                    String statusName = state.getStatus();
3691:                    if (statusName != null) {
3692:                        if (statusName.equals("showMetadata")) {
3693:                            boolean s1 = true;
3694:                            boolean s2 = true;
3695:                            // int m = seperatorMatrix(menu_new, menu_delete, menu_revise);
3696:                            int m = seperatorMatrix(menu_new, menu_revise,
3697:                                    menu_delete);
3698:                            if (m == 10)
3699:                                s2 = false; // 10
3700:                            if (m == 1)
3701:                                s1 = false; // 01
3702:                            if (m == 0)
3703:                                s1 = s2 = false; // 00
3704:
3705:                            bar.add(new MenuEntry(rb.getString("gen.new"),
3706:                                    null, menu_new, MenuItem.CHECKED_NA,
3707:                                    "doNewannouncement"));
3708:                            if (s1)
3709:                                bar.add(new MenuDivider());
3710:                            bar.add(new MenuEntry(rb.getString("gen.revise"),
3711:                                    null, menu_revise, MenuItem.CHECKED_NA,
3712:                                    "doReviseannouncementfrommenu"));
3713:                            if (s2)
3714:                                bar.add(new MenuDivider());
3715:                            bar.add(new MenuEntry(rb.getString("gen.delete2"),
3716:                                    null, menu_delete, MenuItem.CHECKED_NA,
3717:                                    "doDeleteannouncement"));
3718:                            buttonRequiringCheckboxesPresent = true;
3719:                        } else {
3720:                            bar.add(new MenuEntry(rb.getString("gen.new"),
3721:                                    null, menu_new, MenuItem.CHECKED_NA,
3722:                                    "doNewannouncement"));
3723:                            buttonRequiringCheckboxesPresent = true;
3724:
3725:                        } // if (statusName.equals("showMetadata"))
3726:                    } else {
3727:                        bar.add(new MenuEntry(rb.getString("gen.new"), null,
3728:                                menu_new, MenuItem.CHECKED_NA,
3729:                                "doNewannouncement"));
3730:                        buttonRequiringCheckboxesPresent = true;
3731:                    } // if-else (statusName != null)
3732:
3733:                    // add merge button, if allowed
3734:                    if (menu_merge) {
3735:                        bar.add(new MenuEntry(rb.getString("java.merge"),
3736:                                MERGE_BUTTON_HANDLER));
3737:                    }
3738:                } // if-else (!displayOptions.isShowOnlyOptionsButton())
3739:
3740:                // add options if allowed
3741:                if (menu_options) {
3742:                    addOptionsMenu(bar, (JetspeedRunData) rundata);
3743:                }
3744:
3745:                // let the permissions button to be the last one in the toolbar
3746:                if (!displayOptions.isShowOnlyOptionsButton()) {
3747:                    // add permissions, if allowed
3748:                    if (menu_permissions) {
3749:                        bar.add(new MenuEntry(rb.getString("java.permissions"),
3750:                                PERMISSIONS_BUTTON_HANDLER));
3751:                    }
3752:                }
3753:
3754:                // Set menu state attribute
3755:                SessionState stateForMenus = ((JetspeedRunData) rundata)
3756:                        .getPortletSessionState(portlet.getID());
3757:                stateForMenus.setAttribute(MenuItem.STATE_MENU, bar);
3758:
3759:                Iterator it = bar.getItems().iterator();
3760:
3761:                // See if we have any enabled menu items.
3762:                boolean enabledItemExists = false;
3763:
3764:                while (it.hasNext()) {
3765:                    MenuItem menuItem = (MenuItem) it.next();
3766:                    if (menuItem.getIsEnabled()) {
3767:                        enabledItemExists = true;
3768:                        break;
3769:                    }
3770:                }
3771:
3772:                // Set a flag in the context to indicate that at least one menu item is enabled.
3773:                context.put(ENABLED_MENU_ITEM_EXISTS, Boolean
3774:                        .valueOf(enabledItemExists));
3775:
3776:                context.put(CONTEXT_ENABLE_ITEM_CHECKBOXES, Boolean
3777:                        .valueOf(enabledItemExists
3778:                                && buttonRequiringCheckboxesPresent));
3779:                context.put(CONTEXT_ENABLED_MENU_ITEM_EXISTS, Boolean
3780:                        .valueOf(enabledItemExists));
3781:
3782:                context.put(Menu.CONTEXT_MENU, bar);
3783:                context.put(Menu.CONTEXT_ACTION, "AnnouncementAction");
3784:                context.put("tlang", rb);
3785:
3786:            } // buildMenu
3787:
3788:            /*
3789:             * what i've done to make this tool automaticlly updated includes some corresponding imports in buildMail, tell observer just the page is just refreshed in the do() functions related to show the list, enable the obeserver in other do() functions
3790:             * related to not show the list, disable the obeserver in the do(), define the session sstate object, and protlet. add initState add updateObservationOfChannel() add state attribute STATE_CHANNEL_REF
3791:             */
3792:
3793:            /**
3794:             * Populate the state object, if needed.
3795:             */
3796:            protected void initState(SessionState state,
3797:                    VelocityPortlet portlet, JetspeedRunData rundata) {
3798:                super .initState(state, portlet, rundata);
3799:
3800:                // retrieve the state from state object
3801:                AnnouncementActionState annState = (AnnouncementActionState) getState(
3802:                        portlet, rundata, AnnouncementActionState.class);
3803:
3804:                // get the current channel ID from state object or prolet initial parameter
3805:                String channelId = annState.getChannelId();
3806:                if (channelId == null) {
3807:                    // try the portlet parameter
3808:                    channelId = StringUtil.trimToNull(portlet
3809:                            .getPortletConfig().getInitParameter("channel"));
3810:                    if (channelId == null) {
3811:                        // form based on the request's context's "main" channel
3812:                        channelId = AnnouncementService.channelReference(
3813:                                ToolManager.getCurrentPlacement().getContext(),
3814:                                SiteService.MAIN_CONTAINER);
3815:                    }
3816:
3817:                    // let the state object have the current channel id
3818:                    annState.setChannelId(channelId);
3819:                    annState.setIsListVM(true);
3820:                }
3821:                state.setAttribute(STATE_CHANNEL_REF, channelId);
3822:
3823:                if (state.getAttribute(STATE_SELECTED_VIEW) == null) {
3824:                    state.setAttribute(STATE_SELECTED_VIEW, VIEW_MODE_ALL);
3825:                }
3826:
3827:                // // get the current collection ID from state object or prolet initial parameter
3828:                // String collectionId = annState.getCollectionId();
3829:                // if (collectionId == null)
3830:                // {
3831:                // // get the current channel ID for prolet initial parameter
3832:                // collectionId = StringUtil.trimToNull(portlet.getPortletConfig().getInitParameter("collection"));
3833:                // if (collectionId == null)
3834:                // collectionId = ContentHostingService.getSiteCollection(PortalService.getCurrentSiteId());
3835:                //
3836:                // // let the state object have the current channel id
3837:                // annState.setCollectionId(collectionId);
3838:                // }
3839:
3840:                // String channel = StringUtil.trimToNull(config.getInitParameter(PARAM_CHANNEL));
3841:                // setup the observer to notify our main panel
3842:                if (state.getAttribute(STATE_INITED) == null) {
3843:                    state.setAttribute(STATE_INITED, STATE_INITED);
3844:
3845:                    // check if the channel is marked public read
3846:                    if (SecurityService.unlock(UserDirectoryService
3847:                            .getAnonymousUser(),
3848:                            AnnouncementService.SECURE_ANNC_READ, channelId)) {
3849:                        state.setAttribute(STATE_CHANNEL_PUBVIEW,
3850:                                STATE_CHANNEL_PUBVIEW);
3851:                    }
3852:
3853:                    // // the delivery location for this tool
3854:                    // String deliveryId = clientWindowId(state, portlet.getID());
3855:                    //
3856:                    // // the html element to update on delivery
3857:                    // String elementId = mainPanelUpdateId(portlet.getID());
3858:                    //
3859:                    // // the event resource reference pattern to watch for
3860:                    // Reference r = new Reference(channelId);
3861:                    // String pattern = AnnouncementService.messageReference(r.getContext(), r.getId(), "");
3862:                    //
3863:                    // ObservingCourier observer = new ObservingCourier(deliveryId, elementId, pattern);
3864:                    //			
3865:                    // state.setAttribute(STATE_OBSERVER, observer);
3866:
3867:                    MergedList mergedAnnouncementList = new MergedList();
3868:
3869:                    String[] channelArrayFromConfigParameterValue = null;
3870:
3871:                    // TODO - MERGE FIX
3872:                    // Figure out the list of channel references that we'll be using.
3873:                    // If we're on the workspace tab, we get everything.
3874:                    // Don't do this if we're the super-user, since we'd be
3875:                    // overwhelmed.
3876:                    if (isOnWorkspaceTab() && !SecurityService.isSuperUser()) {
3877:                        channelArrayFromConfigParameterValue = mergedAnnouncementList
3878:                                .getAllPermittedChannels(new AnnouncementChannelReferenceMaker());
3879:                    } else {
3880:                        // Get the list of merged announcement sources.
3881:                        channelArrayFromConfigParameterValue = mergedAnnouncementList
3882:                                .getChannelReferenceArrayFromDelimitedString(
3883:                                        annState.getChannelId(),
3884:                                        portlet
3885:                                                .getPortletConfig()
3886:                                                .getInitParameter(
3887:                                                        getPortletConfigParameterNameForLoadOnly(portlet)));
3888:                    }
3889:
3890:                    mergedAnnouncementList
3891:                            .loadChannelsFromDelimitedString(
3892:                                    isOnWorkspaceTab(),
3893:                                    new MergedListEntryProviderFixedListWrapper(
3894:                                            new EntryProvider(),
3895:                                            annState.getChannelId(),
3896:                                            channelArrayFromConfigParameterValue,
3897:                                            new AnnouncementReferenceToChannelConverter()),
3898:                                    StringUtil.trimToZero(SessionManager
3899:                                            .getCurrentSessionUserId()),
3900:                                    channelArrayFromConfigParameterValue,
3901:                                    SecurityService.isSuperUser(), ToolManager
3902:                                            .getCurrentPlacement().getContext());
3903:                }
3904:
3905:                // Set up or display options if we haven't done it yet.
3906:                if (annState.getDisplayOptions() == null) {
3907:                    loadDisplayOptionsFromPortletConfig(portlet, annState);
3908:                }
3909:
3910:                // default is to not disable the public selection - FALSE
3911:                state.setAttribute(PUBLIC_DISPLAY_DISABLE_BOOLEAN,
3912:                        Boolean.FALSE);
3913:
3914:                Site site = null;
3915:                try {
3916:                    site = SiteService.getSite(ToolManager
3917:                            .getCurrentPlacement().getContext());
3918:                    String[] disableStrgs = ServerConfigurationService
3919:                            .getStrings("prevent.public.announcements");
3920:                    if (disableStrgs != null) {
3921:                        for (int i = 0; i < disableStrgs.length; i++) {
3922:                            if ((StringUtil.trimToZero(disableStrgs[i]))
3923:                                    .equals(site.getType()))
3924:                                state.setAttribute(
3925:                                        PUBLIC_DISPLAY_DISABLE_BOOLEAN,
3926:                                        Boolean.TRUE);
3927:                            ;
3928:                        }
3929:                    }
3930:                } catch (IdUnusedException e) {
3931:                } catch (NullPointerException e) {
3932:                }
3933:
3934:            } // initState
3935:
3936:            // /**
3937:            // * Adds the merged sites to the list of events that we're interested
3938:            // * in watching.
3939:            // */
3940:            // private void addMergedAnnouncementsToObserver(MergedList mergedAnnouncementList, AnnouncementActionState annState, ObservingCourier observer)
3941:            // {
3942:            // Iterator it = mergedAnnouncementList.iterator();
3943:            //		
3944:            // while (it.hasNext())
3945:            // {
3946:            // MergedList.MergedEntry entry = (MergedList.MergedEntry) it.next();
3947:            //
3948:            // if ( entry.isMerged() )
3949:            // {
3950:            // Reference ref = new Reference(entry.getReference());
3951:            //
3952:            // String pattern =
3953:            // AnnouncementService.messageReference(
3954:            // ref.getContext(),
3955:            // ref.getId(),
3956:            // "");
3957:            //	
3958:            // // observer.addResourcePattern(pattern);
3959:            // }
3960:            // }
3961:            // }
3962:
3963:            /**
3964:             * Loads the display options object we save in the ActionState with the settings from the PortletConfig.
3965:             */
3966:            private void loadDisplayOptionsFromPortletConfig(
3967:                    VelocityPortlet portlet, AnnouncementActionState annState) {
3968:                AnnouncementActionState.DisplayOptions displayOptions = new AnnouncementActionState.DisplayOptions();
3969:                annState.setDisplayOptions(displayOptions);
3970:
3971:                //PortletConfig portletConfig = portlet.getPortletConfig();
3972:                //displayOptions.loadProperties(portletConfig.getInitParameters());
3973:                Properties registeredProperties = ToolManager.getCurrentTool()
3974:                        .getRegisteredConfig();
3975:                displayOptions.loadProperties((Map) registeredProperties);
3976:
3977:            } // initState
3978:
3979:            /**
3980:             * Setup our observer to be watching for change events for our channel.
3981:             */
3982:            private void updateObservationOfChannel(
3983:                    MergedList mergedAnnouncementList, RunData runData,
3984:                    SessionState state, AnnouncementActionState annState) {
3985:                // String peid = ((JetspeedRunData) runData).getJs_peid();
3986:                //		
3987:                // ObservingCourier observer =
3988:                // (ObservingCourier) state.getAttribute(STATE_OBSERVER);
3989:                //
3990:                // addMergedAnnouncementsToObserver(mergedAnnouncementList, annState, observer);
3991:                //
3992:                // // the delivery location for this tool
3993:                // String deliveryId = clientWindowId(state, peid);
3994:                // observer.setDeliveryId(deliveryId);
3995:
3996:            } // updateObservationOfChannel
3997:
3998:            /**
3999:             * Fire up the permissions editor
4000:             */
4001:            public void doPermissions(RunData data, Context context) {
4002:                // get into helper mode with this helper tool
4003:                startHelper(data.getRequest(), "sakai.permissions.helper");
4004:
4005:                // setup the parameters for the helper
4006:                SessionState state = ((JetspeedRunData) data)
4007:                        .getPortletSessionState(((JetspeedRunData) data)
4008:                                .getJs_peid());
4009:                AnnouncementActionState stateObj = (AnnouncementActionState) getState(
4010:                        context, data, AnnouncementActionState.class);
4011:
4012:                String channelRefStr = stateObj.getChannelId();
4013:                Reference channelRef = EntityManager
4014:                        .newReference(channelRefStr);
4015:                String siteRef = SiteService.siteReference(channelRef
4016:                        .getContext());
4017:
4018:                // setup for editing the permissions of the site for this tool, using the roles of this site, too
4019:                state.setAttribute(PermissionsHelper.TARGET_REF, siteRef);
4020:
4021:                // ... with this description
4022:                state.setAttribute(PermissionsHelper.DESCRIPTION, rb
4023:                        .getString("java.set")
4024:                        + SiteService.getSiteDisplay(channelRef.getContext()));
4025:
4026:                // ... showing only locks that are prpefixed with this
4027:                state.setAttribute(PermissionsHelper.PREFIX, "annc.");
4028:            }
4029:
4030:            /**
4031:             * Handle the "Merge" button on the toolbar
4032:             */
4033:            public void doMerge(RunData runData, Context context) {
4034:                AnnouncementActionState state = (AnnouncementActionState) getState(
4035:                        context, runData, AnnouncementActionState.class);
4036:                String peid = ((JetspeedRunData) runData).getJs_peid();
4037:                SessionState sstate = ((JetspeedRunData) runData)
4038:                        .getPortletSessionState(peid);
4039:
4040:                doOptions(runData, context);
4041:
4042:                // if we didn't end up in options mode, bail out
4043:                if (!MODE_OPTIONS.equals(sstate.getAttribute(STATE_MODE)))
4044:                    return;
4045:
4046:                // Disable the observer
4047:                enableObserver(sstate, false);
4048:
4049:                state.setStatus(MERGE_STATUS);
4050:            } // doMerge
4051:
4052:            /**
4053:             * Handles the user clicking on the save button on the page to specify which calendars will be merged into the present schedule.
4054:             */
4055:            public void doUpdate(RunData runData, Context context) {
4056:                AnnouncementActionState state = (AnnouncementActionState) getState(
4057:                        context, runData, AnnouncementActionState.class);
4058:
4059:                if (state.getStatus().equals(MERGE_STATUS)) {
4060:                    doMergeUpdate(runData, context);
4061:                } else if (state.getStatus().equals(OPTIONS_STATUS)) {
4062:                    doOptionsUpdate(runData, context);
4063:                } else {
4064:                    Log.debug("chef", this  + ".doUpdate - Unexpected status");
4065:                }
4066:            }
4067:
4068:            /**
4069:             * This handles the "doUpdate" if we're processing an update from the "merge" page.
4070:             */
4071:            private void doMergeUpdate(RunData runData, Context context) {
4072:                AnnouncementActionState state = (AnnouncementActionState) getState(
4073:                        context, runData, AnnouncementActionState.class);
4074:                String peid = ((JetspeedRunData) runData).getJs_peid();
4075:                SessionState sstate = ((JetspeedRunData) runData)
4076:                        .getPortletSessionState(peid);
4077:
4078:                // Get the merged calendar list out of our session state
4079:                MergedList mergedChannelList = (MergedList) sstate
4080:                        .getAttribute(SSTATE_ATTRIBUTE_MERGED_CHANNELS);
4081:
4082:                if (mergedChannelList != null) {
4083:                    // Get the information from the run data and load it into
4084:                    // our calendar list that we have in the session state.
4085:                    mergedChannelList.loadFromRunData(runData.getParameters());
4086:                } else {
4087:                    if (Log.getLogger("chef").isDebugEnabled()) {
4088:                        Log.debug("chef", this 
4089:                                + ".doUpdate mergedChannelList == null");
4090:                    }
4091:                }
4092:
4093:                // update the tool config
4094:                Placement placement = ToolManager.getCurrentPlacement();
4095:
4096:                // Make sure that the older, incorrectly named paramter is gone.
4097:                placement.getPlacementConfig().remove(
4098:                        PORTLET_CONFIG_PARM_NON_MERGED_CHANNELS);
4099:
4100:                if (mergedChannelList != null) {
4101:                    placement.getPlacementConfig().setProperty(
4102:                            PORTLET_CONFIG_PARM_MERGED_CHANNELS,
4103:                            mergedChannelList
4104:                                    .getDelimitedChannelReferenceString());
4105:                } else {
4106:                    placement.getPlacementConfig().remove(
4107:                            PORTLET_CONFIG_PARM_MERGED_CHANNELS);
4108:                }
4109:
4110:                // commit the change
4111:                saveOptions();
4112:
4113:                updateObservationOfChannel(mergedChannelList, runData, sstate,
4114:                        state);
4115:
4116:                // Turn the observer back on.
4117:                enableObserver(sstate, true);
4118:
4119:                state.setStatus(null);
4120:
4121:                sstate.removeAttribute(STATE_MODE);
4122:            } // doUpdate} // AnnouncementAction
4123:
4124:            /**
4125:             * This handles the "doUpdate" if we're in a processing an update from the options page.
4126:             */
4127:            public void doOptionsUpdate(RunData runData, Context context) {
4128:                AnnouncementActionState state = (AnnouncementActionState) getState(
4129:                        context, runData, AnnouncementActionState.class);
4130:                String peid = ((JetspeedRunData) runData).getJs_peid();
4131:                SessionState sstate = ((JetspeedRunData) runData)
4132:                        .getPortletSessionState(peid);
4133:
4134:                doUpdateDisplayOptions(runData, state, sstate);
4135:
4136:                // We're omitting processing of the "showAnnouncementBody" since these
4137:                // options are currently mutually exclusive.
4138:
4139:                // commit the change
4140:                saveOptions();
4141:
4142:                // Turn the observer back on.
4143:                enableObserver(sstate, true);
4144:
4145:                state.setStatus(null);
4146:
4147:                sstate.removeAttribute(STATE_MODE);
4148:            }
4149:
4150:            /*
4151:             * (non-Javadoc)
4152:             * 
4153:             * @see org.chefproject.actions.VelocityPortletPaneledAction#doOptions(org.apache.turbine.util.RunData, org.apache.velocity.context.Context)
4154:             */
4155:            public void doOptions(RunData runData, Context context) {
4156:                super .doOptions(runData, context);
4157:
4158:                String peid = ((JetspeedRunData) runData).getJs_peid();
4159:                SessionState sstate = ((JetspeedRunData) runData)
4160:                        .getPortletSessionState(peid);
4161:
4162:                // go to option editing if no error message which means the option editing is locked successfully
4163:                // otherwise, stay at whatever state we are at
4164:                String msg = (String) sstate.getAttribute(STATE_MESSAGE);
4165:                if ((msg == null) || (msg.equals(""))) {
4166:                    // Keep track of our state
4167:                    AnnouncementActionState state = (AnnouncementActionState) getState(
4168:                            context, runData, AnnouncementActionState.class);
4169:                    state.setStatus(OPTIONS_STATUS);
4170:                }
4171:            } // doOptions
4172:
4173:            private void doUpdateDisplayOptions(RunData runData,
4174:                    AnnouncementActionState state, SessionState sstate) {
4175:                AnnouncementActionState.DisplayOptions displayOptions = state
4176:                        .getDisplayOptions();
4177:
4178:                ParameterParser parameters = runData.getParameters();
4179:
4180:                displayOptions.loadProperties(parameters);
4181:
4182:                // update the tool config
4183:                Placement placement = ToolManager.getCurrentPlacement();
4184:
4185:                displayOptions.saveProperties(placement.getPlacementConfig());
4186:
4187:            } // doUpdateDisplayOptions
4188:
4189:            /**
4190:             * is notification enabled?
4191:             */
4192:            protected boolean notificationEnabled(AnnouncementActionState state) {
4193:                return true;
4194:            } // notificationEnabled
4195:
4196:            /**
4197:             * Processes formatted text that is coming back from the browser (from the formatted text editing widget).
4198:             * 
4199:             * @param state
4200:             *        Used to pass in any user-visible alerts or errors when processing the text
4201:             * @param strFromBrowser
4202:             *        The string from the browser
4203:             * @return The formatted text
4204:             */
4205:            private String processFormattedTextFromBrowser(SessionState state,
4206:                    String strFromBrowser) {
4207:                StringBuffer alertMsg = new StringBuffer();
4208:                try {
4209:                    String text = FormattedText.processFormattedText(
4210:                            strFromBrowser, alertMsg);
4211:                    if (alertMsg.length() > 0)
4212:                        addAlert(state, alertMsg.toString());
4213:                    return text;
4214:                } catch (Exception e) {
4215:                    Log.warn("chef", this  + ": ", e);
4216:                    return strFromBrowser;
4217:                }
4218:            }
4219:
4220:            /*
4221:             * (non-Javadoc)
4222:             * 
4223:             * @see org.sakaiproject.cheftool.PagedResourceActionII#readResourcesPage(org.sakaiproject.service.framework.session.SessionState, int, int)
4224:             */
4225:            protected List readResourcesPage(SessionState state, int first,
4226:                    int last) {
4227:                List rv = (List) state.getAttribute("messages");
4228:                if (rv == null)
4229:                    return new Vector();
4230:
4231:                String sortedBy = "";
4232:                if (state.getAttribute(STATE_CURRENT_SORTED_BY) != null)
4233:                    sortedBy = state.getAttribute(STATE_CURRENT_SORTED_BY)
4234:                            .toString();
4235:
4236:                boolean asc = false;
4237:                if (state.getAttribute(STATE_CURRENT_SORT_ASC) != null)
4238:                    asc = ((Boolean) state.getAttribute(STATE_CURRENT_SORT_ASC))
4239:                            .booleanValue();
4240:
4241:                if ((sortedBy == null) || sortedBy.equals("")) {
4242:                    sortedBy = "date";
4243:                    asc = false;
4244:                }
4245:                SortedIterator rvSorted = new SortedIterator(rv.iterator(),
4246:                        new AnnouncementComparator(sortedBy, asc));
4247:
4248:                PagingPosition page = new PagingPosition(first, last);
4249:                page.validate(rv.size());
4250:
4251:                Vector subrv = new Vector();
4252:                for (int index = 0; index < rv.size(); index++) {
4253:                    if ((index >= (page.getFirst() - 1))
4254:                            && index < page.getLast())
4255:                        subrv.add(rvSorted.next());
4256:                    else
4257:                        rvSorted.next();
4258:                }
4259:                return subrv;
4260:            }
4261:
4262:            /*
4263:             * (non-Javadoc)
4264:             * 
4265:             * @see org.sakaiproject.cheftool.PagedResourceActionII#sizeResources(org.sakaiproject.service.framework.session.SessionState)
4266:             */
4267:            protected int sizeResources(SessionState state) {
4268:                List rv = (List) state.getAttribute("messages");
4269:                if (rv == null)
4270:                    return 0;
4271:
4272:                return rv.size();
4273:            }
4274:
4275:            // toggle through different views
4276:            public void doView(RunData data, Context context) {
4277:                SessionState state = ((JetspeedRunData) data)
4278:                        .getPortletSessionState(((JetspeedRunData) data)
4279:                                .getJs_peid());
4280:
4281:                String viewMode = data.getParameters().getString("view");
4282:                state.setAttribute(STATE_SELECTED_VIEW, viewMode);
4283:
4284:                if (viewMode.equals(VIEW_MODE_ALL)) {
4285:
4286:                } else if (viewMode.equals(VIEW_MODE_PUBLIC)) {
4287:
4288:                } else if (viewMode.equals(VIEW_MODE_BYGROUP)) {
4289:                    state.setAttribute(STATE_CURRENT_SORTED_BY, SORT_FOR);
4290:                    state.setAttribute(STATE_CURRENT_SORT_ASC, Boolean.TRUE);
4291:                } else if (viewMode.equals(VIEW_MODE_MYGROUPS)) {
4292:
4293:                }
4294:
4295:                // we are changing the view, so start with first page again.
4296:                resetPaging(state);
4297:
4298:                // clear search form
4299:                doSearch_clear(data, context);
4300:
4301:            } // doView
4302:
4303:            // ********
4304:            // ******** functions copied from VelocityPortletStateAction ********
4305:            // ********
4306:            /**
4307:             * Get the proper state for this instance (if portlet is not known, only context).
4308:             * 
4309:             * @param context
4310:             *        The Template Context (it contains a reference to the portlet).
4311:             * @param rundata
4312:             *        The Jetspeed (Turbine) rundata associated with the request.
4313:             * @param stateClass
4314:             *        The Class of the ControllerState to find / create.
4315:             * @return The proper state object for this instance.
4316:             */
4317:            protected ControllerState getState(Context context,
4318:                    RunData rundata, Class stateClass) {
4319:                return getState(((JetspeedRunData) rundata).getJs_peid(),
4320:                        rundata, stateClass);
4321:
4322:            } // getState
4323:
4324:            /**
4325:             * Get the proper state for this instance (if portlet is known).
4326:             * 
4327:             * @param portlet
4328:             *        The portlet being rendered.
4329:             * @param rundata
4330:             *        The Jetspeed (Turbine) rundata associated with the request.
4331:             * @param stateClass
4332:             *        The Class of the ControllerState to find / create.
4333:             * @return The proper state object for this instance.
4334:             */
4335:            protected ControllerState getState(VelocityPortlet portlet,
4336:                    RunData rundata, Class stateClass) {
4337:                if (portlet == null) {
4338:                    Log.warn("chef", this  + ".getState(): portlet null");
4339:                    return null;
4340:                }
4341:
4342:                return getState(portlet.getID(), rundata, stateClass);
4343:
4344:            } // getState
4345:
4346:            /**
4347:             * Get the proper state for this instance (if portlet id is known).
4348:             * 
4349:             * @param peid
4350:             *        The portlet id.
4351:             * @param rundata
4352:             *        The Jetspeed (Turbine) rundata associated with the request.
4353:             * @param stateClass
4354:             *        The Class of the ControllerState to find / create.
4355:             * @return The proper state object for this instance.
4356:             */
4357:            protected ControllerState getState(String peid, RunData rundata,
4358:                    Class stateClass) {
4359:                if (peid == null) {
4360:                    Log.warn("chef", this  + ".getState(): peid null");
4361:                    return null;
4362:                }
4363:
4364:                try {
4365:                    // get the PortletSessionState
4366:                    SessionState ss = ((JetspeedRunData) rundata)
4367:                            .getPortletSessionState(peid);
4368:
4369:                    // get the state object
4370:                    ControllerState state = (ControllerState) ss
4371:                            .getAttribute("state");
4372:
4373:                    if (state != null)
4374:                        return state;
4375:
4376:                    // if there's no "state" object in there, make one
4377:                    state = (ControllerState) stateClass.newInstance();
4378:                    state.setId(peid);
4379:
4380:                    // remember it!
4381:                    ss.setAttribute("state", state);
4382:
4383:                    return state;
4384:                } catch (Exception e) {
4385:                    Log.warn("chef", "", e);
4386:                }
4387:
4388:                return null;
4389:
4390:            } // getState
4391:
4392:            /**
4393:             * Release the proper state for this instance (if portlet is not known, only context).
4394:             * 
4395:             * @param context
4396:             *        The Template Context (it contains a reference to the portlet).
4397:             * @param rundata
4398:             *        The Jetspeed (Turbine) rundata associated with the request.
4399:             */
4400:            protected void releaseState(Context context, RunData rundata) {
4401:                releaseState(((JetspeedRunData) rundata).getJs_peid(), rundata);
4402:
4403:            } // releaseState
4404:
4405:            /**
4406:             * Release the proper state for this instance (if portlet is known).
4407:             * 
4408:             * @param portlet
4409:             *        The portlet being rendered.
4410:             * @param rundata
4411:             *        The Jetspeed (Turbine) rundata associated with the request.
4412:             */
4413:            protected void releaseState(VelocityPortlet portlet, RunData rundata) {
4414:                releaseState(portlet.getID(), rundata);
4415:
4416:            } // releaseState
4417:
4418:            /**
4419:             * Release the proper state for this instance (if portlet id is known).
4420:             * 
4421:             * @param peid
4422:             *        The portlet id being rendered.
4423:             * @param rundata
4424:             *        The Jetspeed (Turbine) rundata associated with the request.
4425:             */
4426:            protected void releaseState(String peid, RunData rundata) {
4427:                try {
4428:                    // get the PortletSessionState
4429:                    SessionState ss = ((JetspeedRunData) rundata)
4430:                            .getPortletSessionState(peid);
4431:
4432:                    // get the state object
4433:                    ControllerState state = (ControllerState) ss
4434:                            .getAttribute("state");
4435:
4436:                    // recycle the state object
4437:                    state.recycle();
4438:
4439:                    // clear out the SessionState for this Portlet
4440:                    ss.removeAttribute("state");
4441:
4442:                    ss.clear();
4443:
4444:                } catch (Exception e) {
4445:                    Log.warn("chef", "", e);
4446:                }
4447:
4448:            } // releaseState
4449:
4450:            // ******* end of copy from VelocityPortletStateAction
4451:
4452:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.