@Override
  public DataApprovalLevel getLowestDataApprovalLevel(
      OrganisationUnit orgUnit, DataElementCategoryOptionCombo attributeOptionCombo) {
    Set<CategoryOptionGroupSet> cogSets = null;

    if (attributeOptionCombo != null
        && attributeOptionCombo != categoryService.getDefaultDataElementCategoryOptionCombo()) {
      cogSets = new HashSet<>();

      for (DataElementCategoryOption option : attributeOptionCombo.getCategoryOptions()) {
        if (option.getGroupSets() != null) {
          cogSets.addAll(option.getGroupSets());
        }
      }
    }

    int orgUnitLevel = orgUnit.getLevel();

    List<DataApprovalLevel> approvalLevels = getDataApprovalLevelsByOrgUnitLevel(orgUnitLevel);

    for (DataApprovalLevel level : Lists.reverse(approvalLevels)) {
      if (level.getCategoryOptionGroupSet() == null) {
        if (cogSets == null) {
          return level;
        }
      } else if (cogSets != null && cogSets.contains(level.getCategoryOptionGroupSet())) {
        return level;
      }
    }

    return null;
  }
  public String execute() {
    if (name != null) {
      DataElementCategoryOption match =
          dataElementCategoryService.getDataElementCategoryOptionByName(name);

      if (match != null && (id == null || match.getId() != id)) {
        message = i18n.getString("name_in_use");

        return ERROR;
      }
    }

    message = "ok";

    return SUCCESS;
  }
  @Override
  protected void importMatching(DataElementCategoryOption object, DataElementCategoryOption match) {
    match.setCode(object.getCode());
    match.setUid(object.getUid());
    match.setName(object.getName());

    categoryService.updateDataElementCategoryOption(match);
  }
  @Override
  protected boolean isIdentical(
      DataElementCategoryOption object, DataElementCategoryOption existing) {
    boolean codeMatch = true;
    boolean uidMatch = true;

    // if there is a code that must also match
    if (object.getCode() != null) {
      codeMatch = object.getCode().equals(existing.getCode());
    }
    // if there is a uid that must also match
    if (object.getUid() != null) {
      uidMatch = object.getUid().equals(existing.getUid());
    }

    return (object.getName().equals(existing.getName()) && codeMatch && uidMatch);
  }
  @Override
  public void setUpTest() {
    // ---------------------------------------------------------------------
    // Services
    // ---------------------------------------------------------------------

    importObjectService = (ImportObjectService) getBean(ImportObjectService.ID);

    batchHandlerFactory = (BatchHandlerFactory) getBean("batchHandlerFactory");

    dataElementService = (DataElementService) getBean(DataElementService.ID);

    categoryService = (DataElementCategoryService) getBean(DataElementCategoryService.ID);

    periodService = (PeriodService) getBean(PeriodService.ID);

    organisationUnitService = (OrganisationUnitService) getBean(OrganisationUnitService.ID);

    dataValueService = (DataValueService) getBean(DataValueService.ID);

    // ---------------------------------------------------------------------
    // CategoryOption
    // ---------------------------------------------------------------------

    categoryOptionA = new DataElementCategoryOption("CategoryOptionA");
    categoryOptionB = new DataElementCategoryOption("CategoryOptionB");
    categoryOptionC = new DataElementCategoryOption("CategoryOptionC");
    categoryOptionD = new DataElementCategoryOption("CategoryOptionD");

    categoryService.addDataElementCategoryOption(categoryOptionA);
    categoryService.addDataElementCategoryOption(categoryOptionB);
    categoryService.addDataElementCategoryOption(categoryOptionC);
    categoryService.addDataElementCategoryOption(categoryOptionD);

    categoryOptionADuplicate = new DataElementCategoryOption("CategoryOptionA");
    categoryOptionBDuplicate = new DataElementCategoryOption("CategoryOptionB");
    categoryOptionCDuplicate = new DataElementCategoryOption("CategoryOptionC");
    categoryOptionDDuplicate = new DataElementCategoryOption("CategoryOptionD");

    categoryOptionADuplicate.setId('A');
    categoryOptionBDuplicate.setId('B');
    categoryOptionCDuplicate.setId('C');
    categoryOptionDDuplicate.setId('D');

    importObjectService.addImportObject(ImportObjectStatus.MATCH, categoryOptionADuplicate, null);
    importObjectService.addImportObject(ImportObjectStatus.MATCH, categoryOptionBDuplicate, null);
    importObjectService.addImportObject(ImportObjectStatus.MATCH, categoryOptionCDuplicate, null);
    importObjectService.addImportObject(ImportObjectStatus.MATCH, categoryOptionDDuplicate, null);

    // ---------------------------------------------------------------------
    // Category
    // ---------------------------------------------------------------------

    categoryA = new DataElementCategory("CategoryA");
    categoryB = new DataElementCategory("CategoryB");

    categoryA.getCategoryOptions().add(categoryOptionA);
    categoryA.getCategoryOptions().add(categoryOptionB);
    categoryB.getCategoryOptions().add(categoryOptionC);
    categoryB.getCategoryOptions().add(categoryOptionD);

    categoryService.addDataElementCategory(categoryA);
    categoryService.addDataElementCategory(categoryB);

    categoryADuplicate = new DataElementCategory("CategoryA");
    categoryBDuplicate = new DataElementCategory("CategoryB");

    categoryADuplicate.setId('A');
    categoryBDuplicate.setId('B');

    importObjectService.addImportObject(ImportObjectStatus.MATCH, categoryADuplicate, null);
    importObjectService.addImportObject(ImportObjectStatus.MATCH, categoryBDuplicate, null);

    // ---------------------------------------------------------------------
    // Category - CategoryOption Association
    // ---------------------------------------------------------------------

    categoryCategoryOptionAssociationA = new GroupMemberAssociation('A', 'A', 1);
    categoryCategoryOptionAssociationB = new GroupMemberAssociation('A', 'B', 2);
    categoryCategoryOptionAssociationC = new GroupMemberAssociation('B', 'C', 1);
    categoryCategoryOptionAssociationD = new GroupMemberAssociation('B', 'D', 2);

    importObjectService.addImportObject(
        ImportObjectStatus.NEW,
        GroupMemberType.CATEGORY_CATEGORYOPTION,
        categoryCategoryOptionAssociationA);
    importObjectService.addImportObject(
        ImportObjectStatus.NEW,
        GroupMemberType.CATEGORY_CATEGORYOPTION,
        categoryCategoryOptionAssociationB);
    importObjectService.addImportObject(
        ImportObjectStatus.NEW,
        GroupMemberType.CATEGORY_CATEGORYOPTION,
        categoryCategoryOptionAssociationC);
    importObjectService.addImportObject(
        ImportObjectStatus.NEW,
        GroupMemberType.CATEGORY_CATEGORYOPTION,
        categoryCategoryOptionAssociationD);

    // ---------------------------------------------------------------------
    // CategoryCombo
    // ---------------------------------------------------------------------

    categoryComboA = new DataElementCategoryCombo("CategoryComboA");
    categoryComboB = new DataElementCategoryCombo("CategoryComboB");

    categoryComboA.getCategories().add(categoryA);
    categoryComboA.getCategories().add(categoryB);
    categoryComboB.getCategories().add(categoryA);

    categoryService.addDataElementCategoryCombo(categoryComboA);
    categoryService.addDataElementCategoryCombo(categoryComboB);

    categoryComboADuplicate = new DataElementCategoryCombo("CategoryComboA");
    categoryComboBDuplicate = new DataElementCategoryCombo("CategoryComboB");

    categoryComboADuplicate.setId('A');
    categoryComboBDuplicate.setId('B');

    importObjectService.addImportObject(ImportObjectStatus.MATCH, categoryComboADuplicate, null);
    importObjectService.addImportObject(ImportObjectStatus.MATCH, categoryComboBDuplicate, null);

    // ---------------------------------------------------------------------
    // CategoryCombo - Category Association
    // ---------------------------------------------------------------------

    categoryComboCategoryAssociationA = new GroupMemberAssociation('A', 'A', 1);
    categoryComboCategoryAssociationB = new GroupMemberAssociation('A', 'B', 2);
    categoryComboCategoryAssociationC = new GroupMemberAssociation('B', 'A', 1);

    importObjectService.addImportObject(
        ImportObjectStatus.NEW,
        GroupMemberType.CATEGORYCOMBO_CATEGORY,
        categoryComboCategoryAssociationA);
    importObjectService.addImportObject(
        ImportObjectStatus.NEW,
        GroupMemberType.CATEGORYCOMBO_CATEGORY,
        categoryComboCategoryAssociationB);
    importObjectService.addImportObject(
        ImportObjectStatus.NEW,
        GroupMemberType.CATEGORYCOMBO_CATEGORY,
        categoryComboCategoryAssociationC);

    // ---------------------------------------------------------------------
    // CategoryOptionCombo
    // ---------------------------------------------------------------------

    categoryOptionComboA = new DataElementCategoryOptionCombo();
    categoryOptionComboB = new DataElementCategoryOptionCombo();
    categoryOptionComboC = new DataElementCategoryOptionCombo();
    categoryOptionComboD = new DataElementCategoryOptionCombo();

    categoryOptionComboA.setCategoryCombo(categoryComboA);
    categoryOptionComboB.setCategoryCombo(categoryComboA);
    categoryOptionComboC.setCategoryCombo(categoryComboB);
    categoryOptionComboD.setCategoryCombo(categoryComboB);

    categoryOptionComboA.getCategoryOptions().add(categoryOptionA);
    categoryOptionComboA.getCategoryOptions().add(categoryOptionC);
    categoryOptionComboB.getCategoryOptions().add(categoryOptionB);
    categoryOptionComboB.getCategoryOptions().add(categoryOptionD);
    categoryOptionComboC.getCategoryOptions().add(categoryOptionA);
    categoryOptionComboD.getCategoryOptions().add(categoryOptionB);

    categoryService.addDataElementCategoryOptionCombo(categoryOptionComboA);
    categoryService.addDataElementCategoryOptionCombo(categoryOptionComboB);
    categoryService.addDataElementCategoryOptionCombo(categoryOptionComboC);
    categoryService.addDataElementCategoryOptionCombo(categoryOptionComboD);

    categoryOptionComboADuplicate = new DataElementCategoryOptionCombo();
    categoryOptionComboBDuplicate = new DataElementCategoryOptionCombo();
    categoryOptionComboCDuplicate = new DataElementCategoryOptionCombo();
    categoryOptionComboDDuplicate = new DataElementCategoryOptionCombo();

    categoryOptionComboADuplicate.setId('A');
    categoryOptionComboBDuplicate.setId('B');
    categoryOptionComboCDuplicate.setId('C');
    categoryOptionComboDDuplicate.setId('D');

    categoryOptionComboADuplicate.setCategoryCombo(categoryComboADuplicate);
    categoryOptionComboBDuplicate.setCategoryCombo(categoryComboADuplicate);
    categoryOptionComboCDuplicate.setCategoryCombo(categoryComboBDuplicate);
    categoryOptionComboDDuplicate.setCategoryCombo(categoryComboBDuplicate);

    categoryOptionComboADuplicate.getCategoryOptions().add(categoryOptionADuplicate);
    categoryOptionComboADuplicate.getCategoryOptions().add(categoryOptionCDuplicate);
    categoryOptionComboBDuplicate.getCategoryOptions().add(categoryOptionBDuplicate);
    categoryOptionComboBDuplicate.getCategoryOptions().add(categoryOptionDDuplicate);
    categoryOptionComboCDuplicate.getCategoryOptions().add(categoryOptionADuplicate);
    categoryOptionComboDDuplicate.getCategoryOptions().add(categoryOptionBDuplicate);

    importObjectService.addImportObject(
        ImportObjectStatus.MATCH, categoryOptionComboADuplicate, null);
    importObjectService.addImportObject(
        ImportObjectStatus.MATCH, categoryOptionComboBDuplicate, null);
    importObjectService.addImportObject(
        ImportObjectStatus.MATCH, categoryOptionComboCDuplicate, null);
    importObjectService.addImportObject(
        ImportObjectStatus.MATCH, categoryOptionComboDDuplicate, null);

    // ---------------------------------------------------------------------
    // DataElement
    // ---------------------------------------------------------------------

    dataElementA = createDataElement('A', categoryComboA);
    dataElementB = createDataElement('B', categoryComboA);
    dataElementC = createDataElement('C', categoryComboA);
    dataElementD = createDataElement('D', categoryComboA);

    dataElementAModified = createDataElement('A', categoryComboADuplicate);
    dataElementBModified = createDataElement('B', categoryComboADuplicate);
    dataElementCModified = createDataElement('C', categoryComboADuplicate);
    dataElementDModified = createDataElement('D', categoryComboADuplicate);

    dataElementAModified.setId('A');
    dataElementBModified.setId('B');
    dataElementCModified.setId('C');
    dataElementDModified.setId('D');

    dataElementAModified.setShortName("ShortNameModifiedA");
    dataElementBModified.setShortName("ShortNameModifiedB");
    dataElementCModified.setShortName("ShortNameModifiedC");
    dataElementDModified.setShortName("ShortNameModifiedD");

    // ---------------------------------------------------------------------
    // DataElementGroup
    // ---------------------------------------------------------------------

    dataElementGroupA = createDataElementGroup('A');
    dataElementGroupB = createDataElementGroup('B');
    dataElementGroupC = createDataElementGroup('C');

    dataElementGroupADuplicate = createDataElementGroup('A');
    dataElementGroupBDuplicate = createDataElementGroup('B');
    dataElementGroupCDuplicate = createDataElementGroup('C');

    dataElementGroupADuplicate.setId('A');
    dataElementGroupBDuplicate.setId('B');
    dataElementGroupCDuplicate.setId('C');

    dataElementGroupAssociationA = new GroupMemberAssociation('A', 'A');
    dataElementGroupAssociationB = new GroupMemberAssociation('A', 'B');
    dataElementGroupAssociationC = new GroupMemberAssociation('A', 'C');
    dataElementGroupAssociationD = new GroupMemberAssociation('A', 'D');
    dataElementGroupAssociationE = new GroupMemberAssociation('B', 'A');
    dataElementGroupAssociationF = new GroupMemberAssociation('B', 'B');
    dataElementGroupAssociationG = new GroupMemberAssociation('B', 'C');
    dataElementGroupAssociationH = new GroupMemberAssociation('B', 'D');
    dataElementGroupAssociationI = new GroupMemberAssociation('C', 'A');
    dataElementGroupAssociationJ = new GroupMemberAssociation('C', 'B');
    dataElementGroupAssociationK = new GroupMemberAssociation('C', 'C');
    dataElementGroupAssociationL = new GroupMemberAssociation('C', 'D');

    // ---------------------------------------------------------------------
    // Period
    // ---------------------------------------------------------------------

    periodTypeA = periodService.getPeriodTypeByName(MonthlyPeriodType.NAME);

    periodA = createPeriod(periodTypeA, getDate(1, 0, 2000), getDate(31, 0, 2000));

    periodADuplicate = createPeriod(periodTypeA, getDate(1, 0, 2000), getDate(31, 0, 2000));

    periodADuplicate.setId('A');

    // ---------------------------------------------------------------------
    // OrganisationUnit
    // ---------------------------------------------------------------------

    organisationUnitA = createOrganisationUnit('A');
    organisationUnitB = createOrganisationUnit('B');
    organisationUnitC = createOrganisationUnit('C');

    organisationUnitAModified = createOrganisationUnit('A');
    organisationUnitBModified = createOrganisationUnit('B');
    organisationUnitCModified = createOrganisationUnit('C');

    organisationUnitAModified.setId('A');
    organisationUnitBModified.setId('B');
    organisationUnitCModified.setId('C');

    organisationUnitAModified.setShortName("ShortNameModifiedA");
    organisationUnitBModified.setShortName("ShortNameModifiedB");
    organisationUnitCModified.setShortName("ShortNameModifiedC");

    // ---------------------------------------------------------------------
    // RelationshipAssociation
    // ---------------------------------------------------------------------

    relationshipAssociationA = new GroupMemberAssociation('A', 'B');
    relationshipAssociationB = new GroupMemberAssociation('B', 'C');

    // ---------------------------------------------------------------------
    // DataValue
    // ---------------------------------------------------------------------

    dataValueA =
        createDataValue(dataElementA, periodA, organisationUnitA, "10", categoryOptionComboA);
    dataValueB =
        createDataValue(dataElementA, periodA, organisationUnitB, "10", categoryOptionComboA);
    dataValueC =
        createDataValue(dataElementA, periodA, organisationUnitC, "10", categoryOptionComboA);
    dataValueD =
        createDataValue(dataElementB, periodA, organisationUnitA, "10", categoryOptionComboA);
    dataValueE =
        createDataValue(dataElementB, periodA, organisationUnitB, "10", categoryOptionComboA);
    dataValueF =
        createDataValue(dataElementB, periodA, organisationUnitC, "10", categoryOptionComboA);
    dataValueG =
        createDataValue(dataElementC, periodA, organisationUnitA, "10", categoryOptionComboA);
    dataValueH =
        createDataValue(dataElementC, periodA, organisationUnitB, "10", categoryOptionComboA);
    dataValueI =
        createDataValue(dataElementC, periodA, organisationUnitC, "10", categoryOptionComboA);

    dataValueADuplicate =
        createDataValue(
            dataElementAModified,
            periodADuplicate,
            organisationUnitAModified,
            "10",
            categoryOptionComboADuplicate);
    dataValueBDuplicate =
        createDataValue(
            dataElementAModified,
            periodADuplicate,
            organisationUnitBModified,
            "10",
            categoryOptionComboADuplicate);
    dataValueCDuplicate =
        createDataValue(
            dataElementAModified,
            periodADuplicate,
            organisationUnitCModified,
            "10",
            categoryOptionComboADuplicate);
    dataValueDDuplicate =
        createDataValue(
            dataElementBModified,
            periodADuplicate,
            organisationUnitAModified,
            "10",
            categoryOptionComboADuplicate);
    dataValueEDuplicate =
        createDataValue(
            dataElementBModified,
            periodADuplicate,
            organisationUnitBModified,
            "10",
            categoryOptionComboADuplicate);
    dataValueFDuplicate =
        createDataValue(
            dataElementBModified,
            periodADuplicate,
            organisationUnitCModified,
            "10",
            categoryOptionComboADuplicate);
    dataValueGDuplicate =
        createDataValue(
            dataElementCModified,
            periodADuplicate,
            organisationUnitAModified,
            "10",
            categoryOptionComboADuplicate);
    dataValueHDuplicate =
        createDataValue(
            dataElementCModified,
            periodADuplicate,
            organisationUnitBModified,
            "10",
            categoryOptionComboADuplicate);
    dataValueIDuplicate =
        createDataValue(
            dataElementCModified,
            periodADuplicate,
            organisationUnitCModified,
            "10",
            categoryOptionComboADuplicate);
  }
 @Override
 protected DataElementCategoryOption getMatching(DataElementCategoryOption object) {
   return categoryService.getDataElementCategoryOptionByName(object.getName());
 }
  @Override
  public void importObject(DataElementCategoryOption object, ImportParams params) {
    NameMappingUtil.addCategoryOptionMapping(object.getId(), object.getName());

    read(object, GroupMemberType.NONE, params);
  }