0001: /**********************************************************************************
0002: * $URL: https://source.sakaiproject.org/svn/discussion/tags/sakai_2-4-1/discussion-tool/tool/src/java/org/sakaiproject/discussion/tool/DiscussionAction.java $
0003: * $Id: DiscussionAction.java 19434 2006-12-12 21:03:26Z zqian@umich.edu $
0004: ***********************************************************************************
0005: *
0006: * Copyright (c) 2003, 2004, 2005, 2006 The Sakai Foundation.
0007: *
0008: * Licensed under the Educational Community License, Version 1.0 (the "License");
0009: * you may not use this file except in compliance with the License.
0010: * You may obtain a copy of the License at
0011: *
0012: * http://www.opensource.org/licenses/ecl1.php
0013: *
0014: * Unless required by applicable law or agreed to in writing, software
0015: * distributed under the License is distributed on an "AS IS" BASIS,
0016: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0017: * See the License for the specific language governing permissions and
0018: * limitations under the License.
0019: *
0020: **********************************************************************************/package org.sakaiproject.discussion.tool;
0021:
0022: import java.util.Collections;
0023: import java.util.HashSet;
0024: import java.util.Hashtable;
0025: import java.util.Iterator;
0026: import java.util.List;
0027: import java.util.NoSuchElementException;
0028: import java.util.Set;
0029: import java.util.Stack;
0030: import java.util.Vector;
0031:
0032: import org.sakaiproject.authz.api.PermissionsHelper;
0033: import org.sakaiproject.cheftool.Context;
0034: import org.sakaiproject.cheftool.JetspeedRunData;
0035: import org.sakaiproject.cheftool.PortletConfig;
0036: import org.sakaiproject.cheftool.RunData;
0037: import org.sakaiproject.cheftool.VelocityPortlet;
0038: import org.sakaiproject.cheftool.VelocityPortletPaneledAction;
0039: import org.sakaiproject.cheftool.api.Menu;
0040: import org.sakaiproject.cheftool.api.MenuItem;
0041: import org.sakaiproject.cheftool.menu.MenuEntry;
0042: import org.sakaiproject.cheftool.menu.MenuImpl;
0043: import org.sakaiproject.content.api.ContentTypeImageService;
0044: import org.sakaiproject.content.api.FilePickerHelper;
0045: import org.sakaiproject.discussion.api.DiscussionChannel;
0046: import org.sakaiproject.discussion.api.DiscussionChannelEdit;
0047: import org.sakaiproject.discussion.api.DiscussionMessage;
0048: import org.sakaiproject.discussion.api.DiscussionMessageEdit;
0049: import org.sakaiproject.discussion.api.DiscussionMessageHeader;
0050: import org.sakaiproject.discussion.api.DiscussionMessageHeaderEdit;
0051: import org.sakaiproject.discussion.cover.DiscussionService;
0052: import org.sakaiproject.entity.api.Reference;
0053: import org.sakaiproject.entity.api.ResourceProperties;
0054: import org.sakaiproject.entity.api.ResourcePropertiesEdit;
0055: import org.sakaiproject.entity.cover.EntityManager;
0056: import org.sakaiproject.event.api.SessionState;
0057: import org.sakaiproject.exception.IdInvalidException;
0058: import org.sakaiproject.exception.IdUnusedException;
0059: import org.sakaiproject.exception.IdUsedException;
0060: import org.sakaiproject.exception.InUseException;
0061: import org.sakaiproject.exception.PermissionException;
0062: import org.sakaiproject.site.cover.SiteService;
0063: import org.sakaiproject.time.cover.TimeService;
0064: import org.sakaiproject.tool.cover.ToolManager;
0065: import org.sakaiproject.util.FormattedText;
0066: import org.sakaiproject.util.ParameterParser;
0067: import org.sakaiproject.util.ResourceLoader;
0068: import org.sakaiproject.util.StringUtil;
0069: import org.sakaiproject.util.Validator;
0070: import org.sakaiproject.util.Web;
0071: import org.sakaiproject.vm.ActionURL;
0072:
0073: /**
0074: * <p>
0075: * DiscussionAction is the action class for the dicussion tool.
0076: * </p>
0077: */
0078: public class DiscussionAction extends VelocityPortletPaneledAction {
0079: /* reply type */
0080: private static final String STATE_REPLY_TOPIC = "replyToTopic";
0081:
0082: private static final String STATE_REPLY_MSG = "replyToMsgOnly";
0083:
0084: /** Resource bundle using current language locale */
0085: private static ResourceLoader rb = new ResourceLoader("discussion");
0086:
0087: /** channel exist */
0088: private static final String CHANNEL_EXIST = "channel_exist";
0089:
0090: /** the attachments** */
0091: private static final String ATTACHMENTS = "threadeddiscussionII.attachments";
0092:
0093: /** go to attachments helper view */
0094: private static final String GO_ATTACHMENTS = "threadeddiscussionII.go_attachments";
0095:
0096: /** the channel id ** */
0097: private static final String STATE_CHANNEL_REF = "threadeddiscussionII.channel_id";
0098:
0099: /** the state mode ** */
0100: private static final String STATE_MODE = "threadeddiscussionII.state_mode";
0101:
0102: /** the category show list ** */
0103: private static final String STATE_CATEGORIES_SHOW_LIST = "threadeddiscussionII.state_category_show_list";
0104:
0105: /** the sorted by ** */
0106: private static final String STATE_SORTED_BY = "threadeddiscussionII.state_sorted_by";
0107:
0108: /** sorted by topic * */
0109: private static final String STATE_SORTED_BY_TOPIC = "topic";
0110:
0111: /** sorted by author * */
0112: private static final String STATE_SORTED_BY_AUTHOR = "author";
0113:
0114: /** sorted by date * */
0115: private static final String STATE_SORTED_BY_DATE = "date";
0116:
0117: /** sorted by category alphabetically * */
0118: private static final String STATE_SORTED_BY_CATEGORY_ALPHA = "category";
0119:
0120: /** the sorted ascending * */
0121: private static final String STATE_SORTED_ASC = "threadeddiscussionII.state_sorted_asc";
0122:
0123: /** the expand all topic flag * */
0124: private static final String STATE_EXPAND_ALL_TOPIC_FLAG = "threadeddiscussionII.state_expand_all_topic_flag";
0125:
0126: /** the expand message flag * */
0127: private static final String STATE_EXPAND_MESSAGE_LIST = "threadeddiscussionII.state_expand_message_list";
0128:
0129: /** the expand category list * */
0130: private static final String STATE_EXPAND_CATEGORY_LIST = "threadeddiscussionII.state_expand_category_list";
0131:
0132: /** The content type image lookup service in the State. */
0133: private static final String STATE_CONTENT_TYPE_IMAGE_SERVICE = "attachment.content_type_image_service";
0134:
0135: /** ********** new topic context ******************** */
0136: /** the new topic category */
0137: private static final String NEW_TOPIC_CATEGORY = "threadeddiscussionII.new_topic_category";
0138:
0139: /** create new category? */
0140: private static final String NEW_TOPIC_NEW_CATEGORY = "threadeddiscussionII.new_topic_new_category";
0141:
0142: /** the new topic message body */
0143: private static final String NEW_TOPIC_BODY = "threadeddiscussionII.new_topic_body";
0144:
0145: /** the new topic subject */
0146: private static final String NEW_TOPIC_SUBJECT = "threadeddiscussionII.new_topic_subject";
0147:
0148: /** the new topic reply message style */
0149: private static final String NEW_TOPIC_REPLY_STYLE = "threadeddiscussionII.new_topic_reply_style";
0150:
0151: /** ********** new category context ******************** */
0152: private static final String NEW_CATEGORY = "threadeddiscussionII.new_category";
0153:
0154: /** ********** draft topic context ******************** */
0155: /** the draft message category */
0156: private static final String DRAFT_MESSAGE_CATEGORY = "threadeddiscussionII.draft_message_category";
0157:
0158: /** the draft message body */
0159: private static final String DRAFT_MESSAGE_BODY = "threadeddiscussionII.draft_message_body";
0160:
0161: /** the draft message subject */
0162: private static final String DRAFT_MESSAGE_SUBJECT = "threadeddiscussionII.draft_message_subject";
0163:
0164: /** the draft message reply style */
0165: private static final String DRAFT_MESSAGE_REPLY_STYLE = "threadeddiscussionII.draft_message_reply_style";
0166:
0167: /** ********* the respond context ******************** */
0168: /** the respond message body */
0169: private static final String RESPOND_BODY = "threadeddiscussionII.respond_body";
0170:
0171: /** the respond message subject */
0172: private static final String RESPOND_SUBJECT = "threadeddiscussionII.respond_subject";
0173:
0174: /** the respond from */
0175: private static final String RESPOND_REPLY_TO = "threadeddiscussionII.respond_reply_to";
0176:
0177: /** the respond attachment */
0178: private static final String RESPOND_ATTACHMENT = "threadeddiscussionII.respond_attachment";
0179:
0180: /** ************ delete message context ******************* */
0181: /** the delete message id * */
0182: private static final String DELETE_MESSAGE_ID = "threadeddiscussionII.delete_message_id";
0183:
0184: private static final String DELETE_WARNING = "delete_message_warning";
0185:
0186: /** portlet configuration parameter names. */
0187: private static final String PARAM_CHANNEL = "channel";
0188:
0189: private static final String PARAM_ASCENDING = "ascending";
0190:
0191: /** Configure form field names. */
0192: private static final String FORM_CHANNEL = "channel";
0193:
0194: private static final String FORM_ASCENDING = "ascending";
0195:
0196: /** Control form field names. */
0197: private static final String FORM_MESSAGE = "message";
0198:
0199: /** names and values of request parameters to select sub-panels */
0200: private static final String MONITOR_PANEL = "List";
0201:
0202: private static final String CONTROL_PANEL = "Control";
0203:
0204: private static final String TOOLBAR_PANEL = "Toolbar";
0205:
0206: private static final String NEXT_PANEL = "Next";
0207:
0208: /** state attribute names. */
0209: private static final String STATE_ASCENDING = "ascending";
0210:
0211: private static final String STATE_ERROR = "error";
0212:
0213: private static final String STATE_UPDATE = "update";
0214:
0215: /** UI messages. */
0216: private static final String STATE_DISPLAY_MESSAGE = "display_message";
0217:
0218: private static final String STATE_LIST_PANNEL_UPDATED = "state_list_pannel_updated";
0219:
0220: /** the category to be deleted */
0221: private static final String DELETE_CATEGORY = "delete_category";
0222:
0223: /** the id of the showing content topic */
0224: private static final String STATE_SHOW_CONTENT_TOPIC_ID = "show_content_topic_id";
0225:
0226: /** state mode when showing the topic content */
0227: private static final String MODE_SHOW_TOPIC_CONTENT = "mode_show_topic_content";
0228:
0229: /** the state flag of expand all */
0230: private static final String STATE_EXPAND_ALL_FLAG = "state_expand_all_flag";
0231:
0232: /** state mode when showing the new topic form */
0233: private static final String MODE_NEW_TOPIC = "mode_new_topic";
0234:
0235: /** state mode when showing the new category form */
0236: private static final String MODE_NEW_CATEGORY = "mode_new_category";
0237:
0238: /** state mode when showing the reply form */
0239: private static final String MODE_REPLY = "mode_reply";
0240:
0241: /** state mode when showing the reply preview */
0242: private static final String MODE_REPLY_PREVIEW = "mode_reply_preview";
0243:
0244: /** state mode when confirm deleting category */
0245: private static final String MODE_DELETE_CATEGORY_CONFIRM = "mode_delete_category_confirm";
0246:
0247: /** state mode when confirm deleting message */
0248: private static final String MODE_DELETE_MESSAGE_CONFIRM = "mode_delete_message_confirm";
0249:
0250: /** visited messages */
0251: private static final String VISITED_MESSAGES = "visited_messages";
0252:
0253: /** left_right layout */
0254: private static final String STATE_LEFT_RIGHT_LAYOUT = "state_left_right_layout";
0255:
0256: /** search criteria */
0257: private static final String STATE_SEARCH = "state_search";
0258:
0259: /** boolean value indicating the need to update the current message shown */
0260: private static final String STATE_SEARCH_REFRESH = "state_search_refresh";
0261:
0262: /** Form fields. */
0263: protected static final String FORM_SEARCH = "search";
0264:
0265: /** state selected view */
0266: private static final String STATE_SELECTED_VIEW = "state_selected_view";
0267:
0268: /** State attribute set when we need to go into permissions mode. */
0269: private static final String STATE_PERMISSIONS = "sakai:discussion:permissions";
0270:
0271: /** state variable for search results */
0272: private static final String STATE_SEARCH_RESULT = "state_search_result";
0273:
0274: /**
0275: * Populate the state object, if needed.
0276: *
0277: * @param config
0278: * The portlet config.
0279: * @param pageSessionId
0280: * The is of the current portal page session.
0281: * @param elementId
0282: * The id of the portlet element that wants to be notified on change.
0283: */
0284: protected void initState(SessionState state,
0285: VelocityPortlet portlet, JetspeedRunData rundata) {
0286: super .initState(state, portlet, rundata);
0287:
0288: PortletConfig config = portlet.getPortletConfig();
0289: String channelId = (String) state
0290: .getAttribute(STATE_CHANNEL_REF);
0291: String channelExist = (String) state
0292: .getAttribute(CHANNEL_EXIST);
0293: if (channelExist == null) {
0294:
0295: if (channelId == null) {
0296: // read the channel from configuration, or, if not specified, use the default for the page
0297: channelId = StringUtil.trimToNull(config
0298: .getInitParameter("channel"));
0299: if (channelId == null) {
0300: channelId = DiscussionService.channelReference(
0301: ToolManager.getCurrentPlacement()
0302: .getContext(),
0303: SiteService.MAIN_CONTAINER);
0304: }
0305: state.setAttribute(STATE_CHANNEL_REF, channelId);
0306: }
0307:
0308: DiscussionChannel channel = null;
0309: try {
0310: channel = (DiscussionChannel) DiscussionService
0311: .getDiscussionChannel(channelId);
0312: } catch (IdUnusedException e) {
0313: try {
0314: DiscussionChannelEdit channelEdit = DiscussionService
0315: .addDiscussionChannel(channelId);
0316: DiscussionService.commitChannel(channelEdit);
0317: channel = (DiscussionChannel) channelEdit;
0318: } catch (IdUsedException ee) {
0319: Log.error("chef", this + "" + ee);
0320: } catch (IdInvalidException ee) {
0321: Log.error("chef", this + "" + ee);
0322: } catch (PermissionException ee) {
0323: Log.error("chef", this + "no permission");
0324: }
0325: } catch (PermissionException e) {
0326: }
0327:
0328: if (channel != null) {
0329: state.setAttribute(CHANNEL_EXIST, "true");
0330:
0331: // TODO: Note: calling addCatagory here, which uses the state's STATE_EXPAND_CATEGORY_LIST which is not yet set is not good -ggolden
0332: // // make sure that the channel has categories as seeded in the config
0333: // String[] configCategories = parseCategoryString(StringUtil.trimToNull(config.getInitParameter("categories")));
0334: // if (configCategories != null)
0335: // {
0336: // for (int i = 0; i < configCategories.length; i++)
0337: // {
0338: // addCategory(state, channel, configCategories[i]);
0339: // }
0340:
0341: if (state.getAttribute(STATE_CATEGORIES_SHOW_LIST) == null) {
0342: // get the catagories as defined without scanning all messages for more
0343: List categories = channel.getCategories(false);
0344:
0345: Hashtable h = new Hashtable();
0346: for (Iterator i = categories.iterator(); i
0347: .hasNext();) {
0348: String cat = (String) i.next();
0349:
0350: // store the ids of topic messages
0351: List topicMsgIds = channel.getTopicMsgIds(cat);
0352: h.put(cat, topicMsgIds);
0353: }
0354: state.setAttribute(STATE_CATEGORIES_SHOW_LIST, h);
0355:
0356: HashSet s = new HashSet();
0357: s.addAll(categories);
0358: state.setAttribute(STATE_EXPAND_CATEGORY_LIST, s);
0359:
0360: Hashtable t = new Hashtable();
0361: for (Iterator i = categories.iterator(); i
0362: .hasNext();) {
0363: String cat = (String) i.next();
0364: HashSet v = new HashSet();
0365: t.put(cat, v);
0366: }
0367: state.setAttribute(STATE_EXPAND_MESSAGE_LIST, t);
0368:
0369: }
0370: }
0371:
0372: // // setup the observer to notify our MONITOR_PANEL panel(inside the Main panel)
0373: // if (state.getAttribute(STATE_OBSERVER) == null)
0374: // {
0375: // // the delivery location for this tool
0376: // String deliveryId = clientWindowId(state, portlet.getID());
0377: //
0378: // // the html element to update on delivery
0379: // String elementId = mainPanelUpdateId(portlet.getID()) + "." + MONITOR_PANEL;
0380: //
0381: // // the event resource reference pattern to watch for
0382: // Reference r = new Reference(channelId);
0383: //
0384: // // add message pattern
0385: // String pattern = DiscussionService.messageReference(r.getContext(), r.getId(), "");
0386: // MultipleEventsObservingCourier o = new MultipleEventsObservingCourier(deliveryId, elementId, pattern);
0387: // // add channel pattern
0388: // pattern = DiscussionService.channelReference(r.getContext(), r.getId());
0389: // o.addResourcePattern(pattern);
0390: // o.enable();
0391: // state.setAttribute(STATE_OBSERVER, o);
0392: // }
0393: }
0394:
0395: if (state.getAttribute(STATE_DISPLAY_MESSAGE) == null) {
0396: state.setAttribute(STATE_DISPLAY_MESSAGE,
0397: new DisplayMessage(""));
0398: }
0399:
0400: /** The content type image lookup service in the State. */
0401: ContentTypeImageService iService = (ContentTypeImageService) state
0402: .getAttribute(STATE_CONTENT_TYPE_IMAGE_SERVICE);
0403: if (iService == null) {
0404: iService = org.sakaiproject.content.cover.ContentTypeImageService
0405: .getInstance();
0406: state.setAttribute(STATE_CONTENT_TYPE_IMAGE_SERVICE,
0407: iService);
0408: } // if
0409:
0410: if (state.getAttribute(STATE_SORTED_BY) == null) {
0411: state.setAttribute(STATE_SORTED_BY, STATE_SORTED_BY_DATE);
0412: }
0413:
0414: if (state.getAttribute(STATE_SORTED_ASC) == null) {
0415: state.setAttribute(STATE_SORTED_ASC, Boolean.TRUE
0416: .toString());
0417: }
0418:
0419: if (state.getAttribute(STATE_ASCENDING) == null) {
0420: state.setAttribute(STATE_ASCENDING, new Boolean(config
0421: .getInitParameter(PARAM_ASCENDING)));
0422: }
0423:
0424: if (state.getAttribute(STATE_EXPAND_ALL_FLAG) == null) {
0425: state.setAttribute(STATE_EXPAND_ALL_FLAG,
0426: new Boolean(false));
0427: }
0428:
0429: if (state.getAttribute(STATE_LEFT_RIGHT_LAYOUT) == null) {
0430: state.setAttribute(STATE_LEFT_RIGHT_LAYOUT, new Boolean(
0431: false));
0432: }
0433:
0434: if (state.getAttribute(VISITED_MESSAGES) == null) {
0435: state.setAttribute(VISITED_MESSAGES, new HashSet());
0436: }
0437:
0438: // show the list of assignment view first
0439: if (state.getAttribute(STATE_SELECTED_VIEW) == null) {
0440: state.setAttribute(STATE_SELECTED_VIEW, rb
0441: .getString("rowlay"));
0442: }
0443:
0444: if (state.getAttribute(STATE_SEARCH) == null) {
0445: state.setAttribute(STATE_SEARCH, "");
0446: }
0447:
0448: // make sure the observer is in sync with state
0449: updateObservationOfChannel(state, portlet.getID());
0450:
0451: } // initState
0452:
0453: /**
0454: * Action is to use when doAttachment when "add attachments" is clicked
0455: */
0456: public void doAttachments(RunData data, Context context) {
0457: String peid = ((JetspeedRunData) data).getJs_peid();
0458: SessionState state = ((JetspeedRunData) data)
0459: .getPortletSessionState(peid);
0460:
0461: // trigger the switch on the next request (which is going to happen after this action is processed with its redirect response to the build)
0462: state.setAttribute(GO_ATTACHMENTS, GO_ATTACHMENTS);
0463:
0464: ParameterParser params = data.getParameters();
0465: String subject = params.getString("subject");
0466:
0467: String mode = (String) state.getAttribute(STATE_MODE);
0468: if (mode != null && mode.equals(MODE_NEW_TOPIC)) {
0469: subject = ((String) params.getString("subject"));
0470: if (subject != null) {
0471: subject = subject.trim();
0472: }
0473: state.setAttribute(NEW_TOPIC_SUBJECT, subject);
0474:
0475: String body = params.getCleanString("body");
0476: body = processFormattedTextFromBrowser(state, body);
0477: state.setAttribute(NEW_TOPIC_BODY, body);
0478:
0479: String style = params.getString("style");
0480: state.setAttribute(NEW_TOPIC_REPLY_STYLE, style);
0481:
0482: String category = ((String) params.getString("newcategory"));
0483: if (category != null) {
0484: category = category.trim();
0485: }
0486: if (category == null || category.length() == 0) {
0487: // no new category input
0488: state.setAttribute(NEW_TOPIC_NEW_CATEGORY, new Boolean(
0489: Boolean.FALSE.toString()));
0490: category = ((String) params.getString("category"));
0491: if (category != null) {
0492: category = category.trim();
0493: }
0494: state.setAttribute(NEW_TOPIC_CATEGORY, category);
0495: } else {
0496: // new category input
0497: state.setAttribute(NEW_TOPIC_NEW_CATEGORY, new Boolean(
0498: Boolean.TRUE.toString()));
0499: state.setAttribute(NEW_TOPIC_CATEGORY, category);
0500: }
0501: } else if (mode != null && mode.equals(MODE_REPLY)) {
0502: // save the input infos for the respond message
0503: subject = params.getString("subject");
0504: if (subject != null) {
0505: subject = subject.trim();
0506: }
0507: state.setAttribute(RESPOND_SUBJECT, subject);
0508:
0509: String body = params.getCleanString("body");
0510: body = processFormattedTextFromBrowser(state, body);
0511: state.setAttribute(RESPOND_BODY, body);
0512: } else {
0513: // must be inside control pannel editing draft message
0514: state.setAttribute(DRAFT_MESSAGE_BODY,
0515: processFormattedTextFromBrowser(state, params
0516: .getCleanString("body")));
0517: state.setAttribute(DRAFT_MESSAGE_SUBJECT, params.getString(
0518: "subject").trim());
0519: state.setAttribute(DRAFT_MESSAGE_REPLY_STYLE, params
0520: .getString("style"));
0521: }
0522:
0523: // schedule a main refresh to excape from the control panel
0524: schedulePeerFrameRefresh(mainPanelUpdateId(peid));
0525: } // doAttachments
0526:
0527: /**
0528: * Fire up the permissions editor
0529: */
0530: protected void doAttachmentsNow(RunData data, Context context) {
0531: // get into helper mode with this helper tool
0532: startHelper(data.getRequest(), "sakai.filepicker");
0533: SessionState state = ((JetspeedRunData) data)
0534: .getPortletSessionState(((JetspeedRunData) data)
0535: .getJs_peid());
0536: if (state.getAttribute(ATTACHMENTS) == null) {
0537: state.setAttribute(ATTACHMENTS, EntityManager
0538: .newReferenceList());
0539: }
0540: state.setAttribute(FilePickerHelper.FILE_PICKER_ATTACHMENTS,
0541: state.getAttribute(ATTACHMENTS));
0542:
0543: } // doAttachmentsNow
0544:
0545: /**
0546: * Setup our observer to be watching for change events for our channel.
0547: */
0548: private void updateObservationOfChannel(SessionState state,
0549: String peid) {
0550: } // updateObservationOfChannel
0551:
0552: /**
0553: * If the state indicates an update is needed, update the portlet's configuration.
0554: *
0555: * @param state
0556: * The session state.
0557: * @param portlet
0558: * The portlet to update.
0559: * @param data
0560: * The current request run data.
0561: */
0562: private void updatePortlet(SessionState state,
0563: VelocityPortlet portlet, RunData data) {
0564: // check the flag
0565: if (state.getAttribute(STATE_UPDATE) == null)
0566: return;
0567:
0568: // change the portlet's configuration
0569: portlet.setAttribute(PARAM_CHANNEL, (String) state
0570: .getAttribute(STATE_CHANNEL_REF), data);
0571: portlet.setAttribute(PARAM_ASCENDING, ((Boolean) state
0572: .getAttribute(STATE_ASCENDING)).toString(), data);
0573:
0574: // clear the flag
0575: state.removeAttribute(STATE_UPDATE);
0576:
0577: } // updatePortlet
0578:
0579: /**
0580: * build the context for the Layout panel
0581: *
0582: * @return (optional) template name for this panel
0583: */
0584: public String buildMainPanelContext(VelocityPortlet portlet,
0585: Context context, RunData rundata, SessionState state) {
0586: context.put("mainFrameId", Web.escapeJavascript("Main"
0587: + ToolManager.getCurrentPlacement().getId()));
0588:
0589: context.put("tlang", rb);
0590:
0591: String state_mode = (String) state.getAttribute(STATE_MODE);
0592:
0593: if (state_mode != null) {
0594: if (state_mode.equals(MODE_SHOW_TOPIC_CONTENT)) {
0595: return buildContentContext(portlet, context, rundata,
0596: state);
0597: } else if (state_mode.equals(MODE_NEW_TOPIC)) {
0598: return buildNewTopicContext(portlet, context, rundata,
0599: state);
0600: } else if (state_mode.equals(MODE_NEW_CATEGORY)) {
0601: return buildNewCategoryContext(portlet, context,
0602: rundata, state);
0603: } else if (state_mode.equals(MODE_REPLY)) {
0604: return buildReplyContext(portlet, context, rundata,
0605: state);
0606: } else if (state_mode.equals(MODE_REPLY_PREVIEW)) {
0607: return buildReplyPreviewContext(portlet, context,
0608: rundata, state);
0609: } else if (state_mode.equals(MODE_DELETE_CATEGORY_CONFIRM)) {
0610: return buildDeleteCategoryConfirmContext(portlet,
0611: context, rundata, state);
0612: } else if (state_mode.equals(MODE_DELETE_MESSAGE_CONFIRM)) {
0613: return buildDeleteMessageConfirmContext(portlet,
0614: context, rundata, state);
0615: }
0616: }
0617:
0618: // assure that the portlet parameters are current with the user's configuration choices
0619: updatePortlet(state, portlet, rundata);
0620:
0621: context.put("panel-control", CONTROL_PANEL);
0622: context.put("panel-monitor", MONITOR_PANEL);
0623: context.put("panel-toolbar", TOOLBAR_PANEL);
0624: context.put("panel-next", NEXT_PANEL);
0625:
0626: context.put("layout_left_right", (Boolean) state
0627: .getAttribute(STATE_LEFT_RIGHT_LAYOUT));
0628: return (String) getContext(rundata).get("template") + "-Layout";
0629:
0630: } // buildMainPanelContext
0631:
0632: /**
0633: * build the context for the menu panel
0634: *
0635: * @return (optional) template name for this panel
0636: */
0637: public String buildToolbarPanelContext(VelocityPortlet portlet,
0638: Context context, RunData data, SessionState state) {
0639: // we might be on the way to a permissions...
0640: if (state.getAttribute(STATE_PERMISSIONS) != null) {
0641: state.removeAttribute(STATE_PERMISSIONS);
0642: doPermissionsNow(data, context);
0643: }
0644:
0645: boolean allowNewTopic = false;
0646: boolean allowNewCategory = false;
0647: boolean hasPrevious = false;
0648: boolean hasNext = false;
0649:
0650: String channelId = (String) state
0651: .getAttribute(STATE_CHANNEL_REF);
0652:
0653: try {
0654: // get the current channel ID from state object
0655: DiscussionChannel channel = DiscussionService
0656: .getDiscussionChannel(channelId);
0657:
0658: String currentId = null;
0659: DisplayMessage dMessage = (DisplayMessage) state
0660: .getAttribute(STATE_DISPLAY_MESSAGE);
0661: if (dMessage != null) {
0662: currentId = dMessage.getId();
0663: }
0664: if (currentId != null && !currentId.equals("")) {
0665: DiscussionMessage message = channel
0666: .getDiscussionMessageNoException(currentId);
0667: if (message != null) {
0668: String category = message.getDiscussionHeader()
0669: .getCategory();
0670: Vector messageIds = new Vector();
0671: if (((Hashtable) state
0672: .getAttribute(STATE_CATEGORIES_SHOW_LIST))
0673: .get(category) != null) {
0674: messageIds = (Vector) ((Hashtable) state
0675: .getAttribute(STATE_CATEGORIES_SHOW_LIST))
0676: .get(category);
0677: }
0678: hasPrevious = (messageIds.indexOf(currentId) == 0) ? false
0679: : true;
0680: hasNext = ((messageIds.indexOf(currentId) == messageIds
0681: .size() - 1)) ? false : true;
0682: } else {
0683: hasPrevious = false;
0684: hasNext = false;
0685: }
0686: }
0687:
0688: // detect whether channel is existed
0689: if (channel != null) {
0690: allowNewTopic = channel.allowAddTopicMessage();
0691: allowNewCategory = channel.allowAddTopicMessage();
0692: } else {
0693: allowNewTopic = DiscussionService
0694: .allowAddChannel(channelId);
0695: allowNewCategory = DiscussionService
0696: .allowAddChannel(channelId);
0697: }
0698: } catch (IdUnusedException e) {
0699: addAlert(state, rb.getString("cannotfin5"));
0700: } catch (PermissionException e) {
0701: addAlert(state, rb.getString("youdonot1"));
0702: }
0703:
0704: // build menu
0705: Menu bar = new MenuImpl(portlet, data,
0706: "ThreadedDiscussionIIAction");
0707: bar.add(new MenuEntry(rb.getString("newtopic"), null,
0708: allowNewTopic, MenuItem.CHECKED_NA, "doSet_new_topic"));
0709: bar.add(new MenuEntry(rb.getString("newcat"), null,
0710: allowNewCategory, MenuItem.CHECKED_NA,
0711: "doSet_new_category"));
0712:
0713: if (hasPrevious) {
0714: bar.add(new MenuEntry(rb.getString("premess"), null, true,
0715: MenuItem.CHECKED_NA, "doPre_message"));
0716: }
0717: if (hasNext) {
0718: bar.add(new MenuEntry(rb.getString("nexmess"), null, true,
0719: MenuItem.CHECKED_NA, "doNext_message"));
0720: }
0721:
0722: if (!((Boolean) state.getAttribute(STATE_EXPAND_ALL_FLAG))
0723: .booleanValue()) {
0724: bar.add(new MenuEntry(rb.getString("expall"), null, true,
0725: MenuItem.CHECKED_NA, "doExpand_all"));
0726: } else {
0727: bar.add(new MenuEntry(rb.getString("collall"), null, true,
0728: MenuItem.CHECKED_NA, "doCollapse_all"));
0729: }
0730:
0731: // Set menu state attribute
0732: SessionState stateForMenus = ((JetspeedRunData) data)
0733: .getPortletSessionState(portlet.getID());
0734: stateForMenus.setAttribute(MenuItem.STATE_MENU, bar);
0735:
0736: // add permissions, if allowed
0737: if (SiteService.allowUpdateSite(ToolManager
0738: .getCurrentPlacement().getContext())) {
0739: bar.add(new MenuEntry(rb.getString("permis"),
0740: "doPermissions"));
0741: }
0742:
0743: context.put(Menu.CONTEXT_MENU, bar);
0744: context.put(Menu.CONTEXT_ACTION, state
0745: .getAttribute(STATE_ACTION));
0746:
0747: /* Added this array to load the combo box options */
0748: String[] comoptions = { rb.getString("rowlay"),
0749: rb.getString("collay") };
0750: context.put("ord", comoptions);
0751:
0752: context.put("tlang", rb);
0753: add2ndToolbarFields(data, context);
0754:
0755: return null;
0756:
0757: } // buildToolbarPanelContext
0758:
0759: /**
0760: * build the context for the List panel
0761: *
0762: * @return (optional) template name for this panel
0763: */
0764: public String buildListPanelContext(VelocityPortlet portlet,
0765: Context context, RunData rundata, SessionState state) {
0766: context.put("tlang", rb);
0767:
0768: String search = (String) state.getAttribute(STATE_SEARCH);
0769: if (search == null || search.equals("")) {
0770: context.put("searching", Boolean.FALSE);
0771: } else {
0772: context.put("searching", Boolean.TRUE);
0773: }
0774:
0775: String channelId = (String) state
0776: .getAttribute(STATE_CHANNEL_REF);
0777:
0778: // the sorting defaults for the outline view
0779: String sortedBy = "";
0780: String sortedAsc = (String) state
0781: .getAttribute(STATE_SORTED_ASC);
0782:
0783: // set default sort attribute
0784: sortedBy = (String) state.getAttribute(STATE_SORTED_BY);
0785: if ((!sortedBy.equals(STATE_SORTED_BY_TOPIC))
0786: && (!sortedBy.equals(STATE_SORTED_BY_AUTHOR))
0787: && (!sortedBy.equals(STATE_SORTED_BY_DATE))) {
0788: sortedBy = STATE_SORTED_BY_DATE;
0789: state.setAttribute(STATE_SORTED_BY, sortedBy);
0790: }
0791: context.put("currentSortedBy", sortedBy);
0792: context.put("currentSortAsc", sortedAsc);
0793:
0794: boolean allowNewTopic = false;
0795: boolean allowRemoveCategory = false;
0796: try {
0797: // get the current channel ID from state object
0798: DiscussionChannel channel = DiscussionService
0799: .getDiscussionChannel(channelId);
0800:
0801: // detect whether channel is existed
0802: if (channel != null) {
0803: allowNewTopic = channel.allowAddTopicMessage();
0804: allowRemoveCategory = channel.allowRemoveCategory();
0805: context.put("channel", channel);
0806:
0807: // get the sorted categories Vector according to the current sorting criteria
0808: List categories = sortedCategories(channel, sortedBy,
0809: sortedAsc);
0810: if (categories != null) {
0811: context.put("categories", categories);
0812: }
0813:
0814: // provide the expanded category list
0815: HashSet expandedCategories = (HashSet) state
0816: .getAttribute(STATE_EXPAND_CATEGORY_LIST);
0817: context.put("expandedCategoryList", expandedCategories);
0818:
0819: if (categories != null) {
0820: for (Iterator i = categories.iterator(); i
0821: .hasNext();) {
0822: String currentCategory = (String) i.next();
0823:
0824: // the category is expanded; get the most recent topics
0825: if (expandedCategories
0826: .contains(currentCategory)) {
0827: Hashtable showList = (Hashtable) state
0828: .getAttribute(STATE_CATEGORIES_SHOW_LIST);
0829: Vector v = (Vector) showList
0830: .get(currentCategory);
0831: if (v == null)
0832: v = new Vector();
0833: Iterator topics = channel
0834: .getTopics(currentCategory);
0835: while (topics.hasNext()) {
0836: DiscussionMessage topic = (DiscussionMessage) topics
0837: .next();
0838: // the topic is newly added, add the topic
0839: if (!v.contains(topic.getId())) {
0840: int index = 0;
0841: // the replied to message has already been expanded
0842: if (topic.getDiscussionHeader()
0843: .getDraft()) {
0844: try {
0845: // filter out drafts not by this user (unless this user is a super user) %%% not sure I like this -zqian
0846: channel
0847: .getDiscussionMessage(topic
0848: .getId());
0849:
0850: // if the new message is a draft message, add to the bottom of drafts
0851: int firstNondraftIndex = -1;
0852: for (int j = 0; (j < v
0853: .size() && firstNondraftIndex == -1); j++) {
0854: DiscussionMessage next = (DiscussionMessage) channel
0855: .getDiscussionMessage((String) v
0856: .get(j));
0857: index = index + 1;
0858: if (!next
0859: .getDiscussionHeader()
0860: .getDraft()) {
0861: firstNondraftIndex = index;
0862: }
0863: }
0864: if (firstNondraftIndex == -1) {
0865: v.add(topic.getId());
0866: } else {
0867: v
0868: .add(
0869: firstNondraftIndex,
0870: topic
0871: .getId());
0872: }
0873: } catch (PermissionException e) {
0874: } catch (IdUnusedException e) {
0875: }
0876: } else {
0877: // add it to the end
0878: v.add(topic.getId());
0879: } // if-else
0880:
0881: }
0882: }
0883:
0884: // check for the expanded message's responses
0885: Hashtable t = (Hashtable) state
0886: .getAttribute(STATE_EXPAND_MESSAGE_LIST);
0887: HashSet s = (HashSet) t
0888: .get(currentCategory);
0889: if (s != null) {
0890: Iterator expandMessageInCategory = ((HashSet) t
0891: .get(currentCategory))
0892: .iterator();
0893: while (expandMessageInCategory
0894: .hasNext()) {
0895: DiscussionMessage nextMessage = (DiscussionMessage) expandMessageInCategory
0896: .next();
0897: Iterator repliesToNextMessage = nextMessage
0898: .getReplies();
0899: // only test for the direct response
0900: int depth = nextMessage
0901: .getReplyToDepth() + 1;
0902: while (repliesToNextMessage
0903: .hasNext()) {
0904: DiscussionMessage testReply = (DiscussionMessage) repliesToNextMessage
0905: .next();
0906: if ((testReply
0907: .getReplyToDepth() == depth)
0908: && (!v
0909: .contains(testReply
0910: .getId()))) {
0911: int index = v
0912: .indexOf(nextMessage
0913: .getId());
0914: // the replied to message has already been expanded
0915: if (testReply
0916: .getDiscussionHeader()
0917: .getDraft()) {
0918: try {
0919: // filter out drafts not by this user (unless this user is a super user) %%% not sure I like this -zqian
0920: channel
0921: .getDiscussionMessage(testReply
0922: .getId());
0923:
0924: // if the new message is a draft message, add to the bottom of drafts
0925: int firstNondraftIndex = -1;
0926: int k = index;
0927: while (k < v.size()
0928: && (firstNondraftIndex == -1)) {
0929: DiscussionMessage next = (DiscussionMessage) channel
0930: .getDiscussionMessage((String) v
0931: .get(k));
0932: index = index + 1;
0933: if (!next
0934: .getDiscussionHeader()
0935: .getDraft()) {
0936: firstNondraftIndex = index;
0937: }
0938: k++;
0939: }
0940: v
0941: .add(
0942: firstNondraftIndex,
0943: testReply
0944: .getId());
0945: } catch (PermissionException e) {
0946: } catch (IdUnusedException e) {
0947: }
0948:
0949: } else {
0950: // if the new message is not a draft message, add to the bottom of non-drafts
0951: index = v
0952: .indexOf(nextMessage
0953: .getId()) + 1;
0954: String id = nextMessage
0955: .getId();
0956: String replyToId = id;
0957: while (replyToId
0958: .equals(id)
0959: && index < v
0960: .size()) {
0961: DiscussionMessage m = (DiscussionMessage) channel
0962: .getDiscussionMessage((String) v
0963: .get(index));
0964: String newId = m
0965: .getDiscussionHeader()
0966: .getReplyTo();
0967: if (!newId
0968: .equals(id)) {
0969: replyToId = newId;
0970: } else {
0971: index++;
0972: }
0973: }
0974: v.add(index, testReply
0975: .getId());
0976: } // if-else: draft vs. non draft
0977: } // if: the message is not contained in the show list
0978: } // while: check for all response to the message
0979: } // while: check for all opened message
0980: } // if: there is expanded message
0981:
0982: // update the show list in that category
0983: showList.put(currentCategory, v);
0984:
0985: state.setAttribute(
0986: STATE_CATEGORIES_SHOW_LIST,
0987: showList);
0988: } // if: for every opened category
0989: } // for: for all categories
0990: } // if: categories not null
0991:
0992: Vector searchResultList = new Vector();
0993: if (state.getAttribute(STATE_SEARCH_RESULT) != null) {
0994: searchResultList = (Vector) state
0995: .getAttribute(STATE_SEARCH_RESULT);
0996: if (searchResultList.size() > 0) {
0997: // if the current message is not in result list, make the current message to be the first one of search result
0998: state.setAttribute(STATE_DISPLAY_MESSAGE,
0999: new DisplayMessage(
1000: (String) searchResultList
1001: .get(0)));
1002: state.removeAttribute(STATE_SEARCH_REFRESH);
1003: }
1004: context.put("searchResultList", searchResultList);
1005: }
1006:
1007: // provide the category show list
1008: context.put("categoriesShowList", state
1009: .getAttribute(STATE_CATEGORIES_SHOW_LIST));
1010: // the topics has been expanded for outline
1011: context.put("expandAllTopics", state
1012: .getAttribute(STATE_EXPAND_ALL_TOPIC_FLAG));
1013: // provide the expanded message list
1014: context.put("expandedMessageList", state
1015: .getAttribute(STATE_EXPAND_MESSAGE_LIST));
1016: } else {
1017: allowNewTopic = DiscussionService
1018: .allowAddChannel(channelId);
1019: }
1020:
1021: if (state.getAttribute(STATE_DISPLAY_MESSAGE) != null) {
1022: DisplayMessage d = (DisplayMessage) state
1023: .getAttribute(STATE_DISPLAY_MESSAGE);
1024: try {
1025: channel.getDiscussionMessage(d.getId());
1026: context.put("currentMessage", state
1027: .getAttribute(STATE_DISPLAY_MESSAGE));
1028: } catch (Exception e) {
1029: // current displayed message no longer exist, refresh the control pannel
1030: state.removeAttribute(STATE_DISPLAY_MESSAGE);
1031: String peid = ((JetspeedRunData) rundata)
1032: .getJs_peid();
1033: schedulePeerFrameRefresh(VelocityPortletPaneledAction
1034: .mainPanelUpdateId(peid)
1035: + "." + CONTROL_PANEL);
1036: }
1037: }
1038:
1039: // inform the observing courier that we just updated the page...
1040: // if there are pending requests to do so they can be cleared
1041: justDelivered(state);
1042: } catch (IdUnusedException e) {
1043: addAlert(state, rb.getString("cannotfin5"));
1044: } catch (PermissionException e) {
1045: addAlert(state, rb.getString("youdonot2"));
1046: }
1047:
1048: context.put("allowEditChannel", new Boolean(DiscussionService
1049: .allowEditChannel(channelId)));
1050: context
1051: .put("action", (String) state
1052: .getAttribute(STATE_ACTION));
1053: context.put("service", DiscussionService.getInstance());
1054: context.put("contentTypeImageService", state
1055: .getAttribute(STATE_CONTENT_TYPE_IMAGE_SERVICE));
1056:
1057: context.put("allow_new_topic", new Boolean(allowNewTopic));
1058: context.put("allow_new_category", new Boolean(allowNewTopic));
1059: context.put("allow_remove_category", new Boolean(
1060: allowRemoveCategory));
1061:
1062: context.put("panel-control", CONTROL_PANEL);
1063: context.put("panel-monitor", MONITOR_PANEL);
1064: context.put("panel-target", MONITOR_PANEL);
1065: context.put("updated", (String) state
1066: .getAttribute(STATE_LIST_PANNEL_UPDATED));
1067: state.setAttribute(STATE_LIST_PANNEL_UPDATED, "false");
1068:
1069: context.put("visitedMessages", state
1070: .getAttribute(VISITED_MESSAGES));
1071:
1072: if (state.getAttribute(DELETE_WARNING) != null) {
1073: addAlert(state, (String) state.getAttribute(DELETE_WARNING));
1074: state.removeAttribute(DELETE_WARNING);
1075: }
1076:
1077: return null;
1078:
1079: } // buildListPanelContext
1080:
1081: /**
1082: * build the context for the Control panel (has a send field)
1083: *
1084: * @return (optional) template name for this panel
1085: */
1086: public String buildControlPanelContext(VelocityPortlet portlet,
1087: Context context, RunData rundata, SessionState state) {
1088: // we might be on the way to attachments...
1089: if (state.getAttribute(GO_ATTACHMENTS) != null) {
1090: state.removeAttribute(GO_ATTACHMENTS);
1091: doAttachmentsNow(rundata, context);
1092: }
1093:
1094: context.put("tlang", rb);
1095: String channelId = (String) state
1096: .getAttribute(STATE_CHANNEL_REF);
1097: DiscussionChannel channel = null;
1098: try {
1099: channel = DiscussionService.getDiscussionChannel(channelId);
1100:
1101: // possible error message
1102: String error = (String) state.getAttribute(STATE_ERROR);
1103: if (error != null) {
1104: context.put("message", error);
1105: }
1106:
1107: // is this user going to be able to post?
1108: boolean allowed = false;
1109:
1110: // if no channel, we can check the user's allow add discussion Channel(channelId)
1111: if (channel != null) {
1112: allowed = channel.allowAddMessage();
1113: } else {
1114: allowed = DiscussionService.allowAddChannel(channelId);
1115: }
1116: if (!allowed) {
1117: context.put("message", rb.getString("youdonot5")); // %%% or no message?
1118: }
1119: context.put("allow-send", new Boolean(allowed));
1120:
1121: DisplayMessage dMessage = (DisplayMessage) state
1122: .getAttribute(STATE_DISPLAY_MESSAGE);
1123: if (dMessage != null) {
1124: String mId = dMessage.getId();
1125: if (!mId.equals("")) {
1126: try {
1127: DiscussionMessage m = channel
1128: .getDiscussionMessage(mId);
1129: context.put("currentMessage", m);
1130:
1131: DiscussionMessageHeader mHeader = m
1132: .getDiscussionHeader();
1133: String replyTo = (String) state
1134: .getAttribute(RESPOND_REPLY_TO);
1135: if (state.getAttribute(ATTACHMENTS) == null) {
1136: state.setAttribute(ATTACHMENTS, mHeader
1137: .getAttachments());
1138: }
1139: context.put("attachments", state
1140: .getAttribute(ATTACHMENTS));
1141: if (mHeader.getDraft()) {
1142: // a draft message
1143: context
1144: .put(
1145: "draftCategory",
1146: state
1147: .getAttribute(DRAFT_MESSAGE_CATEGORY) != null ? state
1148: .getAttribute(DRAFT_MESSAGE_CATEGORY)
1149: : mHeader
1150: .getCategory());
1151: context
1152: .put(
1153: "draftBody",
1154: state
1155: .getAttribute(DRAFT_MESSAGE_BODY) != null ? state
1156: .getAttribute(DRAFT_MESSAGE_BODY)
1157: : m.getBody());
1158: context
1159: .put(
1160: "draftSubject",
1161: state
1162: .getAttribute(DRAFT_MESSAGE_SUBJECT) != null ? state
1163: .getAttribute(DRAFT_MESSAGE_SUBJECT)
1164: : mHeader
1165: .getSubject());
1166: if (m.getReplyToDepth() == 0) {
1167: String style = (String) state
1168: .getAttribute(DRAFT_MESSAGE_REPLY_STYLE);
1169: if (style == null) {
1170: style = "thread";
1171: }
1172: context.put("draftStyle", style);
1173: }
1174: } else {
1175: // respond to posted message
1176: if (replyTo == null) {
1177: replyTo = "totopic";
1178: }
1179: context.put("replyto", replyTo);
1180: context.put("subject", state
1181: .getAttribute(RESPOND_SUBJECT));
1182: context.put("body", state
1183: .getAttribute(RESPOND_BODY));
1184: }
1185:
1186: DiscussionMessage topic = m;
1187: StringBuffer messagePath = new StringBuffer(
1188: Validator.escapeHtml(m
1189: .getDiscussionHeader()
1190: .getSubject()));
1191: while (topic.getReplyToDepth() != 0) {
1192: replyTo = topic.getDiscussionHeader()
1193: .getReplyTo();
1194: topic = channel
1195: .getDiscussionMessage(replyTo);
1196: messagePath.insert(0, Validator
1197: .escapeHtml(topic
1198: .getDiscussionHeader()
1199: .getSubject()
1200: + " > "));
1201: }
1202: messagePath.insert(0, Validator
1203: .escapeHtml(topic.getDiscussionHeader()
1204: .getCategory()
1205: + " > "));
1206: context.put("messagePath", messagePath
1207: .toString());
1208: context.put("topic", topic);
1209: context
1210: .put(
1211: "style",
1212: topic
1213: .getProperties()
1214: .getProperty(
1215: ResourceProperties.PROP_REPLY_STYLE));
1216: } catch (Exception e) {
1217: } // try - catch
1218: } // if - else
1219: } // based on the DisplayMessage type
1220: context.put("channel", channel);
1221: } catch (IdUnusedException e) {
1222: addAlert(state, rb.getString("cannotfin5"));
1223: } catch (PermissionException e) {
1224: addAlert(state, rb.getString("youdonot1"));
1225: }
1226:
1227: context.put("panel-target", CONTROL_PANEL);
1228:
1229: // put this pannel's name for the return url
1230: context.put("panel-control", CONTROL_PANEL);
1231:
1232: // set the action for form processing
1233: context.put(Menu.CONTEXT_ACTION, state
1234: .getAttribute(STATE_ACTION));
1235:
1236: // set the form field name for the send button
1237: context.put("form-submit", BUTTON + "doSend");
1238:
1239: // set the form field name for the send button
1240: context.put("form-message", FORM_MESSAGE);
1241:
1242: context.put("date", TimeService.newTime());
1243: context.put("contentTypeImageService", state
1244: .getAttribute(STATE_CONTENT_TYPE_IMAGE_SERVICE));
1245:
1246: context
1247: .put("action", (String) state
1248: .getAttribute(STATE_ACTION));
1249:
1250: return null;
1251:
1252: } // buildControlPanelContext
1253:
1254: /**
1255: * build the context for showing topic content (has a send field)
1256: *
1257: * @return (optional) template name for this panel
1258: */
1259: public String buildContentContext(VelocityPortlet portlet,
1260: Context context, RunData rundata, SessionState state) {
1261: String topicId = (String) state
1262: .getAttribute(STATE_SHOW_CONTENT_TOPIC_ID);
1263: context.put("tlang", rb);
1264: try {
1265: DiscussionChannel channel = DiscussionService
1266: .getDiscussionChannel((String) state
1267: .getAttribute(STATE_CHANNEL_REF));
1268: DiscussionMessage msg = channel
1269: .getDiscussionMessage(topicId);
1270:
1271: context.put("topic", msg);
1272: context.put("channel", channel);
1273:
1274: String cat = msg.getDiscussionHeader().getCategory();
1275: List topicMsgIds = channel.getTopicMsgIds(cat);
1276: for (int i = 0; i < topicMsgIds.size(); i++) {
1277: if (topicMsgIds.get(i).equals(topicId)) {
1278: boolean goPT = false;
1279: boolean goNT = false;
1280: if ((i - 1) >= 0) {
1281: goPT = true;
1282: }
1283: if ((i + 1) < topicMsgIds.size()) {
1284: goNT = true;
1285: }
1286: context.put("goPTButton", new Boolean(goPT));
1287: context.put("goNTButton", new Boolean(goNT));
1288: }
1289: }
1290: } catch (IdUnusedException e) {
1291: addAlert(state, rb.getString("cannotfin1"));
1292: } catch (PermissionException e) {
1293: addAlert(state, rb.getString("yodonot2"));
1294: }
1295:
1296: context
1297: .put("action", (String) state
1298: .getAttribute(STATE_ACTION));
1299: context.put("contentTypeImageService", state
1300: .getAttribute(STATE_CONTENT_TYPE_IMAGE_SERVICE));
1301: return (String) getContext(rundata).get("template")
1302: + "-topic_content";
1303:
1304: } // buildContentContext
1305:
1306: /**
1307: * Responding to the request of going to next topic within the current category
1308: */
1309: public void doNext_topic_content(RunData data, Context context) {
1310: SessionState state = ((JetspeedRunData) data)
1311: .getPortletSessionState(((JetspeedRunData) data)
1312: .getJs_peid());
1313:
1314: String topicId = (String) state
1315: .getAttribute(STATE_SHOW_CONTENT_TOPIC_ID);
1316:
1317: try {
1318: DiscussionChannel channel = DiscussionService
1319: .getDiscussionChannel((String) state
1320: .getAttribute(STATE_CHANNEL_REF));
1321: DiscussionMessage msg = channel
1322: .getDiscussionMessage(topicId);
1323: String cat = msg.getDiscussionHeader().getCategory();
1324: List topicMsgIds = channel.getTopicMsgIds(cat);
1325: int index = topicMsgIds.indexOf(topicId);
1326: if ((index != -1) && ((index + 1) < topicMsgIds.size())) {
1327: String prevId = (String) (topicMsgIds.get(index + 1));
1328: state.setAttribute(STATE_SHOW_CONTENT_TOPIC_ID, prevId);
1329: }
1330: } catch (IdUnusedException e) {
1331: addAlert(state, rb.getString("cannotfin1"));
1332: } catch (PermissionException e) {
1333: addAlert(state, rb.getString("yodonot2"));
1334: }
1335:
1336: state.setAttribute(STATE_MODE, MODE_SHOW_TOPIC_CONTENT);
1337:
1338: String peid = ((JetspeedRunData) data).getJs_peid();
1339: schedulePeerFrameRefresh(VelocityPortletPaneledAction
1340: .mainPanelUpdateId(peid));
1341:
1342: } // doNext_topic_content
1343:
1344: /**
1345: * Responding to the request of going to previous topic within the current category
1346: */
1347: public void doPrev_topic_content(RunData data, Context context) {
1348: SessionState state = ((JetspeedRunData) data)
1349: .getPortletSessionState(((JetspeedRunData) data)
1350: .getJs_peid());
1351:
1352: String topicId = (String) state
1353: .getAttribute(STATE_SHOW_CONTENT_TOPIC_ID);
1354:
1355: try {
1356: DiscussionChannel channel = DiscussionService
1357: .getDiscussionChannel((String) state
1358: .getAttribute(STATE_CHANNEL_REF));
1359: DiscussionMessage msg = channel
1360: .getDiscussionMessage(topicId);
1361: String cat = msg.getDiscussionHeader().getCategory();
1362: List topicMsgIds = channel.getTopicMsgIds(cat);
1363: int index = topicMsgIds.indexOf(topicId);
1364: if ((index != -1) && ((index - 1) >= 0)) {
1365: String prevId = (String) (topicMsgIds.get(index - 1));
1366: state.setAttribute(STATE_SHOW_CONTENT_TOPIC_ID, prevId);
1367: }
1368: } catch (IdUnusedException e) {
1369: addAlert(state, rb.getString("cannotfin1"));
1370: } catch (PermissionException e) {
1371: addAlert(state, rb.getString("yodonot2"));
1372: }
1373:
1374: state.setAttribute(STATE_MODE, MODE_SHOW_TOPIC_CONTENT);
1375:
1376: String peid = ((JetspeedRunData) data).getJs_peid();
1377: schedulePeerFrameRefresh(VelocityPortletPaneledAction
1378: .mainPanelUpdateId(peid));
1379:
1380: } // doPrev_topic_content
1381:
1382: /**
1383: * build the context for creating new topic (has a send field)
1384: *
1385: * @return (optional) template name for this panel
1386: */
1387: public String buildNewTopicContext(VelocityPortlet portlet,
1388: Context context, RunData rundata, SessionState state) {
1389: // we might be on the way to attachments...
1390: if (state.getAttribute(GO_ATTACHMENTS) != null) {
1391: state.removeAttribute(GO_ATTACHMENTS);
1392: doAttachmentsNow(rundata, context);
1393: }
1394:
1395: String channelId = (String) state
1396: .getAttribute(STATE_CHANNEL_REF);
1397: context.put("tlang", rb);
1398: try {
1399: DiscussionChannel channel = DiscussionService
1400: .getDiscussionChannel(channelId);
1401: context.put("categories", sortedCategories(channel,
1402: STATE_SORTED_BY_CATEGORY_ALPHA, Boolean.TRUE
1403: .toString()));
1404: context.put("date", TimeService.newTime());
1405: context.put("category", state
1406: .getAttribute(NEW_TOPIC_CATEGORY));
1407: context.put("newcategory", state
1408: .getAttribute(NEW_TOPIC_NEW_CATEGORY));
1409: context.put("newtopicbody", state
1410: .getAttribute(NEW_TOPIC_BODY));
1411: context.put("newtopicsubject", state
1412: .getAttribute(NEW_TOPIC_SUBJECT));
1413: context.put("newtopicreplystyle", state
1414: .getAttribute(NEW_TOPIC_REPLY_STYLE));
1415: context.put("contentTypeImageService", state
1416: .getAttribute(STATE_CONTENT_TYPE_IMAGE_SERVICE));
1417: context.put("action", (String) state
1418: .getAttribute(STATE_ACTION));
1419: context.put("attachments", state.getAttribute(ATTACHMENTS));
1420:
1421: // is user allowed to save drats
1422: context.put("allowSaveDraft", Boolean.valueOf(channel
1423: .allowAddDraftMessage()));
1424:
1425: return (String) getContext(rundata).get("template")
1426: + "-Newtopic";
1427: } catch (IdUnusedException e) {
1428: addAlert(state, rb.getString("cannotfin5"));
1429: } catch (PermissionException e) {
1430: addAlert(state, rb.getString("youarenot4"));
1431: }
1432:
1433: return (String) getContext(rundata).get("template") + "-Layout";
1434:
1435: } // buildNewTopicContext
1436:
1437: /**
1438: * build the context for creating new category (has a send field)
1439: *
1440: * @return (optional) template name for this panel
1441: */
1442: public String buildNewCategoryContext(VelocityPortlet portlet,
1443: Context context, RunData rundata, SessionState state) {
1444: String channelId = (String) state
1445: .getAttribute(STATE_CHANNEL_REF);
1446: context.put("tlang", rb);
1447:
1448: try {
1449: DiscussionChannel channel = DiscussionService
1450: .getDiscussionChannel(channelId);
1451: context.put("categories", sortedCategories(channel,
1452: STATE_SORTED_BY_CATEGORY_ALPHA, Boolean.TRUE
1453: .toString()));
1454: context.put("contentTypeImageService", state
1455: .getAttribute(STATE_CONTENT_TYPE_IMAGE_SERVICE));
1456: context.put("action", (String) state
1457: .getAttribute(STATE_ACTION));
1458: if (state.getAttribute(NEW_CATEGORY) != null) {
1459: context.put("newcategory", state
1460: .getAttribute(NEW_CATEGORY));
1461: }
1462: return (String) getContext(rundata).get("template")
1463: + "-Newcategory";
1464: } catch (IdUnusedException e) {
1465: addAlert(state, rb.getString("cannotfin5"));
1466: } catch (PermissionException e) {
1467: addAlert(state, rb.getString("youarenot4"));
1468: }
1469:
1470: return (String) getContext(rundata).get("template") + "-Layout";
1471:
1472: } // buildNewCategoryContext
1473:
1474: /**
1475: * build the context for confirming the delete of message (has a send field)
1476: *
1477: * @return (optional) template name for this panel
1478: */
1479: public String buildDeleteMessageConfirmContext(
1480: VelocityPortlet portlet, Context context, RunData rundata,
1481: SessionState state) {
1482: String channelId = (String) state
1483: .getAttribute(STATE_CHANNEL_REF);
1484: context.put("tlang", rb);
1485: try {
1486: DiscussionChannel channel = DiscussionService
1487: .getDiscussionChannel(channelId);
1488: DiscussionMessage message = channel
1489: .getDiscussionMessage((String) state
1490: .getAttribute(DELETE_MESSAGE_ID));
1491: context.put("message", message);
1492: context.put("delete_messages", channel.getThread(message));
1493:
1494: // can the user delete all the messages in the thread?
1495: Iterator i = channel.getThread(message);
1496: boolean allowRemove = true;
1497: while (i.hasNext() && allowRemove) {
1498: allowRemove = channel
1499: .allowRemoveMessage((DiscussionMessage) i
1500: .next());
1501: }
1502: context.put("allowRemove", Boolean.valueOf(allowRemove));
1503:
1504: return (String) getContext(rundata).get("template")
1505: + "-DeleteTopicConfirm";
1506: } catch (IdUnusedException e) {
1507: addAlert(state, rb.getString("cannotfin5"));
1508: } catch (PermissionException e) {
1509: addAlert(state, rb.getString("youarenot1"));
1510: }
1511:
1512: return (String) getContext(rundata).get("template") + "-Layout";
1513:
1514: } // buildDeleteMessageConfirmContext
1515:
1516: /**
1517: * build the context for confirming the delete of category (has a send field)
1518: *
1519: * @return (optional) template name for this panel
1520: */
1521: public String buildDeleteCategoryConfirmContext(
1522: VelocityPortlet portlet, Context context, RunData rundata,
1523: SessionState state) {
1524:
1525: String category = (String) state.getAttribute(DELETE_CATEGORY);
1526: context.put("tlang", rb);
1527: context.put("category", category);
1528:
1529: // get all the messages within the category, that will be deleted
1530: try {
1531: DiscussionChannel channel = (DiscussionChannel) DiscussionService
1532: .getChannel((String) state
1533: .getAttribute(STATE_CHANNEL_REF));
1534: Iterator messages = channel.getThreads(category);
1535: context.put("delete_messages", messages);
1536: } catch (IdUnusedException e) {
1537: addAlert(state, rb.getString("cannotfin5"));
1538: return (String) getContext(rundata).get("template");
1539: } catch (PermissionException e) {
1540: addAlert(state, rb.getString("youarenot2"));
1541: return (String) getContext(rundata).get("template");
1542: }
1543:
1544: return (String) getContext(rundata).get("template")
1545: + "-DeleteCategoryConfirm";
1546:
1547: } // buildDeleteCategoryConfirmContext
1548:
1549: /**
1550: * build the context for the reply form (has a send field)
1551: *
1552: * @return (optional) template name for this panel
1553: */
1554: public String buildReplyContext(VelocityPortlet portlet,
1555: Context context, RunData rundata, SessionState state) {
1556: // we might be on the way to attachments...
1557: if (state.getAttribute(GO_ATTACHMENTS) != null) {
1558: state.removeAttribute(GO_ATTACHMENTS);
1559: doAttachmentsNow(rundata, context);
1560: }
1561:
1562: String replyToMessageId = (String) state
1563: .getAttribute(RESPOND_REPLY_TO);
1564: String channelId = (String) state
1565: .getAttribute(STATE_CHANNEL_REF);
1566: context.put("tlang", rb);
1567: try {
1568: DiscussionChannel channel = DiscussionService
1569: .getDiscussionChannel(channelId);
1570:
1571: // is user allowed to save drats
1572: context.put("allowSaveDraft", Boolean.valueOf(channel
1573: .allowAddDraftMessage()));
1574:
1575: try {
1576: DiscussionMessage m = channel
1577: .getDiscussionMessage(replyToMessageId);
1578: context.put("currentMessage", m);
1579:
1580: context.put("subject", state
1581: .getAttribute(RESPOND_SUBJECT));
1582: context.put("body", state.getAttribute(RESPOND_BODY));
1583:
1584: DiscussionMessage topic = m;
1585: String replyTo = "";
1586: StringBuffer replyPath = new StringBuffer(Validator
1587: .escapeHtml(m.getDiscussionHeader()
1588: .getSubject()));
1589: while (topic.getReplyToDepth() != 0) {
1590: replyTo = topic.getDiscussionHeader().getReplyTo();
1591: topic = channel.getDiscussionMessage(replyTo);
1592: replyPath.insert(0, Validator.escapeHtml(topic
1593: .getDiscussionHeader().getSubject()
1594: + " > "));
1595: }
1596: replyPath.insert(0, Validator.escapeHtml(topic
1597: .getDiscussionHeader().getCategory()
1598: + " > "));
1599: context.put("replyPath", replyPath.toString());
1600: context.put("topic", topic);
1601: } catch (IdUnusedException e) {
1602: addAlert(state, rb.getString("cannotfin2"));
1603: } catch (PermissionException e) {
1604: addAlert(state, rb.getString("youarenot3"));
1605: }
1606: } catch (IdUnusedException e) {
1607: addAlert(state, rb.getString("cannotfin5"));
1608: } catch (PermissionException e) {
1609: addAlert(state, rb.getString("youarenot4"));
1610: }
1611:
1612: context.put("contentTypeImageService", state
1613: .getAttribute(STATE_CONTENT_TYPE_IMAGE_SERVICE));
1614: context.put("attachments", state.getAttribute(ATTACHMENTS));
1615: context
1616: .put("action", (String) state
1617: .getAttribute(STATE_ACTION));
1618:
1619: context.put("realDate", TimeService.newTime());
1620:
1621: return (String) getContext(rundata).get("template") + "-Reply";
1622:
1623: } // buildReplyContext
1624:
1625: /**
1626: * build the context for the reply preview (has a send field)
1627: *
1628: * @return (optional) template name for this panel
1629: */
1630: public String buildReplyPreviewContext(VelocityPortlet portlet,
1631: Context context, RunData rundata, SessionState state) {
1632: String replyToId = (String) state
1633: .getAttribute(RESPOND_REPLY_TO);
1634:
1635: String channelId = (String) state
1636: .getAttribute(STATE_CHANNEL_REF);
1637: context.put("tlang", rb);
1638: try {
1639: DiscussionChannel channel = DiscussionService
1640: .getDiscussionChannel(channelId);
1641:
1642: // is user allowed to save drats
1643: context.put("allowSaveDraft", Boolean.valueOf(channel
1644: .allowAddDraftMessage()));
1645:
1646: try {
1647: DiscussionMessage m = channel
1648: .getDiscussionMessage(replyToId);
1649: context.put("currentMessage", m);
1650:
1651: DiscussionMessage topic = m;
1652: String replyTo = "";
1653: while (topic.getReplyToDepth() != 0) {
1654: replyTo = topic.getDiscussionHeader().getReplyTo();
1655: topic = channel.getDiscussionMessage(replyTo);
1656: }
1657: context.put("topic", topic);
1658: } catch (IdUnusedException e) {
1659: addAlert(state, rb.getString("cannotfin2"));
1660: } catch (PermissionException e) {
1661: addAlert(state, rb.getString("youarenot3"));
1662: }
1663: } catch (IdUnusedException e) {
1664: addAlert(state, rb.getString("cannotfin5"));
1665: } catch (PermissionException e) {
1666: addAlert(state, rb.getString("youarenot4"));
1667: }
1668:
1669: context.put("subject", state.getAttribute(RESPOND_SUBJECT));
1670: context.put("body", state.getAttribute(RESPOND_BODY));
1671: context.put("attachments", state
1672: .getAttribute(RESPOND_ATTACHMENT));
1673: context.put("contentTypeImageService", state
1674: .getAttribute(STATE_CONTENT_TYPE_IMAGE_SERVICE));
1675:
1676: context
1677: .put("action", (String) state
1678: .getAttribute(STATE_ACTION));
1679: return (String) getContext(rundata).get("template")
1680: + "-Reply_Preview";
1681:
1682: } // buildReplyPreviewContext
1683:
1684: /**
1685: * Post the draft message
1686: */
1687: public void doPost(RunData data, Context context) {
1688: ParameterParser params = data.getParameters();
1689: SessionState state = ((JetspeedRunData) data)
1690: .getPortletSessionState(((JetspeedRunData) data)
1691: .getJs_peid());
1692:
1693: String messageId = params.getString("messageId");
1694: String subject = ((String) params.getString("subject")).trim();
1695: if (subject.length() == 0) {
1696: state.setAttribute(DRAFT_MESSAGE_SUBJECT, "");
1697: addAlert(state, rb.getString("plespe1"));
1698: }
1699: String body = params.getCleanString("body");
1700: body = processFormattedTextFromBrowser(state, body);
1701: state.setAttribute(DRAFT_MESSAGE_BODY, body);
1702:
1703: String style = params.getString("style");
1704: state.setAttribute(DRAFT_MESSAGE_REPLY_STYLE, style);
1705:
1706: if (state.getAttribute(STATE_MESSAGE) == null) {
1707: try {
1708: DiscussionChannel channel = DiscussionService
1709: .getDiscussionChannel((String) state
1710: .getAttribute(STATE_CHANNEL_REF));
1711: DiscussionMessageEdit postMessage = channel
1712: .editDiscussionMessage(messageId);
1713:
1714: postMessage.getDiscussionHeaderEdit().setSubject(
1715: subject);
1716: postMessage.setBody(body);
1717:
1718: // add the reply style property
1719: if (postMessage.getReplyToDepth() == 0) {
1720: ResourcePropertiesEdit pEdit = postMessage
1721: .getPropertiesEdit();
1722: pEdit.addProperty(
1723: ResourceProperties.PROP_REPLY_STYLE, style);
1724: }
1725: postMessage.getDiscussionHeaderEdit().setDraft(false);
1726: postMessage.getDiscussionHeaderEdit()
1727: .replaceAttachments(
1728: (List) state.getAttribute(ATTACHMENTS));
1729:
1730: // update time
1731: postMessage.getDiscussionHeaderEdit().setDate(
1732: TimeService.newTime());
1733:
1734: channel.commitMessage(postMessage);
1735: state.setAttribute(STATE_DISPLAY_MESSAGE,
1736: new DisplayMessage(postMessage.getId()));
1737: } catch (IdUnusedException e) {
1738: addAlert(state, rb.getString("cannotfin5") + " "
1739: + messageId + " " + rb.getString("hasnotbee"));
1740: } catch (PermissionException e) {
1741: addAlert(state, rb.getString("youarenot5") + " "
1742: + rb.getString("posthemes"));
1743: } catch (InUseException e) {
1744: addAlert(state, rb.getString("themess"));
1745: }
1746: }
1747:
1748: if (state.getAttribute(STATE_MESSAGE) == null) {
1749: state.removeAttribute(DRAFT_MESSAGE_CATEGORY);
1750: state.removeAttribute(DRAFT_MESSAGE_SUBJECT);
1751: state.removeAttribute(DRAFT_MESSAGE_BODY);
1752: state.removeAttribute(DRAFT_MESSAGE_REPLY_STYLE);
1753: state.removeAttribute(ATTACHMENTS);
1754:
1755: // update the list panel
1756: String peid = ((JetspeedRunData) data).getJs_peid();
1757: schedulePeerFrameRefresh(VelocityPortletPaneledAction
1758: .mainPanelUpdateId(peid)
1759: + "." + MONITOR_PANEL);
1760:
1761: // post sucessful
1762: } // if-else
1763:
1764: } // doPost
1765:
1766: /**
1767: * Save the draft message
1768: */
1769: public void doSave(RunData data, Context context) {
1770: ParameterParser params = data.getParameters();
1771: SessionState state = ((JetspeedRunData) data)
1772: .getPortletSessionState(((JetspeedRunData) data)
1773: .getJs_peid());
1774: String messageId = params.getString("messageId");
1775: String subject = ((String) params.getString("subject")).trim();
1776: if (subject.length() == 0) {
1777: state.setAttribute(DRAFT_MESSAGE_SUBJECT, "");
1778: addAlert(state, rb.getString("plespe1"));
1779: }
1780: String body = params.getCleanString("body");
1781: body = processFormattedTextFromBrowser(state, body);
1782: state.setAttribute(DRAFT_MESSAGE_BODY, body);
1783:
1784: if (state.getAttribute(STATE_MESSAGE) == null) {
1785: try {
1786: DiscussionChannel channel = DiscussionService
1787: .getDiscussionChannel((String) state
1788: .getAttribute(STATE_CHANNEL_REF));
1789: DiscussionMessageEdit postMessage = channel
1790: .editDiscussionMessage(messageId);
1791:
1792: postMessage.getDiscussionHeaderEdit().setSubject(
1793: subject);
1794: postMessage.setBody(body);
1795:
1796: // add the reply style property
1797: if (postMessage.getReplyToDepth() == 0) {
1798: String style = params.getString("style");
1799: state
1800: .setAttribute(DRAFT_MESSAGE_REPLY_STYLE,
1801: style);
1802: ResourcePropertiesEdit pEdit = postMessage
1803: .getPropertiesEdit();
1804: pEdit.addProperty(
1805: ResourceProperties.PROP_REPLY_STYLE, style);
1806: }
1807: postMessage.getDiscussionHeaderEdit().setDraft(true);
1808: postMessage.getDiscussionHeaderEdit()
1809: .replaceAttachments(
1810: (List) state.getAttribute(ATTACHMENTS));
1811:
1812: // update time
1813: postMessage.getDiscussionHeaderEdit().setDate(
1814: TimeService.newTime());
1815:
1816: channel.commitMessage(postMessage);
1817: state.setAttribute(STATE_DISPLAY_MESSAGE,
1818: new DisplayMessage(postMessage.getId()));
1819: } catch (IdUnusedException e) {
1820: addAlert(state, rb.getString("theid") + " " + messageId
1821: + " " + rb.getString("hasnotbee"));
1822: } catch (PermissionException e) {
1823: addAlert(state, rb.getString("youarenot5") + " "
1824: + rb.getString("viemes"));
1825: } catch (InUseException e) {
1826: addAlert(state, rb.getString("themess"));
1827: }
1828: }
1829:
1830: if (state.getAttribute(STATE_MESSAGE) == null) {
1831: // save successful
1832: state.removeAttribute(ATTACHMENTS);
1833:
1834: // update the list panel
1835: String peid = ((JetspeedRunData) data).getJs_peid();
1836: schedulePeerFrameRefresh(VelocityPortletPaneledAction
1837: .mainPanelUpdateId(peid)
1838: + "." + MONITOR_PANEL);
1839: } // if-else
1840:
1841: } // doSave
1842:
1843: /**
1844: * Start a new category
1845: */
1846: public void doNew_category(RunData data, Context context) {
1847: SessionState state = ((JetspeedRunData) data)
1848: .getPortletSessionState(((JetspeedRunData) data)
1849: .getJs_peid());
1850:
1851: try {
1852: DiscussionChannel channel = DiscussionService
1853: .getDiscussionChannel((String) state
1854: .getAttribute(STATE_CHANNEL_REF));
1855:
1856: ParameterParser params = data.getParameters();
1857: String category = StringUtil.trimToNull((String) params
1858: .getString("newcategory"));
1859:
1860: if (category == null) {
1861: addAlert(state, rb.getString("pleent"));
1862: } else {
1863: state.setAttribute(NEW_CATEGORY, category);
1864:
1865: List categories = channel.getCategories(true);
1866:
1867: if (categories.contains(category)) {
1868: addAlert(state, rb.getString("samcat"));
1869: } else {
1870: try {
1871: // Note: removed code to detect that the category already exists - we just "fail" quietly to add it again -ggolden
1872: addCategory(state, channel, category);
1873:
1874: // clean the input frame
1875: state.removeAttribute(STATE_DISPLAY_MESSAGE);
1876:
1877: // clean the state mode
1878: state.removeAttribute(STATE_MODE);
1879: } catch (InUseException e) {
1880: addAlert(state, rb.getString("someone")
1881: + " channel.");
1882: } catch (PermissionException e) {
1883: addAlert(state, rb.getString("youdonot1"));
1884: }
1885: }
1886: }
1887: } catch (IdUnusedException e) {
1888: addAlert(state, rb.getString("cannotfin5"));
1889: } catch (PermissionException e) {
1890: addAlert(state, rb.getString("youdonot1"));
1891: }
1892: } // doNew_category
1893:
1894: /**
1895: * Start a new topic
1896: */
1897: public void doNew_topic(RunData data, Context context) {
1898: SessionState state = ((JetspeedRunData) data)
1899: .getPortletSessionState(((JetspeedRunData) data)
1900: .getJs_peid());
1901: try {
1902: DiscussionChannel channel = DiscussionService
1903: .getDiscussionChannel((String) state
1904: .getAttribute(STATE_CHANNEL_REF));
1905:
1906: ParameterParser params = data.getParameters();
1907: String subject = ((String) params.getString("subject"))
1908: .trim();
1909: state.setAttribute(NEW_TOPIC_SUBJECT, subject);
1910:
1911: String body = params.getCleanString("body");
1912: body = processFormattedTextFromBrowser(state, body);
1913: state.setAttribute(NEW_TOPIC_BODY, body);
1914:
1915: String style = params.getString("style");
1916: state.setAttribute(NEW_TOPIC_REPLY_STYLE, style);
1917:
1918: boolean newCategory = true;
1919: String category = ((String) params.getString("newcategory"))
1920: .trim();
1921: if (category.length() == 0) {
1922: // no new category input
1923: state.setAttribute(NEW_TOPIC_NEW_CATEGORY, new Boolean(
1924: "false"));
1925: category = params.getString("category") != null ? ((String) params
1926: .getString("category")).trim()
1927: : "";
1928: state.setAttribute(NEW_TOPIC_CATEGORY, category);
1929: if (category.length() == 0) {
1930: // no category specified
1931: addAlert(state, rb.getString("plecho"));
1932: }
1933: newCategory = false;
1934: } else {
1935: // get the new category
1936: state.setAttribute(NEW_TOPIC_NEW_CATEGORY, new Boolean(
1937: "true"));
1938: state.setAttribute(NEW_TOPIC_CATEGORY, category);
1939: // Note: removed the check that the category already exists - we just quietly "fail" to add it again -ggoldne
1940: } // if
1941:
1942: if (state.getAttribute(STATE_MESSAGE) == null) {
1943: try {
1944: // message is a draft?
1945: boolean draft = false;
1946:
1947: String newTopic_option = params
1948: .getString("eventSubmit_doNew_topic");
1949:
1950: if (newTopic_option.equals(rb
1951: .getString("gen.savdra")))// We put this (not code Strings) because they binds with vm
1952: {
1953: draft = true;
1954: } else if (newTopic_option.equals(rb
1955: .getString("gen.pos"))) {
1956: draft = false;
1957: } // if: draft?
1958:
1959: if (subject.length() == 0) {
1960: addAlert(state, rb.getString("plespe2"));
1961: } else {
1962: boolean sameTopic = false;
1963: Iterator l = channel.getTopics(category);
1964: while (l.hasNext()) {
1965: if (subject.equals(((DiscussionMessage) l
1966: .next()).getDiscussionHeader()
1967: .getSubject())) {
1968: addAlert(state, rb.getString("samtop"));
1969: sameTopic = true;
1970: }
1971: }
1972:
1973: if (!sameTopic) {
1974: // add the reply style property
1975: DiscussionMessageEdit addedMessageEdit = channel
1976: .addDiscussionMessage("");
1977: addedMessageEdit.setBody(body);
1978:
1979: DiscussionMessageHeaderEdit hEdit = addedMessageEdit
1980: .getDiscussionHeaderEdit();
1981: hEdit.setCategory(category);
1982: hEdit.setSubject(subject);
1983: hEdit.setDraft(draft);
1984: hEdit.replaceAttachments((List) state
1985: .getAttribute(ATTACHMENTS));
1986:
1987: ResourcePropertiesEdit pEdit = addedMessageEdit
1988: .getPropertiesEdit();
1989: pEdit
1990: .addProperty(
1991: ResourceProperties.PROP_REPLY_STYLE,
1992: style);
1993:
1994: // update time
1995: hEdit.setDate(TimeService.newTime());
1996:
1997: channel.commitMessage(addedMessageEdit);
1998:
1999: // if the category is newly added
2000: if (newCategory) {
2001: try {
2002: addCategory(state, channel,
2003: category);
2004: } catch (InUseException e) {
2005: addAlert(state, rb
2006: .getString("someone")
2007: + " channel.");
2008: } catch (PermissionException e) {
2009: addAlert(state, rb
2010: .getString("youdonot1"));
2011: }
2012: }
2013: setCategoryExpanded(state, category, true,
2014: channel);
2015:
2016: // make it the current message
2017: showMessage(data, addedMessageEdit.getId());
2018: String peid = ((JetspeedRunData) data)
2019: .getJs_peid();
2020: schedulePeerFrameRefresh(VelocityPortletPaneledAction
2021: .mainPanelUpdateId(peid)
2022: + "." + CONTROL_PANEL);
2023: } // if-else
2024: }
2025: } catch (PermissionException e) {
2026: addAlert(state, rb.getString("youarenot5") + " "
2027: + rb.getString("statop"));
2028: }
2029: } // if category has been specified.
2030: } catch (IdUnusedException e) {
2031: addAlert(state, rb.getString("cannotfin5"));
2032: } catch (PermissionException e) {
2033: addAlert(state, rb.getString("youdonot1"));
2034: }
2035:
2036: if (state.getAttribute(STATE_MESSAGE) == null) {
2037: // add new topic sucessful
2038: state.removeAttribute(NEW_TOPIC_NEW_CATEGORY);
2039: state.removeAttribute(NEW_TOPIC_CATEGORY);
2040: state.removeAttribute(NEW_TOPIC_SUBJECT);
2041: state.removeAttribute(NEW_TOPIC_BODY);
2042: state.removeAttribute(NEW_TOPIC_REPLY_STYLE);
2043:
2044: // clean the state mode
2045: state.removeAttribute(STATE_MODE);
2046:
2047: } // if-else
2048:
2049: } // doNew_topic
2050:
2051: /**
2052: * Handle a user posting a respond message
2053: */
2054: public void doRespond(RunData runData, Context context) {
2055: // access the portlet element id to find our state
2056: String peid = ((JetspeedRunData) runData).getJs_peid();
2057: SessionState state = ((JetspeedRunData) runData)
2058: .getPortletSessionState(peid);
2059: ParameterParser params = runData.getParameters();
2060:
2061: // message is a draft?
2062: boolean draft = false;
2063:
2064: String subject = StringUtil.trimToNull((String) params
2065: .getString("subject"));
2066: state.setAttribute(RESPOND_SUBJECT, subject);
2067:
2068: // get info from input
2069: String body = params.getCleanString("body");
2070: body = processFormattedTextFromBrowser(state, body);
2071: state.setAttribute(RESPOND_BODY, body);
2072:
2073: if (subject == null) {
2074: addAlert(state, rb.getString("plespe1"));
2075: } else {
2076: boolean replyToTopic = state
2077: .getAttribute(STATE_REPLY_TOPIC) != null;
2078: boolean replyToMsg = state.getAttribute(STATE_REPLY_MSG) != null;
2079:
2080: String replyToId = "";
2081: if (replyToMsg) {
2082: replyToId = params.getString("messageId");
2083: } else if (replyToTopic) {
2084: replyToId = params.getString("topicId");
2085: }
2086:
2087: if (state.getAttribute(STATE_MESSAGE) == null) {
2088: try {
2089: DiscussionChannel channel = DiscussionService
2090: .getDiscussionChannel((String) state
2091: .getAttribute(STATE_CHANNEL_REF));
2092:
2093: try {
2094: // get the message thread before adding a new message
2095: DiscussionMessage originalMessage = channel
2096: .getDiscussionMessage(replyToId);
2097: String category = originalMessage
2098: .getDiscussionHeader().getCategory();
2099: Vector v = (Vector) ((Hashtable) state
2100: .getAttribute(STATE_CATEGORIES_SHOW_LIST))
2101: .get(category);
2102: int index = v.indexOf(originalMessage.getId());
2103: Iterator l = originalMessage.getReplies();
2104:
2105: // insert the response message
2106: DiscussionMessage addedMessage = channel
2107: .addDiscussionMessage(
2108: category,
2109: subject,
2110: draft,
2111: replyToId,
2112: (List) state
2113: .getAttribute(ATTACHMENTS),
2114: body);
2115:
2116: // show the added message as the current message
2117: showMessage(runData, addedMessage.getId());
2118:
2119: if (!isMessageExpanded(state, originalMessage)) {
2120: // the replied to message has not been expanded
2121: setMessageExpanded(state, originalMessage,
2122: true, channel);
2123: } else {
2124: if ((l == null) || (!l.hasNext())) {
2125: // if there is no reply message yet
2126: v.add(index + 1, addedMessage.getId());
2127: } else {
2128: // if the new message is not a draft message, add to the bottom of non-drafts
2129: int finalIndexOfShownThread = index;
2130: int finalDraftIndex = 0;
2131: while (l.hasNext()) {
2132: DiscussionMessage next = (DiscussionMessage) l
2133: .next();
2134: if (!next.getHeader().getDraft()) {
2135: finalIndexOfShownThread = v
2136: .indexOf(next.getId());
2137: } else {
2138: finalDraftIndex = v
2139: .indexOf(next.getId());
2140: }
2141: }
2142: if (finalIndexOfShownThread == index) {
2143: // if there is no post yet
2144: finalIndexOfShownThread = finalDraftIndex;
2145: }
2146: v.add(finalIndexOfShownThread + 1,
2147: addedMessage.getId());
2148: setCategoryShowList(state, category, v);
2149: } // if - else
2150: } // if-else
2151:
2152: } catch (PermissionException e) {
2153: addAlert(state, rb.getString("youarenot5")
2154: + " " + rb.getString("res"));
2155: } catch (IdUnusedException e) {
2156: addAlert(state, rb.getString("cannotfin3"));
2157: }
2158: } catch (PermissionException e) {
2159: addAlert(state, rb.getString("youdonot3"));
2160: } catch (IdUnusedException e) {
2161: addAlert(state, rb.getString("cannotfin5"));
2162: }
2163: }
2164: } // if-else
2165:
2166: if (state.getAttribute(STATE_MESSAGE) == null) {
2167: state.removeAttribute(ATTACHMENTS);
2168: // respond sucessful
2169: state.removeAttribute(RESPOND_REPLY_TO);
2170: state.removeAttribute(RESPOND_SUBJECT);
2171: state.removeAttribute(RESPOND_BODY);
2172: state.removeAttribute(RESPOND_ATTACHMENT);
2173: state.removeAttribute(STATE_MODE);
2174:
2175: } // if-else
2176:
2177: } // doRespond
2178:
2179: /**
2180: * Handle a user posting a drafted respond message
2181: */
2182: public void doRespond_draft(RunData runData, Context context) {
2183: // access the portlet element id to find our state
2184: String peid = ((JetspeedRunData) runData).getJs_peid();
2185: SessionState state = ((JetspeedRunData) runData)
2186: .getPortletSessionState(peid);
2187: ParameterParser params = runData.getParameters();
2188: // get the reply to message id
2189: // String replyType = params.getString("replyto");
2190: String replyType = "";
2191:
2192: boolean replyToTopic = state.getAttribute(STATE_REPLY_TOPIC) != null;
2193: boolean replyToMsg = state.getAttribute(STATE_REPLY_MSG) != null;
2194:
2195: if (replyToTopic)
2196: replyType = "totopic";
2197: else if (replyToMsg)
2198: replyType = "tomessage";
2199:
2200: String replyToId = "";
2201: if (replyType.equalsIgnoreCase("tomessage")) {
2202: replyToId = params.getString("messageId");
2203: } else if (replyType.equalsIgnoreCase("totopic")) {
2204: replyToId = params.getString("topicId");
2205: }
2206:
2207: // get info from input
2208: String body = params.getCleanString("body");
2209: body = processFormattedTextFromBrowser(state, body);
2210: String subject = ((String) params.getString("subject")).trim();
2211:
2212: state.setAttribute(RESPOND_SUBJECT, subject);
2213: state.setAttribute(RESPOND_BODY, body);
2214:
2215: if (state.getAttribute(STATE_MESSAGE) == null) {
2216: if (subject.length() == 0) {
2217: addAlert(state, rb.getString("plespe1"));
2218: } else {
2219: try {
2220: DiscussionChannel channel = DiscussionService
2221: .getDiscussionChannel((String) state
2222: .getAttribute(STATE_CHANNEL_REF));
2223:
2224: try {
2225: // message is a draft?
2226: boolean draft = true;
2227:
2228: // get the message thread before adding a new message
2229: DiscussionMessage originalMessage = channel
2230: .getDiscussionMessage(replyToId);
2231: String category = originalMessage
2232: .getDiscussionHeader().getCategory();
2233: Vector v = (Vector) ((Hashtable) state
2234: .getAttribute(STATE_CATEGORIES_SHOW_LIST))
2235: .get(category);
2236: int index = v.indexOf(originalMessage.getId());
2237: Iterator l = originalMessage.getReplies();
2238:
2239: // insert the response message
2240: DiscussionMessage addedMessage = channel
2241: .addDiscussionMessage(
2242: category,
2243: subject,
2244: draft,
2245: replyToId,
2246: (List) state
2247: .getAttribute(ATTACHMENTS),
2248: body);
2249: showMessage(runData, addedMessage.getId());
2250:
2251: if (!isMessageExpanded(state, originalMessage)) {
2252: // the replied to message has not been expanded
2253: setMessageExpanded(state, originalMessage,
2254: true, channel);
2255: } else {
2256: if ((l == null) || (!l.hasNext())) {
2257: // if there is no reply message yet
2258: v.add(index + 1, addedMessage.getId());
2259: } else {
2260: // the replied to message has already been expanded
2261: // if the new message is a draft message, add to the bottom of drafts
2262: int firstNondraftIndex = -1;
2263: while (l.hasNext()) {
2264: DiscussionMessage next = (DiscussionMessage) l
2265: .next();
2266: if (next.getDiscussionHeader()
2267: .getDraft()) {
2268: firstNondraftIndex = v
2269: .indexOf(next.getId());
2270: }
2271: }
2272:
2273: if (firstNondraftIndex == -1) {
2274: // no draft till now
2275: firstNondraftIndex = index + 1;
2276: } else {
2277: // otherwise
2278: firstNondraftIndex++;
2279: }
2280: v.add(firstNondraftIndex, addedMessage
2281: .getId());
2282: setCategoryShowList(state, category, v);
2283: } // if - else
2284:
2285: } // if-else
2286:
2287: } catch (PermissionException e) {
2288: addAlert(state, rb.getString("youarenot5")
2289: + " " + rb.getString("res"));
2290: } catch (IdUnusedException e) {
2291: addAlert(state, rb.getString("cannotfin3"));
2292: }
2293: } catch (PermissionException e) {
2294: addAlert(state, rb.getString("youdonot3"));
2295: } catch (IdUnusedException e) {
2296: addAlert(state, rb.getString("cannotfin5"));
2297: }
2298: }
2299: } // if
2300:
2301: if (state.getAttribute(STATE_MESSAGE) == null) {
2302: // respond sucessful
2303: state.removeAttribute(RESPOND_REPLY_TO);
2304: state.removeAttribute(RESPOND_SUBJECT);
2305: state.removeAttribute(RESPOND_BODY);
2306: state.removeAttribute(RESPOND_ATTACHMENT);
2307: state.removeAttribute(STATE_MODE);
2308:
2309: schedulePeerFrameRefresh(VelocityPortletPaneledAction
2310: .mainPanelUpdateId(peid));
2311: } // if-else
2312:
2313: } // doRespondDraft
2314:
2315: /**
2316: * Cancel from the reply page
2317: */
2318: public void doCancel_reply(RunData data, Context context) {
2319: SessionState state = ((JetspeedRunData) data)
2320: .getPortletSessionState(((JetspeedRunData) data)
2321: .getJs_peid());
2322: state.removeAttribute(RESPOND_REPLY_TO);
2323: state.removeAttribute(RESPOND_SUBJECT);
2324: state.removeAttribute(RESPOND_BODY);
2325: state.removeAttribute(RESPOND_ATTACHMENT);
2326: state.removeAttribute(ATTACHMENTS);
2327: state.removeAttribute(STATE_MODE);
2328:
2329: } // doCancel_reply
2330:
2331: /**
2332: * Cancel from the reply preview page
2333: */
2334: public void doCancel_reply_preview(RunData data, Context context) {
2335: SessionState state = ((JetspeedRunData) data)
2336: .getPortletSessionState(((JetspeedRunData) data)
2337: .getJs_peid());
2338: state.setAttribute(STATE_MODE, MODE_REPLY);
2339:
2340: } // doCancel_reply
2341:
2342: /**
2343: * confirm the deletion of category
2344: */
2345: public void doDelete_category_confirm(RunData data, Context context) {
2346: SessionState state = ((JetspeedRunData) data)
2347: .getPortletSessionState(((JetspeedRunData) data)
2348: .getJs_peid());
2349: ParameterParser params = data.getParameters();
2350: String category = FormattedText
2351: .decodeNumericCharacterReferences(params
2352: .getString("category"));
2353: state.setAttribute(STATE_MODE, MODE_DELETE_CATEGORY_CONFIRM);
2354: state.setAttribute(DELETE_CATEGORY, category);
2355:
2356: String peid = ((JetspeedRunData) data).getJs_peid();
2357: schedulePeerFrameRefresh(VelocityPortletPaneledAction
2358: .mainPanelUpdateId(peid));
2359: } // doDelete_category_confirm
2360:
2361: /**
2362: * cancel the deletion of category
2363: */
2364: public void doCancel_delete_category(RunData data, Context context) {
2365: SessionState state = ((JetspeedRunData) data)
2366: .getPortletSessionState(((JetspeedRunData) data)
2367: .getJs_peid());
2368: state.setAttribute(DELETE_CATEGORY, "");
2369: state.removeAttribute(STATE_MODE);
2370: } // doCancel_delelete_category
2371:
2372: /**
2373: * delete the category
2374: */
2375: public void doDelete_category(RunData data, Context context) {
2376: SessionState state = ((JetspeedRunData) data)
2377: .getPortletSessionState(((JetspeedRunData) data)
2378: .getJs_peid());
2379: ParameterParser params = data.getParameters();
2380: String category = params.getString("category");
2381:
2382: try {
2383: // remove the category from the channel
2384: DiscussionChannel channel = (DiscussionChannel) DiscussionService
2385: .getChannel((String) state
2386: .getAttribute(STATE_CHANNEL_REF));
2387: try {
2388: if (!channel.removeCategory(category)) {
2389: state.setAttribute(DELETE_WARNING, rb
2390: .getString("cannotfin7"));
2391: }
2392: } catch (InUseException e) {
2393: state.setAttribute(DELETE_WARNING, rb
2394: .getString("someone")
2395: + " channel. ");
2396: } catch (PermissionException e) {
2397: state.setAttribute(DELETE_WARNING, rb
2398: .getString("youarenot2"));
2399: }
2400:
2401: // remove the category from the set of categories expanded on the user interface
2402: HashSet expandedCategories = (HashSet) state
2403: .getAttribute(STATE_EXPAND_CATEGORY_LIST);
2404: expandedCategories.remove(category);
2405: state.setAttribute(STATE_EXPAND_CATEGORY_LIST,
2406: expandedCategories);
2407: } catch (IdUnusedException e) {
2408: state.setAttribute(DELETE_WARNING, rb
2409: .getString("cannotfin5"));
2410: } catch (PermissionException e) {
2411: state.setAttribute(DELETE_WARNING, rb
2412: .getString("youarenot2"));
2413: }
2414:
2415: state.setAttribute(DELETE_CATEGORY, "");
2416: state.removeAttribute(STATE_MODE);
2417:
2418: } // doDelete_category
2419:
2420: /**
2421: * confirm the deletion of message
2422: */
2423: public void doDelete_message_confirm(RunData data, Context context) {
2424: SessionState state = ((JetspeedRunData) data)
2425: .getPortletSessionState(((JetspeedRunData) data)
2426: .getJs_peid());
2427: String messageId = data.getParameters().getString("messageId");
2428:
2429: state.setAttribute(STATE_MODE, MODE_DELETE_MESSAGE_CONFIRM);
2430: state.setAttribute(DELETE_MESSAGE_ID, messageId);
2431:
2432: String peid = ((JetspeedRunData) data).getJs_peid();
2433: schedulePeerFrameRefresh(VelocityPortletPaneledAction
2434: .mainPanelUpdateId(peid));
2435: } // doDelete_message_confirm
2436:
2437: public void doDelete_message(RunData data, Context context) {
2438: SessionState state = ((JetspeedRunData) data)
2439: .getPortletSessionState(((JetspeedRunData) data)
2440: .getJs_peid());
2441: ParameterParser params = data.getParameters();
2442: String messageId = params.getString("messageId");
2443:
2444: try {
2445: DiscussionChannel channel = (DiscussionChannel) DiscussionService
2446: .getDiscussionChannel((String) state
2447: .getAttribute(STATE_CHANNEL_REF));
2448:
2449: try {
2450: DiscussionMessage message = (DiscussionMessageEdit) channel
2451: .getMessage(messageId);
2452: String category = message.getDiscussionHeader()
2453: .getCategory();
2454:
2455: // remove all the replies to the message
2456: Iterator replies = channel.getThread(message);
2457: while (replies.hasNext()) {
2458: // remove the message from the channel
2459: DiscussionMessage reply = (DiscussionMessage) replies
2460: .next();
2461: channel.removeMessage(reply.getId());
2462:
2463: // remove the message from the show list
2464: Hashtable t = (Hashtable) state
2465: .getAttribute(STATE_CATEGORIES_SHOW_LIST);
2466: Vector v = (Vector) t.get(category);
2467: v.remove(reply.getId());
2468: t.put(category, v);
2469: state.setAttribute(STATE_CATEGORIES_SHOW_LIST, t);
2470:
2471: // remove the message from the expanded message list if necessary
2472: Hashtable expandMessageTable = (Hashtable) state
2473: .getAttribute(STATE_EXPAND_MESSAGE_LIST);
2474: HashSet expandMessageCategory = (HashSet) expandMessageTable
2475: .get(category);
2476: if (expandMessageCategory != null) {
2477: expandMessageCategory.remove(reply.getId());
2478: }
2479: }
2480: // remove the message
2481: channel.removeMessage(message.getId());
2482:
2483: // remove the message from the show list
2484: Hashtable t = (Hashtable) state
2485: .getAttribute(STATE_CATEGORIES_SHOW_LIST);
2486: Vector v = (Vector) t.get(category);
2487: v.remove(messageId);
2488: t.put(category, v);
2489: state.setAttribute(STATE_CATEGORIES_SHOW_LIST, t);
2490:
2491: // remove the message from the expanded message list if necessary
2492: Hashtable expandMessageTable = (Hashtable) state
2493: .getAttribute(STATE_EXPAND_MESSAGE_LIST);
2494: HashSet expandMessageCategory = (HashSet) expandMessageTable
2495: .get(category);
2496: if (expandMessageCategory != null) {
2497: expandMessageCategory.remove(messageId);
2498: }
2499: } catch (IdUnusedException e) {
2500: state.setAttribute(DELETE_WARNING, rb
2501: .getString("cannotfin6"));
2502: } catch (PermissionException e) {
2503: // addAlert(state, rb.getString("youarenot1"));
2504: }
2505: } catch (IdUnusedException e) {
2506: state.setAttribute(DELETE_WARNING, rb
2507: .getString("cannotfin5"));
2508: } catch (PermissionException e) {
2509: state.setAttribute(DELETE_WARNING, rb
2510: .getString("youarenot1"));
2511: }
2512:
2513: state.removeAttribute(STATE_DISPLAY_MESSAGE);
2514: state.removeAttribute(STATE_MODE);
2515:
2516: } // dodelete_message
2517:
2518: /**
2519: * cancel the deletion of message
2520: */
2521: public void doCancel_delete_message(RunData data, Context context) {
2522: SessionState state = ((JetspeedRunData) data)
2523: .getPortletSessionState(((JetspeedRunData) data)
2524: .getJs_peid());
2525: state.removeAttribute(ATTACHMENTS);
2526: state.setAttribute(DELETE_MESSAGE_ID, "");
2527: state.removeAttribute(STATE_MODE);
2528: } // doCancel_delelete_category
2529:
2530: /**
2531: * Handle the eventSubmit_doCancel_show_topic_content command to abort the show topic content page.
2532: */
2533: public void doCancel_show_topic_content(RunData data) {
2534: SessionState state = ((JetspeedRunData) data)
2535: .getPortletSessionState(((JetspeedRunData) data)
2536: .getJs_peid());
2537: state.removeAttribute(STATE_DISPLAY_MESSAGE);
2538: state.removeAttribute(STATE_SHOW_CONTENT_TOPIC_ID);
2539: state.removeAttribute(STATE_MODE);
2540:
2541: } // doCancel_show_topic_content
2542:
2543: /**
2544: * Handle the eventSubmit_doCancel_draft to stop showing the draft message
2545: */
2546: public void doCancel_draft(RunData data) {
2547: SessionState state = ((JetspeedRunData) data)
2548: .getPortletSessionState(((JetspeedRunData) data)
2549: .getJs_peid());
2550: state.removeAttribute(DRAFT_MESSAGE_CATEGORY);
2551: state.removeAttribute(DRAFT_MESSAGE_SUBJECT);
2552: state.removeAttribute(DRAFT_MESSAGE_BODY);
2553: state.removeAttribute(DRAFT_MESSAGE_REPLY_STYLE);
2554: state.removeAttribute(STATE_DISPLAY_MESSAGE);
2555: state.removeAttribute(ATTACHMENTS);
2556:
2557: String peid = ((JetspeedRunData) data).getJs_peid();
2558: schedulePeerFrameRefresh(VelocityPortletPaneledAction
2559: .mainPanelUpdateId(peid)
2560: + "." + MONITOR_PANEL);
2561: } // doCancel_draft
2562:
2563: /**
2564: * Handle the eventSubmit_doCancel_new_topic to stop showing the new topic page
2565: */
2566: public void doCancel_new_topic(RunData data) {
2567: SessionState state = ((JetspeedRunData) data)
2568: .getPortletSessionState(((JetspeedRunData) data)
2569: .getJs_peid());
2570: state.removeAttribute(NEW_TOPIC_NEW_CATEGORY);
2571: state.removeAttribute(NEW_TOPIC_CATEGORY);
2572: state.removeAttribute(NEW_TOPIC_SUBJECT);
2573: state.removeAttribute(NEW_TOPIC_BODY);
2574: state.removeAttribute(NEW_TOPIC_REPLY_STYLE);
2575: state.removeAttribute(STATE_DISPLAY_MESSAGE);
2576:
2577: // clean state mode
2578: state.removeAttribute(STATE_MODE);
2579:
2580: state.removeAttribute(ATTACHMENTS);
2581: } // doCancel_new_topic
2582:
2583: /**
2584: * Handle the eventSubmit_doCancel_new_category to stop showing the new category page
2585: */
2586: public void doCancel_new_category(RunData data) {
2587: SessionState state = ((JetspeedRunData) data)
2588: .getPortletSessionState(((JetspeedRunData) data)
2589: .getJs_peid());
2590: state.removeAttribute(STATE_DISPLAY_MESSAGE);
2591:
2592: // clean state mode
2593: state.removeAttribute(STATE_MODE);
2594:
2595: } // doCancel_new_category
2596:
2597: /**
2598: * To show the topic content when "add attachments" is clicked
2599: */
2600: public void doShow_topic_content(RunData data, Context context) {
2601: SessionState state = ((JetspeedRunData) data)
2602: .getPortletSessionState(((JetspeedRunData) data)
2603: .getJs_peid());
2604:
2605: ParameterParser params = data.getParameters();
2606: String topicId = params.getString("topicId");
2607: state.setAttribute(STATE_SHOW_CONTENT_TOPIC_ID, topicId);
2608: state.setAttribute(STATE_MODE, MODE_SHOW_TOPIC_CONTENT);
2609:
2610: String peid = ((JetspeedRunData) data).getJs_peid();
2611: schedulePeerFrameRefresh(VelocityPortletPaneledAction
2612: .mainPanelUpdateId(peid));
2613:
2614: } // doShow_topic_content
2615:
2616: /**
2617: * Show the discussion message
2618: */
2619: public void doShow(RunData data, Context context) {
2620: ParameterParser params = data.getParameters();
2621:
2622: // set current message id
2623: String messageId = params.getString("messageId");
2624:
2625: showMessage(data, messageId);
2626: String peid = ((JetspeedRunData) data).getJs_peid();
2627: schedulePeerFrameRefresh(VelocityPortletPaneledAction
2628: .mainPanelUpdateId(peid)
2629: + "." + TOOLBAR_PANEL);
2630: schedulePeerFrameRefresh(VelocityPortletPaneledAction
2631: .mainPanelUpdateId(peid)
2632: + "." + CONTROL_PANEL);
2633: } // doShow
2634:
2635: private void showMessage(RunData data, String messageId) {
2636: SessionState state = ((JetspeedRunData) data)
2637: .getPortletSessionState(((JetspeedRunData) data)
2638: .getJs_peid());
2639:
2640: try {
2641: String channelId = (String) state
2642: .getAttribute(STATE_CHANNEL_REF);
2643: DiscussionChannel channel = DiscussionService
2644: .getDiscussionChannel(channelId);
2645:
2646: try {
2647: DiscussionMessage m = channel
2648: .getDiscussionMessage(messageId);
2649: DiscussionMessageHeader mHeader = m
2650: .getDiscussionHeader();
2651: if (mHeader.getDraft()) {
2652: state.setAttribute(DRAFT_MESSAGE_CATEGORY, mHeader
2653: .getCategory());
2654: state.setAttribute(DRAFT_MESSAGE_BODY, m.getBody());
2655: state.setAttribute(DRAFT_MESSAGE_SUBJECT, mHeader
2656: .getSubject());
2657: if (m.getReplyToDepth() == 0) {
2658: ResourceProperties mProperties = m
2659: .getProperties();
2660: state.setAttribute(DRAFT_MESSAGE_REPLY_STYLE,
2661: mProperties.getProperty(mProperties
2662: .getNamePropReplyStyle()));
2663: }
2664: if (mHeader.getAttachments() != null
2665: && mHeader.getAttachments().size() > 0) {
2666: state.setAttribute(ATTACHMENTS, mHeader
2667: .getAttachments());
2668: }
2669: } else {
2670: state.removeAttribute(ATTACHMENTS);
2671: }
2672: DisplayMessage dMessage = new DisplayMessage(messageId);
2673: state.setAttribute(STATE_DISPLAY_MESSAGE, dMessage);
2674:
2675: // update the visited messages list
2676: HashSet visited = (HashSet) state
2677: .getAttribute(VISITED_MESSAGES);
2678: visited.add(messageId);
2679: state.setAttribute(VISITED_MESSAGES, visited);
2680: } catch (IdUnusedException e) {
2681: addAlert(state, rb.getString("cannotfin2"));
2682: } catch (PermissionException e) {
2683: addAlert(state, rb.getString("youarenot3"));
2684: }
2685: } catch (IdUnusedException e) {
2686: addAlert(state, rb.getString("cannotfin5"));
2687: } catch (PermissionException e) {
2688: addAlert(state, rb.getString("youarenot4"));
2689: }
2690: } // showMessage
2691:
2692: /**
2693: * Preview the response
2694: */
2695: public void doPreview(RunData data, Context context) {
2696: SessionState state = ((JetspeedRunData) data)
2697: .getPortletSessionState(((JetspeedRunData) data)
2698: .getJs_peid());
2699: ParameterParser params = data.getParameters();
2700:
2701: // save the input infos for the respond message
2702: // String replyType = params.getString("replyto");
2703: String replyType = "";
2704:
2705: boolean replyToTopic = state.getAttribute(STATE_REPLY_TOPIC) != null;
2706: boolean replyToMsg = state.getAttribute(STATE_REPLY_MSG) != null;
2707:
2708: if (replyToTopic)
2709: replyType = "totopic";
2710: else if (replyToMsg)
2711: replyType = "tomessage";
2712:
2713: String replyToId = "";
2714: if (replyType.equalsIgnoreCase("tomessage")) {
2715: replyToId = params.getString("messageId");
2716: } else if (replyType.equalsIgnoreCase("totopic")) {
2717: replyToId = params.getString("topicId");
2718: }
2719: state.setAttribute(RESPOND_REPLY_TO, replyToId);
2720:
2721: String subject = ((String) params.getString("subject")).trim();
2722: state.setAttribute(RESPOND_SUBJECT, StringUtil
2723: .trimToZero(subject));
2724:
2725: String body = params.getCleanString("body");
2726: body = processFormattedTextFromBrowser(state, body);
2727: state.setAttribute(RESPOND_BODY, body);
2728:
2729: Vector attachments = (Vector) state.getAttribute(ATTACHMENTS);
2730: state.setAttribute(RESPOND_ATTACHMENT, attachments);
2731:
2732: if (subject == null || subject.length() == 0) {
2733: addAlert(state, rb.getString("plespe1"));
2734: }
2735:
2736: if (state.getAttribute(STATE_MESSAGE) == null) {
2737: state.setAttribute(STATE_MODE, MODE_REPLY_PREVIEW);
2738: }
2739:
2740: } // doPreview
2741:
2742: /**
2743: * set the form for replying
2744: */
2745: public void doSet_reply(RunData data, Context context) {
2746: SessionState state = ((JetspeedRunData) data)
2747: .getPortletSessionState(((JetspeedRunData) data)
2748: .getJs_peid());
2749: String currentMessageId = ((DisplayMessage) state
2750: .getAttribute(STATE_DISPLAY_MESSAGE)).getId();
2751: state.setAttribute(RESPOND_REPLY_TO, currentMessageId);
2752: state.setAttribute(RESPOND_ATTACHMENT, new Vector());
2753: state.setAttribute(STATE_MODE, MODE_REPLY);
2754:
2755: String peid = ((JetspeedRunData) data).getJs_peid();
2756: schedulePeerFrameRefresh(VelocityPortletPaneledAction
2757: .mainPanelUpdateId(peid));
2758:
2759: } // doSet_reply
2760:
2761: /**
2762: * set the form for replying message only
2763: */
2764: public void doSet_reply_msg(RunData data, Context context) {
2765: SessionState state = ((JetspeedRunData) data)
2766: .getPortletSessionState(((JetspeedRunData) data)
2767: .getJs_peid());
2768: String currentMessageId = ((DisplayMessage) state
2769: .getAttribute(STATE_DISPLAY_MESSAGE)).getId();
2770: state.setAttribute(RESPOND_REPLY_TO, currentMessageId);
2771: // empty attachment to start with
2772: state.setAttribute(ATTACHMENTS, EntityManager
2773: .newReferenceList());
2774: state.setAttribute(RESPOND_ATTACHMENT, state
2775: .getAttribute(ATTACHMENTS));
2776: state.setAttribute(STATE_MODE, MODE_REPLY);
2777: state.setAttribute(STATE_REPLY_MSG, Boolean.TRUE);
2778: state.removeAttribute(STATE_REPLY_TOPIC);
2779:
2780: String peid = ((JetspeedRunData) data).getJs_peid();
2781: schedulePeerFrameRefresh(VelocityPortletPaneledAction
2782: .mainPanelUpdateId(peid));
2783: } // doSet_reply_msg
2784:
2785: /**
2786: * set the form for replying
2787: */
2788: public void doSet_reply_topic(RunData data, Context context) {
2789: SessionState state = ((JetspeedRunData) data)
2790: .getPortletSessionState(((JetspeedRunData) data)
2791: .getJs_peid());
2792: state.setAttribute(RESPOND_REPLY_TO, data.getParameters()
2793: .getString("topicId"));
2794: // empty attachment to start with
2795: state.setAttribute(ATTACHMENTS, EntityManager
2796: .newReferenceList());
2797: state.setAttribute(RESPOND_ATTACHMENT, state
2798: .getAttribute(ATTACHMENTS));
2799: state.setAttribute(STATE_MODE, MODE_REPLY);
2800: state.setAttribute(STATE_REPLY_TOPIC, Boolean.TRUE);
2801: state.removeAttribute(STATE_REPLY_MSG);
2802:
2803: String peid = ((JetspeedRunData) data).getJs_peid();
2804: schedulePeerFrameRefresh(VelocityPortletPaneledAction
2805: .mainPanelUpdateId(peid));
2806:
2807: } // doSet_reply_topic
2808:
2809: /**
2810: * get the control pannel ready for input new topic
2811: */
2812: public void doSet_new_topic(RunData data, Context context) {
2813: SessionState state = ((JetspeedRunData) data)
2814: .getPortletSessionState(((JetspeedRunData) data)
2815: .getJs_peid());
2816: state.removeAttribute(ATTACHMENTS);
2817: state.setAttribute(STATE_MODE, MODE_NEW_TOPIC);
2818: addAlert(state, "");
2819:
2820: String peid = ((JetspeedRunData) data).getJs_peid();
2821: schedulePeerFrameRefresh(VelocityPortletPaneledAction
2822: .mainPanelUpdateId(peid));
2823:
2824: } // doSet_new_topic
2825:
2826: /**
2827: * get the control pannel ready for input new category
2828: */
2829: public void doSet_new_category(RunData data, Context context) {
2830: SessionState state = ((JetspeedRunData) data)
2831: .getPortletSessionState(((JetspeedRunData) data)
2832: .getJs_peid());
2833: state.removeAttribute(ATTACHMENTS);
2834: state.removeAttribute(NEW_CATEGORY);
2835: state.setAttribute(STATE_MODE, MODE_NEW_CATEGORY);
2836: addAlert(state, "");
2837:
2838: String peid = ((JetspeedRunData) data).getJs_peid();
2839: schedulePeerFrameRefresh(VelocityPortletPaneledAction
2840: .mainPanelUpdateId(peid));
2841:
2842: } // doSet_new_category
2843:
2844: /**
2845: * Setup for options. %%% Note: not sure this and doUpdate are correct, not currently invoked (no menu entry) -ggolden
2846: */
2847: public String buildOptionsPanelContext(VelocityPortlet portlet,
2848: Context context, RunData rundata, SessionState state) {
2849: // set the action for form processing
2850: context.put(Menu.CONTEXT_ACTION, state
2851: .getAttribute(STATE_ACTION));
2852: context.put("form-submit", BUTTON + "doUpdate");
2853:
2854: // pick the "-customize" template based on the standard template name
2855: String template = (String) getContext(rundata).get("template");
2856: return template + "-customize";
2857:
2858: } // buildOptionsPanelContext
2859:
2860: /**
2861: * doUpdate called for form input tags type="submit" named="eventSubmit_doUpdate"
2862: */
2863: public void doUpdate(RunData data, Context context) {
2864: // access the portlet element id to find our state
2865: String peid = ((JetspeedRunData) data).getJs_peid();
2866: SessionState state = ((JetspeedRunData) data)
2867: .getPortletSessionState(peid);
2868:
2869: // channel
2870: String channel = data.getParameters().getString(FORM_CHANNEL);
2871: if (!channel.equals((String) state
2872: .getAttribute(STATE_CHANNEL_REF))) {
2873: state.setAttribute(STATE_CHANNEL_REF, channel);
2874: if (Log.getLogger("chef").isDebugEnabled())
2875: Log.debug("chef", this + ".doUpdate(): channel: "
2876: + channel);
2877: updateObservationOfChannel(state, ((JetspeedRunData) data)
2878: .getJs_peid());
2879: state.setAttribute(STATE_UPDATE, STATE_UPDATE);
2880: }
2881:
2882: // ascending
2883: String ascending = data.getParameters().getString(
2884: FORM_ASCENDING);
2885: Boolean asc = new Boolean(ascending);
2886: if (!asc.equals((Boolean) state.getAttribute(STATE_ASCENDING))) {
2887: state.setAttribute(STATE_ASCENDING, asc);
2888: state.setAttribute(STATE_UPDATE, STATE_UPDATE);
2889: }
2890:
2891: // we are done with customization
2892: // %%% clear or change mode to something like list to leave the options mode
2893:
2894: } // doUpdate
2895:
2896: /**
2897: * get the categories sorted under the sorting criteria
2898: */
2899: private List sortedCategories(DiscussionChannel channel,
2900: String sortedBy, String sortedAsc) {
2901: // categories
2902: List categories = channel.getCategories(true);
2903: if (categories == null)
2904: return null;
2905:
2906: // return the categories alpha sorted
2907: Collections.sort(categories);
2908:
2909: return categories;
2910:
2911: } // sortedCategories
2912:
2913: /**
2914: * transforms the Iterator to Vector
2915: */
2916: private Vector iterator_to_vector(Iterator l) {
2917: Vector v = new Vector();
2918: while (l.hasNext()) {
2919: v.add(l.next());
2920: }
2921: return v;
2922: } // iterator_to_vector
2923:
2924: /**
2925: * set the category in the expanded category list?
2926: */
2927: private void setCategoryExpanded(SessionState state,
2928: String category, boolean expand, DiscussionChannel channel) {
2929: HashSet s = (HashSet) state
2930: .getAttribute(STATE_EXPAND_CATEGORY_LIST);
2931:
2932: if (expand) {
2933: s.add(category);
2934:
2935: // the show topics in category
2936: Vector topics = iterator_to_vector(channel
2937: .getTopics(category));
2938: Vector drafts = new Vector();
2939: Vector nonDrafts = new Vector();
2940: Vector showTopicsList = new Vector();
2941:
2942: // devide the drafted messages and posted messages; drafted message come first
2943: for (int j = 0; j < topics.size(); j++) {
2944: try {
2945: DiscussionMessage m = (DiscussionMessage) topics
2946: .get(j);
2947:
2948: // filter out drafts not by this user (unless this user is a super user) %%% not sure I like this -zqian
2949: channel.getMessage(m.getId());
2950: if (m.getDiscussionHeader().getDraft()) {
2951: drafts.add(m.getId());
2952: } else {
2953: nonDrafts.add(m.getId());
2954: }
2955: } catch (PermissionException e) {
2956: } catch (IdUnusedException e) {
2957: }
2958: }
2959: showTopicsList.addAll(drafts);
2960: showTopicsList.addAll(nonDrafts);
2961: setCategoryShowList(state, category, showTopicsList);
2962: } else {
2963: s.remove(category);
2964: setCategoryShowList(state, category, new Vector());
2965:
2966: // hide the show message
2967: Hashtable t = (Hashtable) state
2968: .getAttribute(STATE_EXPAND_MESSAGE_LIST);
2969: t.put(category, new HashSet());
2970: }
2971: } // setCategoryExpanded
2972:
2973: /**
2974: * Toggle the state attribute
2975: *
2976: * @param stateName
2977: * The name of the state attribute to toggle
2978: */
2979: private void toggleState(RunData runData, String stateName) {
2980: // access the portlet element id to find our state
2981: // %%% use CHEF api instead of Jetspeed to get state
2982: String peid = ((JetspeedRunData) runData).getJs_peid();
2983: SessionState state = ((JetspeedRunData) runData)
2984: .getPortletSessionState(peid);
2985:
2986: // toggle the state setting
2987: boolean newValue = !((Boolean) state.getAttribute(stateName))
2988: .booleanValue();
2989: state.setAttribute(stateName, new Boolean(newValue));
2990:
2991: } // toggleState
2992:
2993: /**
2994: * Show the whole message hireachy
2995: */
2996: public void doExpand_all(RunData data, Context context) {
2997: SessionState state = ((JetspeedRunData) data)
2998: .getPortletSessionState(((JetspeedRunData) data)
2999: .getJs_peid());
3000:
3001: try {
3002: DiscussionChannel channel = DiscussionService
3003: .getDiscussionChannel((String) state
3004: .getAttribute(STATE_CHANNEL_REF));
3005:
3006: // the sorting defaults for the outline view
3007: String sortedBy = "";
3008: String sortedAsc = (String) state
3009: .getAttribute(STATE_SORTED_ASC);
3010:
3011: // set default sort attribute
3012: sortedBy = (String) state.getAttribute(STATE_SORTED_BY);
3013: if ((!sortedBy.equals(STATE_SORTED_BY_TOPIC))
3014: && (!sortedBy.equals(STATE_SORTED_BY_AUTHOR))
3015: && (!sortedBy.equals(STATE_SORTED_BY_DATE))) {
3016: sortedBy = STATE_SORTED_BY_DATE;
3017: state.setAttribute(STATE_SORTED_BY, sortedBy);
3018: }
3019:
3020: // get the sorted categories Vector according to the current sorting criteria
3021: List categories = sortedCategories(channel, sortedBy,
3022: sortedAsc);
3023: if (categories != null) {
3024: for (Iterator i = categories.iterator(); i.hasNext();) {
3025: String cat = (String) i.next();
3026:
3027: setCategoryExpanded(state, cat, true, channel);
3028: Iterator topics = channel.getTopics(cat);
3029: while (topics.hasNext()) {
3030: // expand all the message in the thread
3031: DiscussionMessage m = (DiscussionMessage) topics
3032: .next();
3033: setMessageExpanded(state, m, true, channel);
3034: Iterator replyThread = channel.getThread(m);
3035: while (replyThread.hasNext()) {
3036: setMessageExpanded(state,
3037: (DiscussionMessage) replyThread
3038: .next(), true, channel);
3039: }
3040: }
3041: }
3042: }
3043: } catch (IdUnusedException e) {
3044: addAlert(state, rb.getString("cannotfin5"));
3045: } catch (PermissionException e) {
3046: addAlert(state, rb.getString("youarenot4"));
3047: }
3048:
3049: toggleState(data, STATE_EXPAND_ALL_FLAG);
3050:
3051: // schedule a refresh of the "List" panel
3052: String peid = ((JetspeedRunData) data).getJs_peid();
3053: // String address = ((EventObservingCourier) state.getAttribute(STATE_OBSERVER)).getDeliveryId();
3054: // String elementID = ((EventObservingCourier) state.getAttribute(STATE_OBSERVER)).getElementId();
3055: schedulePeerFrameRefresh(mainPanelUpdateId(peid) + "."
3056: + MONITOR_PANEL);
3057:
3058: } // doExpand_all
3059:
3060: /**
3061: * Hide the whole message hireachy
3062: */
3063: public void doCollapse_all(RunData data, Context context) {
3064: SessionState state = ((JetspeedRunData) data)
3065: .getPortletSessionState(((JetspeedRunData) data)
3066: .getJs_peid());
3067: try {
3068: DiscussionChannel channel = DiscussionService
3069: .getDiscussionChannel((String) state
3070: .getAttribute(STATE_CHANNEL_REF));
3071:
3072: // the sorting defaults for the outline view
3073: String sortedBy = "";
3074: String sortedAsc = (String) state
3075: .getAttribute(STATE_SORTED_ASC);
3076:
3077: // set default sort attribute
3078: sortedBy = (String) state.getAttribute(STATE_SORTED_BY);
3079: if ((!sortedBy.equals(STATE_SORTED_BY_TOPIC))
3080: && (!sortedBy.equals(STATE_SORTED_BY_AUTHOR))
3081: && (!sortedBy.equals(STATE_SORTED_BY_DATE))) {
3082: sortedBy = STATE_SORTED_BY_DATE;
3083: state.setAttribute(STATE_SORTED_BY, sortedBy);
3084: }
3085: // get the sorted categories Vector according to the current sorting criteria
3086: List categories = sortedCategories(channel, sortedBy,
3087: sortedAsc);
3088: if (categories != null) {
3089: for (Iterator i = categories.iterator(); i.hasNext();) {
3090: setCategoryExpanded(state, (String) i.next(),
3091: false, channel);
3092: }
3093: }
3094: } catch (IdUnusedException e) {
3095: addAlert(state, rb.getString("cannotfin5"));
3096: } catch (PermissionException e) {
3097: addAlert(state, rb.getString("youarenot4"));
3098: }
3099:
3100: // remove current display message due to close of categories
3101: state.setAttribute(STATE_DISPLAY_MESSAGE,
3102: new DisplayMessage(""));
3103:
3104: toggleState(data, STATE_EXPAND_ALL_FLAG);
3105:
3106: // schedule a refresh of the "List" panel
3107: String peid = ((JetspeedRunData) data).getJs_peid();
3108: // String address = ((EventObservingCourier) state.getAttribute(STATE_OBSERVER)).getDeliveryId();
3109: // String elementID = ((EventObservingCourier) state.getAttribute(STATE_OBSERVER)).getElementId();
3110: schedulePeerFrameRefresh(mainPanelUpdateId(peid) + "."
3111: + MONITOR_PANEL);
3112:
3113: schedulePeerFrameRefresh(VelocityPortletPaneledAction
3114: .mainPanelUpdateId(peid)
3115: + "." + CONTROL_PANEL);
3116:
3117: } // doCollapse_all
3118:
3119: /**
3120: * is the message id in the expanded message list?
3121: */
3122: private boolean isMessageExpanded(SessionState state,
3123: DiscussionMessage message) {
3124: String category = message.getDiscussionHeader().getCategory();
3125: Hashtable expandMessageTable = (Hashtable) state
3126: .getAttribute(STATE_EXPAND_MESSAGE_LIST);
3127: HashSet s = (HashSet) expandMessageTable.get(category);
3128: if (s != null)
3129: return s.contains(message);
3130: else
3131: return false;
3132:
3133: } // isMessageExpanded
3134:
3135: /**
3136: * set the message id in the expanded message list?
3137: */
3138: private void setMessageExpanded(SessionState state,
3139: DiscussionMessage message, boolean expand,
3140: DiscussionChannel channel) {
3141: // get the current category message list
3142: String category = message.getDiscussionHeader().getCategory();
3143: Vector v = (Vector) ((Hashtable) state
3144: .getAttribute(STATE_CATEGORIES_SHOW_LIST))
3145: .get(category);
3146:
3147: // get the show message
3148: Hashtable expandMessageTable = (Hashtable) state
3149: .getAttribute(STATE_EXPAND_MESSAGE_LIST);
3150: HashSet expandMessageCategory = (HashSet) expandMessageTable
3151: .get(category);
3152: if (expandMessageCategory == null) {
3153: expandMessageCategory = new HashSet();
3154: }
3155:
3156: // get the index of the original message
3157: int index = v.indexOf(message.getId());
3158:
3159: if (expand) {
3160: if (!expandMessageCategory.contains(message)) {
3161: expandMessageCategory.add(message);
3162: }
3163:
3164: // divide the drafted messages and posted messages, drafted message come first
3165: Vector drafts = new Vector();
3166: Vector nonDrafts = new Vector();
3167: Vector showMessagesList = new Vector();
3168: Vector replies = iterator_to_vector(message.getReplies());
3169: for (int j = 0; j < replies.size(); j++) {
3170: DiscussionMessage m = (DiscussionMessage) replies
3171: .get(j);
3172: try {
3173: // filter out drafts not by this user (unless this user is a super user) %%% not sure I like this -zqian
3174: channel.getDiscussionMessage(m.getId());
3175: if (m.getDiscussionHeader().getDraft()) {
3176: drafts.add(m.getId());
3177: } else {
3178: nonDrafts.add(m.getId());
3179: }
3180: } catch (IdUnusedException e) {
3181: } catch (PermissionException e) {
3182: }
3183: }
3184: showMessagesList.addAll(drafts);
3185: showMessagesList.addAll(nonDrafts);
3186:
3187: v.addAll(index + 1, showMessagesList);
3188: } else {
3189: expandMessageCategory.remove(message);
3190: // remove the whole thread
3191: Vector replies = iterator_to_vector(channel
3192: .getThread(message));
3193: for (int j = 0; j < replies.size(); j++) {
3194: DiscussionMessage m = (DiscussionMessage) replies
3195: .get(j);
3196: if (v.contains(m.getId())) {
3197: v.remove(m.getId());
3198: }
3199: }
3200: }
3201:
3202: setCategoryShowList(state, category, v);
3203: expandMessageTable.put(category, expandMessageCategory);
3204: } // setMessageExpanded
3205:
3206: /**
3207: * set the show list for each category
3208: */
3209: private void setCategoryShowList(SessionState state,
3210: String category, Vector showList) {
3211: Hashtable t = (Hashtable) state
3212: .getAttribute(STATE_CATEGORIES_SHOW_LIST);
3213: t.put(category, showList);
3214: state.setAttribute(STATE_CATEGORIES_SHOW_LIST, t);
3215: } // setCategoryShowList
3216:
3217: /**
3218: * doExpandmessage expand the message with the content and replies
3219: */
3220: public void doExpand_message(RunData data, Context context) {
3221: String messageId = data.getParameters().getString("messageId");
3222: SessionState state = ((JetspeedRunData) data)
3223: .getPortletSessionState(((JetspeedRunData) data)
3224: .getJs_peid());
3225:
3226: try {
3227: DiscussionChannel channel = DiscussionService
3228: .getDiscussionChannel((String) state
3229: .getAttribute(STATE_CHANNEL_REF));
3230:
3231: try {
3232: setMessageExpanded(state, channel
3233: .getDiscussionMessage(messageId), true, channel);
3234: showMessage(data, messageId);
3235: String peid = ((JetspeedRunData) data).getJs_peid();
3236: schedulePeerFrameRefresh(VelocityPortletPaneledAction
3237: .mainPanelUpdateId(peid)
3238: + "." + TOOLBAR_PANEL);
3239: schedulePeerFrameRefresh(VelocityPortletPaneledAction
3240: .mainPanelUpdateId(peid)
3241: + "." + CONTROL_PANEL);
3242: } catch (IdUnusedException e) {
3243: addAlert(state, rb.getString("cannotfin4"));
3244: } catch (PermissionException e) {
3245: addAlert(state, rb.getString("youarenot5") + " "
3246: + rb.getString("toview"));
3247: }
3248: } catch (IdUnusedException e) {
3249: addAlert(state, rb.getString("cannotfin5"));
3250: } catch (PermissionException e) {
3251: addAlert(state, rb.getString("youarenot4"));
3252: }
3253:
3254: } // doExpand_message
3255:
3256: /**
3257: * doCollapsemessage hides all the messages inside the category
3258: */
3259: public void doCollapse_message(RunData data, Context context) {
3260: String messageId = data.getParameters().getString("messageId");
3261: SessionState state = ((JetspeedRunData) data)
3262: .getPortletSessionState(((JetspeedRunData) data)
3263: .getJs_peid());
3264: try {
3265: DiscussionChannel channel = DiscussionService
3266: .getDiscussionChannel((String) state
3267: .getAttribute(STATE_CHANNEL_REF));
3268: try {
3269: DiscussionMessage message = channel
3270: .getDiscussionMessage(messageId);
3271:
3272: // set the message itself to be collapsed
3273: setMessageExpanded(state, message, false, channel);
3274:
3275: // the current message been displayed
3276: String currentMessageId = ((DisplayMessage) state
3277: .getAttribute(STATE_DISPLAY_MESSAGE)).getId();
3278: boolean found = false;
3279:
3280: Iterator replies = channel.getThread(message);
3281: while (replies.hasNext()) {
3282: DiscussionMessage nextReply = (DiscussionMessage) replies
3283: .next();
3284:
3285: // set the message's reply to be collapsed
3286: setMessageExpanded(state, nextReply, false, channel);
3287:
3288: if ((!found)
3289: && currentMessageId.equals(nextReply
3290: .getId())) {
3291: // remove the current message due to close of thread
3292: state.setAttribute(STATE_DISPLAY_MESSAGE,
3293: new DisplayMessage(""));
3294: found = true;
3295: }
3296:
3297: }
3298: } catch (IdUnusedException e) {
3299: addAlert(state, rb.getString("cannotfin4"));
3300: } catch (PermissionException e) {
3301: addAlert(state, rb.getString("youarenot5") + " "
3302: + rb.getString("toview"));
3303: }
3304: } catch (IdUnusedException e) {
3305: addAlert(state, rb.getString("cannotfin5"));
3306: } catch (PermissionException e) {
3307: addAlert(state, rb.getString("youdonot1"));
3308: }
3309:
3310: String peid = ((JetspeedRunData) data).getJs_peid();
3311: schedulePeerFrameRefresh(VelocityPortletPaneledAction
3312: .mainPanelUpdateId(peid)
3313: + "." + CONTROL_PANEL);
3314: schedulePeerFrameRefresh(VelocityPortletPaneledAction
3315: .mainPanelUpdateId(peid)
3316: + "." + TOOLBAR_PANEL);
3317:
3318: } // doCollapse_message
3319:
3320: /**
3321: * doExpandcategory shows all the topics inside the category
3322: */
3323: public void doExpand_category(RunData data, Context context) {
3324: String category = data.getParameters().getString("category");
3325: SessionState state = ((JetspeedRunData) data)
3326: .getPortletSessionState(((JetspeedRunData) data)
3327: .getJs_peid());
3328:
3329: String channelId = (String) state
3330: .getAttribute(STATE_CHANNEL_REF);
3331: try {
3332: // get the current channel ID from state object
3333: DiscussionChannel channel = DiscussionService
3334: .getDiscussionChannel(channelId);
3335: setCategoryExpanded(state, category, true, channel);
3336: } catch (IdUnusedException e) {
3337: addAlert(state, rb.getString("cannotfin5"));
3338: } catch (PermissionException e) {
3339: addAlert(state, rb.getString("youdonot1"));
3340: }
3341:
3342: } // doExpand_category
3343:
3344: /**
3345: * doCollapsecategory hides all the topics inside the category
3346: */
3347: public void doCollapse_category(RunData data, Context context) {
3348: SessionState state = ((JetspeedRunData) data)
3349: .getPortletSessionState(((JetspeedRunData) data)
3350: .getJs_peid());
3351:
3352: String category = data.getParameters().getString("category");
3353:
3354: String channelId = (String) state
3355: .getAttribute(STATE_CHANNEL_REF);
3356: try {
3357: // get the current channel ID from state object
3358: DiscussionChannel channel = DiscussionService
3359: .getDiscussionChannel(channelId);
3360:
3361: String currentId = ((DisplayMessage) state
3362: .getAttribute(STATE_DISPLAY_MESSAGE)).getId();
3363: if (!currentId.equals("")) {
3364: DiscussionMessage message = channel
3365: .getDiscussionMessage(currentId);
3366: String mCategory = message.getDiscussionHeader()
3367: .getCategory();
3368: if (mCategory.equals(category)) {
3369: // remove current display message due to close of category
3370: state.setAttribute(STATE_DISPLAY_MESSAGE,
3371: new DisplayMessage(""));
3372: }
3373: }
3374: setCategoryExpanded(state, category, false, channel);
3375: } catch (IdUnusedException e) {
3376: addAlert(state, rb.getString("cannotfin5"));
3377: } catch (PermissionException e) {
3378: addAlert(state, rb.getString("youdonot1"));
3379: }
3380:
3381: String peid = ((JetspeedRunData) data).getJs_peid();
3382: schedulePeerFrameRefresh(VelocityPortletPaneledAction
3383: .mainPanelUpdateId(peid)
3384: + "." + CONTROL_PANEL);
3385: schedulePeerFrameRefresh(VelocityPortletPaneledAction
3386: .mainPanelUpdateId(peid)
3387: + "." + TOOLBAR_PANEL);
3388:
3389: } // doCollapse_category
3390:
3391: /**
3392: * the class which is using by one of the iFrames to show the content of selected message
3393: */
3394: public class DisplayMessage {
3395: String m_id = null;
3396:
3397: public DisplayMessage(String id) {
3398: m_id = id;
3399: }
3400:
3401: public void setId(String id) {
3402: m_id = id;
3403: }
3404:
3405: public String getId() {
3406: return m_id;
3407: }
3408:
3409: } // DisplayMessage
3410:
3411: /**
3412: * add the category to the state attribute
3413: */
3414: private void addCategory(SessionState state,
3415: DiscussionChannel channel, String category)
3416: throws InUseException, PermissionException {
3417: try {
3418: channel.addCategory(category);
3419:
3420: HashSet expandedCategories = (HashSet) state
3421: .getAttribute(STATE_EXPAND_CATEGORY_LIST);
3422: expandedCategories.add(category);
3423: state.setAttribute(STATE_EXPAND_CATEGORY_LIST,
3424: expandedCategories);
3425:
3426: Hashtable h = (Hashtable) state
3427: .getAttribute(STATE_CATEGORIES_SHOW_LIST);
3428: h.put(category, new Vector());
3429: state.setAttribute(STATE_CATEGORIES_SHOW_LIST, h);
3430: } catch (InUseException e) {
3431: throw new InUseException(channel.getId());
3432: } catch (PermissionException e) {
3433: throw new PermissionException(null, null, null);
3434: }
3435:
3436: } // addCategory
3437:
3438: /**
3439: * Fire up the permissions editor, next request cycle
3440: */
3441: public void doPermissions(RunData data, Context context) {
3442: String peid = ((JetspeedRunData) data).getJs_peid();
3443: SessionState state = ((JetspeedRunData) data)
3444: .getPortletSessionState(peid);
3445:
3446: // trigger the switch on the next request (which is going to happen after this action is processed with its redirect response to the build)
3447: state.setAttribute(STATE_PERMISSIONS, STATE_PERMISSIONS);
3448:
3449: // schedule a main refresh to excape from the toolbar panel
3450: schedulePeerFrameRefresh(mainPanelUpdateId(peid));
3451: }
3452:
3453: /**
3454: * Fire up the permissions editor
3455: */
3456: protected void doPermissionsNow(RunData data, Context context) {
3457: // get into helper mode with this helper tool
3458: startHelper(data.getRequest(), "sakai.permissions.helper");
3459:
3460: String peid = ((JetspeedRunData) data).getJs_peid();
3461: SessionState state = ((JetspeedRunData) data)
3462: .getPortletSessionState(peid);
3463:
3464: String channelRefStr = (String) state
3465: .getAttribute(STATE_CHANNEL_REF);
3466: Reference channelRef = EntityManager
3467: .newReference(channelRefStr);
3468: String siteRef = SiteService.siteReference(channelRef
3469: .getContext());
3470:
3471: // setup for editing the permissions of the site for this tool, using the roles of this site, too
3472: state.setAttribute(PermissionsHelper.TARGET_REF, siteRef);
3473:
3474: // ... with this description
3475: state.setAttribute(PermissionsHelper.DESCRIPTION, rb
3476: .getString("setperfor")
3477: + SiteService.getSiteDisplay(channelRef.getContext()));
3478:
3479: // ... showing only locks that are prpefixed with this
3480: state.setAttribute(PermissionsHelper.PREFIX, "disc.");
3481:
3482: } // doPermissions
3483:
3484: /**
3485: * Handle a \ request.
3486: */
3487: public void doSearch(RunData runData, Context context) {
3488: // access the portlet element id to find our state
3489: String peid = ((JetspeedRunData) runData).getJs_peid();
3490: SessionState state = ((JetspeedRunData) runData)
3491: .getPortletSessionState(peid);
3492:
3493: String channelId = (String) state
3494: .getAttribute(STATE_CHANNEL_REF);
3495: // the sorting defaults for the outline view
3496: String sortedAsc = (String) state
3497: .getAttribute(STATE_SORTED_ASC);
3498: String sortedBy = (String) state.getAttribute(STATE_SORTED_BY);
3499: if ((!sortedBy.equals(STATE_SORTED_BY_TOPIC))
3500: && (!sortedBy.equals(STATE_SORTED_BY_AUTHOR))
3501: && (!sortedBy.equals(STATE_SORTED_BY_DATE))) {
3502: sortedBy = STATE_SORTED_BY_DATE;
3503: state.setAttribute(STATE_SORTED_BY, sortedBy);
3504: }
3505:
3506: // read the search form field into the state object
3507: String search = StringUtil.trimToNull(runData.getParameters()
3508: .getString(FORM_SEARCH));
3509:
3510: Vector searchResultList = new Vector();
3511:
3512: state.setAttribute(STATE_SEARCH_REFRESH, Boolean.TRUE);
3513:
3514: // set the flag to go to the prev page on the next list
3515: if (search == null) {
3516: state.removeAttribute(STATE_SEARCH);
3517: } else {
3518: state.setAttribute(STATE_SEARCH, search);
3519:
3520: try {
3521: // get the current channel ID from state object
3522: DiscussionChannel channel = DiscussionService
3523: .getDiscussionChannel(channelId);
3524:
3525: // detect whether channel is existed
3526: if (channel != null) {
3527: // get the sorted categories Vector according to the current sorting criteria
3528: List categories = sortedCategories(channel,
3529: sortedBy, sortedAsc);
3530:
3531: // provide the expanded category list
3532: HashSet expandedCategories = (HashSet) state
3533: .getAttribute(STATE_EXPAND_CATEGORY_LIST);
3534: Hashtable showList = (Hashtable) state
3535: .getAttribute(STATE_CATEGORIES_SHOW_LIST);
3536: Hashtable t = (Hashtable) state
3537: .getAttribute(STATE_EXPAND_MESSAGE_LIST);
3538: HashSet s = new HashSet();
3539:
3540: if (categories != null) {
3541: String currentCategory = "";
3542:
3543: for (Iterator i = categories.iterator(); i
3544: .hasNext();) {
3545: // current category
3546: currentCategory = (String) i.next();
3547:
3548: // show list in category
3549: Vector v = (Vector) showList
3550: .get(currentCategory);
3551: if (v == null)
3552: v = new Vector();
3553:
3554: s = (HashSet) t.get(currentCategory);
3555:
3556: Iterator allMessagesInCategory = channel
3557: .getThreads(currentCategory);
3558:
3559: // find the any message in the category matches search result
3560: if ((search != null)
3561: && (!search.equals(""))) {
3562: while (allMessagesInCategory.hasNext()) {
3563: DiscussionMessage message = (DiscussionMessage) allMessagesInCategory
3564: .next();
3565: if (StringUtil
3566: .containsIgnoreCase(
3567: message
3568: .getDiscussionHeader()
3569: .getSubject(),
3570: search)
3571: || StringUtil
3572: .containsIgnoreCase(
3573: FormattedText
3574: .convertFormattedTextToPlaintext(message
3575: .getBody()),
3576: search)) {
3577: // mark the search finding
3578: searchResultList.add(message
3579: .getId());
3580:
3581: // once the matching disucssion message is found, mark the corresponding category as expanded
3582: expandedCategories
3583: .add(currentCategory);
3584:
3585: // recursively mark the all containing messages as expanded
3586: if (message.getReplyToDepth() > 0) {
3587: // get the parent messages, sorted by depth ascendingly
3588: Iterator parentMessages = parentMessageIterator(
3589: message, channel);
3590: while (parentMessages
3591: .hasNext()) {
3592: DiscussionMessage iMessage = (DiscussionMessage) parentMessages
3593: .next();
3594:
3595: // mark the message in shown list
3596: if (!v
3597: .contains(iMessage
3598: .getId())) {
3599: v.add(iMessage
3600: .getId());
3601: }
3602:
3603: // mark the message as expanded
3604: s.add(iMessage);
3605: }
3606: }
3607:
3608: // mark the message in shown list
3609: if (!v
3610: .contains(message
3611: .getId())) {
3612: v.add(message.getId());
3613: }
3614: }
3615: }
3616: }
3617:
3618: // assign back
3619: showList.put(currentCategory, v);
3620: t.put(currentCategory, s);
3621: }
3622: // update state variables
3623: state.setAttribute(STATE_SEARCH_RESULT,
3624: searchResultList);
3625: state.setAttribute(STATE_CATEGORIES_SHOW_LIST,
3626: showList);
3627: state.setAttribute(STATE_EXPAND_CATEGORY_LIST,
3628: expandedCategories);
3629: state
3630: .setAttribute(
3631: STATE_EXPAND_MESSAGE_LIST, t);
3632: } // if: categories not null
3633: }
3634: } catch (IdUnusedException e) {
3635: addAlert(state, rb.getString("cannotfin5"));
3636: } catch (PermissionException e) {
3637: addAlert(state, rb.getString("youdonot2"));
3638: }
3639: }
3640:
3641: schedulePeerFrameRefresh(VelocityPortletPaneledAction
3642: .mainPanelUpdateId(peid)
3643: + "." + MONITOR_PANEL);
3644:
3645: // disable auto-updates while in view mode
3646: disableObservers(state);
3647:
3648: } // doSearch
3649:
3650: /**
3651: * return an iterator consisting of all parent DiscussionMessage objects of the current DiscussionMessage item.
3652: * Sorted by depth ascendingly
3653: */
3654: protected Iterator parentMessageIterator(DiscussionMessage message,
3655: DiscussionChannel channel) {
3656:
3657: // start the depth iteration stack with the topics of the channel
3658: final Stack stack = new Stack();
3659: DiscussionMessage m_message = message;
3660:
3661: // construct the stack
3662: boolean atTopLevel = false;
3663: while (!atTopLevel) {
3664: if (((DiscussionMessage) m_message).getReplyToDepth() > 0) {
3665: String pId = ((DiscussionMessage) m_message)
3666: .getDiscussionHeader().getReplyTo();
3667:
3668: // detect whether channel is existed
3669: if (channel != null) {
3670: try {
3671: DiscussionMessage nMessage = channel
3672: .getDiscussionMessage(pId);
3673: // mark the message in shown list
3674: if (!stack.contains(nMessage)) {
3675: stack.push(nMessage);
3676: }
3677: // reassign
3678: m_message = nMessage;
3679: } catch (Exception e) {
3680: Log.warn("chef", e.toString() + pId
3681: + e.toString());
3682: }
3683: }
3684: } else {
3685: atTopLevel = true;
3686: }
3687: }
3688:
3689: // prepare for return
3690: List rv = new Vector();
3691: while (!stack.empty()) {
3692: rv.add(stack.pop());
3693: }
3694: return rv.iterator();
3695: }
3696:
3697: /**
3698: * Handle a Search Clear request.
3699: */
3700: public void doSearch_clear(RunData runData, Context context) {
3701: // access the portlet element id to find our state
3702: String peid = ((JetspeedRunData) runData).getJs_peid();
3703: SessionState state = ((JetspeedRunData) runData)
3704: .getPortletSessionState(peid);
3705:
3706: // clear the search
3707: state.removeAttribute(STATE_SEARCH);
3708: state.removeAttribute(STATE_SEARCH_RESULT);
3709:
3710: // turn on auto refresh
3711: enableObserver(state);
3712:
3713: schedulePeerFrameRefresh(VelocityPortletPaneledAction
3714: .mainPanelUpdateId(peid)
3715: + "." + MONITOR_PANEL);
3716:
3717: // make sure auto-updates are enabled
3718: enableObserver(state);
3719:
3720: } // doSearch_clear
3721:
3722: /**
3723: * Enable the observer, unless we are in search mode, where we want it disabled.
3724: */
3725: public void enableObserver(SessionState state) {
3726: // we leave it disabled if we are searching, or if the user has last selected to be manual
3727: if (state.getAttribute(STATE_SEARCH) != null) {
3728: disableObservers(state);
3729: } else {
3730: enableObservers(state);
3731: }
3732:
3733: } // enableObserver
3734:
3735: public void doView(RunData data, Context context) {
3736: SessionState state = ((JetspeedRunData) data)
3737: .getPortletSessionState(((JetspeedRunData) data)
3738: .getJs_peid());
3739:
3740: String viewMode = data.getParameters().getString("view");
3741: state.setAttribute(STATE_SELECTED_VIEW, viewMode);
3742:
3743: if (viewMode.equalsIgnoreCase(rb.getString("rowlay"))) {
3744: // not left - right layout
3745: state.setAttribute(STATE_LEFT_RIGHT_LAYOUT, new Boolean(
3746: false));
3747:
3748: String peid = ((JetspeedRunData) data).getJs_peid();
3749: schedulePeerFrameRefresh(VelocityPortletPaneledAction
3750: .mainPanelUpdateId(peid));
3751: } else if (viewMode.equalsIgnoreCase(rb.getString("collay"))) {
3752: // not left - right layout
3753: state.setAttribute(STATE_LEFT_RIGHT_LAYOUT, new Boolean(
3754: true));
3755:
3756: String peid = ((JetspeedRunData) data).getJs_peid();
3757: schedulePeerFrameRefresh(VelocityPortletPaneledAction
3758: .mainPanelUpdateId(peid));
3759: }
3760: } // doView
3761:
3762: /**
3763: * put those variables related to 2ndToolbar into context
3764: */
3765: private void add2ndToolbarFields(RunData data, Context context) {
3766: SessionState state = ((JetspeedRunData) data)
3767: .getPortletSessionState(((JetspeedRunData) data)
3768: .getJs_peid());
3769:
3770: context.put("searchString", state.getAttribute(STATE_SEARCH));
3771: context.put("form_search", FORM_SEARCH);
3772: context.put("selectedView", state
3773: .getAttribute(STATE_SELECTED_VIEW));
3774:
3775: } // add2ndToolbarFields
3776:
3777: /**
3778: * navigate to previous message in the category
3779: */
3780: public void doPre_message(RunData data, Context context) {
3781: SessionState state = ((JetspeedRunData) data)
3782: .getPortletSessionState(((JetspeedRunData) data)
3783: .getJs_peid());
3784: String channelId = (String) state
3785: .getAttribute(STATE_CHANNEL_REF);
3786: try {
3787: // get the current channel ID from state object
3788: DiscussionChannel channel = DiscussionService
3789: .getDiscussionChannel(channelId);
3790:
3791: DisplayMessage dMessage = (DisplayMessage) state
3792: .getAttribute(STATE_DISPLAY_MESSAGE);
3793: String currentId = dMessage.getId();
3794: if (!currentId.equals("")) {
3795: DiscussionMessage message = channel
3796: .getDiscussionMessage(currentId);
3797: String category = message.getDiscussionHeader()
3798: .getCategory();
3799: Vector messageIds = (Vector) ((Hashtable) state
3800: .getAttribute(STATE_CATEGORIES_SHOW_LIST))
3801: .get(category);
3802: dMessage.setId((String) messageIds.get(messageIds
3803: .indexOf(currentId) - 1));
3804: state.setAttribute(STATE_DISPLAY_MESSAGE, dMessage);
3805: }
3806: } catch (IdUnusedException e) {
3807: addAlert(state, rb.getString("cannotfin5"));
3808: } catch (PermissionException e) {
3809: addAlert(state, rb.getString("youdonot1"));
3810: }
3811:
3812: String peid = ((JetspeedRunData) data).getJs_peid();
3813: schedulePeerFrameRefresh(VelocityPortletPaneledAction
3814: .mainPanelUpdateId(peid));
3815: } // doPre_message
3816:
3817: /**
3818: * Navigate to next message in the category
3819: */
3820: public void doNext_message(RunData data, Context context) {
3821: SessionState state = ((JetspeedRunData) data)
3822: .getPortletSessionState(((JetspeedRunData) data)
3823: .getJs_peid());
3824: String channelId = (String) state
3825: .getAttribute(STATE_CHANNEL_REF);
3826: try {
3827: // get the current channel ID from state object
3828: DiscussionChannel channel = DiscussionService
3829: .getDiscussionChannel(channelId);
3830:
3831: DisplayMessage dMessage = (DisplayMessage) state
3832: .getAttribute(STATE_DISPLAY_MESSAGE);
3833: String currentId = dMessage.getId();
3834: if (!currentId.equals("")) {
3835: DiscussionMessage message = channel
3836: .getDiscussionMessage(currentId);
3837: String category = message.getDiscussionHeader()
3838: .getCategory();
3839: Vector messageIds = (Vector) ((Hashtable) state
3840: .getAttribute(STATE_CATEGORIES_SHOW_LIST))
3841: .get(category);
3842: dMessage.setId((String) messageIds.get(messageIds
3843: .indexOf(currentId) + 1));
3844: state.setAttribute(STATE_DISPLAY_MESSAGE, dMessage);
3845: }
3846: } catch (IdUnusedException e) {
3847: addAlert(state, rb.getString("cannotfin5"));
3848: } catch (PermissionException e) {
3849: addAlert(state, rb.getString("youdonot1"));
3850: }
3851:
3852: String peid = ((JetspeedRunData) data).getJs_peid();
3853: schedulePeerFrameRefresh(VelocityPortletPaneledAction
3854: .mainPanelUpdateId(peid));
3855:
3856: } // doNext_message
3857:
3858: /**
3859: * Processes formatted text that is coming back from the browser (from the formatted text editing widget).
3860: *
3861: * @param state
3862: * Used to pass in any user-visible alerts or errors when processing the text
3863: * @param strFromBrowser
3864: * The string from the browser
3865: * @return The formatted text
3866: */
3867: private String processFormattedTextFromBrowser(SessionState state,
3868: String strFromBrowser) {
3869: StringBuffer alertMsg = new StringBuffer();
3870: try {
3871: String text = FormattedText.processFormattedText(
3872: strFromBrowser, alertMsg);
3873: if (alertMsg.length() > 0)
3874: addAlert(state, alertMsg.toString());
3875: return text;
3876: } catch (Exception e) {
3877: Log.warn("chef", this + ": ", e);
3878: return strFromBrowser;
3879: }
3880: }
3881: }
|