@Override
  public String readResponse(ThemeDisplay themeDisplay, ActionRequest actionRequest)
      throws PortalException {

    HttpServletRequest request = PortalUtil.getHttpServletRequest(actionRequest);

    request = PortalUtil.getOriginalServletRequest(request);

    String receivingURL = ParamUtil.getString(request, "openid.return_to");
    ParameterList parameterList = new ParameterList(request.getParameterMap());

    HttpSession session = request.getSession();

    DiscoveryInformation discoveryInformation =
        (DiscoveryInformation) session.getAttribute(OpenIdWebKeys.OPEN_ID_DISCO);

    if (discoveryInformation == null) {
      return null;
    }

    AuthSuccess authSuccess = null;
    String firstName = null;
    String lastName = null;
    String emailAddress = null;

    try {
      VerificationResult verificationResult =
          _consumerManager.verify(receivingURL, parameterList, discoveryInformation);

      Identifier identifier = verificationResult.getVerifiedId();

      if (identifier == null) {
        return null;
      }

      authSuccess = (AuthSuccess) verificationResult.getAuthResponse();

      firstName = null;
      lastName = null;
      emailAddress = null;

      if (authSuccess.hasExtension(SRegMessage.OPENID_NS_SREG)) {
        MessageExtension messageExtension = authSuccess.getExtension(SRegMessage.OPENID_NS_SREG);

        if (messageExtension instanceof SRegResponse) {
          SRegResponse sregResp = (SRegResponse) messageExtension;

          String fullName =
              GetterUtil.getString(sregResp.getAttributeValue(_OPEN_ID_SREG_ATTR_FULLNAME));

          String[] names = splitFullName(fullName);

          if (names != null) {
            firstName = names[0];
            lastName = names[1];
          }

          emailAddress = sregResp.getAttributeValue(_OPEN_ID_SREG_ATTR_EMAIL);
        }
      }

      if (authSuccess.hasExtension(AxMessage.OPENID_NS_AX)) {
        MessageExtension messageExtension = authSuccess.getExtension(AxMessage.OPENID_NS_AX);

        if (messageExtension instanceof FetchResponse) {
          FetchResponse fetchResponse = (FetchResponse) messageExtension;

          OpenIdProvider openIdProvider =
              _openIdProviderRegistry.getOpenIdProvider(discoveryInformation.getOPEndpoint());

          String[] openIdAXTypes = openIdProvider.getAxSchema();

          for (String openIdAXType : openIdAXTypes) {
            if (openIdAXType.equals(_OPEN_ID_AX_ATTR_EMAIL)) {
              if (Validator.isNull(emailAddress)) {
                emailAddress =
                    getFirstValue(fetchResponse.getAttributeValues(_OPEN_ID_AX_ATTR_EMAIL));
              }
            } else if (openIdAXType.equals(_OPEN_ID_AX_ATTR_FIRST_NAME)) {

              if (Validator.isNull(firstName)) {
                firstName =
                    getFirstValue(fetchResponse.getAttributeValues(_OPEN_ID_AX_ATTR_FIRST_NAME));
              }
            } else if (openIdAXType.equals(_OPEN_ID_AX_ATTR_FULL_NAME)) {

              String fullName = fetchResponse.getAttributeValue(_OPEN_ID_AX_ATTR_FULL_NAME);

              String[] names = splitFullName(fullName);

              if (names != null) {
                if (Validator.isNull(firstName)) {
                  firstName = names[0];
                }

                if (Validator.isNull(lastName)) {
                  lastName = names[1];
                }
              }
            } else if (openIdAXType.equals(_OPEN_ID_AX_ATTR_LAST_NAME)) {

              if (Validator.isNull(lastName)) {
                lastName =
                    getFirstValue(fetchResponse.getAttributeValues(_OPEN_ID_AX_ATTR_LAST_NAME));
              }
            }
          }
        }
      }
    } catch (AssociationException ae) {
      throw new OpenIdServiceException.AssociationException(ae.getMessage(), ae);
    } catch (DiscoveryException de) {
      throw new OpenIdServiceException.DiscoveryException(de.getMessage(), de);
    } catch (MessageException me) {
      throw new OpenIdServiceException.MessageException(me.getMessage(), me);
    }

    String openId = normalize(authSuccess.getIdentity());

    User user = _userLocalService.fetchUserByOpenId(themeDisplay.getCompanyId(), openId);

    if (user != null) {
      session.setAttribute(WebKeys.OPEN_ID_LOGIN, user.getUserId());

      return null;
    }

    try {
      if (Validator.isNull(firstName)
          || Validator.isNull(lastName)
          || Validator.isNull(emailAddress)) {

        SessionMessages.add(request, "openIdUserInformationMissing");

        if (_log.isInfoEnabled()) {
          _log.info(
              "The OpenID provider did not send the required " + "attributes to create an account");
        }

        String createAccountURL = PortalUtil.getCreateAccountURL(request, themeDisplay);

        String portletId = HttpUtil.getParameter(createAccountURL, "p_p_id", false);

        String portletNamespace = PortalUtil.getPortletNamespace(portletId);

        createAccountURL =
            HttpUtil.setParameter(createAccountURL, portletNamespace + "openId", openId);

        session.setAttribute(WebKeys.OPEN_ID_LOGIN_PENDING, Boolean.TRUE);

        return createAccountURL;
      }
    } catch (Exception e) {
      throw new PortalException(e);
    }

    long creatorUserId = 0;
    long companyId = themeDisplay.getCompanyId();
    boolean autoPassword = false;
    String password1 = PwdGenerator.getPassword();
    String password2 = password1;
    boolean autoScreenName = true;
    String screenName = StringPool.BLANK;
    long facebookId = 0;
    Locale locale = themeDisplay.getLocale();
    String middleName = StringPool.BLANK;
    long prefixId = 0;
    long suffixId = 0;
    boolean male = true;
    int birthdayMonth = Calendar.JANUARY;
    int birthdayDay = 1;
    int birthdayYear = 1970;
    String jobTitle = StringPool.BLANK;
    long[] groupIds = null;
    long[] organizationIds = null;
    long[] roleIds = null;
    long[] userGroupIds = null;
    boolean sendEmail = false;

    ServiceContext serviceContext = new ServiceContext();

    user =
        _userLocalService.addUser(
            creatorUserId,
            companyId,
            autoPassword,
            password1,
            password2,
            autoScreenName,
            screenName,
            emailAddress,
            facebookId,
            openId,
            locale,
            firstName,
            middleName,
            lastName,
            prefixId,
            suffixId,
            male,
            birthdayMonth,
            birthdayDay,
            birthdayYear,
            jobTitle,
            groupIds,
            organizationIds,
            roleIds,
            userGroupIds,
            sendEmail,
            serviceContext);

    session.setAttribute(WebKeys.OPEN_ID_LOGIN, user.getUserId());

    return null;
  }
  @Override
  public String getActualURL(
      long companyId,
      long groupId,
      boolean privateLayout,
      String mainPath,
      String friendlyURL,
      Map<String, String[]> params,
      Map<String, Object> requestContext)
      throws PortalException {

    String urlTitle =
        friendlyURL.substring(JournalArticleConstants.CANONICAL_URL_SEPARATOR.length());

    JournalArticle journalArticle =
        _journalArticleLocalService.getArticleByUrlTitle(groupId, urlTitle);

    Layout layout = getJournalArticleLayout(groupId, privateLayout, friendlyURL);

    String layoutActualURL = PortalUtil.getLayoutActualURL(layout, mainPath);

    InheritableMap<String, String[]> actualParams = new InheritableMap<>();

    if (params != null) {
      actualParams.setParentMap(params);
    }

    UnicodeProperties typeSettingsProperties = layout.getTypeSettingsProperties();

    String defaultAssetPublisherPortletId =
        typeSettingsProperties.get(LayoutTypePortletConstants.DEFAULT_ASSET_PUBLISHER_PORTLET_ID);

    String currentDefaultAssetPublisherPortletId = defaultAssetPublisherPortletId;

    if (Validator.isNull(defaultAssetPublisherPortletId)) {
      PortletInstance portletInstance =
          new PortletInstance(AssetPublisherPortletKeys.ASSET_PUBLISHER);

      defaultAssetPublisherPortletId = portletInstance.getPortletInstanceKey();
    }

    HttpServletRequest request = (HttpServletRequest) requestContext.get("request");

    if (Validator.isNull(currentDefaultAssetPublisherPortletId)) {
      String actualPortletAuthenticationToken =
          AuthTokenUtil.getToken(request, layout.getPlid(), defaultAssetPublisherPortletId);

      actualParams.put("p_p_auth", new String[] {actualPortletAuthenticationToken});
    }

    actualParams.put("p_p_id", new String[] {defaultAssetPublisherPortletId});
    actualParams.put("p_p_lifecycle", new String[] {"0"});

    if (Validator.isNull(currentDefaultAssetPublisherPortletId)) {
      actualParams.put("p_p_state", new String[] {WindowState.MAXIMIZED.toString()});
    }

    actualParams.put("p_p_mode", new String[] {"view"});
    actualParams.put("p_j_a_id", new String[] {String.valueOf(journalArticle.getId())});

    String namespace = PortalUtil.getPortletNamespace(defaultAssetPublisherPortletId);

    actualParams.put(namespace + "mvcPath", new String[] {"/view_content.jsp"});

    AssetRendererFactory<?> assetRendererFactory =
        AssetRendererFactoryRegistryUtil.getAssetRendererFactoryByClassName(
            JournalArticle.class.getName());

    actualParams.put(namespace + "type", new String[] {assetRendererFactory.getType()});

    actualParams.put(namespace + "urlTitle", new String[] {journalArticle.getUrlTitle()});

    String queryString = HttpUtil.parameterMapToString(actualParams, false);

    if (layoutActualURL.contains(StringPool.QUESTION)) {
      layoutActualURL = layoutActualURL + StringPool.AMPERSAND + queryString;
    } else {
      layoutActualURL = layoutActualURL + StringPool.QUESTION + queryString;
    }

    Locale locale = PortalUtil.getLocale(request);

    PortalUtil.addPageSubtitle(journalArticle.getTitle(locale), request);
    PortalUtil.addPageDescription(journalArticle.getDescription(locale), request);

    List<AssetTag> assetTags =
        _assetTagLocalService.getTags(
            JournalArticle.class.getName(), journalArticle.getPrimaryKey());

    if (!assetTags.isEmpty()) {
      PortalUtil.addPageKeywords(ListUtil.toString(assetTags, AssetTag.NAME_ACCESSOR), request);
    }

    return layoutActualURL;
  }
  protected void onRemoveFromLayout(String[] portletIds) {
    Set<String> portletIdList = new HashSet<>();

    for (String portletId : portletIds) {
      removeModesPortletId(portletId);
      removeStatesPortletId(portletId);

      portletIdList.add(portletId);

      String rootPortletId = PortletConstants.getRootPortletId(portletId);

      if (rootPortletId.equals(PortletKeys.NESTED_PORTLETS)) {
        String portletNamespace = PortalUtil.getPortletNamespace(portletId);

        UnicodeProperties typeSettingsProperties = getTypeSettingsProperties();

        for (Map.Entry<String, String> entry : typeSettingsProperties.entrySet()) {

          String key = entry.getKey();

          if (!key.startsWith(portletNamespace)) {
            continue;
          }

          String nestedPortletIds = entry.getValue();

          for (String nestedPortletId : StringUtil.split(nestedPortletIds)) {

            removeModesPortletId(nestedPortletId);
            removeStatesPortletId(nestedPortletId);

            portletIdList.add(nestedPortletId);
          }
        }

        removeNestedColumns(portletNamespace);
      }

      Portlet portlet = PortletLocalServiceUtil.getPortletById(portletId);

      if (portlet == null) {
        continue;
      }

      PortletLayoutListener portletLayoutListener = portlet.getPortletLayoutListenerInstance();

      if (portletLayoutListener == null) {
        continue;
      }

      portletLayoutListener.updatePropertiesOnRemoveFromLayout(
          portletId, getTypeSettingsProperties());
    }

    try {
      PortletLocalServiceUtil.deletePortlets(
          getCompanyId(), portletIdList.toArray(new String[portletIdList.size()]), getPlid());
    } catch (PortalException pe) {
      _log.error(pe, pe);
    }
  }
/**
 * @author Brian Wing Shun Chan
 * @author Berentey Zsolt
 * @author Jorge Ferrer
 * @author Raymond Augé
 */
public class LayoutTypePortletImpl extends LayoutTypeImpl implements LayoutTypePortlet {

  public LayoutTypePortletImpl(
      Layout layout,
      LayoutTypeController layoutTypeController,
      LayoutTypeAccessPolicy layoutTypeAccessPolicy) {

    super(layout, layoutTypeController, layoutTypeAccessPolicy);

    _layoutSetPrototypeLayout = SitesUtil.getLayoutSetPrototypeLayout(layout);
  }

  @Override
  public void addModeAboutPortletId(String portletId) {
    removeModesPortletId(portletId);
    setModeAbout(StringUtil.add(getModeAbout(), portletId));
  }

  @Override
  public void addModeConfigPortletId(String portletId) {
    removeModesPortletId(portletId);
    setModeConfig(StringUtil.add(getModeConfig(), portletId));
  }

  @Override
  public void addModeEditDefaultsPortletId(String portletId) {
    removeModesPortletId(portletId);
    setModeEditDefaults(StringUtil.add(getModeEditDefaults(), portletId));
  }

  @Override
  public void addModeEditGuestPortletId(String portletId) {
    removeModesPortletId(portletId);
    setModeEditGuest(StringUtil.add(getModeEditGuest(), portletId));
  }

  @Override
  public void addModeEditPortletId(String portletId) {
    removeModesPortletId(portletId);
    setModeEdit(StringUtil.add(getModeEdit(), portletId));
  }

  @Override
  public void addModeHelpPortletId(String portletId) {
    removeModesPortletId(portletId);
    setModeHelp(StringUtil.add(getModeHelp(), portletId));
  }

  @Override
  public void addModePreviewPortletId(String portletId) {
    removeModesPortletId(portletId);
    setModePreview(StringUtil.add(getModePreview(), portletId));
  }

  @Override
  public void addModePrintPortletId(String portletId) {
    removeModesPortletId(portletId);
    setModePrint(StringUtil.add(getModePrint(), portletId));
  }

  @Override
  public String addPortletId(long userId, String portletId) {
    return addPortletId(userId, portletId, true);
  }

  @Override
  public String addPortletId(long userId, String portletId, boolean checkPermission) {

    return addPortletId(userId, portletId, null, -1, checkPermission);
  }

  @Override
  public String addPortletId(long userId, String portletId, String columnId, int columnPos) {

    return addPortletId(userId, portletId, columnId, columnPos, true);
  }

  @Override
  public String addPortletId(
      long userId, String portletId, String columnId, int columnPos, boolean checkPermission) {

    return addPortletId(userId, portletId, columnId, columnPos, checkPermission, false);
  }

  @Override
  public void addPortletIds(long userId, String[] portletIds, boolean checkPermission) {

    for (String portletId : portletIds) {
      addPortletId(userId, portletId, checkPermission);
    }
  }

  @Override
  public void addPortletIds(
      long userId, String[] portletIds, String columnId, boolean checkPermission) {

    for (String portletId : portletIds) {
      addPortletId(userId, portletId, columnId, -1, checkPermission);
    }
  }

  @Override
  public void addStateMaxPortletId(String portletId) {
    removeStatesPortletId(portletId);
    // setStateMax(StringUtil.add(getStateMax(), portletId));
    setStateMax(StringUtil.add(StringPool.BLANK, portletId));
  }

  @Override
  public void addStateMinPortletId(String portletId) {
    removeStateMaxPortletId(portletId);
    setStateMin(StringUtil.add(getStateMin(), portletId));
  }

  @Override
  public List<Portlet> addStaticPortlets(
      List<Portlet> portlets, List<Portlet> startPortlets, List<Portlet> endPortlets) {

    // Return the original array of portlets if no static portlets are
    // specified

    if (startPortlets == null) {
      startPortlets = new ArrayList<>();
    }

    if (endPortlets == null) {
      endPortlets = new ArrayList<>();
    }

    if (startPortlets.isEmpty() && endPortlets.isEmpty()) {
      return portlets;
    }

    // New array of portlets that contain the static portlets

    List<Portlet> list =
        new ArrayList<>(portlets.size() + startPortlets.size() + endPortlets.size());

    if (!startPortlets.isEmpty()) {
      list.addAll(startPortlets);
    }

    for (int i = 0; i < portlets.size(); i++) {
      Portlet portlet = portlets.get(i);

      // Add the portlet if and only if it is not also a static portlet

      if (!startPortlets.contains(portlet) && !endPortlets.contains(portlet)) {

        list.add(portlet);
      }
    }

    if (!endPortlets.isEmpty()) {
      list.addAll(endPortlets);
    }

    return list;
  }

  @Override
  public List<Portlet> getAllPortlets() {
    List<Portlet> explicitlyAddedPortlets = getExplicitlyAddedPortlets();

    List<Portlet> staticPortlets = getStaticPortlets(PropsKeys.LAYOUT_STATIC_PORTLETS_ALL);

    List<Portlet> embeddedPortlets = getEmbeddedPortlets();

    return addStaticPortlets(explicitlyAddedPortlets, staticPortlets, embeddedPortlets);
  }

  @Override
  public List<Portlet> getAllPortlets(boolean includeSystem) {
    List<Portlet> filteredPortlets = new ArrayList<>();

    List<Portlet> portlets = getAllPortlets();

    for (Portlet portlet : portlets) {
      if (portlet.isSystem() && !includeSystem) {
        continue;
      }

      filteredPortlets.add(portlet);
    }

    return filteredPortlets;
  }

  @Override
  public List<Portlet> getAllPortlets(String columnId) {
    String columnValue = getColumnValue(columnId);

    String[] portletIds = StringUtil.split(columnValue);

    List<Portlet> portlets = new ArrayList<>(portletIds.length);

    for (String portletId : portletIds) {
      Portlet portlet = PortletLocalServiceUtil.getPortletById(getCompanyId(), portletId);

      if (portlet != null) {
        portlets.add(portlet);
      }
    }

    List<Portlet> startPortlets =
        getStaticPortlets(PropsKeys.LAYOUT_STATIC_PORTLETS_START + columnId);

    List<Portlet> endPortlets = getStaticPortlets(PropsKeys.LAYOUT_STATIC_PORTLETS_END + columnId);

    return addStaticPortlets(portlets, startPortlets, endPortlets);
  }

  @Override
  public List<Portlet> getEmbeddedPortlets() {
    Layout layout = getLayout();

    return layout.getEmbeddedPortlets();
  }

  @Override
  public List<Portlet> getExplicitlyAddedPortlets() {
    List<Portlet> portlets = new ArrayList<>();

    List<String> columns = getColumns();

    for (int i = 0; i < columns.size(); i++) {
      String columnId = columns.get(i);

      portlets.addAll(getAllPortlets(columnId));
    }

    return portlets;
  }

  @Override
  public Layout getLayoutSetPrototypeLayout() {
    return _layoutSetPrototypeLayout;
  }

  @Override
  public String getLayoutSetPrototypeLayoutProperty(String key) {
    if (_layoutSetPrototypeLayout == null) {
      return StringPool.BLANK;
    }

    UnicodeProperties typeSettingsProperties =
        _layoutSetPrototypeLayout.getTypeSettingsProperties();

    return typeSettingsProperties.getProperty(key);
  }

  @Override
  public LayoutTemplate getLayoutTemplate() {
    String themeId = getThemeId();

    LayoutTemplate layoutTemplate =
        LayoutTemplateLocalServiceUtil.getLayoutTemplate(getLayoutTemplateId(), false, themeId);

    if (layoutTemplate == null) {
      layoutTemplate = new LayoutTemplateImpl(StringPool.BLANK, StringPool.BLANK);

      List<String> columns = new ArrayList<>();

      for (int i = 1; i <= 10; i++) {
        columns.add(LayoutTypePortletConstants.COLUMN_PREFIX + i);
      }

      layoutTemplate.setColumns(columns);
    }

    return layoutTemplate;
  }

  @Override
  public String getLayoutTemplateId() {
    return GetterUtil.getString(
        getTypeSettingsProperty(LayoutTypePortletConstants.LAYOUT_TEMPLATE_ID));
  }

  @Override
  public String getModeAbout() {
    return getTypeSettingsProperty(LayoutTypePortletConstants.MODE_ABOUT);
  }

  @Override
  public String getModeConfig() {
    return getTypeSettingsProperty(LayoutTypePortletConstants.MODE_CONFIG);
  }

  @Override
  public String getModeEdit() {
    return getTypeSettingsProperty(LayoutTypePortletConstants.MODE_EDIT);
  }

  @Override
  public String getModeEditDefaults() {
    return getTypeSettingsProperty(LayoutTypePortletConstants.MODE_EDIT_DEFAULTS);
  }

  @Override
  public String getModeEditGuest() {
    return getTypeSettingsProperty(LayoutTypePortletConstants.MODE_EDIT_GUEST);
  }

  @Override
  public String getModeHelp() {
    return getTypeSettingsProperty(LayoutTypePortletConstants.MODE_HELP);
  }

  @Override
  public String getModePreview() {
    return getTypeSettingsProperty(LayoutTypePortletConstants.MODE_PREVIEW);
  }

  @Override
  public String getModePrint() {
    return getTypeSettingsProperty(LayoutTypePortletConstants.MODE_PRINT);
  }

  @Override
  public int getNumOfColumns() {
    return getLayoutTemplate().getColumns().size();
  }

  @Override
  public PortalPreferences getPortalPreferences() {
    return _portalPreferences;
  }

  @Override
  public List<String> getPortletIds() {
    List<String> portletIds = new ArrayList<>();

    List<String> columns = getColumns();

    for (int i = 0; i < columns.size(); i++) {
      String columnId = columns.get(i);

      String columnValue = getColumnValue(columnId);

      portletIds.addAll(ListUtil.fromArray(StringUtil.split(columnValue)));
    }

    return portletIds;
  }

  @Override
  public List<Portlet> getPortlets() {
    List<String> portletIds = getPortletIds();

    List<Portlet> portlets = new ArrayList<>(portletIds.size());

    for (int i = 0; i < portletIds.size(); i++) {
      String portletId = portletIds.get(i);

      Portlet portlet = PortletLocalServiceUtil.getPortletById(getCompanyId(), portletId);

      if (portlet != null) {
        portlets.add(portlet);
      }
    }

    return portlets;
  }

  @Override
  public String getStateMax() {
    return getTypeSettingsProperty(LayoutTypePortletConstants.STATE_MAX);
  }

  @Override
  public String getStateMaxPortletId() {
    String[] stateMax = StringUtil.split(getStateMax());

    if (stateMax.length > 0) {
      return stateMax[0];
    } else {
      return StringPool.BLANK;
    }
  }

  @Override
  public String getStateMin() {
    return getTypeSettingsProperty(LayoutTypePortletConstants.STATE_MIN);
  }

  @Override
  public boolean hasDefaultScopePortletId(long groupId, String portletId) {
    if (hasPortletId(portletId)) {
      long scopeGroupId = PortalUtil.getScopeGroupId(getLayout(), portletId);

      if (groupId == scopeGroupId) {
        return true;
      }
    }

    return false;
  }

  @Override
  public boolean hasModeAboutPortletId(String portletId) {
    return StringUtil.contains(getModeAbout(), portletId);
  }

  @Override
  public boolean hasModeConfigPortletId(String portletId) {
    return StringUtil.contains(getModeConfig(), portletId);
  }

  @Override
  public boolean hasModeEditDefaultsPortletId(String portletId) {
    return StringUtil.contains(getModeEditDefaults(), portletId);
  }

  @Override
  public boolean hasModeEditGuestPortletId(String portletId) {
    return StringUtil.contains(getModeEditGuest(), portletId);
  }

  @Override
  public boolean hasModeEditPortletId(String portletId) {
    return StringUtil.contains(getModeEdit(), portletId);
  }

  @Override
  public boolean hasModeHelpPortletId(String portletId) {
    return StringUtil.contains(getModeHelp(), portletId);
  }

  @Override
  public boolean hasModePreviewPortletId(String portletId) {
    return StringUtil.contains(getModePreview(), portletId);
  }

  @Override
  public boolean hasModePrintPortletId(String portletId) {
    return StringUtil.contains(getModePrint(), portletId);
  }

  @Override
  public boolean hasModeViewPortletId(String portletId) {
    if (hasModeAboutPortletId(portletId)
        || hasModeConfigPortletId(portletId)
        || hasModeEditPortletId(portletId)
        || hasModeEditDefaultsPortletId(portletId)
        || hasModeEditGuestPortletId(portletId)
        || hasModeHelpPortletId(portletId)
        || hasModePreviewPortletId(portletId)
        || hasModePrintPortletId(portletId)) {

      return false;
    } else {
      return true;
    }
  }

  @Override
  public boolean hasPortletId(String portletId) {
    return hasPortletId(portletId, false);
  }

  @Override
  public boolean hasPortletId(String portletId, boolean strict) {
    List<String> columns = getColumns();

    for (String columnId : columns) {
      if (hasNonstaticPortletId(columnId, portletId)) {
        return true;
      }

      if (hasStaticPortletId(columnId, portletId)) {
        return true;
      }
    }

    Layout layout = getLayout();

    if (layout.isTypeControlPanel()) {
      return false;
    }

    if (isCustomizable() && isCustomizedView()) {
      LayoutTypePortletImpl defaultLayoutTypePortletImpl = getDefaultLayoutTypePortletImpl();

      if (defaultLayoutTypePortletImpl.hasNonstaticPortletId(portletId)) {
        return false;
      }
    }

    if (!strict
        && ((PortletPreferencesLocalServiceUtil.getPortletPreferencesCount(
                    PortletKeys.PREFS_OWNER_TYPE_LAYOUT, layout.getPlid(), portletId)
                > 0)
            || (PortletPreferencesLocalServiceUtil.getPortletPreferencesCount(
                    PortletKeys.PREFS_OWNER_TYPE_USER, layout.getPlid(), portletId)
                > 0))) {

      return true;
    }

    return false;
  }

  @Override
  public boolean hasStateMax() {
    String[] stateMax = StringUtil.split(getStateMax());

    if (stateMax.length > 0) {
      return true;
    } else {
      return false;
    }
  }

  @Override
  public boolean hasStateMaxPortletId(String portletId) {
    if (StringUtil.contains(getStateMax(), portletId)) {
      return true;
    } else {
      return false;
    }
  }

  @Override
  public boolean hasStateMin() {
    String[] stateMin = StringUtil.split(getStateMin());

    if (stateMin.length > 0) {
      return true;
    } else {
      return false;
    }
  }

  @Override
  public boolean hasStateMinPortletId(String portletId) {
    if (StringUtil.contains(getStateMin(), portletId)) {
      return true;
    } else {
      return false;
    }
  }

  @Override
  public boolean hasStateNormalPortletId(String portletId) {
    if (hasStateMaxPortletId(portletId) || hasStateMinPortletId(portletId)) {

      return false;
    } else {
      return true;
    }
  }

  @Override
  public boolean hasUpdatePermission() {
    return _updatePermission;
  }

  @Override
  public boolean isCacheable() {
    List<Portlet> portlets = new ArrayList<>();

    for (String columnId : getColumns()) {
      List<Portlet> columnPortlets = getAllPortlets(columnId);

      for (Portlet portlet : columnPortlets) {
        Portlet rootPortlet = portlet.getRootPortlet();

        if (!rootPortlet.isLayoutCacheable()) {
          return false;
        }
      }

      portlets.addAll(columnPortlets);
    }

    List<Portlet> staticPortlets = getStaticPortlets(PropsKeys.LAYOUT_STATIC_PORTLETS_ALL);

    for (Portlet portlet : staticPortlets) {
      Portlet rootPortlet = portlet.getRootPortlet();

      if (!rootPortlet.isLayoutCacheable()) {
        return false;
      }
    }

    List<Portlet> embeddedPortlets = getEmbeddedPortlets();

    for (Portlet portlet : embeddedPortlets) {
      Portlet rootPortlet = portlet.getRootPortlet();

      if (!rootPortlet.isLayoutCacheable()) {
        return false;
      }
    }

    return true;
  }

  @Override
  public boolean isColumnCustomizable(String columnId) {
    if (!isLayoutSetPrototype()) {
      String customizableString =
          getTypeSettingsProperty(CustomizedPages.namespaceColumnId(columnId));

      boolean customizable = GetterUtil.getBoolean(customizableString);

      if (!customizable && hasUserPreferences()) {
        String columnValue =
            _portalPreferences.getValue(
                CustomizedPages.namespacePlid(getPlid()), columnId, StringPool.NULL);

        if (!Objects.equals(columnValue, StringPool.NULL)) {
          setUserPreference(columnId, null);
        }
      }

      return customizable;
    }

    return false;
  }

  @Override
  public boolean isColumnDisabled(String columnId) {
    if ((isCustomizedView() && !isColumnCustomizable(columnId))
        || (!isCustomizedView() && !hasUpdatePermission())) {

      return true;
    }

    return false;
  }

  @Override
  public boolean isCustomizable() {
    for (String columnId : getColumns()) {
      if (isColumnCustomizable(columnId)) {
        return true;
      }
    }

    return false;
  }

  @Override
  public boolean isCustomizedView() {
    return _customizedView;
  }

  @Override
  public boolean isDefaultUpdated() {
    if (!isCustomizedView() || !hasUserPreferences()) {
      return false;
    }

    String preferencesModifiedDateString =
        _portalPreferences.getValue(
            CustomizedPages.namespacePlid(getPlid()), _MODIFIED_DATE, _NULL_DATE);

    DateFormat dateFormat =
        DateFormatFactoryUtil.getSimpleDateFormat(PropsValues.INDEX_DATE_FORMAT_PATTERN);

    try {
      Date preferencesModifiedDate = dateFormat.parse(preferencesModifiedDateString);

      Layout layout = getLayout();

      String propertiesModifiedDateString =
          layout.getTypeSettingsProperty(_MODIFIED_DATE, _NULL_DATE);

      Date propertiesModifiedDate = dateFormat.parse(propertiesModifiedDateString);

      return propertiesModifiedDate.after(preferencesModifiedDate);
    } catch (Exception e) {
      _log.error(e, e);
    }

    return false;
  }

  @Override
  public boolean isPortletCustomizable(String portletId) {
    return isColumnCustomizable(getColumn(portletId));
  }

  @Override
  public boolean isPortletEmbedded(String portletId) {
    Layout layout = getLayout();

    return layout.isPortletEmbedded(portletId, layout.getGroupId());
  }

  @Override
  public void movePortletId(long userId, String portletId, String columnId, int columnPos) {

    if (!hasPortletId(portletId)) {
      return;
    }

    _enablePortletLayoutListener = false;

    try {
      removePortletId(userId, portletId, false);
      addPortletId(userId, portletId, columnId, columnPos, false, true);
    } finally {
      _enablePortletLayoutListener = true;
    }

    Layout layout = getLayout();

    try {
      Portlet portlet = PortletLocalServiceUtil.getPortletById(layout.getCompanyId(), portletId);

      if (portlet != null) {
        PortletLayoutListener portletLayoutListener = portlet.getPortletLayoutListenerInstance();

        if (portletLayoutListener != null) {
          portletLayoutListener.onMoveInLayout(portletId, layout.getPlid());
        }
      }
    } catch (Exception e) {
      _log.error("Unable to fire portlet layout listener event", e);
    }
  }

  @Override
  public void removeCustomization(UnicodeProperties typeSettingsProperties) {
    for (String columnId : getColumns()) {
      if (!isColumnCustomizable(columnId)) {
        continue;
      }

      if (GetterUtil.getBoolean(
          getTypeSettingsProperty(CustomizedPages.namespaceColumnId(columnId)))) {

        typeSettingsProperties.remove(CustomizedPages.namespaceColumnId(columnId));
      }
    }
  }

  @Override
  public void removeModeAboutPortletId(String portletId) {
    setModeAbout(StringUtil.removeFromList(getModeAbout(), portletId));
  }

  @Override
  public void removeModeConfigPortletId(String portletId) {
    setModeConfig(StringUtil.removeFromList(getModeConfig(), portletId));
  }

  @Override
  public void removeModeEditDefaultsPortletId(String portletId) {
    setModeEditDefaults(StringUtil.removeFromList(getModeEditDefaults(), portletId));
  }

  @Override
  public void removeModeEditGuestPortletId(String portletId) {
    setModeEditGuest(StringUtil.removeFromList(getModeEditGuest(), portletId));
  }

  @Override
  public void removeModeEditPortletId(String portletId) {
    setModeEdit(StringUtil.removeFromList(getModeEdit(), portletId));
  }

  @Override
  public void removeModeHelpPortletId(String portletId) {
    setModeHelp(StringUtil.removeFromList(getModeHelp(), portletId));
  }

  @Override
  public void removeModePreviewPortletId(String portletId) {
    setModePreview(StringUtil.removeFromList(getModePreview(), portletId));
  }

  @Override
  public void removeModePrintPortletId(String portletId) {
    setModePrint(StringUtil.removeFromList(getModePrint(), portletId));
  }

  @Override
  public void removeModesPortletId(String portletId) {
    removeModeAboutPortletId(portletId);
    removeModeConfigPortletId(portletId);
    removeModeEditPortletId(portletId);
    removeModeEditDefaultsPortletId(portletId);
    removeModeEditGuestPortletId(portletId);
    removeModeHelpPortletId(portletId);
    removeModePreviewPortletId(portletId);
    removeModePrintPortletId(portletId);
  }

  @Override
  public void removeNestedColumns(String portletNamespace) {
    UnicodeProperties typeSettingsProperties = getTypeSettingsProperties();

    UnicodeProperties newTypeSettingsProperties = new UnicodeProperties();

    for (Map.Entry<String, String> entry : typeSettingsProperties.entrySet()) {

      String key = entry.getKey();

      if (!key.startsWith(portletNamespace)) {
        newTypeSettingsProperties.setProperty(key, entry.getValue());
      }
    }

    Layout layout = getLayout();

    layout.setTypeSettingsProperties(newTypeSettingsProperties);

    String nestedColumnIds =
        GetterUtil.getString(getTypeSettingsProperty(LayoutTypePortletConstants.NESTED_COLUMN_IDS));

    String[] nestedColumnIdsArray =
        ArrayUtil.removeByPrefix(StringUtil.split(nestedColumnIds), portletNamespace);

    setTypeSettingsProperty(
        LayoutTypePortletConstants.NESTED_COLUMN_IDS, StringUtil.merge(nestedColumnIdsArray));
  }

  @Override
  public void removePortletId(long userId, String portletId) {
    removePortletId(userId, portletId, true);
  }

  @Override
  public void removePortletId(long userId, String portletId, boolean cleanUp) {

    try {
      Portlet portlet = PortletLocalServiceUtil.getPortletById(getCompanyId(), portletId);

      if (portlet == null) {
        _log.error("Portlet " + portletId + " cannot be removed because it is not registered");

        return;
      }

      PermissionChecker permissionChecker = PermissionThreadLocal.getPermissionChecker();

      if (!LayoutPermissionUtil.contains(permissionChecker, getLayout(), ActionKeys.UPDATE)
          && !isCustomizable()) {

        return;
      }
    } catch (Exception e) {
      _log.error(e, e);

      return;
    }

    List<String> columns = getColumns();

    for (int i = 0; i < columns.size(); i++) {
      String columnId = columns.get(i);

      if (isCustomizable() && isColumnDisabled(columnId)) {
        continue;
      }

      String columnValue = StringPool.BLANK;

      if (hasUserPreferences()) {
        columnValue = getUserPreference(columnId);
      } else {
        columnValue = getTypeSettingsProperty(columnId);
      }

      columnValue = StringUtil.removeFromList(columnValue, portletId);

      if (hasUserPreferences()) {
        setUserPreference(columnId, columnValue);
      } else {
        setTypeSettingsProperty(columnId, columnValue);
      }
    }

    if (cleanUp) {
      try {
        onRemoveFromLayout(new String[] {portletId});
      } catch (Exception e) {
        _log.error(e, e);
      }
    }
  }

  @Override
  public void removeStateMaxPortletId(String portletId) {
    setStateMax(StringUtil.removeFromList(getStateMax(), portletId));
  }

  @Override
  public void removeStateMinPortletId(String portletId) {
    setStateMin(StringUtil.removeFromList(getStateMin(), portletId));
  }

  @Override
  public void removeStatesPortletId(String portletId) {
    removeStateMaxPortletId(portletId);
    removeStateMinPortletId(portletId);
  }

  @Override
  public void reorganizePortlets(List<String> newColumns, List<String> oldColumns) {

    String lastNewColumnId = newColumns.get(newColumns.size() - 1);
    String lastNewColumnValue = getTypeSettingsProperty(lastNewColumnId);

    for (String oldColumnId : oldColumns) {
      if (!newColumns.contains(oldColumnId)) {
        String oldColumnValue = getTypeSettingsProperties().remove(oldColumnId);

        String[] portletIds = StringUtil.split(oldColumnValue);

        for (String portletId : portletIds) {
          lastNewColumnValue = StringUtil.add(lastNewColumnValue, portletId);
        }
      }
    }

    setTypeSettingsProperty(lastNewColumnId, lastNewColumnValue);
  }

  @Override
  public void resetModes() {
    setModeAbout(StringPool.BLANK);
    setModeConfig(StringPool.BLANK);
    setModeEdit(StringPool.BLANK);
    setModeEditDefaults(StringPool.BLANK);
    setModeEditGuest(StringPool.BLANK);
    setModeHelp(StringPool.BLANK);
    setModePreview(StringPool.BLANK);
    setModePrint(StringPool.BLANK);
  }

  @Override
  public void resetStates() {
    setStateMax(StringPool.BLANK);
    setStateMin(StringPool.BLANK);
  }

  @Override
  public void resetUserPreferences() {
    if (!hasUserPreferences()) {
      return;
    }

    long plid = getPlid();

    Set<String> customPortletIds = new HashSet<>();

    for (String columnId : getColumns()) {
      String value = _portalPreferences.getValue(CustomizedPages.namespacePlid(plid), columnId);

      for (String customPortletId : StringUtil.split(value)) {
        customPortletIds.add(customPortletId);
      }
    }

    try {
      onRemoveFromLayout(customPortletIds.toArray(new String[customPortletIds.size()]));
    } catch (Exception e) {
      _log.error(e, e);
    }

    _portalPreferences.resetValues(CustomizedPages.namespacePlid(plid));

    _portalPreferences.setValue(
        CustomizedPages.namespacePlid(plid), _MODIFIED_DATE, _dateFormat.format(new Date()));
  }

  @Override
  public void setCustomizedView(boolean customizedView) {
    _customizedView = customizedView;
  }

  @Override
  public void setLayoutTemplateId(long userId, String newLayoutTemplateId) {
    setLayoutTemplateId(userId, newLayoutTemplateId, true);
  }

  @Override
  public void setLayoutTemplateId(
      long userId, String newLayoutTemplateId, boolean checkPermission) {

    if (checkPermission
        && !PluginSettingLocalServiceUtil.hasPermission(
            userId, newLayoutTemplateId, Plugin.TYPE_LAYOUT_TEMPLATE)) {

      return;
    }

    LayoutTemplate oldLayoutTemplate = getLayoutTemplate();

    String themeId = getThemeId();

    LayoutTemplate newLayoutTemplate =
        LayoutTemplateLocalServiceUtil.getLayoutTemplate(newLayoutTemplateId, false, themeId);

    if (newLayoutTemplate == null) {
      if (_log.isWarnEnabled()) {
        _log.warn("Unable to find layout template " + newLayoutTemplateId);
      }

      return;
    }

    setTypeSettingsProperty(LayoutTypePortletConstants.LAYOUT_TEMPLATE_ID, newLayoutTemplateId);

    List<String> oldColumns = oldLayoutTemplate.getColumns();
    List<String> newColumns = newLayoutTemplate.getColumns();

    reorganizePortlets(newColumns, oldColumns);
  }

  @Override
  public void setModeAbout(String modeAbout) {
    setTypeSettingsProperty(LayoutTypePortletConstants.MODE_ABOUT, modeAbout);
  }

  @Override
  public void setModeConfig(String modeConfig) {
    setTypeSettingsProperty(LayoutTypePortletConstants.MODE_CONFIG, modeConfig);
  }

  @Override
  public void setModeEdit(String modeEdit) {
    setTypeSettingsProperty(LayoutTypePortletConstants.MODE_EDIT, modeEdit);
  }

  @Override
  public void setModeEditDefaults(String modeEditDefaults) {
    setTypeSettingsProperty(LayoutTypePortletConstants.MODE_EDIT_DEFAULTS, modeEditDefaults);
  }

  @Override
  public void setModeEditGuest(String modeEditGuest) {
    setTypeSettingsProperty(LayoutTypePortletConstants.MODE_EDIT_GUEST, modeEditGuest);
  }

  @Override
  public void setModeHelp(String modeHelp) {
    setTypeSettingsProperty(LayoutTypePortletConstants.MODE_HELP, modeHelp);
  }

  @Override
  public void setModePreview(String modePreview) {
    setTypeSettingsProperty(LayoutTypePortletConstants.MODE_PREVIEW, modePreview);
  }

  @Override
  public void setModePrint(String modePrint) {
    setTypeSettingsProperty(LayoutTypePortletConstants.MODE_PRINT, modePrint);
  }

  @Override
  public void setPortalPreferences(PortalPreferences portalPreferences) {
    _portalPreferences = portalPreferences;
  }

  @Override
  public void setStateMax(String stateMax) {
    setTypeSettingsProperty(LayoutTypePortletConstants.STATE_MAX, stateMax);
  }

  @Override
  public void setStateMin(String stateMin) {
    setTypeSettingsProperty(LayoutTypePortletConstants.STATE_MIN, stateMin);
  }

  @Override
  public void setUpdatePermission(boolean updatePermission) {
    _updatePermission = updatePermission;
  }

  protected void addNestedColumn(String columnId) {
    String nestedColumnIds =
        getTypeSettingsProperty(LayoutTypePortletConstants.NESTED_COLUMN_IDS, StringPool.BLANK);

    if (!nestedColumnIds.contains(columnId)) {
      nestedColumnIds = StringUtil.add(nestedColumnIds, columnId);

      setTypeSettingsProperty(LayoutTypePortletConstants.NESTED_COLUMN_IDS, nestedColumnIds);
    }
  }

  protected String addPortletId(
      long userId,
      String portletId,
      String columnId,
      int columnPos,
      boolean checkPermission,
      boolean strictHasPortlet) {

    portletId = JS.getSafeName(portletId);

    Layout layout = getLayout();

    Portlet portlet = null;

    try {
      portlet = PortletLocalServiceUtil.getPortletById(layout.getCompanyId(), portletId);

      if (portlet == null) {
        if (_log.isWarnEnabled()) {
          _log.warn("Portlet " + portletId + " cannot be added because it is not registered");
        }

        return null;
      }

      PermissionChecker permissionChecker = PermissionThreadLocal.getPermissionChecker();

      if (checkPermission
          && !PortletPermissionUtil.contains(
              permissionChecker, layout, portlet, ActionKeys.ADD_TO_PAGE)) {

        return null;
      }
    } catch (Exception e) {
      _log.error(e, e);
    }

    if (portlet.isSystem()) {
      return null;
    }

    if (portlet.isInstanceable() && !PortletConstants.hasInstanceId(portletId)) {

      portletId =
          PortletConstants.assemblePortletId(portletId, PortletConstants.generateInstanceId());
    }

    if (hasPortletId(portletId, strictHasPortlet)) {
      return null;
    }

    if (columnId == null) {
      LayoutTemplate layoutTemplate = getLayoutTemplate();

      List<String> columns = layoutTemplate.getColumns();

      if (!columns.isEmpty()) {
        columnId = columns.get(0);
      }
    }

    if (columnId == null) {
      return null;
    }

    if (isCustomizable()) {
      if (isColumnDisabled(columnId)) {
        return null;
      }

      if ((PortletConstants.hasInstanceId(portletId) || portlet.isPreferencesUniquePerLayout())
          && hasUserPreferences()) {

        portletId = PortletConstants.assemblePortletId(portletId, userId);
      }
    }

    String columnValue = StringPool.BLANK;

    if (hasUserPreferences()) {
      columnValue = getUserPreference(columnId);
    } else {
      columnValue = getTypeSettingsProperty(columnId);
    }

    if ((columnValue == null) && columnId.startsWith(_NESTED_PORTLETS_NAMESPACE)) {

      addNestedColumn(columnId);
    }

    if (columnPos >= 0) {
      List<String> portletIds = ListUtil.fromArray(StringUtil.split(columnValue));

      if (columnPos <= portletIds.size()) {
        portletIds.add(columnPos, portletId);
      } else {
        portletIds.add(portletId);
      }

      columnValue = StringUtil.merge(portletIds);
    } else {
      columnValue = StringUtil.add(columnValue, portletId);
    }

    if (hasUserPreferences()) {
      setUserPreference(columnId, columnValue);
    } else {
      setTypeSettingsProperty(columnId, columnValue);
    }

    try {
      if (_enablePortletLayoutListener && !portlet.isUndeployedPortlet()) {

        PortletLayoutListener portletLayoutListener = portlet.getPortletLayoutListenerInstance();

        if (portletLayoutListener != null) {
          portletLayoutListener.onAddToLayout(portletId, layout.getPlid());
        }
      }
    } catch (Exception e) {
      _log.error("Unable to fire portlet layout listener event", e);
    }

    return portletId;
  }

  protected void copyPreferences(long userId, String sourcePortletId, String targetPortletId) {

    Layout layout = getLayout();

    try {
      PortletPreferencesIds portletPreferencesIds =
          PortletPreferencesFactoryUtil.getPortletPreferencesIds(
              layout.getGroupId(), 0, layout, sourcePortletId, false);

      javax.portlet.PortletPreferences sourcePortletPreferences =
          PortletPreferencesLocalServiceUtil.getStrictPreferences(portletPreferencesIds);

      portletPreferencesIds =
          PortletPreferencesFactoryUtil.getPortletPreferencesIds(
              layout.getGroupId(), userId, layout, targetPortletId, false);

      PortletPreferencesLocalServiceUtil.updatePreferences(
          portletPreferencesIds.getOwnerId(),
          portletPreferencesIds.getOwnerType(),
          portletPreferencesIds.getPlid(),
          portletPreferencesIds.getPortletId(),
          sourcePortletPreferences);
    } catch (Exception e) {
    }
  }

  protected void copyResourcePermissions(String sourcePortletId, String targetPortletId) {

    Layout layout = getLayout();

    Portlet portlet = PortletLocalServiceUtil.getPortletById(getCompanyId(), sourcePortletId);

    String sourcePortletPrimaryKey =
        PortletPermissionUtil.getPrimaryKey(layout.getPlid(), sourcePortletId);

    List<ResourcePermission> resourcePermissions =
        ResourcePermissionLocalServiceUtil.getResourcePermissions(
            portlet.getCompanyId(),
            portlet.getPortletName(),
            PortletKeys.PREFS_OWNER_TYPE_USER,
            sourcePortletPrimaryKey);

    for (ResourcePermission resourcePermission : resourcePermissions) {
      String targetPortletPrimaryKey =
          PortletPermissionUtil.getPrimaryKey(layout.getPlid(), targetPortletId);

      resourcePermission.setResourcePermissionId(CounterLocalServiceUtil.increment());
      resourcePermission.setPrimKey(targetPortletPrimaryKey);

      ResourcePermissionLocalServiceUtil.addResourcePermission(resourcePermission);
    }
  }

  protected String getColumn(String portletId) {
    String portletIdColumnId = StringPool.BLANK;

    List<String> columnIds = getColumns();

    for (String columnId : columnIds) {
      String columnValue = getColumnValue(columnId);

      String[] portletIds = StringUtil.split(columnValue);

      for (String columnPortletId : portletIds) {
        if (columnPortletId.equals(portletId)) {
          return columnId;
        }

        if (Validator.isNull(portletIdColumnId)
            && PortletConstants.hasIdenticalRootPortletId(columnPortletId, portletId)) {

          portletIdColumnId = columnId;
        }
      }
    }

    return portletIdColumnId;
  }

  protected List<String> getColumns() {
    List<String> columns = new ArrayList<>();

    Layout layout = getLayout();

    if (layout.isTypePortlet()) {
      LayoutTemplate layoutTemplate = getLayoutTemplate();

      columns.addAll(layoutTemplate.getColumns());

      columns.addAll(getNestedColumns());
    } else if (layout.isTypePanel()) {
      columns.add("panelSelectedPortlets");
    }

    return columns;
  }

  protected String getColumnValue(String columnId) {
    if (hasUserPreferences() && isCustomizable() && !isColumnDisabled(columnId)) {

      return getUserPreference(columnId);
    }

    return getTypeSettingsProperty(columnId);
  }

  protected long getCompanyId() {
    Layout layout = getLayout();

    return layout.getCompanyId();
  }

  protected LayoutTypePortletImpl getDefaultLayoutTypePortletImpl() {
    if (!isCustomizedView()) {
      return this;
    }

    LayoutTypePortletImpl defaultLayoutTypePortletImpl =
        (LayoutTypePortletImpl) LayoutTypePortletFactoryUtil.create(getLayout());

    defaultLayoutTypePortletImpl._layoutSetPrototypeLayout = _layoutSetPrototypeLayout;
    defaultLayoutTypePortletImpl._updatePermission = _updatePermission;

    return defaultLayoutTypePortletImpl;
  }

  protected List<String> getNestedColumns() {
    String nestedColumnIds = getTypeSettingsProperty(LayoutTypePortletConstants.NESTED_COLUMN_IDS);

    return ListUtil.fromArray(StringUtil.split(nestedColumnIds));
  }

  protected long getPlid() {
    Layout layout = getLayout();

    return layout.getPlid();
  }

  protected String[] getStaticPortletIds(String position) {
    Layout layout = getLayout();

    String selector1 = StringPool.BLANK;

    Group group = null;

    try {
      group = layout.getGroup();
    } catch (PortalException pe) {
      _log.error("Unable to get group " + layout.getGroupId());

      return new String[0];
    }

    if (group.isUser()) {
      selector1 = LayoutTypePortletConstants.STATIC_PORTLET_USER_SELECTOR;
    } else if (group.isOrganization()) {
      selector1 = LayoutTypePortletConstants.STATIC_PORTLET_ORGANIZATION_SELECTOR;
    } else if (group.isRegularSite()) {
      selector1 = LayoutTypePortletConstants.STATIC_PORTLET_REGULAR_SITE_SELECTOR;
    }

    String selector2 = layout.getFriendlyURL();

    String[] portletIds = PropsUtil.getArray(position, new Filter(selector1, selector2));

    for (int i = 0; i < portletIds.length; i++) {
      portletIds[i] = JS.getSafeName(portletIds[i]);
    }

    return portletIds;
  }

  protected List<Portlet> getStaticPortlets(String position) {
    String[] portletIds = getStaticPortletIds(position);

    List<Portlet> portlets = new ArrayList<>();

    for (String portletId : portletIds) {
      if (Validator.isNull(portletId) || hasNonstaticPortletId(portletId)) {

        continue;
      }

      Portlet portlet = PortletLocalServiceUtil.getPortletById(getCompanyId(), portletId);

      if (portlet != null) {
        Portlet staticPortlet = portlet;

        if (portlet.isInstanceable()) {

          // Instanceable portlets do not need to be cloned because
          // they are already cloned. See the method getPortletById in
          // the class PortletLocalServiceImpl and how it references
          // the method getClonedInstance in the class PortletImpl.

        } else {
          staticPortlet = (Portlet) staticPortlet.clone();
        }

        staticPortlet.setStatic(true);

        if (position.startsWith("layout.static.portlets.start")) {
          staticPortlet.setStaticStart(true);
        }

        portlets.add(staticPortlet);
      }
    }

    return portlets;
  }

  protected String getThemeId() {
    String themeId = null;

    try {
      Layout layout = getLayout();

      Theme theme = layout.getTheme();

      if (theme != null) {
        themeId = theme.getThemeId();
      } else {
        themeId = layout.getThemeId();
      }
    } catch (Exception e) {
      _log.error(e, e);
    }

    return themeId;
  }

  protected String getUserPreference(String key) {
    String value = StringPool.BLANK;

    if (!hasUserPreferences()) {
      return value;
    }

    value =
        _portalPreferences.getValue(CustomizedPages.namespacePlid(getPlid()), key, StringPool.NULL);

    if (!value.equals(StringPool.NULL)) {
      return value;
    }

    value = getTypeSettingsProperty(key);

    if (Validator.isNull(value)) {
      return value;
    }

    List<String> newPortletIds = new ArrayList<>();

    PermissionChecker permissionChecker = PermissionThreadLocal.getPermissionChecker();

    String[] portletIds = StringUtil.split(value);

    for (String portletId : portletIds) {
      try {
        if (!PortletPermissionUtil.contains(
            permissionChecker, getLayout(), portletId, ActionKeys.VIEW, true)) {

          continue;
        }

        String rootPortletId = PortletConstants.getRootPortletId(portletId);

        if (!PortletPermissionUtil.contains(
            permissionChecker, rootPortletId, ActionKeys.ADD_TO_PAGE)) {

          continue;
        }
      } catch (Exception e) {
        _log.error(e, e);
      }

      String newPortletId = null;

      boolean preferencesUniquePerLayout = false;

      try {
        Portlet portlet = PortletLocalServiceUtil.getPortletById(getCompanyId(), portletId);

        preferencesUniquePerLayout = portlet.isPreferencesUniquePerLayout();
      } catch (SystemException se) {
        _log.error(se, se);
      }

      if (PortletConstants.hasInstanceId(portletId) || preferencesUniquePerLayout) {

        String instanceId = null;

        if (PortletConstants.hasInstanceId(portletId)) {
          instanceId = PortletConstants.generateInstanceId();
        }

        newPortletId =
            PortletConstants.assemblePortletId(
                portletId, _portalPreferences.getUserId(), instanceId);

        copyPreferences(_portalPreferences.getUserId(), portletId, newPortletId);

        copyResourcePermissions(portletId, newPortletId);
      } else {
        newPortletId = portletId;
      }

      newPortletIds.add(newPortletId);
    }

    value = StringUtil.merge(newPortletIds);

    setUserPreference(key, value);

    return value;
  }

  protected boolean hasNonstaticPortletId(String portletId) {
    LayoutTemplate layoutTemplate = getLayoutTemplate();

    List<String> columns = layoutTemplate.getColumns();

    for (int i = 0; i < columns.size(); i++) {
      String columnId = columns.get(i);

      if (hasNonstaticPortletId(columnId, portletId)) {
        return true;
      }
    }

    return false;
  }

  protected boolean hasNonstaticPortletId(String columnId, String portletId) {
    String columnValue = getColumnValue(columnId);

    String[] columnValues = StringUtil.split(columnValue);

    for (String nonstaticPortletId : columnValues) {
      if (nonstaticPortletId.equals(portletId)
          || PortletConstants.getRootPortletId(nonstaticPortletId).equals(portletId)) {

        return true;
      }
    }

    return false;
  }

  protected boolean hasStaticPortletId(String columnId, String portletId) {
    String[] staticPortletIdsStart =
        getStaticPortletIds(PropsKeys.LAYOUT_STATIC_PORTLETS_START + columnId);

    String[] staticPortletIdsEnd =
        getStaticPortletIds(PropsKeys.LAYOUT_STATIC_PORTLETS_END + columnId);

    for (String staticPortletId : staticPortletIdsStart) {
      if (staticPortletId.equals(portletId)
          || PortletConstants.getRootPortletId(staticPortletId).equals(portletId)) {

        return true;
      }
    }

    for (String staticPortletId : staticPortletIdsEnd) {
      if (staticPortletId.equals(portletId)
          || PortletConstants.getRootPortletId(staticPortletId).equals(portletId)) {

        return true;
      }
    }

    return false;
  }

  protected boolean hasUserPreferences() {
    if (_portalPreferences != null) {
      return true;
    }

    return false;
  }

  protected boolean isLayoutSetPrototype() {
    try {
      Layout layout = getLayout();

      LayoutSet layoutSet = layout.getLayoutSet();

      Group group = layoutSet.getGroup();

      return group.isLayoutSetPrototype();
    } catch (Exception e) {
      _log.error(e, e);
    }

    return false;
  }

  protected void onRemoveFromLayout(String[] portletIds) {
    Set<String> portletIdList = new HashSet<>();

    for (String portletId : portletIds) {
      removeModesPortletId(portletId);
      removeStatesPortletId(portletId);

      portletIdList.add(portletId);

      String rootPortletId = PortletConstants.getRootPortletId(portletId);

      if (rootPortletId.equals(PortletKeys.NESTED_PORTLETS)) {
        String portletNamespace = PortalUtil.getPortletNamespace(portletId);

        UnicodeProperties typeSettingsProperties = getTypeSettingsProperties();

        for (Map.Entry<String, String> entry : typeSettingsProperties.entrySet()) {

          String key = entry.getKey();

          if (!key.startsWith(portletNamespace)) {
            continue;
          }

          String nestedPortletIds = entry.getValue();

          for (String nestedPortletId : StringUtil.split(nestedPortletIds)) {

            removeModesPortletId(nestedPortletId);
            removeStatesPortletId(nestedPortletId);

            portletIdList.add(nestedPortletId);
          }
        }

        removeNestedColumns(portletNamespace);
      }

      Portlet portlet = PortletLocalServiceUtil.getPortletById(portletId);

      if (portlet == null) {
        continue;
      }

      PortletLayoutListener portletLayoutListener = portlet.getPortletLayoutListenerInstance();

      if (portletLayoutListener == null) {
        continue;
      }

      portletLayoutListener.updatePropertiesOnRemoveFromLayout(
          portletId, getTypeSettingsProperties());
    }

    try {
      PortletLocalServiceUtil.deletePortlets(
          getCompanyId(), portletIdList.toArray(new String[portletIdList.size()]), getPlid());
    } catch (PortalException pe) {
      _log.error(pe, pe);
    }
  }

  protected void setUserPreference(String key, String value) {
    if (!hasUserPreferences()) {
      return;
    }

    _portalPreferences.setValue(CustomizedPages.namespacePlid(getPlid()), key, value);

    _portalPreferences.setValue(
        CustomizedPages.namespacePlid(getPlid()), _MODIFIED_DATE, _dateFormat.format(new Date()));
  }

  private static final String _MODIFIED_DATE = "modifiedDate";

  private static final String _NESTED_PORTLETS_NAMESPACE =
      PortalUtil.getPortletNamespace(PortletKeys.NESTED_PORTLETS);

  private static final String _NULL_DATE = "00000000000000";

  private static final Log _log = LogFactoryUtil.getLog(LayoutTypePortletImpl.class);

  private boolean _customizedView;
  private final Format _dateFormat =
      FastDateFormatFactoryUtil.getSimpleDateFormat(PropsValues.INDEX_DATE_FORMAT_PATTERN);
  private boolean _enablePortletLayoutListener = true;
  private Layout _layoutSetPrototypeLayout;
  private PortalPreferences _portalPreferences;
  private boolean _updatePermission;
}
Ejemplo n.º 5
0
 protected String getServerNamespace() {
   return PortalUtil.getPortletNamespace(getServerPortletId());
 }