protected Layout fetchMissingReference(String uuid, long groupId, boolean privateLayout) {

    // Try to fetch the existing layout from the importing group

    Layout layout = _layoutLocalService.fetchLayoutByUuidAndGroupId(uuid, groupId, privateLayout);

    if (layout != null) {
      return layout;
    }

    try {

      // Try to fetch the existing layout from the parent sites

      Group originalGroup = _groupLocalService.getGroup(groupId);

      Group group = originalGroup.getParentGroup();

      while (group != null) {
        layout =
            _layoutLocalService.fetchLayoutByUuidAndGroupId(
                uuid, group.getGroupId(), privateLayout);

        if (layout != null) {
          break;
        }

        group = group.getParentGroup();
      }

      if (layout == null) {
        List<Layout> layouts =
            fetchStagedModelsByUuidAndCompanyId(uuid, originalGroup.getCompanyId());

        if (ListUtil.isEmpty(layouts)) {
          return null;
        }

        layout = layouts.get(0);
      }

      return layout;
    } catch (Exception e) {
      if (_log.isDebugEnabled()) {
        _log.debug(e, e);
      } else if (_log.isWarnEnabled()) {
        _log.warn("Unable to fetch missing reference layout from group " + groupId);
      }

      return null;
    }
  }
  @Test
  public void testFilterFindByG_N() throws Exception {
    Group scopeGroup = addScopeGroup();

    Group siteGroup = scopeGroup.getParentGroup();

    String assetTagName = ServiceTestUtil.randomString();

    addAssetTag(siteGroup.getGroupId(), assetTagName, null);

    User user = UserTestUtil.addUser(null, 0);

    PermissionChecker originalPermissionChecker = PermissionThreadLocal.getPermissionChecker();

    try {
      PermissionChecker permissionChecker = PermissionCheckerFactoryUtil.create(user);

      PermissionThreadLocal.setPermissionChecker(permissionChecker);

      try {
        AssetTagFinderUtil.filterFindByG_N(scopeGroup.getGroupId(), assetTagName);

        Assert.fail();
      } catch (NoSuchTagException nste) {
      }

      AssetTag siteGroupAssetTag =
          AssetTagFinderUtil.filterFindByG_N(siteGroup.getGroupId(), assetTagName);

      Assert.assertEquals(StringUtil.toLowerCase(assetTagName), siteGroupAssetTag.getName());
    } finally {
      PermissionThreadLocal.setPermissionChecker(originalPermissionChecker);
    }
  }
  public long getDDMTemplateGroupId(ThemeDisplay themeDisplay) {
    try {
      Group scopeGroup = themeDisplay.getScopeGroup();

      if (scopeGroup.isLayout()) {
        scopeGroup = scopeGroup.getParentGroup();
      }

      if (scopeGroup.isStagingGroup()) {
        Group liveGroup = scopeGroup.getLiveGroup();

        if (!liveGroup.isStagedPortlet(PortletKeys.PORTLET_DISPLAY_TEMPLATES)) {

          return liveGroup.getGroupId();
        }
      }

      return scopeGroup.getGroupId();
    } catch (Exception e) {
      if (_log.isWarnEnabled()) {
        _log.warn(e, e);
      }
    }

    return themeDisplay.getScopeGroupId();
  }
  @Override
  public long getDDMTemplateGroupId(long groupId) {
    try {
      Group group = GroupLocalServiceUtil.getGroup(groupId);

      if (group.isLayout()) {
        group = group.getParentGroup();
      }

      if (group.isStagingGroup()) {
        Group liveGroup = group.getLiveGroup();

        if (!liveGroup.isStagedPortlet(PortletKeys.PORTLET_DISPLAY_TEMPLATE)) {

          return liveGroup.getGroupId();
        }
      }

      return group.getGroupId();
    } catch (Exception e) {
      if (_log.isWarnEnabled()) {
        _log.warn(e, e);
      }
    }

    return groupId;
  }
  protected void buildTreePath(StringBundler sb, Group group)
      throws PortalException, SystemException {

    if (group == null) {
      sb.append(StringPool.SLASH);
    } else {
      buildTreePath(sb, group.getParentGroup());

      sb.append(group.getGroupId());
      sb.append(StringPool.SLASH);
    }
  }
  public int getMaxAge(Group group) throws PortalException, SystemException {
    if (group.isLayout()) {
      group = group.getParentGroup();
    }

    int trashEntriesMaxAge =
        PrefsPropsUtil.getInteger(
            group.getCompanyId(),
            PropsKeys.TRASH_ENTRIES_MAX_AGE,
            GetterUtil.getInteger(PropsUtil.get(PropsKeys.TRASH_ENTRIES_MAX_AGE)));

    UnicodeProperties typeSettingsProperties = group.getTypeSettingsProperties();

    return GetterUtil.getInteger(
        typeSettingsProperties.getProperty("trashEntriesMaxAge"), trashEntriesMaxAge);
  }
  public List<Group> getAncestors() throws PortalException, SystemException {
    List<Group> groups = new ArrayList<Group>();

    Group group = this;

    while (true) {
      if (!group.isRoot()) {
        group = group.getParentGroup();

        groups.add(group);
      } else {
        break;
      }
    }

    return groups;
  }
  @Test
  public void testFilterCountByG_N_P() throws Exception {
    Group scopeGroup = addScopeGroup();

    Group siteGroup = scopeGroup.getParentGroup();

    String assetTagName = ServiceTestUtil.randomString();
    String[] assetTagProperties = {
      "key" + AssetTagConstants.PROPERTY_KEY_VALUE_SEPARATOR + "value"
    };

    int initialScopeGroupAssetTagsCount =
        AssetTagFinderUtil.filterCountByG_N_P(
            scopeGroup.getGroupId(), assetTagName, assetTagProperties);
    int initialTagsCountSiteGroup =
        AssetTagFinderUtil.filterCountByG_N_P(
            siteGroup.getGroupId(), assetTagName, assetTagProperties);

    addAssetTag(siteGroup.getGroupId(), assetTagName, assetTagProperties);

    User user = UserTestUtil.addUser(null, 0);

    PermissionChecker originalPermissionChecker = PermissionThreadLocal.getPermissionChecker();

    try {
      PermissionChecker permissionChecker = PermissionCheckerFactoryUtil.create(user);

      PermissionThreadLocal.setPermissionChecker(permissionChecker);

      int scopeGroupAssetTagsCount =
          AssetTagFinderUtil.filterCountByG_N_P(
              scopeGroup.getGroupId(), assetTagName, assetTagProperties);

      Assert.assertEquals(initialScopeGroupAssetTagsCount, scopeGroupAssetTagsCount);

      int siteGroupAssetTagsCount =
          AssetTagFinderUtil.filterCountByG_N_P(
              siteGroup.getGroupId(), assetTagName, assetTagProperties);

      Assert.assertEquals(initialTagsCountSiteGroup + 1, siteGroupAssetTagsCount);
    } finally {
      PermissionThreadLocal.setPermissionChecker(originalPermissionChecker);
    }
  }
  @Override
  public List<Group> getAncestors() throws PortalException, SystemException {
    Group group = null;

    if (isStagingGroup()) {
      group = getLiveGroup();
    } else {
      group = this;
    }

    List<Group> groups = new ArrayList<Group>();

    while (!group.isRoot()) {
      group = group.getParentGroup();

      groups.add(group);
    }

    return groups;
  }
  @Test
  public void testFilterCountByG_C_N() throws Exception {
    Group scopeGroup = addScopeGroup();

    Group siteGroup = scopeGroup.getParentGroup();

    long classNameId = PortalUtil.getClassNameId(BlogsEntry.class);
    String assetTagName = ServiceTestUtil.randomString();

    int initialScopeGroupAssetTagsCount =
        AssetTagFinderUtil.filterCountByG_C_N(scopeGroup.getGroupId(), classNameId, assetTagName);
    int initialSiteGroupAssetTagsCount =
        AssetTagFinderUtil.filterCountByG_C_N(siteGroup.getGroupId(), classNameId, assetTagName);

    addBlogsEntry(scopeGroup.getGroupId(), assetTagName);

    User user = UserTestUtil.addUser(null, 0);

    PermissionChecker originalPermissionChecker = PermissionThreadLocal.getPermissionChecker();

    try {
      PermissionChecker permissionChecker = PermissionCheckerFactoryUtil.create(user);

      PermissionThreadLocal.setPermissionChecker(permissionChecker);

      int scopeGroupAssetTagsCount =
          AssetTagFinderUtil.filterCountByG_C_N(scopeGroup.getGroupId(), classNameId, assetTagName);

      Assert.assertEquals(initialScopeGroupAssetTagsCount + 1, scopeGroupAssetTagsCount);

      int siteGroupAssetTagsCount =
          AssetTagFinderUtil.filterCountByG_C_N(siteGroup.getGroupId(), classNameId, assetTagName);

      Assert.assertEquals(initialSiteGroupAssetTagsCount, siteGroupAssetTagsCount);
    } finally {
      PermissionThreadLocal.setPermissionChecker(originalPermissionChecker);
    }
  }
  @Test
  public void testFilterFindByG_N_P() throws Exception {
    Group scopeGroup = addScopeGroup();

    Group siteGroup = scopeGroup.getParentGroup();

    String assetTagName = ServiceTestUtil.randomString();
    String[] assetTagProperties = {
      "key" + AssetTagConstants.PROPERTY_KEY_VALUE_SEPARATOR + "value"
    };

    List<AssetTag> initialScopeGroupAssetTags =
        AssetTagFinderUtil.filterFindByG_N_P(
            new long[] {scopeGroup.getGroupId()},
            assetTagName,
            assetTagProperties,
            QueryUtil.ALL_POS,
            QueryUtil.ALL_POS,
            null);
    List<AssetTag> initialSiteGroupAssetTags =
        AssetTagFinderUtil.filterFindByG_N_P(
            new long[] {siteGroup.getGroupId()},
            assetTagName,
            assetTagProperties,
            QueryUtil.ALL_POS,
            QueryUtil.ALL_POS,
            null);

    addAssetTag(siteGroup.getGroupId(), assetTagName, assetTagProperties);

    User user = UserTestUtil.addUser(null, 0);

    PermissionChecker originalPermissionChecker = PermissionThreadLocal.getPermissionChecker();

    try {
      PermissionChecker permissionChecker = PermissionCheckerFactoryUtil.create(user);

      PermissionThreadLocal.setPermissionChecker(permissionChecker);

      List<AssetTag> scopeGroupAssetTags =
          AssetTagFinderUtil.filterFindByG_N_P(
              new long[] {scopeGroup.getGroupId()},
              assetTagName,
              assetTagProperties,
              QueryUtil.ALL_POS,
              QueryUtil.ALL_POS,
              null);

      Assert.assertEquals(initialScopeGroupAssetTags.size(), scopeGroupAssetTags.size());

      List<AssetTag> siteGroupAssetTags =
          AssetTagFinderUtil.filterFindByG_N_P(
              new long[] {siteGroup.getGroupId()},
              assetTagName,
              assetTagProperties,
              QueryUtil.ALL_POS,
              QueryUtil.ALL_POS,
              null);

      Assert.assertEquals(initialSiteGroupAssetTags.size() + 1, siteGroupAssetTags.size());
    } finally {
      PermissionThreadLocal.setPermissionChecker(originalPermissionChecker);
    }
  }
  @Override
  public boolean contains(PermissionChecker permissionChecker, Group group, String actionId)
      throws PortalException, SystemException {

    long groupId = group.getGroupId();

    if (group.isStagingGroup()) {
      group = group.getLiveGroup();
    }

    if (group.isUser()) {

      // An individual user would never reach this block because he would
      // be an administrator of his own layouts. However, a user who
      // manages a set of organizations may be modifying pages of a user
      // he manages.

      User user = UserLocalServiceUtil.getUserById(group.getClassPK());

      if ((permissionChecker.getUserId() != user.getUserId())
          && UserPermissionUtil.contains(
              permissionChecker, user.getUserId(), user.getOrganizationIds(), ActionKeys.UPDATE)) {

        return true;
      }
    }

    if (actionId.equals(ActionKeys.ADD_COMMUNITY)
            && permissionChecker.hasPermission(
                groupId, Group.class.getName(), groupId, ActionKeys.MANAGE_SUBGROUPS)
        || PortalPermissionUtil.contains(permissionChecker, ActionKeys.ADD_COMMUNITY)) {

      return true;
    } else if (actionId.equals(ActionKeys.ADD_LAYOUT)
        && !group.isLayoutPrototype()
        && permissionChecker.hasPermission(
            groupId, Group.class.getName(), groupId, ActionKeys.MANAGE_LAYOUTS)) {

      return true;
    } else if ((actionId.equals(ActionKeys.EXPORT_IMPORT_LAYOUTS)
            || actionId.equals(ActionKeys.EXPORT_IMPORT_PORTLET_INFO))
        && permissionChecker.hasPermission(
            groupId, Group.class.getName(), groupId, ActionKeys.PUBLISH_STAGING)) {

      return true;
    } else if (actionId.equals(ActionKeys.VIEW)
        && (permissionChecker.hasPermission(
                groupId, Group.class.getName(), groupId, ActionKeys.ASSIGN_USER_ROLES)
            || permissionChecker.hasPermission(
                groupId, Group.class.getName(), groupId, ActionKeys.MANAGE_LAYOUTS))) {

      return true;
    } else if (actionId.equals(ActionKeys.VIEW_STAGING)
        && (permissionChecker.hasPermission(
                groupId, Group.class.getName(), groupId, ActionKeys.MANAGE_LAYOUTS)
            || permissionChecker.hasPermission(
                groupId, Group.class.getName(), groupId, ActionKeys.MANAGE_STAGING)
            || permissionChecker.hasPermission(
                groupId, Group.class.getName(), groupId, ActionKeys.PUBLISH_STAGING)
            || permissionChecker.hasPermission(
                groupId, Group.class.getName(), groupId, ActionKeys.UPDATE))) {

      return true;
    }

    // Group id must be set so that users can modify their personal pages

    if (permissionChecker.hasPermission(groupId, Group.class.getName(), groupId, actionId)) {

      return true;
    }

    while (!group.isRoot()) {
      if (contains(permissionChecker, group.getParentGroupId(), ActionKeys.MANAGE_SUBGROUPS)) {

        return true;
      }

      group = group.getParentGroup();
    }

    return false;
  }