class UnitInheritedRule {

    public UnitInheritedRule createNewInheritedRule(ObjectNode unitManagement, String unitId)
        throws InvalidParseOperationException {
        UnitInheritedRule newRule = deepCopy(this);
        if (newRule.unitId.length() == 0) {
            newRule.unitId = unitId;
        }
        Map<String, ObjectNode> ruleCategoryFromUnit = new HashMap<>();
        Map<String, String> ruleIdTodReplace = new HashMap<>();
        List<String> parentCategoryList = new ArrayList<>();

        // By Category
        for (Entry<String, Map<String, Map<String, InheritedRuleModel>>> categoryEntry : newRule.inheritedRule
            .entrySet()) {
            String categoryName = categoryEntry.getKey();
            parentCategoryList.add(categoryName);
            Map<String, Map<String, InheritedRuleModel>> categoryValue = categoryEntry.getValue();
            ruleCategoryFromUnit.remove(categoryName);
            if (unitManagement.get(categoryName) == null ||
                unitManagement.get(categoryName).get(RULES) == null ||
                unitManagement.get(categoryName).get(RULES).size() == 0) {
                // Unit management does not contain category rule
                // By rule
                for (Entry<String, Map<String, InheritedRuleModel>> ruleEntry : categoryValue.entrySet()) {
                    Map<String, InheritedRuleModel> ruleValue = ruleEntry.getValue();
                    // By origin
                    for (Entry<String, InheritedRuleModel> ruleForOriginEntry : ruleValue.entrySet()) {
                        ArrayNode pathNode = (ArrayNode) ruleForOriginEntry.getValue().getPath();
                        updateOriginPath(pathNode, unitId);
                    }
                }
            } else {
                // Unit management contains category rule
                // By rule
                for (Entry<String, Map<String, InheritedRuleModel>> ruleEntry : categoryValue.entrySet()) {
                    String ruleId = ruleEntry.getKey();
                    Map<String, InheritedRuleModel> ruleValue = ruleEntry.getValue();
                    JsonNode unitManagementRuleCategory = unitManagement.get(categoryName);
                    compareInheritedRuleWithManagement(unitManagementRuleCategory, ruleId, ruleValue, unitId,
                        ruleIdTodReplace);
                }

                for (Entry<String, String> ruleIdEntry : ruleIdTodReplace.entrySet()) {
                    String originId = ruleIdEntry.getKey().split(SEPERATOR, 2)[0];
                    String ruleId = ruleIdEntry.getKey().split(SEPERATOR, 2)[1];

                    InheritedRuleModel ruleModel = categoryValue.get(ruleId).get(originId);
                    categoryValue.get(ruleId).remove(originId);
                    categoryValue.get(ruleId).put(ruleIdEntry.getValue(), ruleModel);
                }
                ruleIdTodReplace.clear();
            }

            if (unitManagement.get(categoryName) != null &&
                unitManagement.get(categoryName).get("Inheritance") != null) {
                addPreventRulesId(unitManagement.get(categoryName).get("Inheritance").get("PreventRulesId"));
            }
        }


        for (String ruleCategory : VitamConstants.getSupportedRules()) {
            JsonNode unitManagementRuleCategory = unitManagement.get(ruleCategory);
            if (unitManagementRuleCategory == null) {
                continue;
            }
            if (unitManagementRuleCategory.has("Inheritance")) {
                JsonNode inheritance = unitManagementRuleCategory.get("Inheritance");
                if (inheritance.has(PREVENTRULESID)) {
                    addPreventRulesId(inheritance.get(PREVENTRULESID));
                }
                computeRuleCategoryInheritancePrevent(inheritance, newRule, ruleCategory);
            }

            if (unitManagementRuleCategory.has(RULES)) {
                computeRuleCategoryInheritance(unitManagementRuleCategory, newRule, ruleCategory, ruleCategoryFromUnit,
                    parentCategoryList);
            }

        }

        for (Map.Entry<String, ObjectNode> entry : ruleCategoryFromUnit.entrySet()) {
            String categoryName = entry.getKey();
            ObjectNode category = entry.getValue();
            Map<String, Map<String, InheritedRuleModel>> rulesMap = new HashMap<>();
            if (newRule.inheritedRule.containsKey(categoryName)) {
                rulesMap = newRule.inheritedRule.get(categoryName);
            } else {
                newRule.inheritedRule.put(categoryName, rulesMap);
            }

            Iterator<String> categoryRules = category.fieldNames();
            while (categoryRules.hasNext()) {
                String idRule = categoryRules.next();
                JsonNode rule = category.get(idRule);
                Map<String, InheritedRuleModel> originsMap = new HashMap<>();
                if (rulesMap.containsKey(idRule)) {
                    originsMap = rulesMap.get(idRule);
                } else {
                    rulesMap.put(idRule, originsMap);
                }

                Iterator<String> origins = rule.fieldNames();
                while (origins.hasNext()) {
                    String idOrigin = origins.next();
                    JsonNode origin = rule.get(idOrigin);
                    InheritedRuleModel ruleModel = JsonHandler.getFromJsonNode(origin, InheritedRuleModel.class);
                    ruleModel.setPath((ArrayNode) origin.get("path"));
                    originsMap.put(idOrigin, ruleModel);
                }
            }
        }

        for (String categoryName : parentCategoryList) {
            if (newRule.inheritedRule.containsKey(categoryName)) {
                if (newRule.inheritedRule.get(categoryName).isEmpty()) {
                    newRule.inheritedRule.remove(categoryName);
                }
            }
        }
        return newRule;
    }

    public  UnitInheritedRule();

}