<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def _construct_filter_value(self, candidate, data):
 """ Construct and return a LDAP directory search filter value from the candidate identifier. Argument 'canidate' is a dictionary with one required key and two optional keys: key required value attribute_names Y list of identifier names name_id_format N NameID format (string) add_scope N "issuer_entityid" or other string Argument 'data' is that object passed into the microservice method process(). If the attribute_names list consists of more than one identifier name then the values of the identifiers will be concatenated together to create the filter value. If one of the identifier names in the attribute_names is the string 'name_id' then the NameID value with format name_id_format will be concatenated to the filter value. If the add_scope key is present with value 'issuer_entityid' then the entityID for the IdP will be concatenated to "scope" the value. If the string is any other value it will be directly concatenated. """

        context = self.context

        attributes = data.attributes
        satosa_logging(logger, logging.DEBUG, "Input attributes {}".format(attributes), context.state)

        # Get the values configured list of identifier names for this candidate
        # and substitute None if there are no values for a configured identifier.
        values = []
        for identifier_name in candidate['attribute_names']:
            v = attributes.get(identifier_name, None)
            if isinstance(v, list):
                v = v[0]
            values.append(v)
        satosa_logging(logger, logging.DEBUG, "Found candidate values {}".format(values), context.state)

        # If one of the configured identifier names is name_id then if there is also a configured
        # name_id_format add the value for the NameID of that format if it was asserted by the IdP
        # or else add the value None.
        if 'name_id' in candidate['attribute_names']:
            candidate_nameid_value = None
            candidate_name_id_format = candidate.get('name_id_format')
            name_id_value = data.subject_id
            name_id_format = data.subject_type
            if (
                name_id_value
                and candidate_name_id_format
                and candidate_name_id_format == name_id_format
            ):
                satosa_logging(logger, logging.DEBUG, "IdP asserted NameID {}".format(name_id_value), context.state)
                candidate_nameid_value = name_id_value

            # Only add the NameID value asserted by the IdP if it is not already
            # in the list of values. This is necessary because some non-compliant IdPs
            # have been known, for example, to assert the value of eduPersonPrincipalName
            # in the value for SAML2 persistent NameID as well as asserting
            # eduPersonPrincipalName.
            if candidate_nameid_value not in values:
                satosa_logging(logger, logging.DEBUG, "Added NameID {} to candidate values".format(candidate_nameid_value), context.state)
                values.append(candidate_nameid_value)
            else:
                satosa_logging(logger, logging.WARN, "NameID {} value also asserted as attribute value".format(candidate_nameid_value), context.state)

        # If no value was asserted by the IdP for one of the configured list of identifier names
        # for this candidate then go onto the next candidate.
        if None in values:
            satosa_logging(logger, logging.DEBUG, "Candidate is missing value so skipping", context.state)
            return None

        # All values for the configured list of attribute names are present
        # so we can create a value. Add a scope if configured
        # to do so.
        if 'add_scope' in candidate:
            if candidate['add_scope'] == 'issuer_entityid':
                scope = data.auth_info.issuer
            else:
                scope = candidate['add_scope']
            satosa_logging(logger, logging.DEBUG, "Added scope {} to values".format(scope), context.state)
            values.append(scope)

        # Concatenate all values to create the filter value.
        value = ''.join(values)

        satosa_logging(logger, logging.DEBUG, "Constructed filter value {}".format(value), context.state)

        return value