/**
* Copyright (C) 2009 eXo Platform SAS.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.exoplatform.portal.webui.page;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.ResourceBundle;
import javax.portlet.ActionResponse;
import javax.xml.namespace.QName;
import org.exoplatform.commons.serialization.api.annotations.Serialized;
import org.exoplatform.portal.application.PortalRequestContext;
import org.exoplatform.portal.config.DataStorage;
import org.exoplatform.portal.config.Query;
import org.exoplatform.portal.config.UserACL;
import org.exoplatform.portal.config.UserPortalConfigService;
import org.exoplatform.portal.config.model.ModelObject;
import org.exoplatform.portal.config.model.Page;
import org.exoplatform.portal.config.model.PortalConfig;
import org.exoplatform.portal.mop.SiteKey;
import org.exoplatform.portal.mop.navigation.Scope;
import org.exoplatform.portal.mop.page.PageContext;
import org.exoplatform.portal.mop.page.PageKey;
import org.exoplatform.portal.mop.page.PageService;
import org.exoplatform.portal.mop.page.PageState;
import org.exoplatform.portal.mop.user.UserNavigation;
import org.exoplatform.portal.mop.user.UserNode;
import org.exoplatform.portal.mop.user.UserPortal;
import org.exoplatform.portal.webui.application.UIPortlet;
import org.exoplatform.portal.webui.portal.PageNodeEvent;
import org.exoplatform.portal.webui.portal.UIPortal;
import org.exoplatform.portal.webui.util.PortalDataMapper;
import org.exoplatform.portal.webui.util.Util;
import org.exoplatform.portal.webui.workspace.UIMaskWorkspace;
import org.exoplatform.portal.webui.workspace.UIPortalApplication;
import org.exoplatform.portal.webui.workspace.UIWorkingWorkspace;
import org.exoplatform.web.application.ApplicationMessage;
import org.exoplatform.webui.application.WebuiRequestContext;
import org.exoplatform.webui.config.annotation.ComponentConfig;
import org.exoplatform.webui.config.annotation.ComponentConfigs;
import org.exoplatform.webui.config.annotation.EventConfig;
import org.exoplatform.webui.config.annotation.ParamConfig;
import org.exoplatform.webui.core.UIApplication;
import org.exoplatform.webui.core.UIComponent;
import org.exoplatform.webui.core.UIContainer;
import org.exoplatform.webui.core.UIPopupWindow;
import org.exoplatform.webui.core.UIRepeater;
import org.exoplatform.webui.core.UIVirtualList;
import org.exoplatform.webui.core.lifecycle.UIFormLifecycle;
import org.exoplatform.webui.core.model.SelectItemOption;
import org.exoplatform.webui.event.Event;
import org.exoplatform.webui.event.Event.Phase;
import org.exoplatform.webui.event.EventListener;
import org.exoplatform.webui.form.UIForm;
import org.exoplatform.webui.form.UIFormInputSet;
import org.exoplatform.webui.form.UIFormSelectBox;
import org.exoplatform.webui.form.UIFormStringInput;
@ComponentConfigs({
@ComponentConfig(template = "system:/groovy/portal/webui/page/UIPageBrowser.gtmpl", events = {
@EventConfig(listeners = UIPageBrowser.DeleteActionListener.class, confirm = "UIPageBrowse.deletePage"),
@EventConfig(listeners = UIPageBrowser.EditInfoActionListener.class),
@EventConfig(listeners = UIPageBrowser.AddNewActionListener.class) }),
@ComponentConfig(id = "UIBrowserPageForm", type = UIPageForm.class, lifecycle = UIFormLifecycle.class, template = "system:/groovy/webui/form/UIFormTabPane.gtmpl", events = {
@EventConfig(listeners = UIPageBrowser.SavePageActionListener.class, name = "Save"),
@EventConfig(listeners = UIPageForm.ChangeOwnerTypeActionListener.class, phase = Phase.DECODE),
@EventConfig(listeners = UIPageForm.ChangeOwnerIdActionListener.class, phase = Phase.DECODE),
@EventConfig(listeners = UIPageForm.SelectMembershipActionListener.class, phase = Phase.DECODE),
@EventConfig(listeners = UIMaskWorkspace.CloseActionListener.class, phase = Phase.DECODE) }, initParams = @ParamConfig(name = "PageTemplate", value = "system:/WEB-INF/conf/uiconf/portal/webui/page/PageTemplate.groovy")),
@ComponentConfig(type = UIFormInputSet.class, id = "PermissionSetting", template = "system:/groovy/webui/core/UITabSelector.gtmpl", events = { @EventConfig(listeners = UIFormInputSet.SelectComponentActionListener.class) }) })
@Serialized
public class UIPageBrowser extends UIContainer {
public static final String[] BEAN_FIELD = { "pageId", "title", "accessPermissions", "editPermission" };
public static final String[] ACTIONS = { "EditInfo", "Delete" };
private boolean showAddNewPage = false;
protected String pageSelectedId_;
private List<SelectItemOption<String>> OPTIONS = new ArrayList<SelectItemOption<String>>(2);
private Query<Page> lastQuery_;
public UIPageBrowser() throws Exception {
WebuiRequestContext contextui = WebuiRequestContext.getCurrentInstance();
ResourceBundle res = contextui.getApplicationResourceBundle();
OPTIONS.add(new SelectItemOption<String>(res.getString("UIPageSearchForm.label.option.portal"), "portal"));
OPTIONS.add(new SelectItemOption<String>(res.getString("UIPageSearchForm.label.option.group"), "group"));
UIPageSearchForm uiSearchForm = addChild(UIPageSearchForm.class, null, null);
uiSearchForm.setOptions(OPTIONS);
uiSearchForm.setId("UIPageSearchForm");
UIRepeater uiRepeater = createUIComponent(UIRepeater.class, null, null);
uiRepeater.configure("pageId", BEAN_FIELD, ACTIONS);
lastQuery_ = new Query<Page>(null, null, null, null, Page.class);
lastQuery_.setOwnerType(OPTIONS.get(0).getValue());
UIVirtualList virtualList = addChild(UIVirtualList.class, null, null);
virtualList.setUIComponent(uiRepeater);
}
public Query<Page> getLastQuery() {
return lastQuery_;
}
public Query<Page> getQuery(UIFormInputSet searchInputs) {
Query<Page> query = new Query<Page>(null, null, null, null, Page.class);
UIFormStringInput titleInput = (UIFormStringInput) searchInputs.getChild(0);
UIFormStringInput siteNameInput = (UIFormStringInput) searchInputs.getChild(1);
UIFormSelectBox select = (UIFormSelectBox) searchInputs.getChild(2);
String siteName = siteNameInput.getValue();
String title = titleInput.getValue();
String ownerType = select.getValue();
if (title != null) {
query.setTitle(title.trim());
}
if (siteName != null && !siteName.trim().equals("")) {
query.setOwnerId(siteName.trim());
}
query.setOwnerType(ownerType);
query.setName(null);
return query;
}
/**
* Update data feed in UIRepeater with a given query. Returns false if no result is found, true other wise
*
* @param query
* @return
* @throws Exception
*/
public boolean feedDataWithQuery(Query<Page> query) throws Exception {
lastQuery_ = query;
UIVirtualList virtualList = getChild(UIVirtualList.class);
if (lastQuery_ == null) {
lastQuery_ = new Query<Page>(null, null, null, null, Page.class);
}
// virtualList.dataBind(new PageQueryAccessList(lastQuery_, 10));
virtualList.dataBind(new PageIterator(lastQuery_.getOwnerType(), lastQuery_.getOwnerId(), lastQuery_.getName(),
lastQuery_.getTitle(), 10));
//
UIRepeater repeater = (UIRepeater) virtualList.getRepeater();
if (repeater.hasNext()) {
return true;
} else {
return false;
}
}
/**
* Show a popup informing that no result available for the last query
*
*/
public static void showNoResultMessagePopup() {
UIApplication uiApp = Util.getPortalRequestContext().getUIApplication();
uiApp.addMessage(new ApplicationMessage("UISearchForm.msg.empty", null));
}
public void quickSearch(UIFormInputSet quickSearchInput) throws Exception {
lastQuery_ = this.getQuery(quickSearchInput);
boolean dataAvailable = feedDataWithQuery(lastQuery_);
if (!dataAvailable) {
showNoResultMessagePopup();
}
if (this.<UIComponent> getParent() instanceof UIPopupWindow) {
UIPopupWindow popupWindow = getParent();
popupWindow.setShow(true);
}
}
public boolean isShowAddNewPage() {
return showAddNewPage;
}
public void setShowAddNewPage(boolean showAddNewPage) {
this.showAddNewPage = showAddNewPage;
}
public void processDecode(WebuiRequestContext context) throws Exception {
super.processDecode(context);
UIForm uiForm = getAncestorOfType(UIForm.class);
String action = null;
if (uiForm != null) {
action = uiForm.getSubmitAction();
} else {
action = context.getRequestParameter(UIForm.ACTION);
}
if (action == null)
return;
Event<UIComponent> event = createEvent(action, Event.Phase.PROCESS, context);
if (event != null)
event.broadcast();
}
public void advancedSearch(UIFormInputSet advancedSearchInput) {
}
public static class DeleteActionListener extends EventListener<UIPageBrowser> {
public void execute(Event<UIPageBrowser> event) throws Exception {
UIPageBrowser uiPageBrowser = event.getSource();
WebuiRequestContext context = event.getRequestContext();
String id = context.getRequestParameter(OBJECTID);
UserPortalConfigService service = uiPageBrowser.getApplicationComponent(UserPortalConfigService.class);
UIApplication uiApp = context.getUIApplication();
PageContext page = (id != null) ? service.getPageService().loadPage(PageKey.parse(id)) : null;
if (page == null) {
uiApp.addMessage(new ApplicationMessage("UIPageBrowser.msg.PageNotExist", new String[] { id }, 1));
return;
}
UserACL userACL = uiPageBrowser.getApplicationComponent(UserACL.class);
if (!userACL.hasEditPermission(page)) {
uiApp.addMessage(new ApplicationMessage("UIPageBrowser.msg.delete.NotDelete", new String[] { id }, 1));
return;
}
UIPortal uiPortal = Util.getUIPortal();
UserNode userNode = uiPortal.getSelectedUserNode();
boolean isDeleteCurrentPage = page.getKey().equals(userNode.getPageRef());
service.getPageService().destroyPage(page.getKey());
// Minh Hoang TO: The cached UIPage objects corresponding to removed Page should be removed here.
// As we have multiple UIPortal, which means multiple caches of UIPage. It 's unwise to garbage
// all UIPage caches at once. Better solution is to clear UIPage on browsing to PageNode having Page
// removed
if (isDeleteCurrentPage) {
SiteKey siteKey = userNode.getNavigation().getKey();
PageNodeEvent<UIPortalApplication> pnevent = new PageNodeEvent<UIPortalApplication>(
Util.getUIPortalApplication(), PageNodeEvent.CHANGE_NODE, siteKey, userNode.getURI());
uiPortal.broadcast(pnevent, Phase.PROCESS);
} else {
boolean dataAvailable = uiPageBrowser.feedDataWithQuery(uiPageBrowser.getLastQuery());
if (!dataAvailable) {
showNoResultMessagePopup();
}
event.getRequestContext().addUIComponentToUpdateByAjax(uiPageBrowser);
}
}
/**
*
* This method remove User Page node that reference to page. If page is exist, remove User Page node. If page is not
* exist, do nothing.
*
* @param page the page is referenced by User Page node
* @param event
* @throws Exception any exception
*/
private void removePageNode(PageContext page, Event<UIPageBrowser> event) throws Exception {
PortalRequestContext prc = Util.getPortalRequestContext();
UserPortal userPortal = prc.getUserPortalConfig().getUserPortal();
UserNavigation userNav = userPortal.getNavigation(SiteKey.user(event.getRequestContext().getRemoteUser()));
UserNode rootNode = userPortal.getNode(userNav, Scope.CHILDREN, null, null);
if (rootNode == null) {
return;
}
for (UserNode userNode : rootNode.getChildren()) {
if (page.getKey().equals(userNode.getPageRef())) {
// Remove pageNode
rootNode.removeChild(userNode.getName());
userPortal.saveNode(rootNode, null);
// Update navigation and UserToolbarGroupPortlet
String pageRef = page.getKey().format();
if (pageRef != null && pageRef.length() > 0) {
// Remove from cache
UIPortal uiPortal = Util.getUIPortal();
uiPortal.clearUIPage(pageRef);
}
// Update UserToolbarDashboardPortlet
ActionResponse actResponse = event.getRequestContext().getResponse();
actResponse.setEvent(new QName("NavigationChange"), userNode.getName());
return;
}
}
}
}
public static class EditInfoActionListener extends EventListener<UIPageBrowser> {
public void execute(Event<UIPageBrowser> event) throws Exception {
UIPageBrowser uiPageBrowser = event.getSource();
WebuiRequestContext context = event.getRequestContext();
PortalRequestContext pcontext = (PortalRequestContext) context.getParentAppRequestContext();
UIPortalApplication uiPortalApp = (UIPortalApplication) pcontext.getUIApplication();
String id = context.getRequestParameter(OBJECTID);
UserPortalConfigService service = uiPageBrowser.getApplicationComponent(UserPortalConfigService.class);
// Check existence of the page
PageContext pageContext = (id != null) ? service.getPage(PageKey.parse(id)) : null;
if (pageContext == null) {
uiPortalApp.addMessage(new ApplicationMessage("UIPageBrowser.msg.PageNotExist", new String[] { id }, 1));
return;
}
// Check current user 's permissions on the page
UserACL userACL = uiPageBrowser.getApplicationComponent(UserACL.class);
if (!userACL.hasEditPermission(pageContext)) {
uiPortalApp.addMessage(new ApplicationMessage("UIPageBrowser.msg.edit.NotEditPage", new String[] { id }, 1));
return;
}
// Need this code to override editpage action in extension project
UIPageFactory clazz = UIPageFactory.getInstance(pageContext.getState().getFactoryId());
UIPage uipage = clazz.createUIPage(null);
Page page = service.getDataStorage().getPage(id);
pageContext.update(page);
uipage.switchToEditMode(page);
}
}
public static class AddNewActionListener extends EventListener<UIPageBrowser> {
public void execute(Event<UIPageBrowser> event) throws Exception {
PortalRequestContext prContext = Util.getPortalRequestContext();
UIPortalApplication uiApp = (UIPortalApplication) prContext.getUIApplication();
UIMaskWorkspace uiMaskWS = uiApp.getChildById(UIPortalApplication.UI_MASK_WS_ID);
UIPageForm uiPageForm = uiMaskWS.createUIComponent(UIPageForm.class, "UIBrowserPageForm", "UIPageForm");
uiPageForm.buildForm(null);
uiMaskWS.setUIComponent(uiPageForm);
uiMaskWS.setShow(true);
UIFormSelectBox slcOwnerType = uiPageForm.getUIFormSelectBox(UIPageForm.OWNER_TYPE);
List<SelectItemOption<String>> types = slcOwnerType.getOptions();
for (int i = 0; i < types.size(); i++) {
if (PortalConfig.USER_TYPE.equals(types.get(i).getValue())) {
types.remove(types.get(i));
break;
}
}
slcOwnerType.setOptions(types);
Event<UIComponent> slcEvent = uiPageForm.createEvent("ChangeOwnerType", Phase.DECODE, event.getRequestContext());
slcEvent.broadcast();
prContext.addUIComponentToUpdateByAjax(uiMaskWS);
}
}
public static class SavePageActionListener extends UIPageForm.SaveActionListener {
public void execute(Event<UIPageForm> event) throws Exception {
UIPageForm uiPageForm = event.getSource();
UIPortalApplication uiPortalApp = uiPageForm.getAncestorOfType(UIPortalApplication.class);
PortalRequestContext pcontext = Util.getPortalRequestContext();
UIPage uiPage = uiPageForm.getUIPage();
Page page = new Page();
uiPageForm.invokeSetBindingBean(page);
DataStorage dataService = uiPageForm.getApplicationComponent(DataStorage.class);
// create new page
if (uiPage == null) {
PageService pageService = uiPageForm.getApplicationComponent(PageService.class);
PageContext existPage = pageService.loadPage(page.getPageKey());
if (existPage != null) {
uiPortalApp.addMessage(new ApplicationMessage("UIPageForm.msg.sameName", null));
return;
}
page.setModifiable(true);
if (page.getChildren() == null) {
page.setChildren(new ArrayList<ModelObject>());
}
//
PageState pageState = new PageState(page.getTitle(), page.getDescription(), page.isShowMaxWindow(),
page.getFactoryId(), page.getAccessPermissions() != null ? Arrays.asList(page.getAccessPermissions())
: null, page.getEditPermission());
pageService.savePage(new PageContext(page.getPageKey(), pageState));
//
dataService.save(page);
postSave(uiPortalApp, pcontext);
return;
}
page.setOwnerType(uiPage.getSiteKey().getTypeName());
List<UIPortlet> uiPortlets = new ArrayList<UIPortlet>();
findAllPortlet(uiPortlets, uiPage);
ArrayList<ModelObject> applications = new ArrayList<ModelObject>();
for (UIPortlet uiPortlet : uiPortlets) {
applications.add(PortalDataMapper.buildModelObject(uiPortlet));
}
List<UIComponent> uiChildren = uiPage.getChildren();
if (uiChildren == null)
return;
ArrayList<ModelObject> children = new ArrayList<ModelObject>();
for (UIComponent child : uiChildren) {
ModelObject component = PortalDataMapper.buildModelObject(child);
if (component != null)
children.add(component);
}
page.setChildren(children);
uiPage.getChildren().clear();
PortalDataMapper.toUIPage(uiPage, page);
// if (page.getTemplate() == null) page.setTemplate(uiPage.getTemplate());
if (page.getChildren() == null)
page.setChildren(new ArrayList<ModelObject>());
}
private void postSave(UIPortalApplication uiPortalApp, WebuiRequestContext context) throws Exception {
UIMaskWorkspace uiMaskWS = uiPortalApp.getChildById(UIPortalApplication.UI_MASK_WS_ID);
uiMaskWS.createEvent("Close", Phase.DECODE, context).broadcast();
UIWorkingWorkspace uiWorkWS = uiPortalApp.getChildById(UIPortalApplication.UI_WORKING_WS_ID);
uiWorkWS.updatePortletsByName("PageManagementPortlet");
}
}
}