<commit_before># -*- coding: utf-8 -*-
import json
from typing import Dict, Tuple, List, Optional

from requests import Response

from TM1py.Objects import Hierarchy, Element, ElementAttribute
from TM1py.Services.ElementService import ElementService
from TM1py.Services.ObjectService import ObjectService
from TM1py.Services.RestService import RestService
from TM1py.Services.SubsetService import SubsetService
from TM1py.Utils.Utils import case_and_space_insensitive_equals, format_url


class HierarchyService(ObjectService):
    """ Service to handle Object Updates for TM1 Hierarchies
    
    """

    # Tuple with TM1 Versions where Edges need to be created through TI, due to bug:
    # https://www.ibm.com/developerworks/community/forums/html/topic?id=75f2b99e-6961-4c71-9364-1d5e1e083eff
    EDGES_WORKAROUND_VERSIONS = ('11.0.002', '11.0.003', '11.1.000')

    def __init__(self, rest: RestService):
        super().__init__(rest)
        self.subsets = SubsetService(rest)
        self.elements = ElementService(rest)

    def create(self, hierarchy: Hierarchy, **kwargs):
        """ Create a hierarchy in an existing dimension

        :param hierarchy:
        :return:
        """
        url = format_url("/api/v1/Dimensions('{}')/Hierarchies", hierarchy.dimension_name)
        response = self._rest.POST(url, hierarchy.body, **kwargs)
        return response

    def get(self, dimension_name: str, hierarchy_name: str, **kwargs):
        """ get hierarchy

        :param dimension_name: name of the dimension
        :param hierarchy_name: name of the hierarchy
        :return:
        """
        url = format_url(
            "/api/v1/Dimensions('{}')/Hierarchies('{}')?$expand=Edges,Elements,ElementAttributes,Subsets,DefaultMember",
            dimension_name,
            hierarchy_name)
        response = self._rest.GET(url, **kwargs)
        return Hierarchy.from_dict(response.json())

    def get_all_names(self, dimension_name: str, **kwargs):
        """ get all names of existing Hierarchies in a dimension

        :param dimension_name:
        :return:
        """
        url = format_url("/api/v1/Dimensions('{}')/Hierarchies?$select=Name", dimension_name)
        response = self._rest.GET(url, **kwargs)
        return [hierarchy["Name"] for hierarchy in response.json()["value"]]

    def update(self, hierarchy: Hierarchy, **kwargs) -> List[Response]:
        """ update a hierarchy. It's a two step process: 
        1. Update Hierarchy
        2. Update Element-Attributes

        Function caters for Bug with Edge Creation:
        https://www.ibm.com/developerworks/community/forums/html/topic?id=75f2b99e-6961-4c71-9364-1d5e1e083eff

        :param hierarchy: instance of TM1py.Hierarchy
        :return: list of responses
        """
        # functions returns multiple responses
        responses = list()
        # 1. Update Hierarchy
        url = format_url("/api/v1/Dimensions('{}')/Hierarchies('{}')", hierarchy.dimension_name, hierarchy.name)
        # Workaround EDGES: Handle Issue, that Edges cant be created in one batch with the Hierarchy in certain versions
        hierarchy_body = hierarchy.body_as_dict
        if self.version[0:8] in self.EDGES_WORKAROUND_VERSIONS:
            del hierarchy_body["Edges"]
        responses.append(self._rest.PATCH(url, json.dumps(hierarchy_body), **kwargs))

        # 2. Update Attributes
        responses.append(self.update_element_attributes(hierarchy=hierarchy, **kwargs))

        # Workaround EDGES
        if self.version[0:8] in self.EDGES_WORKAROUND_VERSIONS:
            from TM1py.Services import ProcessService
            process_service = ProcessService(self._rest)
            ti_function = "HierarchyElementComponentAdd('{}', '{}', '{}', '{}', {});"
            ti_statements = [ti_function.format(hierarchy.dimension_name, hierarchy.name,
                                                edge[0],
                                                edge[1],
                                                hierarchy.edges[(edge[0], edge[1])])
                             for edge
                             in hierarchy.edges]
            responses.append(process_service.execute_ti_code(lines_prolog=ti_statements, **kwargs))

        return responses

    def exists(self, dimension_name: str, hierarchy_name: str, **kwargs) -> bool:
        """

        :param dimension_name: 
        :param hierarchy_name: 
        :return: 
        """
        url = format_url("/api/v1/Dimensions('{}')/Hierarchies('{}')", dimension_name, hierarchy_name)
        return self._exists(url, **kwargs)

    def delete(self, dimension_name: str, hierarchy_name: str, **kwargs) -> Response:
        url = format_url("/api/v1/Dimensions('{}')/Hierarchies('{}')", dimension_name, hierarchy_name)
        return self._rest.DELETE(url, **kwargs)

    def get_hierarchy_summary(self, dimension_name: str, hierarchy_name: str, **kwargs) -> Dict[str, int]:<commit_msg>add update_or_create to HierarchyService<commit_after># -*- coding: utf-8 -*-
import json
from typing import Dict, Tuple, List, Optional

from requests import Response

from TM1py.Objects import Hierarchy, Element, ElementAttribute
from TM1py.Services.ElementService import ElementService
from TM1py.Services.ObjectService import ObjectService
from TM1py.Services.RestService import RestService
from TM1py.Services.SubsetService import SubsetService
from TM1py.Utils.Utils import case_and_space_insensitive_equals, format_url, hierarchy_name_from_element_unique_name


class HierarchyService(ObjectService):
    """ Service to handle Object Updates for TM1 Hierarchies
    
    """

    # Tuple with TM1 Versions where Edges need to be created through TI, due to bug:
    # https://www.ibm.com/developerworks/community/forums/html/topic?id=75f2b99e-6961-4c71-9364-1d5e1e083eff
    EDGES_WORKAROUND_VERSIONS = ('11.0.002', '11.0.003', '11.1.000')

    def __init__(self, rest: RestService):
        super().__init__(rest)
        self.subsets = SubsetService(rest)
        self.elements = ElementService(rest)

    def create(self, hierarchy: Hierarchy, **kwargs):
        """ Create a hierarchy in an existing dimension

        :param hierarchy:
        :return:
        """
        url = format_url("/api/v1/Dimensions('{}')/Hierarchies", hierarchy.dimension_name)
        response = self._rest.POST(url, hierarchy.body, **kwargs)
        return response

    def get(self, dimension_name: str, hierarchy_name: str, **kwargs):
        """ get hierarchy

        :param dimension_name: name of the dimension
        :param hierarchy_name: name of the hierarchy
        :return:
        """
        url = format_url(
            "/api/v1/Dimensions('{}')/Hierarchies('{}')?$expand=Edges,Elements,ElementAttributes,Subsets,DefaultMember",
            dimension_name,
            hierarchy_name)
        response = self._rest.GET(url, **kwargs)
        return Hierarchy.from_dict(response.json())

    def get_all_names(self, dimension_name: str, **kwargs):
        """ get all names of existing Hierarchies in a dimension

        :param dimension_name:
        :return:
        """
        url = format_url("/api/v1/Dimensions('{}')/Hierarchies?$select=Name", dimension_name)
        response = self._rest.GET(url, **kwargs)
        return [hierarchy["Name"] for hierarchy in response.json()["value"]]

    def update(self, hierarchy: Hierarchy, **kwargs) -> List[Response]:
        """ update a hierarchy. It's a two step process: 
        1. Update Hierarchy
        2. Update Element-Attributes

        Function caters for Bug with Edge Creation:
        https://www.ibm.com/developerworks/community/forums/html/topic?id=75f2b99e-6961-4c71-9364-1d5e1e083eff

        :param hierarchy: instance of TM1py.Hierarchy
        :return: list of responses
        """
        # functions returns multiple responses
        responses = list()
        # 1. Update Hierarchy
        url = format_url("/api/v1/Dimensions('{}')/Hierarchies('{}')", hierarchy.dimension_name, hierarchy.name)
        # Workaround EDGES: Handle Issue, that Edges cant be created in one batch with the Hierarchy in certain versions
        hierarchy_body = hierarchy.body_as_dict
        if self.version[0:8] in self.EDGES_WORKAROUND_VERSIONS:
            del hierarchy_body["Edges"]
        responses.append(self._rest.PATCH(url, json.dumps(hierarchy_body), **kwargs))

        # 2. Update Attributes
        responses.append(self.update_element_attributes(hierarchy=hierarchy, **kwargs))

        # Workaround EDGES
        if self.version[0:8] in self.EDGES_WORKAROUND_VERSIONS:
            from TM1py.Services import ProcessService
            process_service = ProcessService(self._rest)
            ti_function = "HierarchyElementComponentAdd('{}', '{}', '{}', '{}', {});"
            ti_statements = [ti_function.format(hierarchy.dimension_name, hierarchy.name,
                                                edge[0],
                                                edge[1],
                                                hierarchy.edges[(edge[0], edge[1])])
                             for edge
                             in hierarchy.edges]
            responses.append(process_service.execute_ti_code(lines_prolog=ti_statements, **kwargs))

        return responses

    def update_or_create(self, hierarchy: Hierarchy, **kwargs):
        """ update if exists else create

        :param Hierarchy:
        :return:
        """
        if self.exists(dimension_name=hierarchy.dimension_name, hierarchy_name=hierarchy.name, **kwargs):
            self.update(hierarchy=hierarchy, **kwargs)
        else:
            self.create(hierarchy=hierarchy, **kwargs)

    def exists(self, dimension_name: str, hierarchy_name: str, **kwargs) -> bool:
        """

        :param dimension_name: 
        :param hierarchy_name: 
        :return: 
        """
        url = format_url("/api/v1/Dimensions('{}')/Hierarchies('{}')", dimension_name, hierarchy_name)
        return self._exists(url, **kwargs)

    def delete(self, dimension_name: str, hierarchy_name: str, **kwargs) -> Response:
        url = format_url("/api/v1/Dimensions('{}')/Hierarchies('{}')", dimension_name, hierarchy_name)
        return self._rest.DELETE(url, **kwargs)

    def get_hierarchy_summary(self, dimension_name: str, hierarchy_name: str, **kwargs) -> Dict[str, int]:
{'fraction_non_alphanumeric': 0.11359260685406238, 'fraction_numerical': 0.01752021563342318, 'mean_word_length': 2.764130434782609, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 11, 'https://': 4, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 14, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2117135', 'n_tokens_mistral': 3082, 'n_tokens_neox': 2939, 'n_words': 673}