001: /**********************************************************************************
002: * $URL: https://source.sakaiproject.org/svn/site-manage/tags/sakai_2-4-1/site-manage-tool/tool/src/java/org/sakaiproject/site/tool/MembershipAction.java $
003: * $Id: MembershipAction.java 20062 2007-01-02 22:51:54Z zqian@umich.edu $
004: ***********************************************************************************
005: *
006: * Copyright (c) 2003, 2004, 2005, 2006 The Sakai Foundation.
007: *
008: * Licensed under the Educational Community License, Version 1.0 (the "License");
009: * you may not use this file except in compliance with the License.
010: * You may obtain a copy of the License at
011: *
012: * http://www.opensource.org/licenses/ecl1.php
013: *
014: * Unless required by applicable law or agreed to in writing, software
015: * distributed under the License is distributed on an "AS IS" BASIS,
016: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: * See the License for the specific language governing permissions and
018: * limitations under the License.
019: *
020: **********************************************************************************/package org.sakaiproject.site.tool;
021:
022: import java.util.ArrayList;
023: import java.util.Arrays;
024: import java.util.List;
025: import java.util.Vector;
026:
027: import org.sakaiproject.cheftool.Context;
028: import org.sakaiproject.cheftool.JetspeedRunData;
029: import org.sakaiproject.cheftool.PagedResourceActionII;
030: import org.sakaiproject.cheftool.RunData;
031: import org.sakaiproject.cheftool.VelocityPortlet;
032: import org.sakaiproject.component.cover.ServerConfigurationService;
033: import org.sakaiproject.event.api.SessionState;
034: import org.sakaiproject.exception.IdUnusedException;
035: import org.sakaiproject.exception.InUseException;
036: import org.sakaiproject.exception.PermissionException;
037: import org.sakaiproject.javax.PagingPosition;
038: import org.sakaiproject.site.cover.SiteService;
039: import org.sakaiproject.util.ResourceLoader;
040:
041: /**
042: * <p>
043: * MembershipAction is a tool which displays Sites and lets the user join and un-join joinable Sites.
044: * </p>
045: */
046: public class MembershipAction extends PagedResourceActionII {
047: private static String STATE_VIEW_MODE = "state_view";
048:
049: private static ResourceLoader rb = new ResourceLoader("membership");
050:
051: private static String SORT_ASC = "sort_asc";
052:
053: private static String JOINABLE_SORT_ASC = "sort_asc";
054:
055: private static String STATE_CONFIRM_VIEW_MODE = "state_confirm_view";
056:
057: private static String UNJOIN_SITE = "unjoin_site";
058:
059: private static String SEARCH_TERM = "search";
060:
061: /*
062: * (non-Javadoc)
063: *
064: * @see org.sakaiproject.cheftool.PagedResourceActionII#sizeResources(org.sakaiproject.service.framework.session.SessionState)
065: */
066: protected int sizeResources(SessionState state) {
067: int size = 0;
068:
069: String search = (String) state.getAttribute(SEARCH_TERM);
070: if ((search != null) && search.trim().equals("")) {
071: search = null;
072: }
073:
074: List openSites = SiteService
075: .getSites(
076: org.sakaiproject.site.api.SiteService.SelectionType.JOINABLE,
077: // null, null, null, org.sakaiproject.service.legacy.site.SiteService.SortType.TITLE_ASC, null);
078: null,
079: search,
080: null,
081: org.sakaiproject.site.api.SiteService.SortType.TITLE_ASC,
082: null);
083: size = openSites.size();
084:
085: return size;
086: }
087:
088: /*
089: * (non-Javadoc)
090: *
091: * @see org.sakaiproject.cheftool.PagedResourceActionII#readResourcesPage(org.sakaiproject.service.framework.session.SessionState, int, int)
092: */
093: protected List readResourcesPage(SessionState state, int first,
094: int last) {
095: List rv = new Vector();
096:
097: String search = (String) state.getAttribute(SEARCH_TERM);
098: if ((search != null) && search.trim().equals("")) {
099: search = null;
100: }
101:
102: if (((Boolean) state.getAttribute(SORT_ASC)).booleanValue()) {
103: rv = SiteService
104: .getSites(
105: org.sakaiproject.site.api.SiteService.SelectionType.JOINABLE,
106: // null, null, null, org.sakaiproject.service.legacy.site.SiteService.SortType.TITLE_ASC, null);
107: null,
108: search,
109: null,
110: org.sakaiproject.site.api.SiteService.SortType.TITLE_ASC,
111: null);
112: } else {
113: rv = SiteService
114: .getSites(
115: org.sakaiproject.site.api.SiteService.SelectionType.JOINABLE,
116: // null, null, null, org.sakaiproject.service.legacy.site.SiteService.SortType.TITLE_DESC, null);
117: null,
118: search,
119: null,
120: org.sakaiproject.site.api.SiteService.SortType.TITLE_DESC,
121: null);
122: }
123:
124: PagingPosition page = new PagingPosition(first, last);
125: page.validate(rv.size());
126: rv = rv.subList(page.getFirst() - 1, page.getLast());
127:
128: return rv;
129: }
130:
131: /** the above : paging * */
132:
133: /**
134: * build the context
135: */
136: public String buildMainPanelContext(VelocityPortlet portlet,
137: Context context, RunData rundata, SessionState state) {
138: // buildMenu(portlet, context, rundata, state);
139:
140: String template = (String) getContext(rundata).get("template");
141:
142: // read the group ids to join
143: if (state.getAttribute(SORT_ASC) == null) {
144: state.setAttribute(SORT_ASC, Boolean.TRUE);
145: }
146: Boolean sortAsc = (Boolean) state.getAttribute(SORT_ASC);
147: context.put("currentSortAsc", sortAsc);
148:
149: if (state.getAttribute(SEARCH_TERM) == null) {
150: state.setAttribute(SEARCH_TERM, "");
151: }
152: context.put(SEARCH_TERM, state.getAttribute(SEARCH_TERM));
153:
154: boolean defaultMode = state.getAttribute(STATE_VIEW_MODE) == null;
155: if (defaultMode) {
156: // process all the sites the user has access to so can unjoin
157: List unjoinableSites = new Vector();
158: if (sortAsc.booleanValue()) {
159: unjoinableSites = SiteService
160: .getSites(
161: org.sakaiproject.site.api.SiteService.SelectionType.ACCESS,
162: null,
163: null,
164: null,
165: org.sakaiproject.site.api.SiteService.SortType.TITLE_ASC,
166: null);
167: } else {
168: unjoinableSites = SiteService
169: .getSites(
170: org.sakaiproject.site.api.SiteService.SelectionType.ACCESS,
171: null,
172: null,
173: null,
174: org.sakaiproject.site.api.SiteService.SortType.TITLE_DESC,
175: null);
176: }
177: context.put("unjoinableSites", unjoinableSites);
178:
179: context.put("SiteService", SiteService.getInstance());
180:
181: // if property set in sakai.properties then completely disable 'unjoin' link
182: if (ServerConfigurationService.getBoolean(
183: "disable.membership.unjoin.selection", false)) {
184: context.put("disableUnjoinSelection", Boolean.TRUE);
185: }
186:
187: if (ServerConfigurationService
188: .getStrings("wsetup.disable.unjoin") != null) {
189: context.put("disableUnjoinSiteTypes", new ArrayList(
190: Arrays.asList(ServerConfigurationService
191: .getStrings("wsetup.disable.unjoin"))));
192: }
193: } else {
194: template = buildJoinableContext(portlet, context, rundata,
195: state);
196: }
197: // build confirmation screen context
198: if (state.getAttribute(STATE_CONFIRM_VIEW_MODE) != null) {
199: if (state.getAttribute(STATE_CONFIRM_VIEW_MODE).equals(
200: "unjoinconfirm")) {
201: template = buildUnjoinconfirmContext(portlet, context,
202: rundata, state);
203: }
204: }
205: context.put("tlang", rb);
206: context.put("alertMessage", state.getAttribute(STATE_MESSAGE));
207:
208: return template;
209:
210: } // buildMainPanelContext
211:
212: /**
213: * Navigate to confirmation screen
214: */
215: public void doGoto_unjoinconfirm(RunData data) {
216: SessionState state = ((JetspeedRunData) data)
217: .getPortletSessionState(((JetspeedRunData) data)
218: .getJs_peid());
219: state.setAttribute(STATE_CONFIRM_VIEW_MODE, "unjoinconfirm");
220: String id = data.getParameters().getString("itemReference");
221: state.setAttribute(UNJOIN_SITE, id);
222: }
223:
224: /**
225: * Build context for confirmation screen
226: *
227: * @param portlet
228: * @param context
229: * @param runData
230: * @param state
231: * @return
232: */
233: public String buildUnjoinconfirmContext(VelocityPortlet portlet,
234: Context context, RunData runData, SessionState state) {
235:
236: context.put("tlang", rb);
237: if (state.getAttribute(UNJOIN_SITE) != null) {
238: try {
239: context.put("unjoinSite", SiteService.getSite(
240: ((String) state.getAttribute(UNJOIN_SITE)))
241: .getTitle());
242: } catch (IdUnusedException e) {
243: Log.warn("chef", this
244: + ".buildUnjoinconfirmContext(): " + e);
245: }
246: }
247:
248: String template = (String) getContext(runData).get("template");
249: return template + "_confirm";
250: }
251:
252: /**
253: * process unjoin
254: *
255: * @param data
256: */
257: public void doGoto_unjoinyes(RunData data) {
258: SessionState state = ((JetspeedRunData) data)
259: .getPortletSessionState(((JetspeedRunData) data)
260: .getJs_peid());
261: state.removeAttribute(STATE_CONFIRM_VIEW_MODE);
262: doUnjoin(data);
263: }
264:
265: /**
266: * cancel unjoin of site
267: *
268: * @param data
269: */
270: public void doGoto_unjoincancel(RunData data) {
271: SessionState state = ((JetspeedRunData) data)
272: .getPortletSessionState(((JetspeedRunData) data)
273: .getJs_peid());
274: state.removeAttribute(STATE_CONFIRM_VIEW_MODE);
275: }
276:
277: /**
278: * Setup for the options panel.
279: */
280: public String buildJoinableContext(VelocityPortlet portlet,
281: Context context, RunData runData, SessionState state) {
282: // the sorting sequence
283: if (state.getAttribute(JOINABLE_SORT_ASC) == null) {
284: state.setAttribute(JOINABLE_SORT_ASC, Boolean.TRUE);
285: }
286: context.put("currentSortAsc", state
287: .getAttribute(JOINABLE_SORT_ASC));
288:
289: if (state.getAttribute(SEARCH_TERM) == null) {
290: state.setAttribute(SEARCH_TERM, "");
291: }
292: context.put(SEARCH_TERM, state.getAttribute(SEARCH_TERM));
293:
294: List openSites = prepPage(state);
295: context.put("openSites", openSites);
296:
297: pagingInfoToContext(state, context);
298:
299: context.put("tlang", rb);
300:
301: String template = (String) getContext(runData).get("template");
302: return template + "_joinable";
303: }
304:
305: /**
306: * Handle the eventSubmit_doGoto_unJoinable command to shwo the list of site which are unjoinable.
307: */
308: public void doGoto_unjoinable(RunData data) {
309: SessionState state = ((JetspeedRunData) data)
310: .getPortletSessionState(((JetspeedRunData) data)
311: .getJs_peid());
312: state.removeAttribute(STATE_VIEW_MODE);
313: }
314:
315: /**
316: * Handle the eventSubmit_doGoto_unJoinable command to shwo the list of site which are joinable.
317: */
318: public void doGoto_joinable(RunData data) {
319: SessionState state = ((JetspeedRunData) data)
320: .getPortletSessionState(((JetspeedRunData) data)
321: .getJs_peid());
322: state.setAttribute(STATE_VIEW_MODE, "joinable");
323: }
324:
325: /**
326: * Handle the eventSubmit_doJoin command to have the user join one or more sites.
327: */
328: public void doJoin(RunData data) {
329: SessionState state = ((JetspeedRunData) data)
330: .getPortletSessionState(((JetspeedRunData) data)
331: .getJs_peid());
332:
333: // read the group ids to join
334: String id = data.getParameters().getString("itemReference");
335: if (id != null) {
336: try {
337: // join the site
338: SiteService.join(id);
339: String msg = rb.getString("mb.youhave2") + " "
340: + SiteService.getSite(id).getTitle();
341: addAlert(state, msg);
342: } catch (IdUnusedException e) {
343: Log.warn("chef", this + ".doJoin(): " + e);
344: } catch (PermissionException e) {
345: Log.warn("chef", this + ".doJoin(): " + e);
346: } catch (InUseException e) {
347: addAlert(state, rb.getString("mb.sitebeing"));
348: }
349: }
350:
351: // TODO: hard coding this frame id is fragile, portal dependent, and needs to be fixed -ggolden
352: // schedulePeerFrameRefresh("sitenav");
353:
354: scheduleTopRefresh();
355:
356: } // doJoin
357:
358: /**
359: * Handle the eventSubmit_doUnjoin command to have the user un-join one or more groups.
360: */
361: public void doUnjoin(RunData data) {
362: SessionState state = ((JetspeedRunData) data)
363: .getPortletSessionState(((JetspeedRunData) data)
364: .getJs_peid());
365:
366: // read the form / state to figure out which attachment(s) to add.
367: // String id = data.getParameters().getString("itemReference");
368: String id = (String) state.getAttribute(UNJOIN_SITE);
369: if (id != null) {
370: try {
371: SiteService.unjoin(id);
372: String msg = rb.getString("mb.youhave") + " "
373: + SiteService.getSite(id).getTitle();
374: addAlert(state, msg);
375: } catch (IdUnusedException ignore) {
376: } catch (PermissionException e) {
377: // This could occur if the user's role is the maintain role for the site, and we don't let the user
378: // unjoin sites they are maintainers of
379: Log.warn("chef", this + ".doUnjoin(): " + e);
380: } catch (InUseException e) {
381: Log.warn("chef", this + ".doJoin(): " + e);
382: addAlert(state, rb.getString("mb.sitebeing"));
383: }
384: }
385:
386: // TODO: hard coding this frame id is fragile, portal dependent, and needs to be fixed -ggolden
387: schedulePeerFrameRefresh("sitenav");
388:
389: } // doUnjoin
390:
391: /**
392: * toggle the sort ascending vs decending property in main view
393: */
394: public void doToggle_sort(RunData data) {
395: SessionState state = ((JetspeedRunData) data)
396: .getPortletSessionState(((JetspeedRunData) data)
397: .getJs_peid());
398:
399: if (state.getAttribute(SORT_ASC) != null) {
400: state.setAttribute(SORT_ASC, new Boolean(!((Boolean) state
401: .getAttribute(SORT_ASC)).booleanValue()));
402: }
403: } // doToggle_sort
404:
405: /**
406: * toggle the sort ascending vs decending property in joinable view
407: */
408: public void doToggle_joinable_sort(RunData data) {
409: SessionState state = ((JetspeedRunData) data)
410: .getPortletSessionState(((JetspeedRunData) data)
411: .getJs_peid());
412:
413: if (state.getAttribute(JOINABLE_SORT_ASC) != null) {
414: state.setAttribute(JOINABLE_SORT_ASC, new Boolean(
415: !((Boolean) state.getAttribute(JOINABLE_SORT_ASC))
416: .booleanValue()));
417: }
418: }
419: }
|