@Test
  public void testValidateMissingReferences() throws Exception {
    String xml = replaceParameters(getContent("missing_references.txt"), _fileEntry);

    ZipWriter zipWriter = ZipWriterFactoryUtil.getZipWriter();

    zipWriter.addEntry("/manifest.xml", xml);

    MissingReferences missingReferences =
        ExportImportHelperUtil.validateMissingReferences(
            TestPropsValues.getUserId(),
            _stagingGroup.getGroupId(),
            new HashMap<String, String[]>(),
            zipWriter.getFile());

    Map<String, MissingReference> dependencyMissingReferences =
        missingReferences.getDependencyMissingReferences();

    Map<String, MissingReference> weakMissingReferences =
        missingReferences.getWeakMissingReferences();

    Assert.assertEquals(2, dependencyMissingReferences.size());
    Assert.assertEquals(1, weakMissingReferences.size());

    FileUtil.delete(zipWriter.getFile());
  }
  @Test
  public void testExportLinksToLayouts() throws Exception {
    Element rootElement = _portletDataContextExport.getExportDataRootElement();

    String content = replaceParameters(getContent("layout_links.txt"), _fileEntry);

    content =
        ExportImportHelperUtil.replaceExportContentReferences(
            _portletDataContextExport,
            _referrerStagedModel,
            rootElement.element("entry"),
            content,
            true);

    StringBundler sb = new StringBundler(5);

    sb.append("[1@private-group@");
    sb.append(_stagingPrivateLayout.getUuid());
    sb.append(StringPool.AT);
    sb.append(_stagingPrivateLayout.getFriendlyURL());
    sb.append(StringPool.CLOSE_BRACKET);

    Assert.assertTrue(content.contains(sb.toString()));

    sb.setIndex(0);

    sb.append("[1@public@");
    sb.append(_stagingPublicLayout.getUuid());
    sb.append(StringPool.AT);
    sb.append(_stagingPublicLayout.getFriendlyURL());
    sb.append(StringPool.CLOSE_BRACKET);

    Assert.assertTrue(content.contains(sb.toString()));
  }
  @Test
  public void testExportDLReferences() throws Exception {
    Element rootElement = _portletDataContextExport.getExportDataRootElement();

    String content = replaceParameters(getContent("dl_references.txt"), _fileEntry);

    List<String> urls = getURLs(content);

    content =
        ExportImportHelperUtil.replaceExportContentReferences(
            _portletDataContextExport,
            _referrerStagedModel,
            rootElement.element("entry"),
            content,
            true);

    for (String url : urls) {
      Assert.assertFalse(content.contains(url));
    }

    TestReaderWriter testReaderWriter = (TestReaderWriter) _portletDataContextExport.getZipWriter();

    List<String> entries = testReaderWriter.getEntries();

    Assert.assertEquals(entries.size(), 1);

    List<String> binaryEntries = testReaderWriter.getBinaryEntries();

    Assert.assertEquals(binaryEntries.size(), entries.size());

    for (String entry : testReaderWriter.getEntries()) {
      Assert.assertTrue(content.contains("[$dl-reference=" + entry + "$]"));
    }
    ;
  }
  @Override
  protected void validateExport(
      PortletDataContext portletDataContext,
      StagedModel stagedModel,
      Map<String, List<StagedModel>> dependentStagedModelsMap)
      throws Exception {

    ManifestSummary manifestSummary = portletDataContext.getManifestSummary();

    Map<String, LongWrapper> modelAdditionCounters = manifestSummary.getModelAdditionCounters();

    Assert.assertEquals(4, modelAdditionCounters.size());
    Assert.assertEquals(
        1, manifestSummary.getModelAdditionCount(DDMStructure.class, JournalArticle.class));
    Assert.assertEquals(
        1, manifestSummary.getModelAdditionCount(DDMTemplate.class, DDMStructure.class));
    Assert.assertEquals(1, manifestSummary.getModelAdditionCount(JournalArticle.class));
    Assert.assertEquals(1, manifestSummary.getModelAdditionCount(JournalFolder.class));

    Document document = SAXReaderUtil.createDocument();

    Element rootElement = document.addElement("root");

    Element headerElement = rootElement.addElement("header");

    _exportDate = new Date();

    headerElement.addAttribute("export-date", Time.getRFC822(_exportDate));

    ExportImportHelperUtil.writeManifestSummary(document, manifestSummary);

    zipWriter.addEntry("/manifest.xml", document.asXML());
  }
  @Test
  public void testImportDLReferences() throws Exception {
    Element rootElement = _portletDataContextExport.getExportDataRootElement();

    Element entryElement = rootElement.element("entry");

    String content = replaceParameters(getContent("dl_references.txt"), _fileEntry);

    content =
        ExportImportHelperUtil.replaceExportContentReferences(
            _portletDataContextExport, _referrerStagedModel, entryElement, content, true);
    content =
        ExportImportHelperUtil.replaceImportContentReferences(
            _portletDataContextImport, entryElement, content, true);

    Assert.assertFalse(content.contains("[$dl-reference="));
  }
  @Test
  public void testImportLinksToLayouts() throws Exception {
    Element rootElement = _portletDataContextExport.getExportDataRootElement();

    Element entryElement = rootElement.element("entry");

    String content = replaceParameters(getContent("layout_links.txt"), _fileEntry);

    content =
        ExportImportHelperUtil.replaceExportContentReferences(
            _portletDataContextExport, _referrerStagedModel, entryElement, content, true);

    String importedContent =
        ExportImportHelperUtil.replaceExportContentReferences(
            _portletDataContextExport, _referrerStagedModel, entryElement, content, true);

    Assert.assertEquals(importedContent, content);
  }
  @Test
  public void testExportImportLayoutsPriorities() throws Exception {
    Layout layout1 = LayoutTestUtil.addLayout(group);
    Layout layout2 = LayoutTestUtil.addLayout(group);
    Layout layout3 = LayoutTestUtil.addLayout(group);

    int priority = layout1.getPriority();

    layout1.setPriority(layout3.getPriority());
    layout3.setPriority(priority);

    layout1 = LayoutLocalServiceUtil.updateLayout(layout1);
    layout3 = LayoutLocalServiceUtil.updateLayout(layout3);

    long[] layoutIds = new long[] {layout1.getLayoutId(), layout2.getLayoutId()};

    exportImportLayouts(layoutIds, getImportParameterMap());

    Layout importedLayout1 =
        LayoutLocalServiceUtil.fetchLayoutByUuidAndGroupId(
            layout1.getUuid(), importedGroup.getGroupId(), false);

    Assert.assertNotEquals(layout1.getPriority(), importedLayout1.getPriority());

    Layout importedLayout2 =
        LayoutLocalServiceUtil.fetchLayoutByUuidAndGroupId(
            layout2.getUuid(), importedGroup.getGroupId(), false);

    Assert.assertNotEquals(layout2.getPriority(), importedLayout2.getPriority());

    List<Layout> layouts = LayoutLocalServiceUtil.getLayouts(group.getGroupId(), false);

    layoutIds = ExportImportHelperUtil.getLayoutIds(layouts);

    exportImportLayouts(layoutIds, getImportParameterMap());

    importedLayout1 =
        LayoutLocalServiceUtil.fetchLayoutByUuidAndGroupId(
            layout1.getUuid(), importedGroup.getGroupId(), false);

    Assert.assertEquals(layout1.getPriority(), importedLayout1.getPriority());

    importedLayout2 =
        LayoutLocalServiceUtil.fetchLayoutByUuidAndGroupId(
            layout2.getUuid(), importedGroup.getGroupId(), false);

    Assert.assertEquals(layout2.getPriority(), importedLayout2.getPriority());

    Layout importedLayout3 =
        LayoutLocalServiceUtil.fetchLayoutByUuidAndGroupId(
            layout3.getUuid(), importedGroup.getGroupId(), false);

    Assert.assertEquals(layout3.getPriority(), importedLayout3.getPriority());
  }
  @Test
  public void testImportLayoutReferences() throws Exception {
    Element rootElement = _portletDataContextExport.getExportDataRootElement();

    Element entryElement = rootElement.element("entry");

    String content = replaceParameters(getContent("layout_references.txt"), _fileEntry);

    content =
        ExportImportHelperUtil.replaceExportContentReferences(
            _portletDataContextExport, _referrerStagedModel, entryElement, content, true);
    content =
        ExportImportHelperUtil.replaceImportContentReferences(
            _portletDataContextExport, entryElement, content, true);

    Assert.assertFalse(content.contains("@data_handler_group_friendly_url@"));
    Assert.assertFalse(content.contains("@data_handler_path_context@"));
    Assert.assertFalse(content.contains("@data_handler_private_group_servlet_mapping@"));
    Assert.assertFalse(content.contains("@data_handler_private_user_servlet_mapping@"));
    Assert.assertFalse(content.contains("@data_handler_public_servlet_mapping@"));
  }
  @Test
  public void testExportImportLayouts() throws Exception {
    LayoutTestUtil.addLayout(group);

    List<Layout> layouts = LayoutLocalServiceUtil.getLayouts(group.getGroupId(), false);

    exportImportLayouts(ExportImportHelperUtil.getLayoutIds(layouts), getImportParameterMap());

    Assert.assertEquals(
        LayoutLocalServiceUtil.getLayoutsCount(group, false),
        LayoutLocalServiceUtil.getLayoutsCount(importedGroup, false));
  }
  @Test
  public void testExportLayoutReferencesWithContext() throws Exception {
    PortalImpl portalImpl = spy(new PortalImpl());

    when(portalImpl.getPathContext()).thenReturn("/de");

    PortalUtil portalUtil = new PortalUtil();

    portalUtil.setPortal(portalImpl);

    _OLD_LAYOUT_FRIENDLY_URL_PRIVATE_USER_SERVLET_MAPPING =
        PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_USER_SERVLET_MAPPING;

    setFinalStaticField(
        PropsValues.class.getField("LAYOUT_FRIENDLY_URL_PRIVATE_USER_SERVLET_MAPPING"), "/en");

    setFinalStaticField(
        ExportImportHelperImpl.class.getDeclaredField("_PRIVATE_USER_SERVLET_MAPPING"), "/en/");

    Element rootElement = _portletDataContextExport.getExportDataRootElement();

    String content = replaceParameters(getContent("layout_references.txt"), _fileEntry);

    content =
        ExportImportHelperUtil.replaceExportContentReferences(
            _portletDataContextExport,
            _referrerStagedModel,
            rootElement.element("entry"),
            content,
            true);

    Assert.assertFalse(
        content.contains(PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_GROUP_SERVLET_MAPPING));
    Assert.assertFalse(content.contains(PropsValues.LAYOUT_FRIENDLY_URL_PUBLIC_SERVLET_MAPPING));
    Assert.assertFalse(content.contains(_stagingGroup.getFriendlyURL()));
    Assert.assertFalse(content.contains(PortalUtil.getPathContext()));
    Assert.assertFalse(content.contains("/en/en"));

    setFinalStaticField(
        PropsValues.class.getDeclaredField("LAYOUT_FRIENDLY_URL_PRIVATE_USER_SERVLET_MAPPING"),
        _OLD_LAYOUT_FRIENDLY_URL_PRIVATE_USER_SERVLET_MAPPING);

    setFinalStaticField(
        ExportImportHelperImpl.class.getDeclaredField("_PRIVATE_USER_SERVLET_MAPPING"),
        PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_USER_SERVLET_MAPPING + StringPool.SLASH);

    portalUtil.setPortal(new PortalImpl());
  }
  protected File exportLayoutsAsFile(
      long sourceGroupId,
      boolean privateLayout,
      Map<Long, Boolean> layoutIdMap,
      Map<String, String[]> parameterMap,
      long remoteGroupId,
      Date startDate,
      Date endDate,
      HttpPrincipal httpPrincipal)
      throws PortalException {

    List<Layout> layouts = new ArrayList<>();

    if (layoutIdMap != null) {
      for (Map.Entry<Long, Boolean> entry : layoutIdMap.entrySet()) {
        long plid = GetterUtil.getLong(String.valueOf(entry.getKey()));
        boolean includeChildren = entry.getValue();

        Layout layout = LayoutLocalServiceUtil.getLayout(plid);

        if (!layouts.contains(layout)) {
          layouts.add(layout);
        }

        List<Layout> parentLayouts =
            getMissingRemoteParentLayouts(httpPrincipal, layout, remoteGroupId);

        for (Layout parentLayout : parentLayouts) {
          if (!layouts.contains(parentLayout)) {
            layouts.add(parentLayout);
          }
        }

        if (includeChildren) {
          for (Layout childLayout : layout.getAllChildren()) {
            if (!layouts.contains(childLayout)) {
              layouts.add(childLayout);
            }
          }
        }
      }
    }

    long[] layoutIds = ExportImportHelperUtil.getLayoutIds(layouts);

    return LayoutLocalServiceUtil.exportLayoutsAsFile(
        sourceGroupId, privateLayout, layoutIds, parameterMap, startDate, endDate);
  }
  public long performCount() throws PortalException, SystemException {
    ManifestSummary manifestSummary = _portletDataContext.getManifestSummary();

    StagedModelType stagedModelType = getStagedModelType();

    long modelAdditionCount = super.performCount();

    manifestSummary.addModelAdditionCount(stagedModelType.toString(), modelAdditionCount);

    long modelDeletionCount =
        ExportImportHelperUtil.getModelDeletionCount(_portletDataContext, stagedModelType);

    manifestSummary.addModelDeletionCount(stagedModelType.toString(), modelDeletionCount);

    return modelAdditionCount;
  }
  @Test
  public void testDeleteMissingLayouts() throws Exception {
    Layout layout1 = LayoutTestUtil.addLayout(group);
    Layout layout2 = LayoutTestUtil.addLayout(group);

    List<Layout> layouts = LayoutLocalServiceUtil.getLayouts(group.getGroupId(), false);

    long[] layoutIds = ExportImportHelperUtil.getLayoutIds(layouts);

    exportImportLayouts(layoutIds, getImportParameterMap());

    Assert.assertEquals(
        LayoutLocalServiceUtil.getLayoutsCount(group, false),
        LayoutLocalServiceUtil.getLayoutsCount(importedGroup, false));

    LayoutTestUtil.addLayout(importedGroup);

    Map<String, String[]> parameterMap = getImportParameterMap();

    parameterMap.put(
        PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS, new String[] {Boolean.TRUE.toString()});

    layoutIds = new long[] {layout1.getLayoutId()};

    exportImportLayouts(layoutIds, getImportParameterMap());

    Assert.assertEquals(
        LayoutLocalServiceUtil.getLayoutsCount(group, false),
        LayoutLocalServiceUtil.getLayoutsCount(importedGroup, false));

    Layout importedLayout1 =
        LayoutLocalServiceUtil.fetchLayoutByUuidAndGroupId(
            layout1.getUuid(), importedGroup.getGroupId(), false);

    Assert.assertNotNull(importedLayout1);

    Layout importedLayout2 =
        LayoutLocalServiceUtil.fetchLayoutByUuidAndGroupId(
            layout2.getUuid(), importedGroup.getGroupId(), false);

    Assert.assertNotNull(importedLayout2);
  }
  @Override
  protected void validateImport(
      StagedModel stagedModel,
      StagedModelAssets stagedModelAssets,
      Map<String, List<StagedModel>> dependentStagedModelsMap,
      Group group)
      throws Exception {

    ManifestSummary manifestSummary = ExportImportHelperUtil.getManifestSummary(portletDataContext);

    Map<String, LongWrapper> modelAdditionCounters = manifestSummary.getModelAdditionCounters();

    Assert.assertEquals(4, modelAdditionCounters.size());
    Assert.assertEquals(
        1, manifestSummary.getModelAdditionCount(DDMStructure.class, JournalArticle.class));
    Assert.assertEquals(
        1, manifestSummary.getModelAdditionCount(DDMTemplate.class, DDMStructure.class));
    Assert.assertEquals(1, manifestSummary.getModelAdditionCount(JournalArticle.class));
    Assert.assertEquals(1, manifestSummary.getModelAdditionCount(JournalFolder.class));
    Assert.assertTrue(DateUtil.equals(_exportDate, manifestSummary.getExportDate(), true));
  }
  protected boolean[] getExportPortletControls(
      long companyId, String portletId, Map<String, String[]> parameterMap, String type)
      throws Exception {

    boolean exportPortletConfiguration =
        MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.PORTLET_CONFIGURATION);
    boolean exportPortletConfigurationAll =
        MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.PORTLET_CONFIGURATION_ALL);
    boolean exportPortletData =
        MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.PORTLET_DATA);
    boolean exportPortletDataAll =
        MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.PORTLET_DATA_ALL);

    if (_log.isDebugEnabled()) {
      _log.debug("Export portlet data " + exportPortletData);
      _log.debug("Export all portlet data " + exportPortletDataAll);
      _log.debug("Export portlet configuration " + exportPortletConfiguration);
    }

    boolean exportCurPortletData = exportPortletData;

    String rootPortletId = ExportImportHelperUtil.getExportableRootPortletId(companyId, portletId);

    if (exportPortletDataAll) {
      exportCurPortletData = true;
    } else if (rootPortletId != null) {

      // PORTLET_DATA and the PORTLET_DATA for this specific data handler
      // must be true

      exportCurPortletData =
          exportPortletData
              && MapUtil.getBoolean(
                  parameterMap,
                  PortletDataHandlerKeys.PORTLET_DATA + StringPool.UNDERLINE + rootPortletId);
    }

    boolean exportCurPortletArchivedSetups = exportPortletConfiguration;
    boolean exportCurPortletSetup = exportPortletConfiguration;
    boolean exportCurPortletUserPreferences = exportPortletConfiguration;

    if (exportPortletConfigurationAll
        || (exportPortletConfiguration && type.equals("layout-prototype"))) {

      exportCurPortletArchivedSetups =
          MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.PORTLET_ARCHIVED_SETUPS_ALL);
      exportCurPortletSetup =
          MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.PORTLET_SETUP_ALL);
      exportCurPortletUserPreferences =
          MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.PORTLET_USER_PREFERENCES_ALL);
    } else if (rootPortletId != null) {
      boolean exportCurPortletConfiguration =
          exportPortletConfiguration
              && MapUtil.getBoolean(
                  parameterMap,
                  PortletDataHandlerKeys.PORTLET_CONFIGURATION
                      + StringPool.UNDERLINE
                      + rootPortletId);

      exportCurPortletArchivedSetups =
          exportCurPortletConfiguration
              && MapUtil.getBoolean(
                  parameterMap,
                  PortletDataHandlerKeys.PORTLET_ARCHIVED_SETUPS
                      + StringPool.UNDERLINE
                      + rootPortletId);
      exportCurPortletSetup =
          exportCurPortletConfiguration
              && MapUtil.getBoolean(
                  parameterMap,
                  PortletDataHandlerKeys.PORTLET_SETUP + StringPool.UNDERLINE + rootPortletId);
      exportCurPortletUserPreferences =
          exportCurPortletConfiguration
              && MapUtil.getBoolean(
                  parameterMap,
                  PortletDataHandlerKeys.PORTLET_USER_PREFERENCES
                      + StringPool.UNDERLINE
                      + rootPortletId);
    }

    return new boolean[] {
      exportCurPortletArchivedSetups, exportCurPortletData,
      exportCurPortletSetup, exportCurPortletUserPreferences
    };
  }
  protected File doExportLayoutsAsFile(
      long groupId,
      boolean privateLayout,
      long[] layoutIds,
      Map<String, String[]> parameterMap,
      Date startDate,
      Date endDate)
      throws Exception {

    boolean exportCategories = MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.CATEGORIES);
    boolean exportIgnoreLastPublishDate =
        MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.IGNORE_LAST_PUBLISH_DATE);
    boolean exportPermissions =
        MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.PERMISSIONS);
    boolean exportPortletDataAll =
        MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.PORTLET_DATA_ALL);
    boolean exportTheme = MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.THEME);
    boolean exportThemeSettings =
        MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.THEME_REFERENCE);
    boolean exportLogo = MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.LOGO);
    boolean exportLayoutSetSettings =
        MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.LAYOUT_SET_SETTINGS);
    boolean updateLastPublishDate =
        MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.UPDATE_LAST_PUBLISH_DATE);

    if (_log.isDebugEnabled()) {
      _log.debug("Export permissions " + exportPermissions);
      _log.debug("Export theme " + exportTheme);
    }

    LayoutSet layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(groupId, privateLayout);

    long companyId = layoutSet.getCompanyId();
    long defaultUserId = UserLocalServiceUtil.getDefaultUserId(companyId);

    ServiceContext serviceContext = ServiceContextThreadLocal.getServiceContext();

    if (serviceContext == null) {
      serviceContext = new ServiceContext();

      serviceContext.setCompanyId(companyId);
      serviceContext.setSignedIn(false);
      serviceContext.setUserId(defaultUserId);

      ServiceContextThreadLocal.pushServiceContext(serviceContext);
    }

    serviceContext.setAttribute("exporting", Boolean.TRUE);

    long layoutSetBranchId = MapUtil.getLong(parameterMap, "layoutSetBranchId");

    serviceContext.setAttribute("layoutSetBranchId", layoutSetBranchId);

    long lastPublishDate = System.currentTimeMillis();

    if (endDate != null) {
      lastPublishDate = endDate.getTime();
    }

    if (exportIgnoreLastPublishDate) {
      endDate = null;
      startDate = null;
    }

    StopWatch stopWatch = null;

    if (_log.isInfoEnabled()) {
      stopWatch = new StopWatch();

      stopWatch.start();
    }

    LayoutCache layoutCache = new LayoutCache();

    ZipWriter zipWriter = ZipWriterFactoryUtil.getZipWriter();

    PortletDataContext portletDataContext =
        PortletDataContextFactoryUtil.createExportPortletDataContext(
            companyId, groupId, parameterMap, startDate, endDate, zipWriter);

    portletDataContext.setPortetDataContextListener(
        new PortletDataContextListenerImpl(portletDataContext));

    Document document = SAXReaderUtil.createDocument();

    Element rootElement = document.addElement("root");

    portletDataContext.setExportDataRootElement(rootElement);

    Element headerElement = rootElement.addElement("header");

    headerElement.addAttribute(
        "available-locales",
        StringUtil.merge(LanguageUtil.getAvailableLocales(portletDataContext.getScopeGroupId())));
    headerElement.addAttribute("build-number", String.valueOf(ReleaseInfo.getBuildNumber()));
    headerElement.addAttribute("export-date", Time.getRFC822());

    if (portletDataContext.hasDateRange()) {
      headerElement.addAttribute("start-date", String.valueOf(portletDataContext.getStartDate()));
      headerElement.addAttribute("end-date", String.valueOf(portletDataContext.getEndDate()));
    }

    headerElement.addAttribute("company-id", String.valueOf(portletDataContext.getCompanyId()));
    headerElement.addAttribute(
        "company-group-id", String.valueOf(portletDataContext.getCompanyGroupId()));
    headerElement.addAttribute("group-id", String.valueOf(groupId));
    headerElement.addAttribute(
        "user-personal-site-group-id",
        String.valueOf(portletDataContext.getUserPersonalSiteGroupId()));
    headerElement.addAttribute("private-layout", String.valueOf(privateLayout));

    Group group = layoutSet.getGroup();

    String type = "layout-set";

    if (group.isLayoutPrototype()) {
      type = "layout-prototype";

      LayoutPrototype layoutPrototype =
          LayoutPrototypeLocalServiceUtil.getLayoutPrototype(group.getClassPK());

      headerElement.addAttribute("type-uuid", layoutPrototype.getUuid());
    } else if (group.isLayoutSetPrototype()) {
      type = "layout-set-prototype";

      LayoutSetPrototype layoutSetPrototype =
          LayoutSetPrototypeLocalServiceUtil.getLayoutSetPrototype(group.getClassPK());

      headerElement.addAttribute("type-uuid", layoutSetPrototype.getUuid());
    }

    headerElement.addAttribute("type", type);

    if (exportTheme || exportThemeSettings) {
      headerElement.addAttribute("theme-id", layoutSet.getThemeId());
      headerElement.addAttribute("color-scheme-id", layoutSet.getColorSchemeId());
    }

    if (exportLogo) {
      Image image = ImageLocalServiceUtil.getImage(layoutSet.getLogoId());

      if ((image != null) && (image.getTextObj() != null)) {
        String logoPath = ExportImportPathUtil.getRootPath(portletDataContext);

        logoPath += "/logo";

        headerElement.addAttribute("logo-path", logoPath);

        portletDataContext.addZipEntry(logoPath, image.getTextObj());
      }
    }

    if (exportLayoutSetSettings) {
      Element settingsElement = headerElement.addElement("settings");

      settingsElement.addCDATA(layoutSet.getSettings());
    }

    Element cssElement = headerElement.addElement("css");

    cssElement.addCDATA(layoutSet.getCss());

    Map<String, Object[]> portletIds = new LinkedHashMap<String, Object[]>();

    List<Layout> layouts = LayoutLocalServiceUtil.getLayouts(groupId, privateLayout);

    List<Portlet> portlets = getDataSiteLevelPortlets(companyId);

    long plid = LayoutConstants.DEFAULT_PLID;

    if (!layouts.isEmpty()) {
      Layout firstLayout = layouts.get(0);

      plid = firstLayout.getPlid();
    }

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

    for (Portlet portlet : portlets) {
      String portletId = portlet.getRootPortletId();

      if (!group.isStagedPortlet(portletId)) {
        continue;
      }

      String key = PortletPermissionUtil.getPrimaryKey(0, portletId);

      if (portletIds.get(key) == null) {
        portletIds.put(
            key, new Object[] {portletId, plid, groupId, StringPool.BLANK, StringPool.BLANK});
      }
    }

    Element missingReferencesElement = rootElement.addElement("missing-references");

    portletDataContext.setMissingReferencesElement(missingReferencesElement);

    portletDataContext.addDeletionSystemEventStagedModelTypes(new StagedModelType(Layout.class));

    Element layoutsElement = portletDataContext.getExportDataGroupElement(Layout.class);

    String layoutSetPrototypeUuid = layoutSet.getLayoutSetPrototypeUuid();

    if (Validator.isNotNull(layoutSetPrototypeUuid)) {
      LayoutSetPrototype layoutSetPrototype =
          LayoutSetPrototypeLocalServiceUtil.getLayoutSetPrototypeByUuidAndCompanyId(
              layoutSetPrototypeUuid, companyId);

      layoutsElement.addAttribute("layout-set-prototype-uuid", layoutSetPrototypeUuid);

      layoutsElement.addAttribute(
          "layout-set-prototype-name", layoutSetPrototype.getName(LocaleUtil.getDefault()));
    }

    for (Layout layout : layouts) {
      exportLayout(portletDataContext, portlets, layoutIds, portletIds, layout);
    }

    long previousScopeGroupId = portletDataContext.getScopeGroupId();

    Element portletsElement = rootElement.addElement("portlets");

    for (Map.Entry<String, Object[]> portletIdsEntry : portletIds.entrySet()) {

      Object[] portletObjects = portletIdsEntry.getValue();

      String portletId = null;
      plid = LayoutConstants.DEFAULT_PLID;
      long scopeGroupId = 0;
      String scopeType = StringPool.BLANK;
      String scopeLayoutUuid = null;

      if (portletObjects.length == 4) {
        portletId = (String) portletIdsEntry.getValue()[0];
        plid = (Long) portletIdsEntry.getValue()[1];
        scopeGroupId = (Long) portletIdsEntry.getValue()[2];
        scopeLayoutUuid = (String) portletIdsEntry.getValue()[3];
      } else {
        portletId = (String) portletIdsEntry.getValue()[0];
        plid = (Long) portletIdsEntry.getValue()[1];
        scopeGroupId = (Long) portletIdsEntry.getValue()[2];
        scopeType = (String) portletIdsEntry.getValue()[3];
        scopeLayoutUuid = (String) portletIdsEntry.getValue()[4];
      }

      Layout layout = LayoutLocalServiceUtil.fetchLayout(plid);

      if (layout == null) {
        if (!group.isCompany() && (plid <= LayoutConstants.DEFAULT_PLID)) {

          continue;
        }

        if (_log.isWarnEnabled()) {
          _log.warn("Assuming global scope because no layout was found");
        }

        layout = new LayoutImpl();

        layout.setGroupId(groupId);
        layout.setCompanyId(companyId);
      }

      portletDataContext.setPlid(plid);
      portletDataContext.setOldPlid(plid);
      portletDataContext.setScopeGroupId(scopeGroupId);
      portletDataContext.setScopeType(scopeType);
      portletDataContext.setScopeLayoutUuid(scopeLayoutUuid);

      boolean[] exportPortletControls =
          getExportPortletControls(companyId, portletId, parameterMap, type);

      _portletExporter.exportPortlet(
          portletDataContext,
          layoutCache,
          portletId,
          layout,
          portletsElement,
          defaultUserId,
          exportPermissions,
          exportPortletControls[0],
          exportPortletControls[1],
          exportPortletControls[2],
          exportPortletControls[3]);
    }

    portletDataContext.setScopeGroupId(previousScopeGroupId);

    exportAssetCategories(
        portletDataContext, exportPortletDataAll, exportCategories, group.isCompany());

    _portletExporter.exportAssetLinks(portletDataContext);
    _portletExporter.exportAssetTags(portletDataContext);
    _portletExporter.exportComments(portletDataContext);
    _portletExporter.exportExpandoTables(portletDataContext);
    _portletExporter.exportLocks(portletDataContext);

    _deletionSystemEventExporter.exportDeletionSystemEvents(portletDataContext);

    if (exportPermissions) {
      _permissionExporter.exportPortletDataPermissions(portletDataContext);
    }

    _portletExporter.exportRatingsEntries(portletDataContext, rootElement);

    if (exportTheme && !portletDataContext.isPerformDirectBinaryImport()) {
      exportTheme(layoutSet, zipWriter);
    }

    ExportImportHelperUtil.writeManifestSummary(document, portletDataContext.getManifestSummary());

    if (_log.isInfoEnabled()) {
      if (stopWatch != null) {
        _log.info("Exporting layouts takes " + stopWatch.getTime() + " ms");
      } else {
        _log.info("Exporting layouts is finished");
      }
    }

    portletDataContext.addZipEntry("/manifest.xml", document.formattedString());

    try {
      return zipWriter.getFile();
    } finally {
      if (updateLastPublishDate) {
        updateLastPublishDate(layoutSet, lastPublishDate);
      }
    }
  }