001: /******************************************************************************
002: * JBoss, a division of Red Hat *
003: * Copyright 2006, Red Hat Middleware, LLC, and individual *
004: * contributors as indicated by the @authors tag. See the *
005: * copyright.txt in the distribution for a full listing of *
006: * individual contributors. *
007: * *
008: * This is free software; you can redistribute it and/or modify it *
009: * under the terms of the GNU Lesser General Public License as *
010: * published by the Free Software Foundation; either version 2.1 of *
011: * the License, or (at your option) any later version. *
012: * *
013: * This software is distributed in the hope that it will be useful, *
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of *
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
016: * Lesser General Public License for more details. *
017: * *
018: * You should have received a copy of the GNU Lesser General Public *
019: * License along with this software; if not, write to the Free *
020: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
021: * 02110-1301 USA, or see the FSF site: http://www.fsf.org. *
022: ******************************************************************************/package org.jboss.portal.core.admin.ui.common;
023:
024: import org.jboss.portal.Mode;
025: import org.jboss.portal.core.admin.ui.actions.WindowComparator;
026: import org.jboss.portal.core.impl.model.content.ContentProviderRegistryService;
027: import org.jboss.portal.core.model.content.Content;
028: import org.jboss.portal.core.model.content.ContentType;
029: import org.jboss.portal.core.model.content.spi.ContentProvider;
030: import org.jboss.portal.core.model.content.spi.portlet.ContentPortlet;
031: import org.jboss.portal.core.model.portal.DuplicatePortalObjectException;
032: import org.jboss.portal.core.model.portal.NoSuchPortalObjectException;
033: import org.jboss.portal.core.model.portal.Page;
034: import org.jboss.portal.core.model.portal.PortalObject;
035: import org.jboss.portal.core.model.portal.Window;
036: import org.jboss.portal.faces.component.portlet.PortletActionEvent;
037: import org.jboss.portal.faces.component.portlet.PortletRenderEvent;
038: import org.jboss.portal.faces.el.PropertyValue;
039: import org.jboss.portal.faces.el.dynamic.DynamicBean;
040: import org.jboss.portal.portlet.PortletInvoker;
041: import org.jboss.portal.theme.LayoutService;
042: import org.jboss.portal.theme.PortalLayout;
043: import org.jboss.portal.theme.ThemeConstants;
044:
045: import javax.faces.application.FacesMessage;
046: import javax.faces.context.FacesContext;
047: import javax.faces.event.AbortProcessingException;
048: import javax.faces.event.ActionEvent;
049: import javax.faces.model.SelectItem;
050: import java.util.ArrayList;
051: import java.util.Collections;
052: import java.util.HashMap;
053: import java.util.Iterator;
054: import java.util.LinkedHashMap;
055: import java.util.LinkedList;
056: import java.util.List;
057: import java.util.Map;
058: import java.util.SortedSet;
059: import java.util.TreeSet;
060:
061: /**
062: * @author <a href="mailto:julien@jboss.org">Julien Viet</a>
063: * @version $Revision: 9088 $
064: */
065: public class PageManagerBean {
066:
067: /** . */
068: private static final String CONTENT_ACTION_SELECT = "content.action.select";
069:
070: /** . */
071: private static final String CONTENT_URI = "content.uri";
072:
073: /** . */
074: private static final String CONTENT_PARAM_PREFIX = "content.param.";
075:
076: /** . */
077: private static final int CONTENT_PARAM_PREFIX_LENGTH = CONTENT_PARAM_PREFIX
078: .length();
079:
080: /** . */
081: private static final int MOVE_UP = 'u';
082:
083: /** . */
084: private static final int MOVE_DOWN = 'd';
085:
086: /** . */
087: private static final int MOVE_LEFT = 'l';
088:
089: /** . */
090: private static final int ADD_ACTION = 'a';
091:
092: public PageManagerBean(LayoutService layoutService,
093: PortletInvoker portletInvoker) {
094: this .layoutService = layoutService;
095: this .portletInvoker = portletInvoker;
096: this .selectedContentType = ContentType.PORTLET;
097: this .selectedRenderParameters = new HashMap();
098: }
099:
100: /** . */
101: public final LayoutService layoutService;
102:
103: /** . */
104: public final PortletInvoker portletInvoker;
105:
106: /** . */
107: public Page page;
108:
109: /** . */
110: private ContentType selectedContentType;
111:
112: /** . */
113: public DynamicMap assignedWindows = new DynamicMap();
114:
115: /** . */
116: public String selectedContentURI;
117:
118: /** . */
119: public Map selectedContentParameters;
120:
121: /** . */
122: public Map selectedRenderParameters;
123:
124: public List getContentTypeItems() {
125: LinkedList types = new LinkedList();
126: for (Iterator i = ContentProviderRegistryService.getInstance()
127: .getContentTypes().iterator(); i.hasNext();) {
128: ContentType contentType = (ContentType) i.next();
129: SelectItem item = new SelectItem();
130: item.setValue(contentType);
131: item.setLabel(contentType.toString());
132: if (contentType.equals(ContentType.PORTLET)) {
133: types.addFirst(item);
134: } else {
135: types.addLast(item);
136: }
137: }
138: return types;
139: }
140:
141: public ContentType getSelectedContentType() {
142: return selectedContentType;
143: }
144:
145: public void setSelectedContentType(ContentType selectedContentType) {
146: this .selectedContentType = selectedContentType;
147: this .selectedContentURI = null;
148: this .selectedContentParameters = null;
149: this .selectedRenderParameters = new HashMap();
150: }
151:
152: public String getSelectedEditorPortletId() {
153: if (selectedContentType != null) {
154: return ContentProviderRegistryService.getInstance()
155: .getContentProvider(selectedContentType)
156: .getPortletInfo().getPortletName(
157: ContentPortlet.EDIT_CONTENT_MODE);
158: } else {
159: return null;
160: }
161: }
162:
163: protected String createWindowName(String contentType,
164: String contentURI, boolean appendNumber) {
165: String windowName = null;
166: ContentProvider contentProvider = ContentProviderRegistryService
167: .getInstance().getContentProvider(
168: ContentType.create(contentType));
169: String instanceName = contentProvider.getPortletInfo()
170: .getPortletName(Mode.VIEW);
171:
172: if (instanceName == null) {
173: // Content type portlet: use URI (PortletInstance)
174: windowName = contentURI;
175: } else {
176: // Always append a random number for content portlets
177: // e.g. a widget with the same name is not refreshed until the session is destroyed although the content.uri changed
178: appendNumber = true;
179: windowName = instanceName;
180: }
181:
182: //
183: if (windowName.indexOf("Instance") != -1) {
184: // Replace the instance with window
185: windowName = windowName.replace("Instance", "Window");
186: } else {
187: // Or just append window
188: windowName = windowName + "Window";
189: }
190:
191: //
192: if (appendNumber) {
193: // if the window already exists add a random number
194: return windowName + "_" + (int) (100 * Math.random());
195: } else {
196: // Just the window without any number
197: return windowName;
198: }
199: }
200:
201: public void assignWindows(ActionEvent event) {
202: String id = event.getComponent().getId();
203: char direction = id.charAt(0);
204: String regionName = id.substring(2);
205:
206: // Contains the names selected window in the UI
207: List selectedWindows = (List) assignedWindows.values
208: .get(regionName);
209:
210: // Get the windows belonging to the selected region sorted by order
211: List windows = new ArrayList();
212: for (Iterator i = page.getChildren(PortalObject.WINDOW_MASK)
213: .iterator(); i.hasNext();) {
214: Window window = (Window) i.next();
215: if (regionName.equals(window
216: .getProperty(ThemeConstants.PORTAL_PROP_REGION))) {
217: windows.add(window);
218: }
219: }
220: Collections.sort(windows, new WindowComparator());
221:
222: //
223: if (direction == MOVE_UP || direction == MOVE_DOWN) {
224: //
225: int index = direction == MOVE_UP ? 1 : windows.size() - 2;
226: int length = windows.size() - 1;
227: int step = direction == MOVE_UP ? 1 : -1;
228:
229: // Perform swaps
230: while (length-- > 0) {
231: Window window = (Window) windows.get(index);
232: if (selectedWindows.contains(window.getName())) {
233: Collections.swap(windows, index - step, index);
234: }
235: index += step;
236: }
237: } else if (direction == ADD_ACTION) {
238: if (selectedContentURI != null) {
239: //
240: String selectedContentURI = this .selectedContentURI;
241: Map selectedContentParams = this .selectedContentParameters;
242:
243: // Reset to new state
244: this .selectedContentURI = null;
245: this .selectedContentParameters = null;
246: this .selectedRenderParameters = new HashMap();
247:
248: // Obtain a window name
249: String windowName = (String) FacesContext
250: .getCurrentInstance().getExternalContext()
251: .getRequestParameterMap().get("blah");
252: if (windowName.trim().length() == 0) {
253: windowName = createWindowName(selectedContentType
254: .toString(), selectedContentURI, false);
255: while (page.getWindow(windowName) != null) {
256: windowName = createWindowName(
257: selectedContentType.toString(),
258: selectedContentURI, true);
259: }
260: }
261:
262: // Check for duplicate window name
263: if (page.getWindow(windowName) != null) {
264: FacesContext faces = FacesContext
265: .getCurrentInstance();
266: FacesMessage message = new FacesMessage(
267: FacesMessage.SEVERITY_ERROR,
268: "Duplicate window name found on this page!",
269: null);
270: faces.addMessage("windowName", message);
271: throw new AbortProcessingException();
272: }
273:
274: //
275: try {
276: Window window = page.createWindow(windowName,
277: selectedContentType, selectedContentURI);
278: Content content = window.getContent();
279: for (Iterator i = selectedContentParams.entrySet()
280: .iterator(); i.hasNext();) {
281: Map.Entry entry = (Map.Entry) i.next();
282: String paramName = (String) entry.getKey();
283: String paramValue = (String) entry.getValue();
284: content.setParameter(paramName, paramValue);
285: }
286:
287: //
288: window.setDeclaredProperty(
289: ThemeConstants.PORTAL_PROP_REGION,
290: regionName);
291: window.setDeclaredProperty(
292: ThemeConstants.PORTAL_PROP_ORDER, ""
293: + Integer.MAX_VALUE);
294:
295: // Sort windows
296: Collections.sort(windows, new WindowComparator());
297:
298: // Add the created one
299: windows.add(window);
300:
301: // Update the order states
302: for (int i = 0; i < windows.size(); i++) {
303: Window tmp = (Window) windows.get(i);
304: tmp.setDeclaredProperty(
305: ThemeConstants.PORTAL_PROP_ORDER, ""
306: + i);
307: }
308:
309: this .windowName = "";
310: } catch (DuplicatePortalObjectException unexpected) {
311: unexpected.printStackTrace();
312: }
313: } else {
314: FacesContext faces = FacesContext.getCurrentInstance();
315: FacesMessage message = new FacesMessage(
316: FacesMessage.SEVERITY_ERROR,
317: "No content was selected!", null);
318: faces.addMessage("layoutForm", message);
319: throw new AbortProcessingException();
320: }
321: } else if (direction == MOVE_LEFT) {
322: for (Iterator i = windows.iterator(); i.hasNext();) {
323: Window window = (Window) i.next();
324: if (selectedWindows.contains(window.getName())) {
325: i.remove();
326: try {
327: page.destroyChild(window.getName());
328: } catch (NoSuchPortalObjectException ignore) {
329: ignore.printStackTrace();
330: }
331: }
332: }
333: }
334:
335: // Update the order states
336: for (int i = 0; i < windows.size(); i++) {
337: Window window = (Window) windows.get(i);
338: window.setDeclaredProperty(
339: ThemeConstants.PORTAL_PROP_ORDER, "" + i);
340: }
341:
342: //
343: assignedWindows.values.clear();
344: }
345:
346: private String windowName;
347:
348: public String getWindowName() {
349: return windowName;
350: }
351:
352: public void setWindowName(String windowName) {
353: this .windowName = windowName;
354: }
355:
356: /** Portlet event */
357: public void assignWindow(ActionEvent event) {
358: if (event instanceof PortletRenderEvent) {
359: PortletRenderEvent renderEvent = (PortletRenderEvent) event;
360: Map renderParams = renderEvent.getParameterMap();
361:
362: // Keep window name and region defined
363: setWindowName(((String[]) renderParams.get("windowName"))[0]);
364: } else if (event instanceof PortletActionEvent) {
365: PortletActionEvent actionEvent = (PortletActionEvent) event;
366: Map actionParams = actionEvent.getParameterMap();
367:
368: // Keep window name and region defined
369: String[] windowNames = ((String[]) actionParams
370: .get("windowName"));
371: if (windowNames != null && windowNames.length > 0) {
372: setWindowName(windowNames[0]);
373: }
374:
375: //
376: if (actionParams.get(CONTENT_ACTION_SELECT) != null) {
377: String[] uris = (String[]) actionParams
378: .get(CONTENT_URI);
379: if (uris != null && uris.length > 0) {
380: String uri = uris[0];
381:
382: //
383: Map parameters = new HashMap();
384: for (Iterator i = actionParams.entrySet()
385: .iterator(); i.hasNext();) {
386: Map.Entry entry = (Map.Entry) i.next();
387: String name = (String) entry.getKey();
388: if (name.startsWith(CONTENT_PARAM_PREFIX)) {
389: String paramName = name
390: .substring(CONTENT_PARAM_PREFIX_LENGTH);
391: String paramValue = ((String[]) entry
392: .getValue())[0];
393: parameters.put(paramName, paramValue);
394: }
395: }
396:
397: //
398: this .selectedContentURI = uri;
399: this .selectedContentParameters = parameters;
400: }
401: }
402: }
403: }
404:
405: /** Return the <Region>List on the selected object which must be a page. */
406: public List getRegionNames() {
407: try {
408: Map windows = getWindows(page);
409:
410: //
411: List regions = new ArrayList(windows.keySet());
412: regions.remove("unknown");
413: Collections.sort(regions);
414:
415: //
416: return regions;
417: } catch (Exception e) {
418: e.printStackTrace();
419:
420: //
421: return Collections.EMPTY_LIST;
422: }
423: }
424:
425: public List getRegionItems() {
426: try {
427: Map windows = getWindows(page);
428:
429: // We don't want the unknown region
430: windows.remove("unknown");
431:
432: //
433: ArrayList regions = new ArrayList(windows.keySet());
434: Collections.sort(regions);
435: for (int i = 0; i < regions.size(); i++) {
436: String regionName = (String) regions.get(i);
437: SelectItem regionItem = new SelectItem(regionName,
438: regionName);
439: regions.set(i, regionItem);
440: }
441:
442: //
443: return regions;
444: } catch (Exception e) {
445: e.printStackTrace();
446:
447: //
448: return Collections.EMPTY_LIST;
449: }
450: }
451:
452: public Map getWindowItemsMap() throws Exception {
453: Map windowMap = getWindows(page);
454: for (Iterator i = windowMap.entrySet().iterator(); i.hasNext();) {
455: Map.Entry entry = (Map.Entry) i.next();
456: SortedSet windows = (SortedSet) entry.getValue();
457: ArrayList windowItems = new ArrayList(windows.size());
458: for (Iterator j = windows.iterator(); j.hasNext();) {
459: Window window = (Window) j.next();
460: SelectItem windowItem = new SelectItem();
461: windowItem.setValue(window.getName());
462: windowItem.setLabel(window.getName());
463: windowItems.add(windowItem);
464: }
465: entry.setValue(windowItems);
466: }
467: return windowMap;
468: }
469:
470: /** Returns a <Region,<Window>SortedSet>Map. */
471: private Map getWindows(Page page) throws Exception {
472: // Get the layout
473: String layoutId = page
474: .getProperty(ThemeConstants.PORTAL_PROP_LAYOUT);
475: PortalLayout layout = layoutService.getLayout(layoutId, true);
476:
477: //
478: LinkedHashMap windows = new LinkedHashMap();
479: for (Iterator i = layout.getLayoutInfo().getRegionNames()
480: .iterator(); i.hasNext();) {
481: String region = (String) i.next();
482: windows.put(region, new TreeSet(new WindowComparator()));
483: }
484: windows.put("unknown", new TreeSet(new WindowComparator()));
485:
486: //
487: for (Iterator j = page.getChildren(PortalObject.WINDOW_MASK)
488: .iterator(); j.hasNext();) {
489: PortalObject window = (PortalObject) j.next();
490: String region = window
491: .getProperty(ThemeConstants.PORTAL_PROP_REGION);
492: if (!windows.containsKey(region)) {
493: region = "unknown";
494: }
495: SortedSet set = (SortedSet) windows.get(region);
496: set.add(window);
497: }
498: return windows;
499: }
500:
501: public static class DynamicMap implements DynamicBean {
502:
503: /** . */
504: private Map values = new HashMap();
505:
506: public Class getType(Object propertyName)
507: throws IllegalArgumentException {
508: return List.class;
509: }
510:
511: public PropertyValue getValue(Object propertyName)
512: throws IllegalArgumentException {
513: List list = (List) values.get(propertyName);
514: if (list == null) {
515: list = new ArrayList();
516: values.put(propertyName, list);
517: }
518: return new PropertyValue(list);
519: }
520:
521: public boolean setValue(Object propertyName, Object value)
522: throws IllegalArgumentException {
523: values.put(propertyName, value);
524: return true;
525: }
526: }
527: }
|