Java tutorial
/** * Copyright (c) 2000-present Liferay, Inc. All rights reserved. * * 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. */ package com.liferay.layout.internal.util; import com.liferay.exportimport.kernel.staging.LayoutStagingUtil; import com.liferay.exportimport.kernel.staging.Staging; import com.liferay.petra.string.StringPool; import com.liferay.portal.kernel.dao.orm.QueryUtil; import com.liferay.portal.kernel.exception.PortalException; import com.liferay.portal.kernel.json.JSONArray; import com.liferay.portal.kernel.json.JSONFactoryUtil; import com.liferay.portal.kernel.json.JSONObject; import com.liferay.portal.kernel.log.Log; import com.liferay.portal.kernel.log.LogFactoryUtil; import com.liferay.portal.kernel.model.Group; import com.liferay.portal.kernel.model.Layout; import com.liferay.portal.kernel.model.LayoutBranch; import com.liferay.portal.kernel.model.LayoutConstants; import com.liferay.portal.kernel.model.LayoutRevision; import com.liferay.portal.kernel.model.LayoutSetBranch; import com.liferay.portal.kernel.model.impl.VirtualLayout; import com.liferay.portal.kernel.security.permission.ActionKeys; import com.liferay.portal.kernel.service.LayoutLocalService; import com.liferay.portal.kernel.service.LayoutRevisionLocalService; import com.liferay.portal.kernel.service.LayoutService; import com.liferay.portal.kernel.service.LayoutSetBranchLocalService; import com.liferay.portal.kernel.service.permission.GroupPermissionUtil; import com.liferay.portal.kernel.service.permission.LayoutPermissionUtil; import com.liferay.portal.kernel.servlet.BrowserSnifferUtil; import com.liferay.portal.kernel.theme.ThemeDisplay; import com.liferay.portal.kernel.util.ArrayUtil; import com.liferay.portal.kernel.util.ParamUtil; import com.liferay.portal.kernel.util.Portal; import com.liferay.portal.kernel.util.SessionClicks; import com.liferay.portal.kernel.util.StringBundler; import com.liferay.portal.kernel.util.WebKeys; import com.liferay.portal.util.PropsValues; import com.liferay.portlet.layoutsadmin.util.LayoutsTree; import com.liferay.sites.kernel.util.SitesUtil; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Locale; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; /** * @author Brian Wing Shun Chan * @author Eduardo Lundgren * @author Bruno Basto * @author Marcellus Tavares * @author Zsolt Szab * @author Tibor Lipusz */ @Component(immediate = true) public class LayoutsTreeImpl implements LayoutsTree { @Override public String getLayoutsJSON(HttpServletRequest request, long groupId, boolean privateLayout, long parentLayoutId, boolean incomplete, String treeId) throws Exception { return getLayoutsJSON(request, groupId, privateLayout, parentLayoutId, incomplete, treeId, null); } @Override public String getLayoutsJSON(HttpServletRequest request, long groupId, boolean privateLayout, long parentLayoutId, boolean incomplete, String treeId, LayoutSetBranch layoutSetBranch) throws Exception { return getLayoutsJSON(request, groupId, privateLayout, parentLayoutId, null, incomplete, treeId, layoutSetBranch); } @Override public String getLayoutsJSON(HttpServletRequest request, long groupId, boolean privateLayout, long layoutId, int max) throws Exception { return getLayoutsJSON(request, groupId, privateLayout, layoutId, max, null); } @Override public String getLayoutsJSON(HttpServletRequest request, long groupId, boolean privateLayout, long layoutId, int max, LayoutSetBranch layoutSetBranch) throws Exception { Layout layout = _layoutLocalService.getLayout(groupId, privateLayout, layoutId); long parentLayoutId = layout.getParentLayoutId(); long includedLayoutIndex = _layoutService.getLayoutsCount(groupId, privateLayout, parentLayoutId, layout.getPriority()); int total = _layoutService.getLayoutsCount(groupId, privateLayout, parentLayoutId); int start = (int) includedLayoutIndex - 1; int end = (int) includedLayoutIndex + max; if (end > total) { start = total - max; end = total; if (start < 0) { start = 0; } } List<Layout> layouts = _layoutService.getLayouts(groupId, privateLayout, parentLayoutId, true, start, end); JSONObject jsonObject = _toJSONObject(request, groupId, layouts, total, layoutSetBranch); List<Layout> ancestorLayouts = _layoutService.getAncestorLayouts(layout.getPlid()); long[] ancestorLayoutIds = new long[ancestorLayouts.size()]; String[] ancestorLayoutNames = new String[ancestorLayouts.size()]; Locale locale = _portal.getLocale(request); for (int i = 0; i < ancestorLayouts.size(); i++) { Layout ancestorLayout = ancestorLayouts.get(i); ancestorLayoutIds[i] = ancestorLayout.getLayoutId(); ancestorLayoutNames[i] = ancestorLayout.getName(locale); } jsonObject.put("ancestorLayoutIds", ancestorLayoutIds); jsonObject.put("ancestorLayoutNames", ancestorLayoutNames); jsonObject.put("start", start); return jsonObject.toString(); } @Override public String getLayoutsJSON(HttpServletRequest request, long groupId, boolean privateLayout, long parentLayoutId, long[] expandedLayoutIds, boolean incomplete, String treeId) throws Exception { return getLayoutsJSON(request, groupId, privateLayout, parentLayoutId, expandedLayoutIds, incomplete, treeId, null); } @Override public String getLayoutsJSON(HttpServletRequest request, long groupId, boolean privateLayout, long parentLayoutId, long[] expandedLayoutIds, boolean incomplete, String treeId, LayoutSetBranch layoutSetBranch) throws Exception { if (_log.isDebugEnabled()) { StringBundler sb = new StringBundler(13); sb.append("getLayoutsJSON(groupId="); sb.append(groupId); sb.append(", privateLayout="); sb.append(privateLayout); sb.append(", parentLayoutId="); sb.append(parentLayoutId); sb.append(", expandedLayoutIds="); sb.append(expandedLayoutIds); sb.append(", incomplete="); sb.append(incomplete); sb.append(", treeId="); sb.append(treeId); sb.append(StringPool.CLOSE_PARENTHESIS); _log.debug(sb.toString()); } LayoutTreeNodes layoutTreeNodes = _getLayoutTreeNodes(request, groupId, privateLayout, parentLayoutId, incomplete, expandedLayoutIds, treeId); return _toJSON(request, groupId, layoutTreeNodes, layoutSetBranch); } @Override public String getLayoutsJSON(HttpServletRequest request, long groupId, String treeId) throws Exception { return getLayoutsJSON(request, groupId, treeId, null); } @Override public String getLayoutsJSON(HttpServletRequest request, long groupId, String treeId, LayoutSetBranch layoutSetBranch) throws Exception { if (_log.isDebugEnabled()) { StringBundler sb = new StringBundler(5); sb.append("getLayoutsJSON(groupId="); sb.append(groupId); sb.append(", treeId="); sb.append(treeId); sb.append(StringPool.CLOSE_PARENTHESIS); _log.debug(sb.toString()); } LayoutTreeNodes layoutTreeNodes = new LayoutTreeNodes(); layoutTreeNodes.addAll(_getLayoutTreeNodes(request, groupId, true, LayoutConstants.DEFAULT_PARENT_LAYOUT_ID, false, null, treeId)); layoutTreeNodes.addAll(_getLayoutTreeNodes(request, groupId, false, LayoutConstants.DEFAULT_PARENT_LAYOUT_ID, false, null, treeId)); return _toJSON(request, groupId, layoutTreeNodes, layoutSetBranch); } private Layout _fetchCurrentLayout(HttpServletRequest request) { long selPlid = ParamUtil.getLong(request, "selPlid"); if (selPlid > 0) { return _layoutLocalService.fetchLayout(selPlid); } ThemeDisplay themeDisplay = (ThemeDisplay) request.getAttribute(WebKeys.THEME_DISPLAY); Layout layout = themeDisplay.getLayout(); if (!layout.isTypeControlPanel()) { return layout; } return null; } private List<Layout> _getAncestorLayouts(HttpServletRequest request) throws Exception { Layout layout = _fetchCurrentLayout(request); if (layout == null) { return Collections.emptyList(); } List<Layout> ancestorLayouts = _layoutService.getAncestorLayouts(layout.getPlid()); if (_log.isDebugEnabled()) { StringBundler sb = new StringBundler(7); sb.append("_getAncestorLayouts(plid="); sb.append(layout.getPlid()); sb.append(", ancestorLayouts="); sb.append(ancestorLayouts); sb.append(", layout="); sb.append(layout); sb.append(StringPool.CLOSE_PARENTHESIS); _log.debug(sb.toString()); } ancestorLayouts.add(layout); return ancestorLayouts; } private LayoutTreeNodes _getLayoutTreeNodes(HttpServletRequest request, long groupId, boolean privateLayout, long parentLayoutId, boolean incomplete, long[] expandedLayoutIds, String treeId) throws Exception { if (_log.isDebugEnabled()) { StringBundler sb = new StringBundler(13); sb.append("_getLayoutTreeNodes(groupId="); sb.append(groupId); sb.append(", privateLayout="); sb.append(privateLayout); sb.append(", parentLayoutId="); sb.append(parentLayoutId); sb.append(", expandedLayoutIds="); sb.append(expandedLayoutIds); sb.append(", incomplete="); sb.append(incomplete); sb.append(", treeId="); sb.append(treeId); sb.append(StringPool.CLOSE_PARENTHESIS); _log.debug(sb.toString()); } List<LayoutTreeNode> layoutTreeNodes = new ArrayList<>(); List<Layout> ancestorLayouts = _getAncestorLayouts(request); List<Layout> layouts = _layoutService.getLayouts(groupId, privateLayout, parentLayoutId, incomplete, QueryUtil.ALL_POS, QueryUtil.ALL_POS); for (Layout layout : _paginateLayouts(request, groupId, privateLayout, parentLayoutId, layouts, treeId)) { LayoutTreeNode layoutTreeNode = new LayoutTreeNode(layout); LayoutTreeNodes childLayoutTreeNodes = null; if (_isExpandableLayout(request, ancestorLayouts, expandedLayoutIds, layout)) { if (layout instanceof VirtualLayout) { VirtualLayout virtualLayout = (VirtualLayout) layout; childLayoutTreeNodes = _getLayoutTreeNodes(request, virtualLayout.getSourceGroupId(), virtualLayout.isPrivateLayout(), virtualLayout.getLayoutId(), incomplete, expandedLayoutIds, treeId); } else { childLayoutTreeNodes = _getLayoutTreeNodes(request, groupId, layout.isPrivateLayout(), layout.getLayoutId(), incomplete, expandedLayoutIds, treeId); } } else { int childLayoutsCount = _layoutService.getLayoutsCount(groupId, privateLayout, layout.getLayoutId()); childLayoutTreeNodes = new LayoutTreeNodes(new ArrayList<LayoutTreeNode>(), childLayoutsCount); } layoutTreeNode.setChildLayoutTreeNodes(childLayoutTreeNodes); layoutTreeNodes.add(layoutTreeNode); } return new LayoutTreeNodes(layoutTreeNodes, layouts.size()); } private int _getLoadedLayoutsCount(HttpSession session, long groupId, boolean privateLayout, long layoutId, String treeId) throws Exception { StringBundler sb = new StringBundler(7); sb.append(treeId); sb.append(StringPool.COLON); sb.append(groupId); sb.append(StringPool.COLON); sb.append(privateLayout); sb.append(StringPool.COLON); sb.append("Pagination"); String key = sb.toString(); String paginationJSON = SessionClicks.get(session, key, JSONFactoryUtil.getNullJSON()); JSONObject paginationJSONObject = JSONFactoryUtil.createJSONObject(paginationJSON); if (_log.isDebugEnabled()) { sb = new StringBundler(9); sb.append("_getLoadedLayoutsCount(key="); sb.append(key); sb.append(", layoutId="); sb.append(layoutId); sb.append(", paginationJSON="); sb.append(paginationJSON); sb.append(", paginationJSONObject"); sb.append(paginationJSONObject); sb.append(StringPool.CLOSE_PARENTHESIS); _log.debug(sb.toString()); } return paginationJSONObject.getInt(String.valueOf(layoutId), 0); } private boolean _isDeleteable(Layout layout, ThemeDisplay themeDisplay, LayoutSetBranch layoutSetBranch) throws PortalException { if (!LayoutPermissionUtil.contains(themeDisplay.getPermissionChecker(), layout, ActionKeys.DELETE)) { return false; } Group group = layout.getGroup(); if (group.isGuest() && !layout.isPrivateLayout() && layout.isRootLayout() && (_layoutLocalService .getLayoutsCount(group, false, LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) == 1)) { return false; } if (layoutSetBranch != null) { List<LayoutRevision> layoutRevisions = _layoutRevisionLocalService .getLayoutRevisions(layoutSetBranch.getLayoutSetBranchId(), layout.getPlid()); if (layoutRevisions.size() == 1) { LayoutRevision layoutRevision = layoutRevisions.get(0); if (layoutRevision.isIncomplete()) { return false; } } } return true; } private boolean _isExpandableLayout(HttpServletRequest request, List<Layout> ancestorLayouts, long[] expandedLayoutIds, Layout layout) { boolean expandParentLayouts = ParamUtil.getBoolean(request, "expandParentLayouts"); if (expandParentLayouts || ancestorLayouts.contains(layout) || ArrayUtil.contains(expandedLayoutIds, layout.getLayoutId())) { return true; } return false; } private boolean _isPaginationEnabled(HttpServletRequest request) { boolean paginate = ParamUtil.getBoolean(request, "paginate", true); if (paginate && (PropsValues.LAYOUT_MANAGE_PAGES_INITIAL_CHILDREN > -1)) { return true; } return false; } private List<Layout> _paginateLayouts(HttpServletRequest request, long groupId, boolean privateLayout, long parentLayoutId, List<Layout> layouts, String treeId) throws Exception { if (!_isPaginationEnabled(request)) { return layouts; } HttpSession session = request.getSession(); int loadedLayoutsCount = _getLoadedLayoutsCount(session, groupId, privateLayout, parentLayoutId, treeId); int start = ParamUtil.getInteger(request, "start"); start = Math.max(0, Math.min(start, layouts.size())); int end = ParamUtil.getInteger(request, "end", start + PropsValues.LAYOUT_MANAGE_PAGES_INITIAL_CHILDREN); if (loadedLayoutsCount > end) { end = loadedLayoutsCount; } end = Math.max(start, Math.min(end, layouts.size())); if (_log.isDebugEnabled()) { StringBundler sb = new StringBundler(7); sb.append("_paginateLayouts(loadedLayoutsCount="); sb.append(loadedLayoutsCount); sb.append(", start="); sb.append(start); sb.append(", end="); sb.append(end); sb.append(StringPool.CLOSE_PARENTHESIS); _log.debug(sb.toString()); } return layouts.subList(start, end); } private String _toJSON(HttpServletRequest request, long groupId, LayoutTreeNodes layoutTreeNodes, LayoutSetBranch layoutSetBranch) throws Exception { JSONObject jsonObject = _toJSONObject(request, groupId, layoutTreeNodes, layoutSetBranch); return jsonObject.toString(); } private JSONObject _toJSONObject(HttpServletRequest request, long groupId, LayoutTreeNodes layoutTreeNodes, LayoutSetBranch layoutSetBranch) throws Exception { if (_log.isDebugEnabled()) { StringBundler sb = new StringBundler(5); sb.append("_toJSON(groupId="); sb.append(groupId); sb.append(", layoutTreeNodes="); sb.append(layoutTreeNodes); sb.append(StringPool.CLOSE_PARENTHESIS); _log.debug(sb.toString()); } ThemeDisplay themeDisplay = (ThemeDisplay) request.getAttribute(WebKeys.THEME_DISPLAY); JSONArray jsonArray = JSONFactoryUtil.createJSONArray(); boolean hasManageLayoutsPermission = GroupPermissionUtil.contains(themeDisplay.getPermissionChecker(), groupId, ActionKeys.MANAGE_LAYOUTS); boolean mobile = BrowserSnifferUtil.isMobile(request); for (LayoutTreeNode layoutTreeNode : layoutTreeNodes) { JSONObject jsonObject = JSONFactoryUtil.createJSONObject(); JSONObject childrenJSONObject = _toJSONObject(request, groupId, layoutTreeNode.getChildLayoutTreeNodes(), layoutSetBranch); jsonObject.put("children", childrenJSONObject); Layout layout = layoutTreeNode.getLayout(); jsonObject.put("contentDisplayPage", layout.isContentDisplayPage()); jsonObject.put("deleteable", _isDeleteable(layout, themeDisplay, layoutSetBranch)); jsonObject.put("friendlyURL", layout.getFriendlyURL()); if (layout instanceof VirtualLayout) { VirtualLayout virtualLayout = (VirtualLayout) layout; jsonObject.put("groupId", virtualLayout.getSourceGroupId()); } else { jsonObject.put("groupId", layout.getGroupId()); } jsonObject.put("hasChildren", layout.hasChildren()); jsonObject.put("layoutId", layout.getLayoutId()); jsonObject.put("name", layout.getName(themeDisplay.getLocale())); jsonObject.put("parentable", LayoutPermissionUtil.contains(themeDisplay.getPermissionChecker(), layout, ActionKeys.ADD_LAYOUT)); jsonObject.put("parentLayoutId", layout.getParentLayoutId()); jsonObject.put("plid", layout.getPlid()); jsonObject.put("priority", layout.getPriority()); jsonObject.put("privateLayout", layout.isPrivateLayout()); jsonObject.put("regularURL", layout.getRegularURL(request)); jsonObject.put("sortable", hasManageLayoutsPermission && !mobile && SitesUtil.isLayoutSortable(layout)); jsonObject.put("type", layout.getType()); jsonObject.put("updateable", LayoutPermissionUtil.contains(themeDisplay.getPermissionChecker(), layout, ActionKeys.UPDATE)); jsonObject.put("uuid", layout.getUuid()); LayoutRevision layoutRevision = LayoutStagingUtil.getLayoutRevision(layout); if (layoutRevision != null) { long layoutSetBranchId = layoutRevision.getLayoutSetBranchId(); if (_staging.isIncomplete(layout, layoutSetBranchId)) { jsonObject.put("incomplete", true); } LayoutSetBranch boundLayoutSetBranch = _layoutSetBranchLocalService .getLayoutSetBranch(layoutSetBranchId); LayoutBranch layoutBranch = layoutRevision.getLayoutBranch(); if (!layoutBranch.isMaster()) { jsonObject.put("layoutBranchId", layoutBranch.getLayoutBranchId()); jsonObject.put("layoutBranchName", layoutBranch.getName()); } if (layoutRevision.isHead()) { jsonObject.put("layoutRevisionHead", true); } jsonObject.put("layoutRevisionId", layoutRevision.getLayoutRevisionId()); jsonObject.put("layoutSetBranchId", layoutSetBranchId); jsonObject.put("layoutSetBranchName", boundLayoutSetBranch.getName()); } jsonArray.put(jsonObject); } JSONObject responseJSONObject = JSONFactoryUtil.createJSONObject(); responseJSONObject.put("layouts", jsonArray); responseJSONObject.put("total", layoutTreeNodes.getTotal()); return responseJSONObject; } private JSONObject _toJSONObject(HttpServletRequest request, long groupId, List<Layout> layouts, int total, LayoutSetBranch layoutSetBranch) throws Exception { List<LayoutTreeNode> layoutTreeNodesList = new ArrayList<>(); for (Layout layout : layouts) { LayoutTreeNode layoutTreeNode = new LayoutTreeNode(layout); layoutTreeNodesList.add(layoutTreeNode); } LayoutTreeNodes layoutTreeNodes = new LayoutTreeNodes(layoutTreeNodesList, total); return _toJSONObject(request, groupId, layoutTreeNodes, layoutSetBranch); } private static final Log _log = LogFactoryUtil.getLog(LayoutsTreeImpl.class); @Reference private LayoutLocalService _layoutLocalService; @Reference private LayoutRevisionLocalService _layoutRevisionLocalService; @Reference private LayoutService _layoutService; @Reference private LayoutSetBranchLocalService _layoutSetBranchLocalService; @Reference private Portal _portal; @Reference private Staging _staging; private static class LayoutTreeNode { public LayoutTreeNode(Layout layout) { _layout = layout; } public LayoutTreeNodes getChildLayoutTreeNodes() { return _childLayoutTreeNodes; } public Layout getLayout() { return _layout; } public void setChildLayoutTreeNodes(LayoutTreeNodes childLayoutTreeNodes) { _childLayoutTreeNodes = childLayoutTreeNodes; } @Override public String toString() { StringBundler sb = new StringBundler(5); sb.append("{childLayoutTreeNodes="); sb.append(_childLayoutTreeNodes); sb.append(", layout="); sb.append(_layout); sb.append(StringPool.CLOSE_CURLY_BRACE); return sb.toString(); } private LayoutTreeNodes _childLayoutTreeNodes = new LayoutTreeNodes(); private final Layout _layout; } private static class LayoutTreeNodes implements Iterable<LayoutTreeNode> { public LayoutTreeNodes() { _layoutTreeNodesList = new ArrayList<>(); } public LayoutTreeNodes(List<LayoutTreeNode> layoutTreeNodesList, int total) { _layoutTreeNodesList = layoutTreeNodesList; _total = total; } public void addAll(LayoutTreeNodes layoutTreeNodes) { _layoutTreeNodesList.addAll(layoutTreeNodes.getLayoutTreeNodesList()); _total += layoutTreeNodes.getTotal(); } public List<LayoutTreeNode> getLayoutTreeNodesList() { return _layoutTreeNodesList; } public int getTotal() { return _total; } @Override public Iterator<LayoutTreeNode> iterator() { return _layoutTreeNodesList.iterator(); } @Override public String toString() { StringBundler sb = new StringBundler(5); sb.append("{layoutTreeNodesList="); sb.append(_layoutTreeNodesList); sb.append(", total="); sb.append(_total); sb.append(StringPool.CLOSE_CURLY_BRACE); return sb.toString(); } private final List<LayoutTreeNode> _layoutTreeNodesList; private int _total; } }