@Override
  public String replaceImportContentReferences(
      PortletDataContext portletDataContext, StagedModel stagedModel, String content)
      throws Exception {

    JournalFeed feed = (JournalFeed) stagedModel;

    Group group = _groupLocalService.getGroup(portletDataContext.getScopeGroupId());

    String newGroupFriendlyURL = group.getFriendlyURL();

    newGroupFriendlyURL = newGroupFriendlyURL.substring(1);

    String[] friendlyURLParts = StringUtil.split(feed.getTargetLayoutFriendlyUrl(), '/');

    String oldGroupFriendlyURL = friendlyURLParts[2];

    if (oldGroupFriendlyURL.equals(DATA_HANDLER_GROUP_FRIENDLY_URL)) {
      feed.setTargetLayoutFriendlyUrl(
          StringUtil.replace(
              feed.getTargetLayoutFriendlyUrl(),
              DATA_HANDLER_GROUP_FRIENDLY_URL,
              newGroupFriendlyURL));
    }

    return content;
  }
  @Override
  public String replaceExportContentReferences(
      PortletDataContext portletDataContext,
      StagedModel stagedModel,
      String content,
      boolean exportReferencedContent,
      boolean escapeContent)
      throws Exception {

    JournalFeed feed = (JournalFeed) stagedModel;

    Group group = _groupLocalService.getGroup(portletDataContext.getScopeGroupId());

    String newGroupFriendlyURL = group.getFriendlyURL();

    newGroupFriendlyURL = newGroupFriendlyURL.substring(1);

    String[] friendlyURLParts =
        StringUtil.split(feed.getTargetLayoutFriendlyUrl(), StringPool.FORWARD_SLASH);

    String oldGroupFriendlyURL = friendlyURLParts[2];

    if (newGroupFriendlyURL.equals(oldGroupFriendlyURL)) {
      String targetLayoutFriendlyUrl =
          StringUtil.replaceFirst(
              feed.getTargetLayoutFriendlyUrl(),
              StringPool.SLASH + newGroupFriendlyURL + StringPool.SLASH,
              StringPool.SLASH + DATA_HANDLER_GROUP_FRIENDLY_URL + StringPool.SLASH);

      feed.setTargetLayoutFriendlyUrl(targetLayoutFriendlyUrl);
    }

    Group targetLayoutGroup =
        _groupLocalService.fetchFriendlyURLGroup(
            portletDataContext.getCompanyId(), StringPool.SLASH + oldGroupFriendlyURL);

    boolean privateLayout = false;

    if (!PropsValues.LAYOUT_FRIENDLY_URL_PUBLIC_SERVLET_MAPPING.equals(
        StringPool.SLASH + friendlyURLParts[1])) {

      privateLayout = true;
    }

    String targetLayoutFriendlyURL = StringPool.SLASH + friendlyURLParts[3];

    Layout targetLayout =
        _layoutLocalService.fetchLayoutByFriendlyURL(
            targetLayoutGroup.getGroupId(), privateLayout, targetLayoutFriendlyURL);

    Element feedElement = portletDataContext.getExportDataElement(feed);

    portletDataContext.addReferenceElement(
        feed, feedElement, targetLayout, PortletDataContext.REFERENCE_TYPE_DEPENDENCY, true);

    return content;
  }
  @Override
  protected void doImportStagedModel(PortletDataContext portletDataContext, MDRAction action)
      throws Exception {

    Map<Long, Long> ruleGroupInstanceIds =
        (Map<Long, Long>) portletDataContext.getNewPrimaryKeysMap(MDRRuleGroupInstance.class);

    long ruleGroupInstanceId =
        MapUtil.getLong(
            ruleGroupInstanceIds, action.getRuleGroupInstanceId(), action.getRuleGroupInstanceId());

    ServiceContext serviceContext = portletDataContext.createServiceContext(action);

    serviceContext.setUserId(portletDataContext.getUserId(action.getUserUuid()));

    Element element = portletDataContext.getImportDataStagedModelElement(action);

    validateLayout(element, action);

    MDRAction importedAction = null;

    if (portletDataContext.isDataStrategyMirror()) {
      MDRAction existingAction =
          fetchStagedModelByUuidAndGroupId(action.getUuid(), portletDataContext.getScopeGroupId());

      if (existingAction == null) {
        serviceContext.setUuid(action.getUuid());

        importedAction =
            _mdrActionLocalService.addAction(
                ruleGroupInstanceId,
                action.getNameMap(),
                action.getDescriptionMap(),
                action.getType(),
                action.getTypeSettingsProperties(),
                serviceContext);
      } else {
        importedAction =
            _mdrActionLocalService.updateAction(
                existingAction.getActionId(), action.getNameMap(),
                action.getDescriptionMap(), action.getType(),
                action.getTypeSettingsProperties(), serviceContext);
      }
    } else {
      importedAction =
          _mdrActionLocalService.addAction(
              ruleGroupInstanceId,
              action.getNameMap(),
              action.getDescriptionMap(),
              action.getType(),
              action.getTypeSettingsProperties(),
              serviceContext);
    }

    portletDataContext.importClassedModel(action, importedAction);
  }
  @Override
  protected PortletPreferences doDeleteData(
      PortletDataContext portletDataContext,
      String portletId,
      PortletPreferences portletPreferences)
      throws Exception {

    if (portletDataContext.addPrimaryKey(DDLPortletDataHandler.class, "deleteData")) {

      return portletPreferences;
    }

    _ddlRecordSetLocalService.deleteRecordSets(portletDataContext.getScopeGroupId());

    _ddmStructureLocalService.deleteStructures(
        portletDataContext.getScopeGroupId(), PortalUtil.getClassNameId(DDLRecordSet.class));

    return portletPreferences;
  }
  protected String deletePortletData(
      PortletDataContext portletDataContext, javax.portlet.PortletPreferences portletPreferences)
      throws Exception {

    Group group = _groupLocalService.getGroup(portletDataContext.getGroupId());

    if (!group.isStagedPortlet(portletDataContext.getPortletId())) {
      if (_log.isDebugEnabled()) {
        _log.debug(
            "Do not delete portlet data for "
                + portletDataContext.getPortletId()
                + " because the portlet is not staged");
      }

      return null;
    }

    PortletDataHandler portletDataHandler =
        _portletDataHandlerProvider.provide(
            portletDataContext.getCompanyId(), portletDataContext.getPortletId());

    if (portletDataHandler == null) {
      if (_log.isDebugEnabled()) {
        StringBundler sb = new StringBundler(4);

        sb.append("Do not delete portlet data for ");
        sb.append(portletDataContext.getPortletId());
        sb.append(" because the portlet does not have a ");
        sb.append("PortletDataHandler");

        _log.debug(sb.toString());
      }

      return null;
    }

    if (_log.isDebugEnabled()) {
      _log.debug("Deleting data for " + portletDataContext.getPortletId());
    }

    try {
      portletPreferences =
          portletDataHandler.deleteData(
              portletDataContext, portletDataContext.getPortletId(), portletPreferences);
    } finally {
      portletDataContext.setGroupId(portletDataContext.getScopeGroupId());
    }

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

    return PortletPreferencesFactoryUtil.toXML(portletPreferences);
  }
  @Override
  protected PortletPreferences doDeleteData(
      PortletDataContext portletDataContext,
      String portletId,
      PortletPreferences portletPreferences)
      throws Exception {

    if (portletDataContext.addPrimaryKey(MBPortletDataHandler.class, "deleteData")) {

      return portletPreferences;
    }

    _mbBanLocalService.deleteBansByGroupId(portletDataContext.getScopeGroupId());

    _mbCategoryLocalService.deleteCategories(portletDataContext.getScopeGroupId());

    _mbStatsUserLocalService.deleteStatsUsersByGroupId(portletDataContext.getScopeGroupId());

    _mbThreadLocalService.deleteThreads(
        portletDataContext.getScopeGroupId(), MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID);

    return portletPreferences;
  }
  @Override
  public ExportActionableDynamicQuery getExportActionableDynamicQuery(
      final PortletDataContext portletDataContext) {
    final ExportActionableDynamicQuery exportActionableDynamicQuery =
        new ExportActionableDynamicQuery() {
          @Override
          public long performCount() throws PortalException {
            ManifestSummary manifestSummary = portletDataContext.getManifestSummary();

            StagedModelType stagedModelType = getStagedModelType();

            long modelAdditionCount = super.performCount();

            manifestSummary.addModelAdditionCount(stagedModelType, modelAdditionCount);

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

            manifestSummary.addModelDeletionCount(stagedModelType, modelDeletionCount);

            return modelAdditionCount;
          }
        };

    initActionableDynamicQuery(exportActionableDynamicQuery);

    exportActionableDynamicQuery.setAddCriteriaMethod(
        new ActionableDynamicQuery.AddCriteriaMethod() {
          @Override
          public void addCriteria(DynamicQuery dynamicQuery) {
            portletDataContext.addDateRangeCriteria(dynamicQuery, "modifiedDate");
          }
        });

    exportActionableDynamicQuery.setCompanyId(portletDataContext.getCompanyId());

    exportActionableDynamicQuery.setGroupId(portletDataContext.getScopeGroupId());

    exportActionableDynamicQuery.setPerformActionMethod(
        new ActionableDynamicQuery.PerformActionMethod<Calendar>() {
          @Override
          public void performAction(Calendar calendar) throws PortalException {
            StagedModelDataHandlerUtil.exportStagedModel(portletDataContext, calendar);
          }
        });
    exportActionableDynamicQuery.setStagedModelType(
        new StagedModelType(PortalUtil.getClassNameId(Calendar.class.getName())));

    return exportActionableDynamicQuery;
  }
  @Override
  protected void doRestoreStagedModel(PortletDataContext portletDataContext, WikiPage page)
      throws Exception {

    long userId = portletDataContext.getUserId(page.getUserUuid());

    WikiPage existingPage =
        fetchStagedModelByUuidAndGroupId(page.getUuid(), portletDataContext.getScopeGroupId());

    if ((existingPage == null) || !existingPage.isInTrash()) {
      return;
    }

    TrashHandler trashHandler = existingPage.getTrashHandler();

    if (trashHandler.isRestorable(existingPage.getResourcePrimKey())) {
      trashHandler.restoreTrashEntry(userId, existingPage.getResourcePrimKey());
    }
  }
  protected Map<Locale, String> getCalendarNameMap(
      PortletDataContext portletDataContext, Calendar calendar) throws Exception {

    Group sourceGroup = _groupLocalService.fetchGroup(portletDataContext.getSourceGroupId());

    String calendarName = calendar.getName(LocaleUtil.getDefault());

    if ((sourceGroup == null) || !calendarName.equals(sourceGroup.getDescriptiveName())) {

      return calendar.getNameMap();
    }

    Map<Locale, String> calendarNameMap = new HashMap<>();

    Group scopeGroup = _groupLocalService.getGroup(portletDataContext.getScopeGroupId());

    calendarNameMap.put(LocaleUtil.getDefault(), scopeGroup.getDescriptiveName());

    return calendarNameMap;
  }
  @Override
  protected String doExportData(
      final PortletDataContext portletDataContext,
      String portletId,
      PortletPreferences portletPreferences)
      throws Exception {

    portletDataContext.addPortletPermissions(MBPermission.RESOURCE_NAME);

    Element rootElement = addExportDataRootElement(portletDataContext);

    rootElement.addAttribute("group-id", String.valueOf(portletDataContext.getScopeGroupId()));

    if (portletDataContext.getBooleanParameter(NAMESPACE, "messages")) {
      ActionableDynamicQuery categoryActionableDynamicQuery =
          _mbCategoryLocalService.getExportActionableDynamicQuery(portletDataContext);

      categoryActionableDynamicQuery.performActions();

      ActionableDynamicQuery messageActionableDynamicQuery =
          getMessageActionableDynamicQuery(portletDataContext);

      messageActionableDynamicQuery.performActions();
    }

    if (portletDataContext.getBooleanParameter(NAMESPACE, "thread-flags")) {
      ActionableDynamicQuery threadFlagActionableDynamicQuery =
          _mbThreadFlagLocalService.getExportActionableDynamicQuery(portletDataContext);

      threadFlagActionableDynamicQuery.performActions();
    }

    if (portletDataContext.getBooleanParameter(NAMESPACE, "user-bans")) {
      ActionableDynamicQuery banActionableDynamicQuery =
          _mbBanLocalService.getExportActionableDynamicQuery(portletDataContext);

      banActionableDynamicQuery.performActions();
    }

    return getExportDataRootElementString(rootElement);
  }
  protected void exportService(
      PortletDataContext portletDataContext, Element rootElement, boolean exportServiceSetup)
      throws Exception {

    if (!exportServiceSetup) {
      return;
    }

    Portlet portlet = _portletLocalService.getPortletById(portletDataContext.getPortletId());

    if ((portlet == null) || portlet.isUndeployedPortlet()) {
      return;
    }

    PortletDataHandler portletDataHandler = portlet.getPortletDataHandlerInstance();

    String serviceName = portletDataHandler.getServiceName();

    if (Validator.isNotNull(serviceName)) {

      // Company service

      exportServicePortletPreferences(
          portletDataContext,
          portletDataContext.getCompanyId(),
          PortletKeys.PREFS_OWNER_TYPE_COMPANY,
          serviceName,
          rootElement);

      // Group service

      exportServicePortletPreferences(
          portletDataContext,
          portletDataContext.getScopeGroupId(),
          PortletKeys.PREFS_OWNER_TYPE_GROUP,
          serviceName,
          rootElement);
    }
  }
  @Override
  protected void doImportStagedModel(PortletDataContext portletDataContext, KBTemplate kbTemplate)
      throws Exception {

    long userId = portletDataContext.getUserId(kbTemplate.getUserUuid());

    ServiceContext serviceContext = portletDataContext.createServiceContext(kbTemplate);

    KBTemplate importedKBTemplate = null;

    if (portletDataContext.isDataStrategyMirror()) {
      KBTemplate existingKBTemplate =
          fetchStagedModelByUuidAndGroupId(
              kbTemplate.getUuid(), portletDataContext.getScopeGroupId());

      if (existingKBTemplate == null) {
        serviceContext.setUuid(kbTemplate.getUuid());

        importedKBTemplate =
            KBTemplateLocalServiceUtil.addKBTemplate(
                userId, kbTemplate.getTitle(), kbTemplate.getContent(), serviceContext);
      } else {
        importedKBTemplate =
            KBTemplateLocalServiceUtil.updateKBTemplate(
                existingKBTemplate.getKbTemplateId(),
                kbTemplate.getTitle(),
                kbTemplate.getContent(),
                serviceContext);
      }
    } else {
      importedKBTemplate =
          KBTemplateLocalServiceUtil.addKBTemplate(
              userId, kbTemplate.getTitle(), kbTemplate.getContent(), serviceContext);
    }

    portletDataContext.importClassedModel(kbTemplate, importedKBTemplate);
  }
  protected File doExport(PortletDataContext portletDataContext, long[] layoutIds)
      throws Exception {

    Map<String, String[]> parameterMap = portletDataContext.getParameterMap();

    boolean ignoreLastPublishDate =
        MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.IGNORE_LAST_PUBLISH_DATE);
    boolean layoutSetPrototypeSettings =
        MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.LAYOUT_SET_PROTOTYPE_SETTINGS);
    boolean layoutSetSettings =
        MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.LAYOUT_SET_SETTINGS);
    boolean logo = MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.LOGO);
    boolean permissions = MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.PERMISSIONS);

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

    LayoutSet layoutSet =
        _layoutSetLocalService.getLayoutSet(
            portletDataContext.getGroupId(), portletDataContext.isPrivateLayout());

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

    ServiceContext serviceContext = ServiceContextThreadLocal.popServiceContext();

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

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

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

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

    serviceContext.setAttribute("layoutSetBranchId", layoutSetBranchId);

    ServiceContextThreadLocal.pushServiceContext(serviceContext);

    if (ignoreLastPublishDate) {
      portletDataContext.setEndDate(null);
      portletDataContext.setStartDate(null);
    }

    StopWatch stopWatch = new StopWatch();

    stopWatch.start();

    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(portletDataContext.getGroupId()));
    headerElement.addAttribute(
        "user-personal-site-group-id",
        String.valueOf(portletDataContext.getUserPersonalSiteGroupId()));
    headerElement.addAttribute(
        "private-layout", String.valueOf(portletDataContext.isPrivateLayout()));

    Group group = layoutSet.getGroup();

    String type = "layout-set";

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

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

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

      layoutIds =
          ExportImportHelperUtil.getAllLayoutIds(
              portletDataContext.getGroupId(), portletDataContext.isPrivateLayout());
    } else if (group.isLayoutSetPrototype()) {
      type = "layout-set-prototype";

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

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

    headerElement.addAttribute("type", type);

    LayoutSetBranch layoutSetBranch =
        _layoutSetBranchLocalService.fetchLayoutSetBranch(layoutSetBranchId);

    if (logo) {
      Image image = null;

      if (layoutSetBranch != null) {
        image = _imageLocalService.getImage(layoutSetBranch.getLogoId());
      } else {
        image = _imageLocalService.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());
      }
    }

    String layoutSetPrototypeUuid = layoutSet.getLayoutSetPrototypeUuid();

    if (layoutSetPrototypeSettings && Validator.isNotNull(layoutSetPrototypeUuid)) {

      LayoutSetPrototype layoutSetPrototype =
          _layoutSetPrototypeLocalService.getLayoutSetPrototypeByUuidAndCompanyId(
              layoutSetPrototypeUuid, companyId);

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

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

    portletDataContext.setMissingReferencesElement(missingReferencesElement);

    if (layoutSetBranch != null) {
      _themeExporter.exportTheme(portletDataContext, layoutSetBranch);
    } else {
      _themeExporter.exportTheme(portletDataContext, layoutSet);
    }

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

      if (layoutSetBranch != null) {
        settingsElement.addCDATA(layoutSetBranch.getSettings());
      } else {
        settingsElement.addCDATA(layoutSet.getSettings());
      }
    }

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

    List<Layout> layouts =
        _layoutLocalService.getLayouts(
            portletDataContext.getGroupId(), portletDataContext.isPrivateLayout());

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

    // Collect data portlets

    for (Portlet portlet : ExportImportHelperUtil.getDataSiteLevelPortlets(companyId)) {

      String portletId = portlet.getRootPortletId();

      if (ExportImportThreadLocal.isStagingInProcess() && !group.isStagedPortlet(portletId)) {

        continue;
      }

      // Calculate the amount of exported data

      if (BackgroundTaskThreadLocal.hasBackgroundTask()) {
        PortletDataHandler portletDataHandler = portlet.getPortletDataHandlerInstance();

        portletDataHandler.prepareManifestSummary(portletDataContext);
      }

      // Add portlet ID to exportable portlets list

      portletIds.put(
          PortletPermissionUtil.getPrimaryKey(0, portletId),
          new Object[] {
            portletId,
            LayoutConstants.DEFAULT_PLID,
            portletDataContext.getGroupId(),
            StringPool.BLANK,
            StringPool.BLANK
          });

      if (!portlet.isScopeable()) {
        continue;
      }

      // Scoped data

      for (Layout layout : layouts) {
        if (!ArrayUtil.contains(layoutIds, layout.getLayoutId())
            || !layout.isTypePortlet()
            || !layout.hasScopeGroup()) {

          continue;
        }

        Group scopeGroup = layout.getScopeGroup();

        portletIds.put(
            PortletPermissionUtil.getPrimaryKey(layout.getPlid(), portlet.getPortletId()),
            new Object[] {
              portlet.getPortletId(),
              layout.getPlid(),
              scopeGroup.getGroupId(),
              StringPool.BLANK,
              layout.getUuid()
            });
      }
    }

    // Collect layout portlets

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

    if (BackgroundTaskThreadLocal.hasBackgroundTask()) {
      ManifestSummary manifestSummary = portletDataContext.getManifestSummary();

      PortletDataHandlerStatusMessageSenderUtil.sendStatusMessage(
          "layout", ArrayUtil.toStringArray(portletIds.keySet()), manifestSummary);

      manifestSummary.resetCounters();
    }

    // Export actual data

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

    // Force to always have a layout group element

    portletDataContext.getExportDataGroupElement(Layout.class);

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

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

    Element servicesElement = rootElement.addElement("services");

    long previousScopeGroupId = portletDataContext.getScopeGroupId();

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

      Object[] portletObjects = portletIdsEntry.getValue();

      String portletId = null;
      long 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 = _layoutLocalService.fetchLayout(plid);

      if (layout == null) {
        layout = new LayoutImpl();

        layout.setCompanyId(companyId);
        layout.setGroupId(portletDataContext.getGroupId());
      }

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

      Map<String, Boolean> exportPortletControlsMap =
          ExportImportHelperUtil.getExportPortletControlsMap(
              companyId, portletId, parameterMap, type);

      try {
        _exportImportLifecycleManager.fireExportImportLifecycleEvent(
            EVENT_PORTLET_EXPORT_STARTED,
            getProcessFlag(),
            PortletDataContextFactoryUtil.clonePortletDataContext(portletDataContext));

        _portletExportController.exportPortlet(
            portletDataContext,
            layout,
            portletsElement,
            permissions,
            exportPortletControlsMap.get(PortletDataHandlerKeys.PORTLET_ARCHIVED_SETUPS),
            exportPortletControlsMap.get(PortletDataHandlerKeys.PORTLET_DATA),
            exportPortletControlsMap.get(PortletDataHandlerKeys.PORTLET_SETUP),
            exportPortletControlsMap.get(PortletDataHandlerKeys.PORTLET_USER_PREFERENCES));
        _portletExportController.exportService(
            portletDataContext,
            servicesElement,
            exportPortletControlsMap.get(PortletDataHandlerKeys.PORTLET_SETUP));

        _exportImportLifecycleManager.fireExportImportLifecycleEvent(
            EVENT_PORTLET_EXPORT_SUCCEEDED,
            getProcessFlag(),
            PortletDataContextFactoryUtil.clonePortletDataContext(portletDataContext));
      } catch (Throwable t) {
        _exportImportLifecycleManager.fireExportImportLifecycleEvent(
            EVENT_PORTLET_EXPORT_FAILED,
            getProcessFlag(),
            PortletDataContextFactoryUtil.clonePortletDataContext(portletDataContext),
            t);

        throw t;
      }
    }

    portletDataContext.setScopeGroupId(previousScopeGroupId);

    _portletExportController.exportAssetLinks(portletDataContext);
    _portletExportController.exportExpandoTables(portletDataContext);
    _portletExportController.exportLocks(portletDataContext);

    _deletionSystemEventExporter.exportDeletionSystemEvents(portletDataContext);

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

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

    if (_log.isInfoEnabled()) {
      _log.info("Exporting layouts takes " + stopWatch.getTime() + " ms");
    }

    boolean updateLastPublishDate =
        MapUtil.getBoolean(
            portletDataContext.getParameterMap(), PortletDataHandlerKeys.UPDATE_LAST_PUBLISH_DATE);

    if (ExportImportThreadLocal.isStagingInProcess() && updateLastPublishDate) {

      ExportImportProcessCallbackRegistryUtil.registerCallback(
          new UpdateLayoutSetLastPublishDateCallable(
              portletDataContext.getDateRange(),
              portletDataContext.getGroupId(),
              portletDataContext.isPrivateLayout()));
    }

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

    ZipWriter zipWriter = portletDataContext.getZipWriter();

    return zipWriter.getFile();
  }
  @Override
  protected void doImportStagedModel(
      PortletDataContext portletDataContext, MDRRuleGroupInstance ruleGroupInstance)
      throws Exception {

    long userId = portletDataContext.getUserId(ruleGroupInstance.getUserUuid());

    Map<Long, Long> ruleGroupIds =
        (Map<Long, Long>) portletDataContext.getNewPrimaryKeysMap(MDRRuleGroup.class);

    Long ruleGroupId =
        MapUtil.getLong(
            ruleGroupIds, ruleGroupInstance.getRuleGroupId(), ruleGroupInstance.getRuleGroupId());

    long classPK = 0;

    Element ruleGroupInstanceElement =
        portletDataContext.getImportDataStagedModelElement(ruleGroupInstance);

    String layoutUuid = ruleGroupInstanceElement.attributeValue("layout-uuid");

    try {
      if (Validator.isNotNull(layoutUuid)) {
        Layout layout =
            _layoutLocalService.getLayoutByUuidAndGroupId(
                layoutUuid,
                portletDataContext.getScopeGroupId(),
                portletDataContext.isPrivateLayout());

        classPK = layout.getPrimaryKey();
      } else {
        LayoutSet layoutSet =
            _layoutSetLocalService.getLayoutSet(
                portletDataContext.getScopeGroupId(), portletDataContext.isPrivateLayout());

        classPK = layoutSet.getLayoutSetId();
      }
    } catch (Exception e) {
      if (_log.isWarnEnabled()) {
        StringBundler sb = new StringBundler(5);

        sb.append("Layout ");
        sb.append(layoutUuid);
        sb.append(" is missing for rule group instance ");
        sb.append(ruleGroupInstance.getRuleGroupInstanceId());
        sb.append(", skipping this rule group instance.");

        _log.warn(sb.toString());
      }

      return;
    }

    ServiceContext serviceContext = portletDataContext.createServiceContext(ruleGroupInstance);

    serviceContext.setUserId(userId);

    MDRRuleGroupInstance importedRuleGroupInstance = null;

    if (portletDataContext.isDataStrategyMirror()) {
      MDRRuleGroupInstance existingMDRRuleGroupInstance =
          fetchStagedModelByUuidAndGroupId(
              ruleGroupInstance.getUuid(), portletDataContext.getScopeGroupId());

      if (existingMDRRuleGroupInstance == null) {
        serviceContext.setUuid(ruleGroupInstance.getUuid());

        importedRuleGroupInstance =
            _mdrRuleGroupInstanceLocalService.addRuleGroupInstance(
                portletDataContext.getScopeGroupId(),
                ruleGroupInstance.getClassName(),
                classPK,
                ruleGroupId,
                ruleGroupInstance.getPriority(),
                serviceContext);
      } else {
        importedRuleGroupInstance =
            _mdrRuleGroupInstanceLocalService.updateRuleGroupInstance(
                existingMDRRuleGroupInstance.getRuleGroupInstanceId(),
                ruleGroupInstance.getPriority());
      }
    } else {
      importedRuleGroupInstance =
          _mdrRuleGroupInstanceLocalService.addRuleGroupInstance(
              portletDataContext.getScopeGroupId(),
              ruleGroupInstance.getClassName(),
              classPK,
              ruleGroupId,
              ruleGroupInstance.getPriority(),
              serviceContext);
    }

    portletDataContext.importClassedModel(ruleGroupInstance, importedRuleGroupInstance);
  }
  protected void getLayoutPortlets(
      PortletDataContext portletDataContext,
      long[] layoutIds,
      Map<String, Object[]> portletIds,
      Layout layout)
      throws Exception {

    if (!ArrayUtil.contains(layoutIds, layout.getLayoutId())) {
      return;
    }

    if (!prepareLayoutStagingHandler(portletDataContext, layout)
        || !layout.isSupportsEmbeddedPortlets()) {

      // Only portlet type layouts support page scoping

      return;
    }

    LayoutTypePortlet layoutTypePortlet = (LayoutTypePortlet) layout.getLayoutType();

    // The getAllPortlets method returns all effective nonsystem portlets
    // for any layout type, including embedded portlets, or in the case of
    // panel type layout, selected portlets

    for (Portlet portlet : layoutTypePortlet.getAllPortlets(false)) {
      String portletId = portlet.getPortletId();

      Settings portletInstanceSettings =
          SettingsFactoryUtil.getSettings(new PortletInstanceSettingsLocator(layout, portletId));

      String scopeType = portletInstanceSettings.getValue("lfrScopeType", null);
      String scopeLayoutUuid = portletInstanceSettings.getValue("lfrScopeLayoutUuid", null);

      long scopeGroupId = portletDataContext.getScopeGroupId();

      if (Validator.isNotNull(scopeType)) {
        Group scopeGroup = null;

        if (scopeType.equals("company")) {
          scopeGroup = _groupLocalService.getCompanyGroup(layout.getCompanyId());
        } else if (scopeType.equals("layout")) {
          Layout scopeLayout = null;

          scopeLayout =
              _layoutLocalService.fetchLayoutByUuidAndGroupId(
                  scopeLayoutUuid,
                  portletDataContext.getGroupId(),
                  portletDataContext.isPrivateLayout());

          if (scopeLayout == null) {
            continue;
          }

          scopeGroup = scopeLayout.getScopeGroup();
        } else {
          throw new IllegalArgumentException("Scope type " + scopeType + " is invalid");
        }

        if (scopeGroup != null) {
          scopeGroupId = scopeGroup.getGroupId();
        }
      }

      String key = PortletPermissionUtil.getPrimaryKey(layout.getPlid(), portletId);

      portletIds.put(
          key,
          new Object[] {portletId, layout.getPlid(), scopeGroupId, scopeType, scopeLayoutUuid});
    }
  }
  @Override
  public ExportActionableDynamicQuery getExportActionableDynamicQuery(
      final PortletDataContext portletDataContext) {
    final ExportActionableDynamicQuery exportActionableDynamicQuery =
        new ExportActionableDynamicQuery() {
          @Override
          public long performCount() throws PortalException {
            ManifestSummary manifestSummary = portletDataContext.getManifestSummary();

            StagedModelType stagedModelType = getStagedModelType();

            long modelAdditionCount = super.performCount();

            manifestSummary.addModelAdditionCount(stagedModelType, modelAdditionCount);

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

            manifestSummary.addModelDeletionCount(stagedModelType, modelDeletionCount);

            return modelAdditionCount;
          }
        };

    initActionableDynamicQuery(exportActionableDynamicQuery);

    exportActionableDynamicQuery.setAddCriteriaMethod(
        new ActionableDynamicQuery.AddCriteriaMethod() {
          @Override
          public void addCriteria(DynamicQuery dynamicQuery) {
            portletDataContext.addDateRangeCriteria(dynamicQuery, "modifiedDate");

            StagedModelType stagedModelType = exportActionableDynamicQuery.getStagedModelType();

            long referrerClassNameId = stagedModelType.getReferrerClassNameId();

            Property classNameIdProperty = PropertyFactoryUtil.forName("classNameId");

            if ((referrerClassNameId != StagedModelType.REFERRER_CLASS_NAME_ID_ALL)
                && (referrerClassNameId != StagedModelType.REFERRER_CLASS_NAME_ID_ANY)) {
              dynamicQuery.add(classNameIdProperty.eq(stagedModelType.getReferrerClassNameId()));
            } else if (referrerClassNameId == StagedModelType.REFERRER_CLASS_NAME_ID_ANY) {
              dynamicQuery.add(classNameIdProperty.isNotNull());
            }
          }
        });

    exportActionableDynamicQuery.setCompanyId(portletDataContext.getCompanyId());

    exportActionableDynamicQuery.setGroupId(portletDataContext.getScopeGroupId());

    exportActionableDynamicQuery.setPerformActionMethod(
        new ActionableDynamicQuery.PerformActionMethod<MBDiscussion>() {
          @Override
          public void performAction(MBDiscussion mbDiscussion) throws PortalException {
            StagedModelDataHandlerUtil.exportStagedModel(portletDataContext, mbDiscussion);
          }
        });
    exportActionableDynamicQuery.setStagedModelType(
        new StagedModelType(
            PortalUtil.getClassNameId(MBDiscussion.class.getName()),
            StagedModelType.REFERRER_CLASS_NAME_ID_ALL));

    return exportActionableDynamicQuery;
  }
  protected void exportPortlet(
      PortletDataContext portletDataContext,
      Layout layout,
      Element parentElement,
      boolean exportPermissions,
      boolean exportPortletArchivedSetups,
      boolean exportPortletData,
      boolean exportPortletSetup,
      boolean exportPortletUserPreferences)
      throws Exception {

    long plid = PortletKeys.PREFS_OWNER_ID_DEFAULT;
    long layoutId = LayoutConstants.DEFAULT_PARENT_LAYOUT_ID;

    if (layout != null) {
      plid = layout.getPlid();
      layoutId = layout.getLayoutId();
    }

    Portlet portlet =
        _portletLocalService.getPortletById(
            portletDataContext.getCompanyId(), portletDataContext.getPortletId());

    if ((portlet == null) || portlet.isUndeployedPortlet()) {
      if (_log.isDebugEnabled()) {
        _log.debug(
            "Do not export portlet "
                + portletDataContext.getPortletId()
                + " because the portlet is not deployed");
      }

      return;
    }

    if (!portlet.isInstanceable()
        && !portlet.isPreferencesUniquePerLayout()
        && portletDataContext.hasNotUniquePerLayout(portletDataContext.getPortletId())) {

      return;
    }

    if (BackgroundTaskThreadLocal.hasBackgroundTask()) {
      PortletDataContext clonedPortletDataContext =
          PortletDataContextFactoryUtil.clonePortletDataContext(portletDataContext);

      ManifestSummary manifestSummary = clonedPortletDataContext.getManifestSummary();

      manifestSummary.resetCounters();

      PortletDataHandler portletDataHandler = portlet.getPortletDataHandlerInstance();

      portletDataHandler.prepareManifestSummary(clonedPortletDataContext);

      PortletDataHandlerStatusMessageSenderUtil.sendStatusMessage(
          "portlet", portletDataContext.getPortletId(), manifestSummary);
    }

    Document document = SAXReaderUtil.createDocument();

    Element portletElement = document.addElement("portlet");

    portletElement.addAttribute("portlet-id", portletDataContext.getPortletId());
    portletElement.addAttribute("root-portlet-id", portletDataContext.getRootPortletId());
    portletElement.addAttribute("old-plid", String.valueOf(plid));
    portletElement.addAttribute(
        "scope-group-id", String.valueOf(portletDataContext.getScopeGroupId()));
    portletElement.addAttribute("scope-layout-type", portletDataContext.getScopeType());
    portletElement.addAttribute("scope-layout-uuid", portletDataContext.getScopeLayoutUuid());
    portletElement.addAttribute("private-layout", String.valueOf(layout.isPrivateLayout()));

    // Data

    if (exportPortletData) {
      javax.portlet.PortletPreferences jxPortletPreferences = null;

      if (ExportImportThreadLocal.isInitialLayoutStagingInProcess()) {
        Group liveGroup = layout.getGroup();

        Group stagingGroup = liveGroup.getStagingGroup();

        layout.setGroupId(stagingGroup.getGroupId());

        jxPortletPreferences =
            PortletPreferencesFactoryUtil.getStrictPortletSetup(
                layout, portletDataContext.getPortletId());

        layout.setGroupId(liveGroup.getGroupId());
      } else {
        jxPortletPreferences =
            PortletPreferencesFactoryUtil.getStrictPortletSetup(
                layout, portletDataContext.getPortletId());
      }

      if (!portlet.isPreferencesUniquePerLayout()) {
        StringBundler sb = new StringBundler(5);

        sb.append(portletDataContext.getPortletId());
        sb.append(StringPool.AT);
        sb.append(portletDataContext.getScopeType());
        sb.append(StringPool.AT);
        sb.append(portletDataContext.getScopeLayoutUuid());

        String dataKey = sb.toString();

        if (!portletDataContext.hasNotUniquePerLayout(dataKey)) {
          portletDataContext.putNotUniquePerLayout(dataKey);

          exportPortletData(
              portletDataContext, portlet, layout, jxPortletPreferences, portletElement);
        }
      } else {
        exportPortletData(
            portletDataContext, portlet, layout, jxPortletPreferences, portletElement);
      }
    }

    // Portlet preferences

    if (exportPortletSetup) {

      // Company

      exportPortletPreferences(
          portletDataContext,
          portletDataContext.getCompanyId(),
          PortletKeys.PREFS_OWNER_TYPE_COMPANY,
          false,
          layout,
          plid,
          portlet.getRootPortletId(),
          portletElement);

      // Group

      exportPortletPreferences(
          portletDataContext,
          portletDataContext.getScopeGroupId(),
          PortletKeys.PREFS_OWNER_TYPE_GROUP,
          false,
          layout,
          PortletKeys.PREFS_PLID_SHARED,
          portlet.getRootPortletId(),
          portletElement);

      // Layout

      exportPortletPreferences(
          portletDataContext,
          PortletKeys.PREFS_OWNER_ID_DEFAULT,
          PortletKeys.PREFS_OWNER_TYPE_LAYOUT,
          false,
          layout,
          plid,
          portletDataContext.getPortletId(),
          portletElement);
    }

    // Portlet user preferences

    if (exportPortletUserPreferences) {
      List<PortletPreferences> portletPreferencesList =
          _portletPreferencesLocalService.getPortletPreferences(
              PortletKeys.PREFS_OWNER_TYPE_USER, plid, portletDataContext.getPortletId());

      for (PortletPreferences portletPreferences : portletPreferencesList) {

        boolean defaultUser = false;

        if (portletPreferences.getOwnerId() == PortletKeys.PREFS_OWNER_ID_DEFAULT) {

          defaultUser = true;
        }

        exportPortletPreferences(
            portletDataContext,
            portletPreferences.getOwnerId(),
            PortletKeys.PREFS_OWNER_TYPE_USER,
            defaultUser,
            layout,
            plid,
            portletDataContext.getPortletId(),
            portletElement);
      }

      try {
        PortletPreferences groupPortletPreferences =
            _portletPreferencesLocalService.getPortletPreferences(
                portletDataContext.getScopeGroupId(),
                PortletKeys.PREFS_OWNER_TYPE_GROUP,
                PortletKeys.PREFS_PLID_SHARED,
                portlet.getRootPortletId());

        exportPortletPreference(
            portletDataContext,
            portletDataContext.getScopeGroupId(),
            PortletKeys.PREFS_OWNER_TYPE_GROUP,
            false,
            groupPortletPreferences,
            portlet.getRootPortletId(),
            PortletKeys.PREFS_PLID_SHARED,
            portletElement);
      } catch (NoSuchPortletPreferencesException nsppe) {
      }
    }

    // Archived setups

    if (exportPortletArchivedSetups) {
      List<PortletItem> portletItems =
          _portletItemLocalService.getPortletItems(
              portletDataContext.getGroupId(),
              portletDataContext.getRootPortletId(),
              PortletPreferences.class.getName());

      for (PortletItem portletItem : portletItems) {
        exportPortletPreferences(
            portletDataContext,
            portletItem.getPortletItemId(),
            PortletKeys.PREFS_OWNER_TYPE_ARCHIVED,
            false,
            null,
            plid,
            portletItem.getPortletId(),
            portletElement);
      }
    }

    // Permissions

    if (exportPermissions) {
      _permissionExporter.exportPortletPermissions(
          portletDataContext, portletDataContext.getPortletId(), layout, portletElement);
    }

    // Zip

    StringBundler pathSB = new StringBundler(4);

    pathSB.append(ExportImportPathUtil.getPortletPath(portletDataContext));
    pathSB.append(StringPool.SLASH);
    pathSB.append(plid);
    pathSB.append("/portlet.xml");

    String path = pathSB.toString();

    Element element = parentElement.addElement("portlet");

    element.addAttribute("portlet-id", portletDataContext.getPortletId());
    element.addAttribute("layout-id", String.valueOf(layoutId));
    element.addAttribute("path", path);
    element.addAttribute("portlet-data", String.valueOf(exportPortletData));

    PortletDataHandler portletDataHandler = portlet.getPortletDataHandlerInstance();

    element.addAttribute("schema-version", portletDataHandler.getSchemaVersion());

    StringBundler configurationOptionsSB = new StringBundler(6);

    if (exportPortletSetup) {
      configurationOptionsSB.append("setup");
      configurationOptionsSB.append(StringPool.COMMA);
    }

    if (exportPortletArchivedSetups) {
      configurationOptionsSB.append("archived-setups");
      configurationOptionsSB.append(StringPool.COMMA);
    }

    if (exportPortletUserPreferences) {
      configurationOptionsSB.append("user-preferences");
      configurationOptionsSB.append(StringPool.COMMA);
    }

    if (configurationOptionsSB.index() > 0) {
      configurationOptionsSB.setIndex(configurationOptionsSB.index() - 1);
    }

    element.addAttribute("portlet-configuration", configurationOptionsSB.toString());

    try {
      portletDataContext.addZipEntry(path, document.formattedString());
    } catch (IOException ioe) {
      if (_log.isWarnEnabled()) {
        _log.warn(ioe.getMessage());
      }
    }
  }
  protected File doExport(PortletDataContext portletDataContext) throws Exception {

    boolean exportPermissions =
        MapUtil.getBoolean(
            portletDataContext.getParameterMap(), PortletDataHandlerKeys.PERMISSIONS);

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

    StopWatch stopWatch = new StopWatch();

    stopWatch.start();

    Layout layout = _layoutLocalService.getLayout(portletDataContext.getPlid());

    if (!layout.isTypeControlPanel() && !layout.isTypePanel() && !layout.isTypePortlet()) {

      throw new LayoutImportException("Layout type " + layout.getType() + " is not valid");
    }

    ServiceContext serviceContext = ServiceContextThreadLocal.getServiceContext();

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

      serviceContext.setCompanyId(layout.getCompanyId());
      serviceContext.setSignedIn(false);

      long defaultUserId = _userLocalService.getDefaultUserId(layout.getCompanyId());

      serviceContext.setUserId(defaultUserId);

      ServiceContextThreadLocal.pushServiceContext(serviceContext);
    }

    long layoutSetBranchId =
        MapUtil.getLong(portletDataContext.getParameterMap(), "layoutSetBranchId");

    serviceContext.setAttribute("layoutSetBranchId", layoutSetBranchId);

    long scopeGroupId = portletDataContext.getGroupId();

    javax.portlet.PortletPreferences jxPortletPreferences =
        PortletPreferencesFactoryUtil.getLayoutPortletSetup(
            layout, portletDataContext.getPortletId());

    String scopeType = GetterUtil.getString(jxPortletPreferences.getValue("lfrScopeType", null));
    String scopeLayoutUuid =
        GetterUtil.getString(jxPortletPreferences.getValue("lfrScopeLayoutUuid", null));

    if (Validator.isNotNull(scopeType)) {
      Group scopeGroup = null;

      if (scopeType.equals("company")) {
        scopeGroup = _groupLocalService.getCompanyGroup(layout.getCompanyId());
      } else if (Validator.isNotNull(scopeLayoutUuid)) {
        scopeGroup = layout.getScopeGroup();
      }

      if (scopeGroup != null) {
        scopeGroupId = scopeGroup.getGroupId();
      }
    }

    portletDataContext.setScopeType(scopeType);
    portletDataContext.setScopeLayoutUuid(scopeLayoutUuid);

    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(
                PortalUtil.getSiteGroupId(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("type", "portlet");
    headerElement.addAttribute("company-id", String.valueOf(portletDataContext.getCompanyId()));
    headerElement.addAttribute(
        "company-group-id", String.valueOf(portletDataContext.getCompanyGroupId()));
    headerElement.addAttribute("group-id", String.valueOf(scopeGroupId));
    headerElement.addAttribute(
        "user-personal-site-group-id",
        String.valueOf(portletDataContext.getUserPersonalSiteGroupId()));
    headerElement.addAttribute("private-layout", String.valueOf(layout.isPrivateLayout()));
    headerElement.addAttribute("root-portlet-id", portletDataContext.getRootPortletId());

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

    portletDataContext.setMissingReferencesElement(missingReferencesElement);

    Map<String, Boolean> exportPortletControlsMap =
        ExportImportHelperUtil.getExportPortletControlsMap(
            layout.getCompanyId(),
            portletDataContext.getPortletId(),
            portletDataContext.getParameterMap());

    exportPortlet(
        portletDataContext,
        layout,
        rootElement,
        exportPermissions,
        exportPortletControlsMap.get(PortletDataHandlerKeys.PORTLET_ARCHIVED_SETUPS),
        exportPortletControlsMap.get(PortletDataHandlerKeys.PORTLET_DATA),
        exportPortletControlsMap.get(PortletDataHandlerKeys.PORTLET_SETUP),
        exportPortletControlsMap.get(PortletDataHandlerKeys.PORTLET_USER_PREFERENCES));
    exportService(
        portletDataContext,
        rootElement,
        exportPortletControlsMap.get(PortletDataHandlerKeys.PORTLET_SETUP));

    exportAssetLinks(portletDataContext);
    exportExpandoTables(portletDataContext);
    exportLocks(portletDataContext);

    _deletionSystemEventExporter.exportDeletionSystemEvents(portletDataContext);

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

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

    if (_log.isInfoEnabled()) {
      _log.info("Exporting portlet took " + stopWatch.getTime() + " ms");
    }

    try {
      portletDataContext.addZipEntry("/manifest.xml", document.formattedString());
    } catch (IOException ioe) {
      throw new SystemException(ioe);
    }

    ZipWriter zipWriter = portletDataContext.getZipWriter();

    return zipWriter.getFile();
  }
  public void exportPortletData(
      PortletDataContext portletDataContext,
      Portlet portlet,
      Layout layout,
      javax.portlet.PortletPreferences jxPortletPreferences,
      Element parentElement)
      throws Exception {

    if (portlet == null) {
      return;
    }

    PortletDataHandler portletDataHandler = portlet.getPortletDataHandlerInstance();

    if ((portletDataHandler == null) || portletDataHandler.isDataPortletInstanceLevel()) {

      return;
    }

    Group group = layout.getGroup();

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

    String portletId = portlet.getPortletId();

    if (ExportImportThreadLocal.isStagingInProcess() && !group.isStagedPortlet(portletId)) {

      if (_log.isDebugEnabled()) {
        _log.debug(
            "Not exporting data for " + portletId + " because it is configured not to be staged");
      }

      return;
    }

    if (_log.isDebugEnabled()) {
      _log.debug("Exporting data for " + portletId);
    }

    StringBundler sb = new StringBundler(4);

    sb.append(ExportImportPathUtil.getPortletPath(portletDataContext, portletId));
    sb.append(StringPool.SLASH);

    if (portlet.isPreferencesUniquePerLayout()) {
      sb.append(layout.getPlid());
    } else {
      sb.append(portletDataContext.getScopeGroupId());
    }

    sb.append("/portlet-data.xml");

    String path = sb.toString();

    if (portletDataContext.hasPrimaryKey(String.class, path)) {
      return;
    }

    Date originalStartDate = portletDataContext.getStartDate();

    Date portletLastPublishDate =
        ExportImportDateUtil.getLastPublishDate(portletDataContext, jxPortletPreferences);

    portletDataContext.setStartDate(portletLastPublishDate);

    long groupId = portletDataContext.getGroupId();

    portletDataContext.setGroupId(portletDataContext.getScopeGroupId());

    portletDataContext.clearScopedPrimaryKeys();

    String data = null;

    try {
      data = portletDataHandler.exportData(portletDataContext, portletId, jxPortletPreferences);
    } catch (PortletDataException pde) {
      throw pde;
    } catch (Exception e) {
      throw new SystemException(e);
    } finally {
      portletDataContext.setGroupId(groupId);
      portletDataContext.setStartDate(originalStartDate);
    }

    if (Validator.isNull(data)) {
      if (_log.isDebugEnabled()) {
        _log.debug("Not exporting data for " + portletId + " because null data was returned");
      }

      return;
    }

    Element portletDataElement = parentElement.addElement("portlet-data");

    portletDataElement.addAttribute("path", path);

    portletDataContext.addZipEntry(path, data);

    boolean updateLastPublishDate =
        MapUtil.getBoolean(
            portletDataContext.getParameterMap(), PortletDataHandlerKeys.UPDATE_LAST_PUBLISH_DATE);

    if (ExportImportThreadLocal.isStagingInProcess() && updateLastPublishDate) {

      DateRange adjustedDateRange =
          new DateRange(portletLastPublishDate, portletDataContext.getEndDate());

      ExportImportProcessCallbackRegistryUtil.registerCallback(
          new UpdatePortletLastPublishDateCallable(
              adjustedDateRange,
              portletDataContext.getEndDate(),
              portletDataContext.getGroupId(),
              layout.getPlid(),
              portletId));
    }
  }
  @Override
  public ExportActionableDynamicQuery getExportActionableDynamicQuery(
      final PortletDataContext portletDataContext) {
    final ExportActionableDynamicQuery exportActionableDynamicQuery =
        new ExportActionableDynamicQuery() {
          @Override
          public long performCount() throws PortalException {
            ManifestSummary manifestSummary = portletDataContext.getManifestSummary();

            StagedModelType stagedModelType = getStagedModelType();

            long modelAdditionCount = super.performCount();

            manifestSummary.addModelAdditionCount(stagedModelType, modelAdditionCount);

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

            manifestSummary.addModelDeletionCount(stagedModelType, modelDeletionCount);

            return modelAdditionCount;
          }
        };

    initActionableDynamicQuery(exportActionableDynamicQuery);

    exportActionableDynamicQuery.setAddCriteriaMethod(
        new ActionableDynamicQuery.AddCriteriaMethod() {
          @Override
          public void addCriteria(DynamicQuery dynamicQuery) {
            Criterion modifiedDateCriterion =
                portletDataContext.getDateRangeCriteria("modifiedDate");
            Criterion statusDateCriterion = portletDataContext.getDateRangeCriteria("statusDate");

            if ((modifiedDateCriterion != null) && (statusDateCriterion != null)) {
              Disjunction disjunction = RestrictionsFactoryUtil.disjunction();

              disjunction.add(modifiedDateCriterion);
              disjunction.add(statusDateCriterion);

              dynamicQuery.add(disjunction);
            }

            Property workflowStatusProperty = PropertyFactoryUtil.forName("status");

            if (portletDataContext.isInitialPublication()) {
              dynamicQuery.add(workflowStatusProperty.ne(WorkflowConstants.STATUS_IN_TRASH));
            } else {
              StagedModelDataHandler<?> stagedModelDataHandler =
                  StagedModelDataHandlerRegistryUtil.getStagedModelDataHandler(
                      BookmarksFolder.class.getName());

              dynamicQuery.add(
                  workflowStatusProperty.in(stagedModelDataHandler.getExportableStatuses()));
            }
          }
        });

    exportActionableDynamicQuery.setCompanyId(portletDataContext.getCompanyId());

    exportActionableDynamicQuery.setGroupId(portletDataContext.getScopeGroupId());

    exportActionableDynamicQuery.setPerformActionMethod(
        new ActionableDynamicQuery.PerformActionMethod<BookmarksFolder>() {
          @Override
          public void performAction(BookmarksFolder bookmarksFolder) throws PortalException {
            StagedModelDataHandlerUtil.exportStagedModel(portletDataContext, bookmarksFolder);
          }
        });
    exportActionableDynamicQuery.setStagedModelType(
        new StagedModelType(PortalUtil.getClassNameId(BookmarksFolder.class.getName())));

    return exportActionableDynamicQuery;
  }
  @Override
  protected void doImportStagedModel(PortletDataContext portletDataContext, WikiPage page)
      throws Exception {

    long userId = portletDataContext.getUserId(page.getUserUuid());

    Element pageElement = portletDataContext.getImportDataStagedModelElement(page);

    String content =
        _wikiPageExportImportContentProcessor.replaceImportContentReferences(
            portletDataContext, page, page.getContent());

    page.setContent(content);

    ServiceContext serviceContext = portletDataContext.createServiceContext(page);

    serviceContext.setUuid(page.getUuid());

    Map<Long, Long> nodeIds =
        (Map<Long, Long>) portletDataContext.getNewPrimaryKeysMap(WikiNode.class);

    long nodeId = MapUtil.getLong(nodeIds, page.getNodeId(), page.getNodeId());

    WikiPage importedPage = null;

    WikiPage existingPage = _wikiPageLocalService.fetchPage(nodeId, page.getTitle());

    if (existingPage == null) {
      importedPage =
          _wikiPageLocalService.addPage(
              userId,
              nodeId,
              page.getTitle(),
              page.getVersion(),
              page.getContent(),
              page.getSummary(),
              page.isMinorEdit(),
              page.getFormat(),
              page.getHead(),
              page.getParentTitle(),
              page.getRedirectTitle(),
              serviceContext);

      WikiPageResource pageResource =
          _wikiPageResourceLocalService.getPageResource(importedPage.getResourcePrimKey());

      String pageResourceUuid =
          GetterUtil.getString(pageElement.attributeValue("page-resource-uuid"));

      if (Validator.isNotNull(pageResourceUuid)) {
        pageResource.setUuid(pageElement.attributeValue("page-resource-uuid"));

        _wikiPageResourceLocalService.updateWikiPageResource(pageResource);
      }
    } else {
      existingPage =
          fetchStagedModelByUuidAndGroupId(page.getUuid(), portletDataContext.getScopeGroupId());

      if (existingPage == null) {
        existingPage = _wikiPageLocalService.fetchPage(nodeId, page.getTitle(), page.getVersion());
      }

      if (existingPage == null) {
        importedPage =
            _wikiPageLocalService.updatePage(
                userId,
                nodeId,
                page.getTitle(),
                0.0,
                page.getContent(),
                page.getSummary(),
                page.isMinorEdit(),
                page.getFormat(),
                page.getParentTitle(),
                page.getRedirectTitle(),
                serviceContext);
      } else {
        importedPage = existingPage;
      }
    }

    if (page.isHead()) {
      List<Element> attachmentElements =
          portletDataContext.getReferenceDataElements(
              pageElement, DLFileEntry.class, PortletDataContext.REFERENCE_TYPE_WEAK);

      for (Element attachmentElement : attachmentElements) {
        String path = attachmentElement.attributeValue("path");

        FileEntry fileEntry = (FileEntry) portletDataContext.getZipEntryAsObject(path);

        InputStream inputStream = null;

        try {
          String binPath = attachmentElement.attributeValue("bin-path");

          if (Validator.isNull(binPath) && portletDataContext.isPerformDirectBinaryImport()) {

            try {
              inputStream = FileEntryUtil.getContentStream(fileEntry);
            } catch (NoSuchFileException nsfe) {
            }
          } else {
            inputStream = portletDataContext.getZipEntryAsInputStream(binPath);
          }

          if (inputStream == null) {
            if (_log.isWarnEnabled()) {
              _log.warn("Unable to import attachment for file entry " + fileEntry.getFileEntryId());
            }

            continue;
          }

          _wikiPageLocalService.addPageAttachment(
              userId,
              importedPage.getNodeId(),
              importedPage.getTitle(),
              fileEntry.getTitle(),
              inputStream,
              null);
        } finally {
          StreamUtil.cleanUp(inputStream);
        }
      }
    }

    portletDataContext.importClassedModel(page, importedPage);

    Map<Long, Long> pageIds =
        (Map<Long, Long>) portletDataContext.getNewPrimaryKeysMap(WikiPage.class + ".pageId");

    pageIds.put(page.getPageId(), importedPage.getPageId());
  }
  protected void importPortletPreferences(
      PortletDataContext portletDataContext,
      long companyId,
      long groupId,
      Layout layout,
      Element parentElement,
      boolean preserveScopeLayoutId,
      boolean importPortletArchivedSetups,
      boolean importPortletData,
      boolean importPortletSetup,
      boolean importPortletUserPreferences)
      throws Exception {

    long plid = LayoutConstants.DEFAULT_PLID;
    String scopeType = StringPool.BLANK;
    String scopeLayoutUuid = StringPool.BLANK;

    if (layout != null) {
      plid = layout.getPlid();

      if (preserveScopeLayoutId) {
        javax.portlet.PortletPreferences jxPortletPreferences =
            PortletPreferencesFactoryUtil.getLayoutPortletSetup(
                layout, portletDataContext.getPortletId());

        scopeType = GetterUtil.getString(jxPortletPreferences.getValue("lfrScopeType", null));
        scopeLayoutUuid =
            GetterUtil.getString(jxPortletPreferences.getValue("lfrScopeLayoutUuid", null));

        portletDataContext.setScopeType(scopeType);
        portletDataContext.setScopeLayoutUuid(scopeLayoutUuid);
      }
    }

    List<Element> portletPreferencesElements = parentElement.elements("portlet-preferences");

    for (Element portletPreferencesElement : portletPreferencesElements) {
      String path = portletPreferencesElement.attributeValue("path");

      if (portletDataContext.isPathNotProcessed(path)) {
        String xml = null;

        Element element = null;

        try {
          xml = portletDataContext.getZipEntryAsString(path);

          Document preferencesDocument = SAXReaderUtil.read(xml);

          element = preferencesDocument.getRootElement();
        } catch (DocumentException de) {
          throw new SystemException(de);
        }

        long ownerId = GetterUtil.getLong(element.attributeValue("owner-id"));
        int ownerType = GetterUtil.getInteger(element.attributeValue("owner-type"));

        if ((ownerType == PortletKeys.PREFS_OWNER_TYPE_COMPANY) || !importPortletSetup) {

          continue;
        }

        if ((ownerType == PortletKeys.PREFS_OWNER_TYPE_ARCHIVED) && !importPortletArchivedSetups) {

          continue;
        }

        if ((ownerType == PortletKeys.PREFS_OWNER_TYPE_USER)
            && (ownerId != PortletKeys.PREFS_OWNER_ID_DEFAULT)
            && !importPortletUserPreferences) {

          continue;
        }

        long curPlid = plid;
        String curPortletId = portletDataContext.getPortletId();

        if (ownerType == PortletKeys.PREFS_OWNER_TYPE_GROUP) {
          curPlid = PortletKeys.PREFS_PLID_SHARED;
          curPortletId = portletDataContext.getRootPortletId();
          ownerId = portletDataContext.getScopeGroupId();
        }

        if (ownerType == PortletKeys.PREFS_OWNER_TYPE_ARCHIVED) {
          String userUuid = element.attributeValue("archive-user-uuid");

          long userId = portletDataContext.getUserId(userUuid);

          String name = element.attributeValue("archive-name");

          curPortletId = portletDataContext.getRootPortletId();

          PortletItem portletItem =
              _portletItemLocalService.updatePortletItem(
                  userId, groupId, name, curPortletId, PortletPreferences.class.getName());

          curPlid = LayoutConstants.DEFAULT_PLID;
          ownerId = portletItem.getPortletItemId();
        }

        if (ownerType == PortletKeys.PREFS_OWNER_TYPE_USER) {
          String userUuid = element.attributeValue("user-uuid");

          ownerId = portletDataContext.getUserId(userUuid);
        }

        boolean defaultUser = GetterUtil.getBoolean(element.attributeValue("default-user"));

        if (defaultUser) {
          ownerId = _userLocalService.getDefaultUserId(companyId);
        }

        javax.portlet.PortletPreferences jxPortletPreferences =
            PortletPreferencesFactoryUtil.fromXML(
                companyId, ownerId, ownerType, curPlid, curPortletId, xml);

        Element importDataRootElement = portletDataContext.getImportDataRootElement();

        try {
          Element preferenceDataElement = portletPreferencesElement.element("preference-data");

          if (preferenceDataElement != null) {
            portletDataContext.setImportDataRootElement(preferenceDataElement);
          }

          Portlet portlet =
              _portletLocalService.getPortletById(portletDataContext.getCompanyId(), curPortletId);

          ExportImportPortletPreferencesProcessor exportImportPortletPreferencesProcessor =
              ExportImportPortletPreferencesProcessorRegistryUtil
                  .getExportImportPortletPreferencesProcessor(portlet.getRootPortletId());

          if (exportImportPortletPreferencesProcessor != null) {
            List<Capability> importCapabilities =
                exportImportPortletPreferencesProcessor.getImportCapabilities();

            if (ListUtil.isNotEmpty(importCapabilities)) {
              for (Capability importCapability : importCapabilities) {

                importCapability.process(portletDataContext, jxPortletPreferences);
              }
            }

            exportImportPortletPreferencesProcessor.processImportPortletPreferences(
                portletDataContext, jxPortletPreferences);
          } else {
            PortletDataHandler portletDataHandler = portlet.getPortletDataHandlerInstance();

            jxPortletPreferences =
                portletDataHandler.processImportPortletPreferences(
                    portletDataContext, curPortletId, jxPortletPreferences);
          }
        } finally {
          portletDataContext.setImportDataRootElement(importDataRootElement);
        }

        updatePortletPreferences(
            portletDataContext,
            ownerId,
            ownerType,
            curPlid,
            curPortletId,
            PortletPreferencesFactoryUtil.toXML(jxPortletPreferences),
            importPortletData);
      }
    }

    if (preserveScopeLayoutId && (layout != null)) {
      javax.portlet.PortletPreferences jxPortletPreferences =
          PortletPreferencesFactoryUtil.getLayoutPortletSetup(
              layout, portletDataContext.getPortletId());

      try {
        jxPortletPreferences.setValue("lfrScopeType", scopeType);
        jxPortletPreferences.setValue("lfrScopeLayoutUuid", scopeLayoutUuid);

        jxPortletPreferences.store();
      } finally {
        portletDataContext.setScopeType(scopeType);
        portletDataContext.setScopeLayoutUuid(scopeLayoutUuid);
      }
    }
  }
  @Override
  protected void doImportStagedModel(PortletDataContext portletDataContext, Calendar calendar)
      throws Exception {

    long userId = portletDataContext.getUserId(calendar.getUserUuid());

    Map<Long, Long> calendarResourceIds =
        (Map<Long, Long>) portletDataContext.getNewPrimaryKeysMap(CalendarResource.class);

    long calendarResourceId =
        MapUtil.getLong(
            calendarResourceIds,
            calendar.getCalendarResourceId(),
            calendar.getCalendarResourceId());

    Map<Locale, String> calendarNameMap = getCalendarNameMap(portletDataContext, calendar);

    ServiceContext serviceContext = portletDataContext.createServiceContext(calendar);

    Calendar importedCalendar = null;

    if (portletDataContext.isDataStrategyMirror()) {
      Calendar existingCalendar =
          fetchStagedModelByUuidAndGroupId(
              calendar.getUuid(), portletDataContext.getScopeGroupId());

      if (existingCalendar == null) {
        serviceContext.setUuid(calendar.getUuid());

        importedCalendar =
            _calendarLocalService.addCalendar(
                userId,
                portletDataContext.getScopeGroupId(),
                calendarResourceId,
                calendarNameMap,
                calendar.getDescriptionMap(),
                calendar.getTimeZoneId(),
                calendar.getColor(),
                calendar.isDefaultCalendar(),
                calendar.isEnableComments(),
                calendar.isEnableRatings(),
                serviceContext);
      } else {
        importedCalendar =
            _calendarLocalService.updateCalendar(
                existingCalendar.getCalendarId(),
                calendar.getNameMap(),
                calendar.getDescriptionMap(),
                calendar.getTimeZoneId(),
                calendar.getColor(),
                calendar.isDefaultCalendar(),
                calendar.isEnableComments(),
                calendar.isEnableRatings(),
                serviceContext);
      }
    } else {
      importedCalendar =
          _calendarLocalService.addCalendar(
              userId,
              portletDataContext.getScopeGroupId(),
              calendarResourceId,
              calendarNameMap,
              calendar.getDescriptionMap(),
              calendar.getTimeZoneId(),
              calendar.getColor(),
              calendar.isDefaultCalendar(),
              calendar.isEnableComments(),
              calendar.isEnableRatings(),
              serviceContext);
    }

    portletDataContext.importClassedModel(calendar, importedCalendar);
  }