protected void exportAssetCategories(PortletDataContext portletDataContext) throws Exception {

    Document document = SAXReaderUtil.createDocument();

    Element rootElement = document.addElement("categories-hierarchy");

    Element assetVocabulariesElement = rootElement.addElement("vocabularies");

    List<AssetVocabulary> assetVocabularies =
        AssetVocabularyLocalServiceUtil.getGroupVocabularies(portletDataContext.getGroupId());

    for (AssetVocabulary assetVocabulary : assetVocabularies) {
      _portletExporter.exportAssetVocabulary(
          portletDataContext, assetVocabulariesElement, assetVocabulary);
    }

    Element categoriesElement = rootElement.addElement("categories");

    List<AssetCategory> assetCategories =
        AssetCategoryUtil.findByGroupId(portletDataContext.getGroupId());

    for (AssetCategory assetCategory : assetCategories) {
      _portletExporter.exportAssetCategory(
          portletDataContext, assetVocabulariesElement, categoriesElement, assetCategory);
    }

    _portletExporter.exportAssetCategories(portletDataContext, rootElement);

    portletDataContext.addZipEntry(
        portletDataContext.getRootPath() + "/categories-hierarchy.xml", document.formattedString());
  }
  protected void exportAssetCategory(
      PortletDataContext portletDataContext,
      Element assetVocabulariesElement,
      Element assetCategoriesElement,
      long assetCategoryId)
      throws Exception {

    AssetCategory assetCategory = AssetCategoryUtil.fetchByPrimaryKey(assetCategoryId);

    if (assetCategory != null) {
      exportAssetCategory(
          portletDataContext, assetVocabulariesElement,
          assetCategoriesElement, assetCategory);
    }
  }
  protected String getCategoryName(
      String uuid, long groupId, long parentCategoryId, String name, long vocabularyId, int count)
      throws Exception {

    AssetCategory category =
        AssetCategoryUtil.fetchByG_P_N_V_First(groupId, parentCategoryId, name, vocabularyId, null);

    if ((category == null) || (Validator.isNotNull(uuid) && uuid.equals(category.getUuid()))) {

      return name;
    }

    name = StringUtil.appendParentheticalSuffix(name, count);

    return getCategoryName(uuid, groupId, parentCategoryId, name, vocabularyId, ++count);
  }
  protected void exportAssetCategories(
      PortletDataContext portletDataContext,
      boolean exportPortletDataAll,
      boolean exportCategories,
      boolean companyGroup)
      throws Exception {

    Document document = SAXReaderUtil.createDocument();

    Element rootElement = document.addElement("categories-hierarchy");

    if (exportPortletDataAll || exportCategories || companyGroup) {
      if (_log.isDebugEnabled()) {
        _log.debug("Export categories");
      }

      Element assetVocabulariesElement = rootElement.addElement("vocabularies");

      List<AssetVocabulary> assetVocabularies =
          AssetVocabularyLocalServiceUtil.getGroupVocabularies(portletDataContext.getGroupId());

      for (AssetVocabulary assetVocabulary : assetVocabularies) {
        _portletExporter.exportAssetVocabulary(
            portletDataContext, assetVocabulariesElement, assetVocabulary);
      }

      Element categoriesElement = rootElement.addElement("categories");

      List<AssetCategory> assetCategories =
          AssetCategoryUtil.findByGroupId(portletDataContext.getGroupId());

      for (AssetCategory assetCategory : assetCategories) {
        _portletExporter.exportAssetCategory(
            portletDataContext, assetVocabulariesElement,
            categoriesElement, assetCategory);
      }
    }

    _portletExporter.exportAssetCategories(portletDataContext, rootElement);

    portletDataContext.addZipEntry(
        ExportImportPathUtil.getRootPath(portletDataContext) + "/categories-hierarchy.xml",
        document.formattedString());
  }
  @Before
  public void setUp() throws Exception {
    _assetCategoryPersistence = AssetCategoryUtil.getPersistence();

    _sessionFactoryInvocationHandler =
        new SessionFactoryInvocationHandler(
            ReflectionTestUtil.getFieldValue(_assetCategoryPersistence, "_sessionFactory"));

    ReflectionTestUtil.setFieldValue(
        _assetCategoryPersistence,
        "_sessionFactory",
        ProxyUtil.newProxyInstance(
            SessionFactory.class.getClassLoader(),
            new Class<?>[] {SessionFactory.class},
            _sessionFactoryInvocationHandler));

    _assetCategoryPersistence.setRebuildTreeEnabled(false);

    _nestedSetsTreeManager =
        new PersistenceNestedSetsTreeManager<AssetCategory>(
            (BasePersistenceImpl<?>) _assetCategoryPersistence,
            "AssetCategory",
            "AssetCategory",
            AssetCategoryImpl.class,
            "categoryId",
            "groupId",
            "leftCategoryId",
            "rightCategoryId");

    _group = GroupTestUtil.addGroup();

    _assetVocabulary = AssetTestUtil.addVocabulary(_group.getGroupId());

    _assetCategories = new AssetCategory[9];

    for (int i = 0; i < 9; i++) {
      _assetCategories[i] =
          AssetTestUtil.addCategory(_group.getGroupId(), _assetVocabulary.getVocabularyId());
    }

    PropsValues.SPRING_HIBERNATE_SESSION_DELEGATED = false;
  }
  protected void readAssetCategories(PortletDataContext portletDataContext) throws Exception {

    String xml =
        portletDataContext.getZipEntryAsString(
            portletDataContext.getSourceRootPath() + "/categories-hierarchy.xml");

    if (xml == null) {
      return;
    }

    Document document = SAXReaderUtil.read(xml);

    Element rootElement = document.getRootElement();

    Element assetVocabulariesElement = rootElement.element("vocabularies");

    List<Element> assetVocabularyElements = assetVocabulariesElement.elements("vocabulary");

    Map<Long, Long> assetVocabularyPKs =
        (Map<Long, Long>) portletDataContext.getNewPrimaryKeysMap(AssetVocabulary.class);

    for (Element assetVocabularyElement : assetVocabularyElements) {
      String path = assetVocabularyElement.attributeValue("path");

      if (!portletDataContext.isPathNotProcessed(path)) {
        continue;
      }

      AssetVocabulary assetVocabulary =
          (AssetVocabulary) portletDataContext.getZipEntryAsObject(path);

      importAssetVocabulary(
          portletDataContext, assetVocabularyPKs, assetVocabularyElement, assetVocabulary);
    }

    Element assetCategoriesElement = rootElement.element("categories");

    List<Element> assetCategoryElements = assetCategoriesElement.elements("category");

    Map<Long, Long> assetCategoryPKs =
        (Map<Long, Long>) portletDataContext.getNewPrimaryKeysMap(AssetCategory.class);

    Map<String, String> assetCategoryUuids =
        (Map<String, String>)
            portletDataContext.getNewPrimaryKeysMap(AssetCategory.class.getName() + "uuid");

    for (Element assetCategoryElement : assetCategoryElements) {
      String path = assetCategoryElement.attributeValue("path");

      if (!portletDataContext.isPathNotProcessed(path)) {
        continue;
      }

      AssetCategory assetCategory = (AssetCategory) portletDataContext.getZipEntryAsObject(path);

      importAssetCategory(
          portletDataContext,
          assetVocabularyPKs,
          assetCategoryPKs,
          assetCategoryUuids,
          assetCategoryElement,
          assetCategory);
    }

    Element assetsElement = rootElement.element("assets");

    List<Element> assetElements = assetsElement.elements("asset");

    for (Element assetElement : assetElements) {
      String className = GetterUtil.getString(assetElement.attributeValue("class-name"));
      long classPK = GetterUtil.getLong(assetElement.attributeValue("class-pk"));
      String[] assetCategoryUuidArray =
          StringUtil.split(GetterUtil.getString(assetElement.attributeValue("category-uuids")));

      long[] assetCategoryIds = new long[0];

      for (String assetCategoryUuid : assetCategoryUuidArray) {
        assetCategoryUuid =
            MapUtil.getString(assetCategoryUuids, assetCategoryUuid, assetCategoryUuid);

        AssetCategory assetCategory =
            AssetCategoryUtil.fetchByUUID_G(
                assetCategoryUuid, portletDataContext.getScopeGroupId());

        if (assetCategory == null) {
          Group companyGroup =
              GroupLocalServiceUtil.getCompanyGroup(portletDataContext.getCompanyId());

          assetCategory =
              AssetCategoryUtil.fetchByUUID_G(assetCategoryUuid, companyGroup.getGroupId());
        }

        if (assetCategory != null) {
          assetCategoryIds = ArrayUtil.append(assetCategoryIds, assetCategory.getCategoryId());
        }
      }

      portletDataContext.addAssetCategories(className, classPK, assetCategoryIds);
    }
  }
  protected void importAssetCategory(
      PortletDataContext portletDataContext,
      Map<Long, Long> assetVocabularyPKs,
      Map<Long, Long> assetCategoryPKs,
      Map<String, String> assetCategoryUuids,
      Element assetCategoryElement,
      AssetCategory assetCategory)
      throws Exception {

    long userId = portletDataContext.getUserId(assetCategory.getUserUuid());
    long assetVocabularyId =
        MapUtil.getLong(
            assetVocabularyPKs, assetCategory.getVocabularyId(), assetCategory.getVocabularyId());
    long parentAssetCategoryId =
        MapUtil.getLong(
            assetCategoryPKs,
            assetCategory.getParentCategoryId(),
            assetCategory.getParentCategoryId());

    if ((parentAssetCategoryId != AssetCategoryConstants.DEFAULT_PARENT_CATEGORY_ID)
        && (parentAssetCategoryId == assetCategory.getParentCategoryId())) {

      String path = getAssetCategoryPath(portletDataContext, parentAssetCategoryId);

      AssetCategory parentAssetCategory =
          (AssetCategory) portletDataContext.getZipEntryAsObject(path);

      Node parentCategoryNode =
          assetCategoryElement.getParent().selectSingleNode("./category[@path='" + path + "']");

      if (parentCategoryNode != null) {
        importAssetCategory(
            portletDataContext,
            assetVocabularyPKs,
            assetCategoryPKs,
            assetCategoryUuids,
            (Element) parentCategoryNode,
            parentAssetCategory);

        parentAssetCategoryId =
            MapUtil.getLong(
                assetCategoryPKs,
                assetCategory.getParentCategoryId(),
                assetCategory.getParentCategoryId());
      }
    }

    ServiceContext serviceContext = new ServiceContext();

    serviceContext.setAddGroupPermissions(true);
    serviceContext.setAddGuestPermissions(true);
    serviceContext.setCreateDate(assetCategory.getCreateDate());
    serviceContext.setModifiedDate(assetCategory.getModifiedDate());
    serviceContext.setScopeGroupId(portletDataContext.getScopeGroupId());

    AssetCategory importedAssetCategory = null;

    try {
      if (parentAssetCategoryId != AssetCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) {

        AssetCategoryUtil.findByPrimaryKey(parentAssetCategoryId);
      }

      List<Element> propertyElements = assetCategoryElement.elements("property");

      String[] properties = new String[propertyElements.size()];

      for (int i = 0; i < propertyElements.size(); i++) {
        Element propertyElement = propertyElements.get(i);

        String key = propertyElement.attributeValue("key");
        String value = propertyElement.attributeValue("value");

        properties[i] = key.concat(StringPool.COLON).concat(value);
      }

      AssetCategory existingAssetCategory =
          AssetCategoryUtil.fetchByP_N_V(
              parentAssetCategoryId, assetCategory.getName(), assetVocabularyId);

      if (existingAssetCategory == null) {
        serviceContext.setUuid(assetCategory.getUuid());

        importedAssetCategory =
            AssetCategoryLocalServiceUtil.addCategory(
                userId,
                parentAssetCategoryId,
                getAssetCategoryTitleMap(assetCategory),
                assetCategory.getDescriptionMap(),
                assetVocabularyId,
                properties,
                serviceContext);
      } else {
        importedAssetCategory =
            AssetCategoryLocalServiceUtil.updateCategory(
                userId,
                existingAssetCategory.getCategoryId(),
                parentAssetCategoryId,
                getAssetCategoryTitleMap(assetCategory),
                assetCategory.getDescriptionMap(),
                assetVocabularyId,
                properties,
                serviceContext);
      }

      assetCategoryPKs.put(assetCategory.getCategoryId(), importedAssetCategory.getCategoryId());

      assetCategoryUuids.put(assetCategory.getUuid(), importedAssetCategory.getUuid());

      portletDataContext.importPermissions(
          AssetCategory.class,
          assetCategory.getCategoryId(),
          importedAssetCategory.getCategoryId());
    } catch (NoSuchCategoryException nsce) {
      _log.error(
          "Could not find the parent category for category " + assetCategory.getCategoryId());
    }
  }
  @Override
  protected void doImportStagedModel(PortletDataContext portletDataContext, AssetCategory category)
      throws Exception {

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

    if (category.getParentCategoryId() != AssetCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) {

      StagedModelDataHandlerUtil.importReferenceStagedModel(
          portletDataContext, category, AssetCategory.class, category.getParentCategoryId());
    } else {
      StagedModelDataHandlerUtil.importReferenceStagedModel(
          portletDataContext, category, AssetVocabulary.class, category.getVocabularyId());
    }

    Map<Long, Long> vocabularyIds =
        (Map<Long, Long>) portletDataContext.getNewPrimaryKeysMap(AssetVocabulary.class);

    long vocabularyId =
        MapUtil.getLong(vocabularyIds, category.getVocabularyId(), category.getVocabularyId());

    Map<Long, Long> categoryIds =
        (Map<Long, Long>) portletDataContext.getNewPrimaryKeysMap(AssetCategory.class);

    long parentCategoryId =
        MapUtil.getLong(
            categoryIds, category.getParentCategoryId(), category.getParentCategoryId());

    Element categoryElement = portletDataContext.getImportDataElement(category);

    List<Element> propertyElements = categoryElement.elements("property");

    String[] properties = new String[propertyElements.size()];

    for (int i = 0; i < propertyElements.size(); i++) {
      Element propertyElement = propertyElements.get(i);

      String key = propertyElement.attributeValue("key");
      String value = propertyElement.attributeValue("value");

      properties[i] = key.concat(AssetCategoryConstants.PROPERTY_KEY_VALUE_SEPARATOR).concat(value);
    }

    ServiceContext serviceContext = createServiceContext(portletDataContext, category);

    AssetCategory importedCategory = null;

    AssetCategory existingCategory =
        AssetCategoryUtil.fetchByUUID_G(category.getUuid(), portletDataContext.getScopeGroupId());

    if (existingCategory == null) {
      existingCategory =
          AssetCategoryUtil.fetchByUUID_G(
              category.getUuid(), portletDataContext.getCompanyGroupId());
    }

    if (existingCategory == null) {
      String name =
          getCategoryName(
              null,
              portletDataContext.getScopeGroupId(),
              parentCategoryId,
              category.getName(),
              category.getVocabularyId(),
              2);

      serviceContext.setUuid(category.getUuid());

      importedCategory =
          AssetCategoryLocalServiceUtil.addCategory(
              userId,
              parentCategoryId,
              getCategoryTitleMap(portletDataContext.getScopeGroupId(), category, name),
              category.getDescriptionMap(),
              vocabularyId,
              properties,
              serviceContext);
    } else {
      String name =
          getCategoryName(
              category.getUuid(),
              portletDataContext.getScopeGroupId(),
              parentCategoryId,
              category.getName(),
              category.getVocabularyId(),
              2);

      importedCategory =
          AssetCategoryLocalServiceUtil.updateCategory(
              userId,
              existingCategory.getCategoryId(),
              parentCategoryId,
              getCategoryTitleMap(portletDataContext.getScopeGroupId(), category, name),
              category.getDescriptionMap(),
              vocabularyId,
              properties,
              serviceContext);
    }

    categoryIds.put(category.getCategoryId(), importedCategory.getCategoryId());

    Map<String, String> categoryUuids =
        (Map<String, String>)
            portletDataContext.getNewPrimaryKeysMap(AssetCategory.class + ".uuid");

    categoryUuids.put(category.getUuid(), importedCategory.getUuid());

    portletDataContext.importPermissions(
        AssetCategory.class, category.getCategoryId(), importedCategory.getCategoryId());
  }