All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opencms.ui.CmsVaadinUtils Maven / Gradle / Ivy

Go to download

OpenCms is an enterprise-ready, easy to use website content management system based on Java and XML technology. Offering a complete set of features, OpenCms helps content managers worldwide to create and maintain beautiful websites fast and efficiently.

There is a newer version: 17.0
Show newest version
/*
 * This library is part of OpenCms -
 * the Open Source Content Management System
 *
 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
 *
 * This library 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 library 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.
 *
 * For further information about Alkacon Software, please see the
 * company website: http://www.alkacon.com
 *
 * For further information about OpenCms, please see the
 * project website: http://www.opencms.org
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package org.opencms.ui;

import org.opencms.ade.galleries.CmsSiteSelectorOptionBuilder;
import org.opencms.ade.galleries.shared.CmsSiteSelectorOption;
import org.opencms.configuration.preferences.CmsLanguagePreference;
import org.opencms.db.CmsUserSettings;
import org.opencms.file.CmsGroup;
import org.opencms.file.CmsObject;
import org.opencms.file.CmsProject;
import org.opencms.file.CmsUser;
import org.opencms.file.types.A_CmsResourceTypeFolderBase;
import org.opencms.file.types.CmsResourceTypeXmlContent;
import org.opencms.file.types.I_CmsResourceType;
import org.opencms.i18n.CmsEncoder;
import org.opencms.i18n.CmsMessages;
import org.opencms.i18n.I_CmsMessageBundle;
import org.opencms.main.CmsException;
import org.opencms.main.CmsLog;
import org.opencms.main.OpenCms;
import org.opencms.security.CmsOrganizationalUnit;
import org.opencms.security.CmsRole;
import org.opencms.security.I_CmsPrincipal;
import org.opencms.ui.apps.CmsAppWorkplaceUi;
import org.opencms.ui.apps.Messages;
import org.opencms.ui.apps.user.CmsOUHandler;
import org.opencms.ui.components.OpenCmsTheme;
import org.opencms.ui.contextmenu.CmsContextMenu;
import org.opencms.ui.contextmenu.I_CmsSimpleContextMenuEntry;
import org.opencms.util.CmsFileUtil;
import org.opencms.util.CmsMacroResolver;
import org.opencms.util.CmsStringUtil;
import org.opencms.util.CmsUUID;
import org.opencms.workplace.CmsWorkplace;
import org.opencms.workplace.CmsWorkplaceMessages;
import org.opencms.workplace.explorer.CmsExplorerTypeSettings;
import org.opencms.workplace.explorer.CmsResourceUtil;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.ClassUtils;
import org.apache.commons.logging.Log;

import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Lists;
import com.vaadin.server.ErrorMessage;
import com.vaadin.server.ExternalResource;
import com.vaadin.server.FontIcon;
import com.vaadin.server.Resource;
import com.vaadin.server.VaadinService;
import com.vaadin.shared.MouseEventDetails.MouseButton;
import com.vaadin.shared.Version;
import com.vaadin.ui.AbstractComponent;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.Component;
import com.vaadin.ui.ComponentContainer;
import com.vaadin.ui.HasComponents;
import com.vaadin.ui.JavaScript;
import com.vaadin.ui.Panel;
import com.vaadin.ui.SingleComponentContainer;
import com.vaadin.ui.TextField;
import com.vaadin.ui.UI;
import com.vaadin.ui.Window;
import com.vaadin.ui.declarative.Design;
import com.vaadin.ui.themes.ValoTheme;
import com.vaadin.v7.data.Container;
import com.vaadin.v7.data.Container.Filter;
import com.vaadin.v7.data.Item;
import com.vaadin.v7.data.util.IndexedContainer;
import com.vaadin.v7.event.ItemClickEvent;
import com.vaadin.v7.shared.ui.combobox.FilteringMode;
import com.vaadin.v7.ui.AbstractField;
import com.vaadin.v7.ui.ComboBox;
import com.vaadin.v7.ui.Label;
import com.vaadin.v7.ui.OptionGroup;
import com.vaadin.v7.ui.Table;
import com.vaadin.v7.ui.VerticalLayout;

/**
 * Vaadin utility functions.

* */ @SuppressWarnings("deprecation") public final class CmsVaadinUtils { /** * Helper class for building option groups.

*/ public static class OptionGroupBuilder { /** The option group being built. */ private OptionGroup m_optionGroup = new OptionGroup(); /** * Adds an option.

* * @param key the option key * @param text the option text * * @return this instance */ public OptionGroupBuilder add(String key, String text) { m_optionGroup.addItem(key); m_optionGroup.setItemCaption(key, text); return this; } /** * Returns the option group.

* * @return the option group */ public OptionGroup build() { return m_optionGroup; } /** * Adds horizontal style to option group.

* * @return this instance */ public OptionGroupBuilder horizontal() { m_optionGroup.addStyleName(ValoTheme.OPTIONGROUP_HORIZONTAL); return this; } } /** Container property ids. */ public static enum PropertyId { /** The caption id. */ caption, /** The icon id. */ icon, /** The is folder id. */ isFolder, /** The is XML content id. */ isXmlContent } /** Container filter for the resource type container to show not folder types only. */ public static final Filter FILTER_NO_FOLDERS = new Filter() { private static final long serialVersionUID = 1L; public boolean appliesToProperty(Object propertyId) { return PropertyId.isFolder.equals(propertyId); } public boolean passesFilter(Object itemId, Item item) throws UnsupportedOperationException { return !((Boolean)item.getItemProperty(PropertyId.isFolder).getValue()).booleanValue(); } }; /** Container filter for the resource type container to show XML content types only. */ public static final Filter FILTER_XML_CONTENTS = new Filter() { private static final long serialVersionUID = 1L; public boolean appliesToProperty(Object propertyId) { return PropertyId.isXmlContent.equals(propertyId); } public boolean passesFilter(Object itemId, Item item) throws UnsupportedOperationException { return ((Boolean)item.getItemProperty(PropertyId.isXmlContent).getValue()).booleanValue(); } }; /** The combo box label item property id. */ public static final String PROPERTY_LABEL = "label"; /** The combo box value item property id. */ public static final String PROPERTY_VALUE = "value"; /** The Vaadin bootstrap script, with some macros to be dynamically replaced later. */ protected static final String BOOTSTRAP_SCRIPT = "vaadin.initApplication(\"%(elementId)\", {\n" + " \"browserDetailsUrl\": \"%(vaadinServlet)\",\n" + " \"serviceUrl\": \"%(vaadinServlet)\",\n" + " \"widgetset\": \"org.opencms.ui.WidgetSet\",\n" + " \"theme\": \"opencms\",\n" + " \"versionInfo\": {\"vaadinVersion\": \"%(vaadinVersion)\"},\n" + " \"vaadinDir\": \"%(vaadinDir)\",\n" + " \"heartbeatInterval\": 30,\n" + " \"debug\": false,\n" + " \"standalone\": false,\n" + " \"authErrMsg\": {\n" + " \"message\": \"Take note of any unsaved data, \"+\n" + " \"and click here<\\/u> to continue.\",\n" + " \"caption\": \"Authentication problem\"\n" + " },\n" + " \"comErrMsg\": {\n" + " \"message\": \"Take note of any unsaved data, \"+\n" + " \"and click here<\\/u> to continue.\",\n" + " \"caption\": \"Communication problem\"\n" + " },\n" + " \"sessExpMsg\": {\n" + " \"message\": \"Take note of any unsaved data, \"+\n" + " \"and click here<\\/u> to continue.\",\n" + " \"caption\": \"Session Expired\"\n" + " }\n" + " });"; /** The logger of this class. */ private static final Log LOG = CmsLog.getLog(CmsVaadinUtils.class); /** * Hidden default constructor for utility class.

*/ private CmsVaadinUtils() { } /** * Builds a container for use in combo boxes from a map of key/value pairs, where the keys are options and the values are captions.

* * @param captionProperty the property name to use for captions * @param map the map * @return the new container */ public static IndexedContainer buildContainerFromMap(String captionProperty, Map map) { IndexedContainer container = new IndexedContainer(); for (Map.Entry entry : map.entrySet()) { container.addItem(entry.getKey()).getItemProperty(captionProperty).setValue(entry.getValue()); } return container; } /** * Centers the parent window of given component.

* * @param component Component as child of window */ public static void centerWindow(Component component) { Window window = getWindow(component); if (window != null) { window.center(); } } /** * Closes the window containing the given component. * * @param component a component */ public static void closeWindow(Component component) { Window window = getWindow(component); if (window != null) { window.close(); } } /** * Creates a click listener which calls a Runnable when activated.

* * @param action the Runnable to execute on a click * * @return the click listener */ public static Button.ClickListener createClickListener(final Runnable action) { return new Button.ClickListener() { /** Serial version id. */ private static final long serialVersionUID = 1L; public void buttonClick(ClickEvent event) { action.run(); } }; } /** * Simple context menu handler for multi-select tables. * * @param table the table * @param menu the table's context menu * @param event the click event * @param entries the context menu entries */ @SuppressWarnings("unchecked") public static void defaultHandleContextMenuForMultiselect( Table table, CmsContextMenu menu, ItemClickEvent event, List>> entries) { if (!event.isCtrlKey() && !event.isShiftKey()) { if (event.getButton().equals(MouseButton.RIGHT)) { Collection oldValue = ((Collection)table.getValue()); if (oldValue.isEmpty() || !oldValue.contains(event.getItemId())) { table.setValue(new HashSet(Arrays.asList(event.getItemId()))); } Collection selection = (Collection)table.getValue(); menu.setEntries(entries, selection); menu.openForTable(event, table); } } } /** * Reads the content of an input stream into a string (using UTF-8 encoding), performs a function on the string, and returns the result * again as an input stream.

* * @param stream the stream producing the input data * @param transformation the function to apply to the input * * @return the stream producing the transformed input data */ public static InputStream filterUtf8ResourceStream(InputStream stream, Function transformation) { try { byte[] streamData = CmsFileUtil.readFully(stream); String dataAsString = new String(streamData, "UTF-8"); byte[] transformedData = transformation.apply(dataAsString).getBytes("UTF-8"); return new ByteArrayInputStream(transformedData); } catch (UnsupportedEncodingException e) { LOG.error(e.getLocalizedMessage(), e); return null; } catch (IOException e) { LOG.error(e.getLocalizedMessage(), e); throw new RuntimeException(e); } } /** * Get all groups with blacklist.

* * @param cms CmsObject * @param ouFqn ou name * @param propCaption property * @param propIcon property for icon * @param propOu organizational unit * @param blackList blacklist * @param iconProvider the icon provider * @return indexed container */ public static IndexedContainer getAvailableGroupsContainerWithout( CmsObject cms, String ouFqn, String propCaption, String propIcon, String propOu, List blackList, java.util.function.Function iconProvider) { if (blackList == null) { blackList = new ArrayList(); } IndexedContainer res = new IndexedContainer(); res.addContainerProperty(propCaption, String.class, ""); res.addContainerProperty(propOu, String.class, ""); if (propIcon != null) { res.addContainerProperty(propIcon, CmsCssIcon.class, null); } try { for (CmsGroup group : OpenCms.getRoleManager().getManageableGroups(cms, ouFqn, true)) { if (!blackList.contains(group)) { Item item = res.addItem(group); if (item == null) { continue; } if (iconProvider != null) { item.getItemProperty(propIcon).setValue(iconProvider.apply(group)); } item.getItemProperty(propCaption).setValue(group.getSimpleName()); item.getItemProperty(propOu).setValue(group.getOuFqn()); } } } catch (CmsException e) { LOG.error("Unable to read groups", e); } return res; } /** * Returns the available projects.

* * @param cms the CMS context * * @return the available projects */ public static List getAvailableProjects(CmsObject cms) { // get all project information List allProjects; try { String ouFqn = ""; CmsUserSettings settings = new CmsUserSettings(cms); if (!settings.getListAllProjects()) { ouFqn = cms.getRequestContext().getCurrentUser().getOuFqn(); } allProjects = new ArrayList( OpenCms.getOrgUnitManager().getAllAccessibleProjects(cms, ouFqn, settings.getListAllProjects())); Iterator itProjects = allProjects.iterator(); while (itProjects.hasNext()) { CmsProject prj = itProjects.next(); if (prj.isHiddenFromSelector()) { itProjects.remove(); } } } catch (CmsException e) { // should usually never happen LOG.error(e.getLocalizedMessage(), e); allProjects = Collections.emptyList(); } return allProjects; } /** * Builds an IndexedContainer containing the sites selectable by the current user.

* * @param cms the CMS context * @param captionPropertyName the name of the property used to store captions * * @return the container with the available sites */ public static IndexedContainer getAvailableSitesContainer(CmsObject cms, String captionPropertyName) { IndexedContainer availableSites = new IndexedContainer(); availableSites.addContainerProperty(captionPropertyName, String.class, null); for (Map.Entry entry : getAvailableSitesMap(cms).entrySet()) { Item siteItem = availableSites.addItem(entry.getKey()); siteItem.getItemProperty(captionPropertyName).setValue(entry.getValue()); } return availableSites; } /** * Gets available sites as a LinkedHashMap, with site roots as keys and site labels as values. * * @param cms the current CMS context * @return the map of available sites */ public static LinkedHashMap getAvailableSitesMap(CmsObject cms) { CmsSiteSelectorOptionBuilder optBuilder = new CmsSiteSelectorOptionBuilder(cms); optBuilder.addNormalSites(true, (new CmsUserSettings(cms)).getStartFolder()); optBuilder.addSharedSite(); LinkedHashMap result = new LinkedHashMap(); for (CmsSiteSelectorOption option : optBuilder.getOptions()) { result.put(option.getSiteRoot(), option.getMessage()); } String currentSiteRoot = cms.getRequestContext().getSiteRoot(); if (!result.containsKey(currentSiteRoot)) { result.put(currentSiteRoot, currentSiteRoot); } return result; } /** * Returns the Javascript code to use for initializing a Vaadin UI.

* * @param cms the CMS context * @param elementId the id of the DOM element in which to initialize the UI * @param servicePath the UI servlet path * @return the Javascript code to initialize Vaadin * * @throws Exception if something goes wrong */ public static String getBootstrapScript(CmsObject cms, String elementId, String servicePath) throws Exception { String script = BOOTSTRAP_SCRIPT; CmsMacroResolver resolver = new CmsMacroResolver(); String context = OpenCms.getSystemInfo().getContextPath(); String vaadinDir = CmsStringUtil.joinPaths(context, "VAADIN/"); String vaadinVersion = Version.getFullVersion(); String vaadinServlet = CmsStringUtil.joinPaths(context, servicePath); String vaadinBootstrap = CmsStringUtil.joinPaths(context, "VAADIN/vaadinBootstrap.js"); resolver.addMacro("vaadinDir", vaadinDir); resolver.addMacro("vaadinVersion", vaadinVersion); resolver.addMacro("elementId", elementId); resolver.addMacro("vaadinServlet", vaadinServlet); resolver.addMacro("vaadinBootstrap", vaadinBootstrap); script = resolver.resolveMacros(script); return script; } /** * Returns the path to the design template file of the given component.

* * @param component the component * * @return the path */ public static String getDefaultDesignPath(Component component) { String className = component.getClass().getName(); String designPath = className.replace(".", "/") + ".html"; return designPath; } /** * Gets container with alls groups of a certain user. * * @param cms cmsobject * @param user to find groups for * @param caption caption property * @param iconProp property * @param ou ou * @param propStatus status property * @param iconProvider the icon provider * @return Indexed Container */ public static IndexedContainer getGroupsOfUser( CmsObject cms, CmsUser user, String caption, String iconProp, String ou, String propStatus, Function iconProvider) { IndexedContainer container = new IndexedContainer(); container.addContainerProperty(caption, String.class, ""); container.addContainerProperty(ou, String.class, ""); container.addContainerProperty(propStatus, Boolean.class, new Boolean(true)); if (iconProvider != null) { container.addContainerProperty(iconProp, CmsCssIcon.class, null); } try { for (CmsGroup group : cms.getGroupsOfUser(user.getName(), true)) { Item item = container.addItem(group); item.getItemProperty(caption).setValue(group.getSimpleName()); item.getItemProperty(ou).setValue(group.getOuFqn()); if (iconProvider != null) { item.getItemProperty(iconProp).setValue(iconProvider.apply(group)); } } } catch (CmsException e) { LOG.error("Unable to read groups from user", e); } return container; } /** * Creates a layout with info panel.

* * @param messageString Message to be displayed * @return layout */ public static VerticalLayout getInfoLayout(String messageString) { VerticalLayout ret = new VerticalLayout(); ret.setMargin(true); ret.addStyleName("o-center"); ret.setWidth("100%"); VerticalLayout inner = new VerticalLayout(); inner.addStyleName("o-workplace-maxwidth"); Panel panel = new Panel(); panel.setWidth("100%"); Label label = new Label(CmsVaadinUtils.getMessageText(messageString)); label.addStyleName("o-report"); panel.setContent(label); inner.addComponent(panel); ret.addComponent(inner); return ret; } /** * Get container with languages.

* * @param captionPropertyName name * @return indexed container */ public static IndexedContainer getLanguageContainer(String captionPropertyName) { IndexedContainer result = new IndexedContainer(); result.addContainerProperty(captionPropertyName, String.class, ""); Iterator itLocales = OpenCms.getLocaleManager().getAvailableLocales().iterator(); while (itLocales.hasNext()) { Locale locale = itLocales.next(); Item item = result.addItem(locale); item.getItemProperty(captionPropertyName).setValue(locale.getDisplayName(A_CmsUI.get().getLocale())); } return result; } /** * Gets the message for the current locale and the given key and arguments.

* * @param messages the messages instance * @param key the message key * @param args the message arguments * * @return the message text for the current locale */ public static String getMessageText(I_CmsMessageBundle messages, String key, Object... args) { return messages.getBundle(A_CmsUI.get().getLocale()).key(key, args); } /** * Gets the workplace message for the current locale and the given key and arguments.

* * @param key the message key * @param args the message arguments * * @return the message text for the current locale */ public static String getMessageText(String key, Object... args) { return getWpMessagesForCurrentLocale().key(key, args); } /** * Creates the ComboBox for OU selection.

* @param cms CmsObject * @param baseOu OU * @param log Logger object * * @return ComboBox */ public static ComboBox getOUComboBox(CmsObject cms, String baseOu, Log log) { return getOUComboBox(cms, baseOu, log, true); } /** * Creates the ComboBox for OU selection.

* @param cms CmsObject * @param baseOu OU * @param log Logger object * @param includeWebOU include webou? * * @return ComboBox */ public static ComboBox getOUComboBox(CmsObject cms, String baseOu, Log log, boolean includeWebOU) { ComboBox combo = null; try { IndexedContainer container = new IndexedContainer(); container.addContainerProperty("desc", String.class, ""); for (String ou : CmsOUHandler.getManagableOUs(cms)) { if (includeWebOU | !OpenCms.getOrgUnitManager().readOrganizationalUnit(cms, ou).hasFlagWebuser()) { Item item = container.addItem(ou); if (ou == "") { CmsOrganizationalUnit root = OpenCms.getOrgUnitManager().readOrganizationalUnit(cms, ""); item.getItemProperty("desc").setValue(root.getDisplayName(A_CmsUI.get().getLocale())); } else { item.getItemProperty("desc").setValue( OpenCms.getOrgUnitManager().readOrganizationalUnit(cms, ou).getDisplayName( A_CmsUI.get().getLocale())); } } } combo = new ComboBox(null, container); combo.setTextInputAllowed(true); combo.setNullSelectionAllowed(false); combo.setWidth("379px"); combo.setInputPrompt( Messages.get().getBundle(UI.getCurrent().getLocale()).key(Messages.GUI_EXPLORER_CLICK_TO_EDIT_0)); combo.setItemCaptionPropertyId("desc"); combo.setFilteringMode(FilteringMode.CONTAINS); combo.select(baseOu); } catch (CmsException e) { if (log != null) { log.error("Unable to read OU", e); } } return combo; } /** * Gives item id from path.

* * @param cnt to be used * @param path to obtain item id from * @return item id */ public static String getPathItemId(Container cnt, String path) { for (String id : Arrays.asList(path, CmsFileUtil.toggleTrailingSeparator(path))) { if (cnt.containsId(id)) { return id; } } return null; } /** * Get container for principal. * * @param cms cmsobject * @param list of principals * @param captionID caption id * @param descID description id * @param iconID icon id * @param ouID ou id * @param icon icon * @param iconList iconlist * @return indexedcontainer */ public static IndexedContainer getPrincipalContainer( CmsObject cms, List list, String captionID, String descID, String iconID, String ouID, String icon, List iconList) { IndexedContainer res = new IndexedContainer(); res.addContainerProperty(captionID, String.class, ""); res.addContainerProperty(ouID, String.class, ""); res.addContainerProperty(iconID, FontIcon.class, new CmsCssIcon(icon)); if (descID != null) { res.addContainerProperty(descID, String.class, ""); } for (I_CmsPrincipal group : list) { Item item = res.addItem(group); item.getItemProperty(captionID).setValue(group.getSimpleName()); item.getItemProperty(ouID).setValue(group.getOuFqn()); if (descID != null) { item.getItemProperty(descID).setValue(group.getDescription(A_CmsUI.get().getLocale())); } } for (int i = 0; i < iconList.size(); i++) { res.getItem(res.getIdByIndex(i)).getItemProperty(iconID).setValue(iconList.get(i)); } return res; } /** * Returns the selectable projects container.

* * @param cms the CMS context * @param captionPropertyName the name of the property used to store captions * * @return the projects container */ public static IndexedContainer getProjectsContainer(CmsObject cms, String captionPropertyName) { IndexedContainer result = new IndexedContainer(); result.addContainerProperty(captionPropertyName, String.class, null); for (Map.Entry entry : getProjectsMap(cms).entrySet()) { Item projectItem = result.addItem(entry.getKey()); projectItem.getItemProperty(captionPropertyName).setValue(entry.getValue()); } return result; } /** * Gets the available projects for the current user as a map, wth project ids as keys and project names as values. * * @param cms the current CMS context * @return the map of projects */ public static LinkedHashMap getProjectsMap(CmsObject cms) { Locale locale = A_CmsUI.get().getLocale(); List projects = getAvailableProjects(cms); boolean isSingleOu = isSingleOu(projects); LinkedHashMap result = new LinkedHashMap<>(); for (CmsProject project : projects) { String projectName = project.getSimpleName(); if (!isSingleOu && !project.isOnlineProject()) { try { projectName = projectName + " - " + OpenCms.getOrgUnitManager().readOrganizationalUnit(cms, project.getOuFqn()).getDisplayName( locale); } catch (CmsException e) { LOG.debug("Error reading project OU.", e); projectName = projectName + " - " + project.getOuFqn(); } } result.put(project.getUuid(), projectName); } return result; } /** * Gets the current Vaadin request, cast to a HttpServletRequest.

* * @return the current request */ public static HttpServletRequest getRequest() { return (HttpServletRequest)VaadinService.getCurrentRequest(); } /** * Gets list of resource types.

* * @return List */ public static List getResourceTypes() { List res = new ArrayList(); for (I_CmsResourceType type : OpenCms.getResourceManager().getResourceTypes()) { CmsExplorerTypeSettings typeSetting = OpenCms.getWorkplaceManager().getExplorerTypeSetting( type.getTypeName()); if (typeSetting != null) { res.add(type); } } return res; } /** * Returns the available resource types container.

* * @return the resource types container */ public static IndexedContainer getResourceTypesContainer() { IndexedContainer types = new IndexedContainer(); types.addContainerProperty(PropertyId.caption, String.class, null); types.addContainerProperty(PropertyId.icon, Resource.class, null); types.addContainerProperty(PropertyId.isFolder, Boolean.class, null); types.addContainerProperty(PropertyId.isXmlContent, Boolean.class, null); for (I_CmsResourceType type : getResourceTypes()) { CmsExplorerTypeSettings typeSetting = OpenCms.getWorkplaceManager().getExplorerTypeSetting( type.getTypeName()); Item typeItem = types.addItem(type); typeItem.getItemProperty(PropertyId.caption).setValue(CmsVaadinUtils.getMessageText(typeSetting.getKey())); typeItem.getItemProperty(PropertyId.icon).setValue(CmsResourceUtil.getSmallIconResource(typeSetting, null)); typeItem.getItemProperty(PropertyId.isXmlContent).setValue( Boolean.valueOf(type instanceof CmsResourceTypeXmlContent)); typeItem.getItemProperty(PropertyId.isFolder).setValue( Boolean.valueOf(type instanceof A_CmsResourceTypeFolderBase)); } return types; } /** * Returns the roles available for a given user.

* * @param cms CmsObject * @param user to get available roles for * @param captionPropertyName name of caption property * @return indexed container */ public static IndexedContainer getRoleContainerForUser(CmsObject cms, CmsUser user, String captionPropertyName) { IndexedContainer result = new IndexedContainer(); result.addContainerProperty(captionPropertyName, String.class, ""); try { List roles = OpenCms.getRoleManager().getRoles(cms, user.getOuFqn(), false); CmsRole.applySystemRoleOrder(roles); for (CmsRole role : roles) { Item item = result.addItem(role); item.getItemProperty(captionPropertyName).setValue(role.getDisplayName(cms, A_CmsUI.get().getLocale())); } } catch (CmsException e) { LOG.error("Unabel to read roles for user", e); } return result; } /** * Gets the window which contains a given component.

* * @param component the component * @return the window containing the component, or null if no component is found */ public static Window getWindow(Component component) { if (component == null) { return null; } else if (component instanceof Window) { return (Window)component; } else { return getWindow(component.getParent()); } } /** * Get container with workpalce languages.

* * @param captionPropertyName name * @return indexed container */ public static IndexedContainer getWorkplaceLanguageContainer(String captionPropertyName) { IndexedContainer result = new IndexedContainer(); result.addContainerProperty(captionPropertyName, String.class, ""); CmsLanguagePreference.getOptionMapForLanguage().forEach((locale, title) -> { Item item = result.addItem(locale); item.getItemProperty(captionPropertyName).setValue(title); }); return result; } /** * Gets the link to the (new) workplace.

* * @return the link to the workplace */ public static String getWorkplaceLink() { return OpenCms.getSystemInfo().getWorkplaceContext(); } /** * Returns the workplace link for the given app.

* * @param appId the app id * * @return the workplace link */ public static String getWorkplaceLink(String appId) { return getWorkplaceLink() + CmsAppWorkplaceUi.WORKPLACE_APP_ID_SEPARATOR + appId; } /** * Returns the workplace link to the given app with the given state.

* * @param appId the app id * @param appState the app state * * @return the workplace link */ public static String getWorkplaceLink(String appId, String appState) { return getWorkplaceLink(appId) + CmsAppWorkplaceUi.WORKPLACE_STATE_SEPARATOR + appState; } /** * Returns the workplace link to the given app with the given state including the given request parameters.

* * @param appId the app id * @param appState the app state * @param requestParameters the request parameters * * @return the workplace link */ public static String getWorkplaceLink(String appId, String appState, Map requestParameters) { String result = getWorkplaceLink(); if ((requestParameters != null) && !requestParameters.isEmpty()) { boolean first = true; for (Entry param : requestParameters.entrySet()) { for (String value : param.getValue()) { if (first) { result += "?"; } else { result += "&"; } result += param.getKey() + "=" + value; first = false; } } } if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(appId)) { result += CmsAppWorkplaceUi.WORKPLACE_APP_ID_SEPARATOR + appId; } if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(appState)) { result += CmsAppWorkplaceUi.WORKPLACE_STATE_SEPARATOR + appState; } return result; } /** * Gets external resource from workplace resource folder.

* * @param subPath path relative to workplace resource folder * * @return the external resource */ public static ExternalResource getWorkplaceResource(String subPath) { return new ExternalResource(CmsWorkplace.getResourceUri(subPath)); } /** * Gets the workplace messages for the current locale.

* * @return the workplace messages */ public static CmsMessages getWpMessagesForCurrentLocale() { Locale locale; if (A_CmsUI.get() != null) { locale = A_CmsUI.get().getLocale(); } else { if (LOG.isWarnEnabled()) { Exception e = new Exception("getWpMessagesForCurrentLocale called from non-Vaadin context"); LOG.warn(e.getLocalizedMessage(), e); } locale = Locale.ENGLISH; } return OpenCms.getWorkplaceManager().getMessages(locale); } /** * Checks if path is itemid in container.

* * @param cnt to be checked * @param path as itemid * @return true id path is itemid in container */ public static boolean hasPathAsItemId(Container cnt, String path) { return cnt.containsId(path) || cnt.containsId(CmsFileUtil.toggleTrailingSeparator(path)); } /** * Checks if a button is pressed.

* * @param button the button * * @return true if the button is pressed */ public static boolean isButtonPressed(Button button) { if (button == null) { return false; } List styles = Arrays.asList(button.getStyleName().split(" ")); return styles.contains(OpenCmsTheme.BUTTON_PRESSED); } /** * Uses the currently set locale to resolve localization macros in the input string using workplace message bundles.

* * @param baseString the string to localize * * @return the localized string */ public static String localizeString(String baseString) { if (baseString == null) { return null; } CmsWorkplaceMessages wpMessages = OpenCms.getWorkplaceManager().getMessages(A_CmsUI.get().getLocale()); CmsMacroResolver resolver = new CmsMacroResolver(); resolver.setMessages(wpMessages); String result = resolver.resolveMacros(baseString); return result; } /** * Message accessior function.

* * @return the message for Cancel buttons */ public static String messageCancel() { return getMessageText(org.opencms.workplace.Messages.GUI_DIALOG_BUTTON_CANCEL_0); } /** * Message accessior function.

* * @return the message for Cancel buttons */ public static String messageClose() { return getMessageText(org.opencms.workplace.Messages.GUI_DIALOG_BUTTON_CLOSE_0); } /** * Message accessor function.

* * @return the message for OK buttons */ public static String messageOk() { return getMessageText(org.opencms.workplace.Messages.GUI_DIALOG_BUTTON_OK_0); } /** * Generates the options items for the combo box using the map entry keys as values and the values as labels.

* * @param box the combo box to prepare * @param options the box options */ public static void prepareComboBox(ComboBox box, Map options) { IndexedContainer container = new IndexedContainer(); container.addContainerProperty(PROPERTY_VALUE, Object.class, null); container.addContainerProperty(PROPERTY_LABEL, String.class, ""); for (Entry entry : options.entrySet()) { Item item = container.addItem(entry.getKey()); item.getItemProperty(PROPERTY_VALUE).setValue(entry.getKey()); item.getItemProperty(PROPERTY_LABEL).setValue(entry.getValue()); } box.setContainerDataSource(container); box.setItemCaptionPropertyId(PROPERTY_LABEL); } /** * Reads the declarative design for a component and localizes it using a messages object.

* * The design will need to be located in the same directory as the component's class and have '.html' as a file extension. * * @param component the component for which to read the design * @param messages the message bundle to use for localization * @param macros the macros to use on the HTML template */ @SuppressWarnings("resource") public static void readAndLocalizeDesign(Component component, CmsMessages messages, Map macros) { Class componentClass = component.getClass(); List> classes = Lists.newArrayList(); classes.add(componentClass); classes.addAll(ClassUtils.getAllSuperclasses(componentClass)); InputStream designStream = null; for (Class cls : classes) { if (cls.getName().startsWith("com.vaadin")) { break; } String filename = cls.getSimpleName() + ".html"; designStream = cls.getResourceAsStream(filename); if (designStream != null) { break; } } if (designStream == null) { throw new IllegalArgumentException("Design not found for : " + component.getClass()); } readAndLocalizeDesign(component, designStream, messages, macros); } /** * Reads a layout from a resource, applies basic i18n macro substitution on the contained text, and returns a stream of the transformed * data.

* * @param layoutClass the class relative to which the layout resource will be looked up * @param relativeName the file name of the layout file * * @return an input stream which produces the transformed layout resource html */ public static InputStream readCustomLayout(Class layoutClass, String relativeName) { CmsMacroResolver resolver = new CmsMacroResolver() { @Override public String getMacroValue(String macro) { return CmsEncoder.escapeXml(super.getMacroValue(macro)); } }; resolver.setMessages(CmsVaadinUtils.getWpMessagesForCurrentLocale()); InputStream layoutStream = CmsVaadinUtils.filterUtf8ResourceStream( layoutClass.getResourceAsStream(relativeName), resolver.toFunction()); return layoutStream; } /** * Replaces component with new component.

* * @param component to be replaced * @param replacement new component */ public static void replaceComponent(Component component, Component replacement) { if (!component.isAttached()) { throw new IllegalArgumentException("Component must be attached"); } HasComponents parent = component.getParent(); if (parent instanceof ComponentContainer) { ((ComponentContainer)parent).replaceComponent(component, replacement); } else if (parent instanceof SingleComponentContainer) { ((SingleComponentContainer)parent).setContent(replacement); } else { throw new IllegalArgumentException("Illegal class for parent: " + parent.getClass()); } } /** * Configures a text field to look like a filter box for a table. * * @param searchBox the text field to configure */ public static void setFilterBoxStyle(TextField searchBox) { searchBox.setIcon(FontOpenCms.FILTER); searchBox.setPlaceholder( org.opencms.ui.apps.Messages.get().getBundle(UI.getCurrent().getLocale()).key( org.opencms.ui.apps.Messages.GUI_EXPLORER_FILTER_0)); searchBox.addStyleName(ValoTheme.TEXTFIELD_INLINE_ICON); } /** * Sets the value of a text field which may be set to read-only mode.

* * When setting a Vaadin field to read-only, you also can't set its value programmatically anymore. * So we need to temporarily disable read-only mode, set the value, and then switch back to read-only mode. * * @param field the field * @param value the value to set */ public static void setReadonlyValue(AbstractField field, T value) { boolean readonly = field.isReadOnly(); try { field.setReadOnly(false); field.setValue(value); } finally { field.setReadOnly(readonly); } } /** * Shows an alert box to the user with the given information, which will perform the given action after the user clicks on OK.

* * @param title the title * @param message the message * * @param callback the callback to execute after clicking OK */ public static void showAlert(String title, String message, final Runnable callback) { final Window window = new Window(); window.setModal(true); Panel panel = new Panel(); panel.setCaption(title); panel.setWidth("500px"); VerticalLayout layout = new VerticalLayout(); layout.setMargin(true); panel.setContent(layout); layout.addComponent(new Label(message)); Button okButton = new Button(); okButton.addClickListener(new ClickListener() { /** The serial version id. */ private static final long serialVersionUID = 1L; public void buttonClick(ClickEvent event) { window.close(); if (callback != null) { callback.run(); } } }); layout.addComponent(okButton); layout.setComponentAlignment(okButton, Alignment.BOTTOM_RIGHT); okButton.setCaption( org.opencms.workplace.Messages.get().getBundle(A_CmsUI.get().getLocale()).key( org.opencms.workplace.Messages.GUI_DIALOG_BUTTON_OK_0)); window.setContent(panel); window.setClosable(false); window.setResizable(false); A_CmsUI.get().addWindow(window); } /** * Creates a new option group builder.

* * @return a new option group builder */ public static OptionGroupBuilder startOptionGroup() { return new OptionGroupBuilder(); } /** * Sets style of a toggle button depending on its current state.

* * @param button the button to update */ public static void toggleButton(Button button) { if (isButtonPressed(button)) { button.removeStyleName(OpenCmsTheme.BUTTON_PRESSED); } else { button.addStyleName(OpenCmsTheme.BUTTON_PRESSED); } } /** * Updates the component error of a component, but only if it differs from the currently set * error.

* * @param component the component * @param error the error * * @return true if the error was changed */ public static boolean updateComponentError(AbstractComponent component, ErrorMessage error) { if (component.getComponentError() != error) { component.setComponentError(error); return true; } return false; } /** * Visits all descendants of a given component (including the component itself) and applies a predicate * to each.

* * If the predicate returns false for a component, no further descendants will be processed.

* * @param component the component * @param handler the predicate */ public static void visitDescendants(Component component, Predicate handler) { List stack = Lists.newArrayList(); stack.add(component); while (!stack.isEmpty()) { Component currentComponent = stack.get(stack.size() - 1); stack.remove(stack.size() - 1); if (!handler.apply(currentComponent)) { return; } if (currentComponent instanceof HasComponents) { List children = Lists.newArrayList((HasComponents)currentComponent); Collections.reverse(children); stack.addAll(children); } } } /** * Waggle the component.

* * @param component to be waggled */ public static void waggleMeOnce(Component component) { //TODO Until now, the component gets a waggler class which can not be removed again here.. component.addStyleName("waggler"); //Add JavaScript code, which adds the waggle class and removes it after a short time. JavaScript.getCurrent().execute( "waggler=document.querySelectorAll(\".waggler\")[0];" + "waggler.className=waggler.className + \" waggle\";" + "setTimeout(function () {\n" + "waggler.className=waggler.className.replace(/\\bwaggle\\b/g, \"\");" + " }, 1500);"); } /** * Reads the given design and resolves the given macros and localizations.

* @param component the component whose design to read * @param designStream stream to read the design from * @param messages the message bundle to use for localization in the design (may be null) * @param macros other macros to substitute in the macro design (may be null) */ protected static void readAndLocalizeDesign( Component component, InputStream designStream, CmsMessages messages, Map macros) { try { byte[] designBytes = CmsFileUtil.readFully(designStream, true); final String encoding = "UTF-8"; String design = new String(designBytes, encoding); CmsMacroResolver resolver = new CmsMacroResolver() { @Override public String getMacroValue(String macro) { String result = super.getMacroValue(macro); // The macro may contain quotes or angle brackets, so we need to escape the values for insertion into the design file return CmsEncoder.escapeXml(result); } }; if (macros != null) { for (Map.Entry entry : macros.entrySet()) { resolver.addMacro(entry.getKey(), entry.getValue()); } } if (messages != null) { resolver.setMessages(messages); } String resolvedDesign = resolver.resolveMacros(design); Design.read(new ByteArrayInputStream(resolvedDesign.getBytes(encoding)), component); } catch (IOException e) { throw new RuntimeException("Could not read design", e); } finally { try { designStream.close(); } catch (IOException e) { LOG.warn(e.getLocalizedMessage(), e); } } } /** * Returns whether only a single OU is visible to the current user.

* * @param projects the selectable projects * * @return true if only a single OU is visible to the current user */ private static boolean isSingleOu(List projects) { String ouFqn = null; for (CmsProject project : projects) { if (project.isOnlineProject()) { // skip the online project continue; } if (ouFqn == null) { // set the first ou ouFqn = project.getOuFqn(); } else if (!ouFqn.equals(project.getOuFqn())) { // break if one different ou is found return false; } } return true; } }