def __init__(self, rest):
     super().__init__(rest)
     self.elements = ElementService(rest)
class HierarchyService(ObjectService):
    """ Service to handle Object Updates for TM1 Hierarchies
    
    """
    def __init__(self, rest):
        super().__init__(rest)
        self.elements = ElementService(rest)

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

        :param hierarchy:
        :return:
        """
        raise NotImplementedError('not supported')

    def get(self, dimension_name, hierarchy_name):
        """ get hierarchy

        :param dimension_name: name of the dimension
        :param hierarchy_name: name of the hierarchy
        :return:
        """
        request = '/api/v1/Dimensions(\'{}\')/Hierarchies(\'{}\')'.format(
            dimension_name, hierarchy_name)
        response = self._rest.GET(request, '')
        return response

    def update(self, hierarchy):
        """ update a hierarchy. Is a two step process.
        1. Update Hierarchy
        2. Update Element-Attributes

        :param hierarchy: instance of TM1py.Hierarchy
        :return:
        """
        # Update Hierarchy
        request = '/api/v1/Dimensions(\'{}\')/Hierarchies(\'{}\')'.format(
            hierarchy.dimension_name, hierarchy.name)
        response = self._rest.PATCH(request, hierarchy.body)
        # Update Attributes
        self._update_element_attributes(hierarchy=hierarchy)
        return response

    def exists(self, dimension_name, hierarchy_name):
        """

        :param dimension_name: 
        :param hierarchy_name: 
        :return: 
        """
        request = '/api/v1/Dimensions(\'{}\')/Hierarchies(\'{}\')'.format(
            dimension_name, hierarchy_name)
        return super(HierarchyService, self).exists(request)

    def delete(self, dimension_name, hierarchy_name):
        request = '/api/v1/Dimensions(\'{}\')/Hierarchies(\'{}\')'.format(
            dimension_name, hierarchy_name)
        return self._rest.DELETE(request)

    def _update_element_attributes(self, hierarchy):
        """ Update the element sattributes of a hierarchy

        :param hierarchy: Instance of TM1py.Hierarchy
        :return:
        """
        # get existing attributes first.
        element_attributes = self.elements.get_element_attributes(
            dimension_name=hierarchy.dimension_name,
            hierarchy_name=hierarchy.name)
        element_attribute_names = [ea.name for ea in element_attributes]
        # write ElementAttributes that don't already exist !
        for element_attribute in hierarchy.element_attributes:
            if element_attribute not in element_attribute_names:
                self.elements.create_element_attribute(
                    dimension_name=hierarchy.dimension_name,
                    hierarchy_name=hierarchy.name,
                    element_attribute=element_attribute)
        # delete attributes that are determined to be removed
        for element_attribute in element_attribute_names:
            if element_attribute not in hierarchy.element_attributes:
                self.elements.delete_element_attribute(
                    dimension_name=hierarchy.dimension_name,
                    hierarchy_name=hierarchy.name,
                    element_attribute=element_attribute)
Beispiel #3
0
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):
        super().__init__(rest)
        self.subsets = SubsetService(rest)
        self.elements = ElementService(rest)

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

        :param hierarchy:
        :return:
        """
        request = '/api/v1/Dimensions(\'{}\')/Hierarchies'.format(hierarchy.dimension_name)
        response = self._rest.POST(request, hierarchy.body)
        return response

    def get(self, dimension_name, hierarchy_name):
        """ get hierarchy

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

    def update(self, hierarchy):
        """ 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
        request = '/api/v1/Dimensions(\'{}\')/Hierarchies(\'{}\')'.format(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(request, json.dumps(hierarchy_body)))

        # 2. Update Attributes
        responses.append(self._update_element_attributes(hierarchy=hierarchy))

        # 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]
            lines_prolog = ''.join(ti_statements)
            responses.append(process_service.execute_ti_code(lines_prolog=lines_prolog))

        return responses

    def exists(self, dimension_name, hierarchy_name):
        """

        :param dimension_name: 
        :param hierarchy_name: 
        :return: 
        """
        request = '/api/v1/Dimensions(\'{}\')/Hierarchies(\'{}\')'.format(dimension_name, hierarchy_name)
        return self._exists(request)

    def delete(self, dimension_name, hierarchy_name):
        request = '/api/v1/Dimensions(\'{}\')/Hierarchies(\'{}\')'.format(dimension_name, hierarchy_name)
        return self._rest.DELETE(request)

    def get_hierarchy_summary(self, dimension_name, hierarchy_name):
        hierarchy_properties = ("Elements", "Edges", "ElementAttributes", "Members", "Levels")
        request = "/api/v1/Dimensions(\'{}\')/Hierarchies(\'{}\')?$expand=Edges/$count,Elements/$count," \
                  "ElementAttributes/$count,Members/$count,Levels/$count&$select=Cardinality"\
            .format(dimension_name, hierarchy_name)
        hierary_summary_raw = self._rest.GET(request).json()

        return {hierarchy_property: hierary_summary_raw[hierarchy_property + "@odata.count"]
                for hierarchy_property
                in hierarchy_properties}


    def _update_element_attributes(self, hierarchy):
        """ Update the elementattributes of a hierarchy

        :param hierarchy: Instance of TM1py.Hierarchy
        :return:
        """
        # get existing attributes first.
        element_attributes = self.elements.get_element_attributes(dimension_name=hierarchy.dimension_name,
                                                                  hierarchy_name=hierarchy.name)
        element_attribute_names = [ea.name
                                   for ea
                                   in element_attributes]
        # write ElementAttributes that don't already exist !
        for element_attribute in hierarchy.element_attributes:
            if element_attribute not in element_attribute_names:
                self.elements.create_element_attribute(dimension_name=hierarchy.dimension_name,
                                                       hierarchy_name=hierarchy.name,
                                                       element_attribute=element_attribute)
        # delete attributes that are determined to be removed
        for element_attribute in element_attribute_names:
            if element_attribute not in hierarchy.element_attributes:
                self.elements.delete_element_attribute(dimension_name=hierarchy.dimension_name,
                                                       hierarchy_name=hierarchy.name,
                                                       element_attribute=element_attribute)