Search code examples
rdfjenasemantic-webrdfsbag

Get bag (container) that contains a particular RDF resource using Jena


I am have a reference to an object of type com.hp.hpl.jena.rdf.model.Resource that is contained in a Bag. I want to list all the Bags that contain this resource. Is there a function similar to listResourcesWithProperty that can be used to search for the containers. ´

The Bag has no properties added. It only has a collection of resources added using Bag.add(RDFNode o)


Solution

  • This is actually a bit tricky if you don't have inference available because a number of properties are actually used to indicate RDF container membership. E.g., here's a model with three bags, the first and third of which both contain resouces x and y:

    @prefix :      <http://stackoverflow.com/q/23568540/1281433/> .
    @prefix rdf:   <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
    
    :Bag1   a       rdf:Bag ;
            rdf:_1  :x ;
            rdf:_2  :y .
    
    :Bag2   a       rdf:Bag ;
            rdf:_1  :y .
    
    :Bag3   a       rdf:Bag ;
            rdf:_1  :y ;
            rdf:_2  :x .
    

    The problem, of course, is that the properties that the first and third bag to, e.g., the resource x are not the same. However, each of those rdf:_nnn properties is an instance of rdfs:ContainerMembershipProperty. In turn, each rdfs:ContainerMembershipProperty is a superproperty of rdfs:member. This means that if you have a reasoner that can infer that, you can ask what resources have x (or y) as an rdfs:member. It doesn't seem (as shown by the following example) that Jena's RDFS reasoners do this. As such, you might just have to iterate over statements that have x as an object, and check whether the property is a container membership property.

    import org.apache.jena.riot.Lang;
    import org.apache.jena.riot.RDFDataMgr;
    
    import com.hp.hpl.jena.ontology.OntModel;
    import com.hp.hpl.jena.ontology.OntModelSpec;
    import com.hp.hpl.jena.rdf.model.Bag;
    import com.hp.hpl.jena.rdf.model.Model;
    import com.hp.hpl.jena.rdf.model.ModelFactory;
    import com.hp.hpl.jena.rdf.model.ResIterator;
    import com.hp.hpl.jena.rdf.model.Resource;
    import com.hp.hpl.jena.rdf.model.Statement;
    import com.hp.hpl.jena.rdf.model.StmtIterator;
    import com.hp.hpl.jena.vocabulary.RDF;
    import com.hp.hpl.jena.vocabulary.RDFS;
    
    
    public class BagExample {
        public static void main(String[] args) {
            Model model = ModelFactory.createDefaultModel();
            String NS = "http://stackoverflow.com/q/23568540/1281433/";
            model.setNsPrefix( "", NS );
            model.setNsPrefix( "rdf", RDF.getURI() );
    
            Bag bag1 = model.createBag( NS+"Bag1" );
            Bag bag2 = model.createBag( NS+"Bag2" );
            Bag bag3 = model.createBag( NS+"Bag3" );
    
            Resource x = model.createResource( NS+"x" );
            Resource y = model.createResource( NS+"y" );
    
            bag1.add( x ).add( y );
            bag2.add( y );
            bag3.add( y ).add( x );
    
            RDFDataMgr.write( System.out, model, Lang.TURTLE );
    
            System.out.println( "=== Bags with X (no inference) ===" );
            ResIterator bagsWithX = model.listSubjectsWithProperty( RDFS.member, x );
            while ( bagsWithX.hasNext() ) {
                System.out.println( bagsWithX.next() );
            }
    
            System.out.println( "=== Bags with X (RDFS inference) ===" );
            OntModel rdfsModel = ModelFactory.createOntologyModel( OntModelSpec.RDFS_MEM_TRANS_INF, model );
            bagsWithX = rdfsModel.listSubjectsWithProperty( RDFS.member, x );
            while ( bagsWithX.hasNext() ) {
                System.out.println( bagsWithX.next() );
            }
    
    
            System.out.println( "=== Bags with X (manual checking) ===" );
            StmtIterator xStmts = model.listStatements( null, null, x );
            while ( xStmts.hasNext() ) {
                Statement s = xStmts.next();
                // This checks whether the URI begins with rdf:_.  A proper
                // solution would make sure that the suffix is actually numeric.
                        // You might also want to check whether the subject actually is 
                        // a Bag.  It could be a member of other kinds of containers, too.
                if ( s.getPredicate().getURI().startsWith( RDF.getURI()+"_" ) ) {
                    System.out.println( s.getObject() );
                }
            }
        }
    }
    
    === Bags with X (no inference) ===
    === Bags with X (RDFS inference) ===
    === Bags with X (manual checking) ===
    http://stackoverflow.com/q/23568540/1281433/x
    http://stackoverflow.com/q/23568540/1281433/x