def _crawl_related_resources(self, resource_id, resource_types=None, predicate_set=None):
        """
        An internal helper function to generate a unique list of related resources
        @return:
        """
        resource_types = resource_types if resource_types is not None else []
        predicate_set = predicate_set if predicate_set is not None else {}
        r = RelatedResourcesCrawler()
        test_real_fn = r.generate_get_related_resources_fn(self.clients.resource_registry, resource_whitelist=resource_types, predicate_dictionary=predicate_set)
        related_objs = test_real_fn(resource_id)

        unique_ids = []
        for i in related_objs:
            if i.o not in unique_ids: unique_ids.append(i.o)
            if i.s not in unique_ids: unique_ids.append(i.s)

        return unique_ids
    def _crawl_related_resources(self, resource_id, resource_types=None, predicate_set=None):
        """
        An internal helper function to generate a unique list of related resources
        @return:
        """
        resource_types = resource_types if resource_types is not None else []
        predicate_set = predicate_set if predicate_set is not None else {}
        r = RelatedResourcesCrawler()
        test_real_fn = r.generate_get_related_resources_fn(self.clients.resource_registry, resource_whitelist=resource_types, predicate_dictionary=predicate_set)
        related_objs = test_real_fn(resource_id)

        unique_ids = []
        for i in related_objs:
            if i.o not in unique_ids: unique_ids.append(i.o)
            if i.s not in unique_ids: unique_ids.append(i.s)

        return unique_ids
    def test_related_resource_crawler(self):
        """

        """
        self.create_dummy_structure()

        r = RelatedResourcesCrawler()

        # test the basic forward-backward searches
        for (st, p, ot) in self.expected_associations:
            rst = self.realtype[st]
            rot = self.realtype[ot]
            s = self.care[st]
            o = self.care[ot]

            test_sto_fn = r.generate_get_related_resources_fn(self.RR, [rot], {p: (True, False)})
            sto_crawl = test_sto_fn(s, 1) # depth of 1
            if 2 < len(sto_crawl): # we get 2 because of care/dontcare
                self.fail("got %s" % self.describe_assn_graph(self.simplify_assn_resource_ids(sto_crawl)))

            self.assertIn(o, [t.o for t in sto_crawl])

            test_ots_fn = r.generate_get_related_resources_fn(self.RR, [rst], {p: (False, True)})
            ots_crawl = test_ots_fn(o, 1) # depth of 1
            if 1 != len(ots_crawl):
                self.fail("got %s" % self.describe_assn_graph(self.simplify_assn_resource_ids(ots_crawl)))


        # test a nontrivial lookup, in which we extract resources related to an instrument device
        rw = []
        pd = {}

        # we want things related to an instrument device
        rw.append(RT.PlatformModel)
        rw.append(RT.InstrumentModel)
        rw.append(RT.PlatformDevice)
        rw.append(RT.InstrumentSite)
        rw.append(RT.PlatformSite)
        rw.append(RT.Subsite)
        rw.append(RT.Observatory)
        rw.append(RT.InstrumentDevice)
        pd[PRED.hasModel] = (True, True)
        pd[PRED.hasDevice] = (False, True)
        pd[PRED.hasSite] = (False, True)

        test_real_fn = r.generate_get_related_resources_fn(self.RR, resource_whitelist=rw, predicate_dictionary=pd)
        related = test_real_fn(self.care[RT.InstrumentDevice])

        log.debug("========= Result is:")
        for l in self.describe_assn_graph(self.simplify_assn_resource_ids(related)):
            log.debug("    %s", l)

        # check that we only got things we care about
        for a in related:
            # special case for platform model, because we don't care about the top-level platform's model
            #  so it will blow up if we don't ignore it.  if we got an extra platform model, we'd have an
            #  extra platform anyway... so this special case is safe.
            if a.st != RT.PlatformModel:
                self.assertIn(a.s, self.care.values(), "%s %s not cared about" % (a.st, a.s))

            if a.ot != RT.PlatformModel:
                self.assertIn(a.o, self.care.values(), "%s %s not cared about" % (a.ot, a.o))
    def test_related_resource_crawler(self):
        """

        """
        self.create_dummy_structure()

        r = RelatedResourcesCrawler()

        # test the basic forward-backward searches
        for (st, p, ot) in self.expected_associations:
            rst = self.realtype[st]
            rot = self.realtype[ot]
            s = self.care[st]
            o = self.care[ot]

            test_sto_fn = r.generate_get_related_resources_fn(
                self.RR, [rot], {p: (True, False)})
            sto_crawl = test_sto_fn(s, 1)  # depth of 1
            if 2 < len(sto_crawl):  # we get 2 because of care/dontcare
                self.fail("got %s" % self.describe_assn_graph(
                    self.simplify_assn_resource_ids(sto_crawl)))

            self.assertIn(o, [t.o for t in sto_crawl])

            test_ots_fn = r.generate_get_related_resources_fn(
                self.RR, [rst], {p: (False, True)})
            ots_crawl = test_ots_fn(o, 1)  # depth of 1
            if 1 != len(ots_crawl):
                self.fail("got %s" % self.describe_assn_graph(
                    self.simplify_assn_resource_ids(ots_crawl)))

        # test a nontrivial lookup, in which we extract resources related to an instrument device
        rw = []
        pd = {}

        # we want things related to an instrument device
        rw.append(RT.PlatformModel)
        rw.append(RT.InstrumentModel)
        rw.append(RT.PlatformDevice)
        rw.append(RT.InstrumentSite)
        rw.append(RT.PlatformSite)
        rw.append(RT.Subsite)
        rw.append(RT.Observatory)
        rw.append(RT.InstrumentDevice)
        pd[PRED.hasModel] = (True, True)
        pd[PRED.hasDevice] = (False, True)
        pd[PRED.hasSite] = (False, True)

        test_real_fn = r.generate_get_related_resources_fn(
            self.RR, resource_whitelist=rw, predicate_dictionary=pd)
        related = test_real_fn(self.care[RT.InstrumentDevice])

        log.debug("========= Result is:")
        for l in self.describe_assn_graph(
                self.simplify_assn_resource_ids(related)):
            log.debug("    %s", l)

        # check that we only got things we care about
        for a in related:
            # special case for platform model, because we don't care about the top-level platform's model
            #  so it will blow up if we don't ignore it.  if we got an extra platform model, we'd have an
            #  extra platform anyway... so this special case is safe.
            if a.st != RT.PlatformModel:
                self.assertIn(a.s, self.care.values(),
                              "%s %s not cared about" % (a.st, a.s))

            if a.ot != RT.PlatformModel:
                self.assertIn(a.o, self.care.values(),
                              "%s %s not cared about" % (a.ot, a.o))