private List<Agent> getAgents(URI base, Individual in, ObjectProperty property) {
    List<Agent> creators = new ArrayList<>();
    for (Individual agent : listObjectProperties(in, property)) {
      Agent a = new Agent();
      if (agent.getURI() != null) a.setUri(relativizeFromBase(agent.getURI(), base));

      RDFNode name = agent.getPropertyValue(foafName);
      if (name != null && name.isLiteral()) a.setName(name.asLiteral().getLexicalForm());
      creators.add(a);
    }
    return creators;
  }
  public static void main(String args[]) {
    String filename = "example5.rdf";

    // Create an empty model
    OntModel model = ModelFactory.createOntologyModel(OntModelSpec.RDFS_MEM);

    // Use the FileManager to find the input file
    InputStream in = FileManager.get().open(filename);

    if (in == null) throw new IllegalArgumentException("File: " + filename + " not found");

    // Read the RDF/XML file
    model.read(in, null);

    // Create a new class named "Researcher"
    OntClass researcher = model.createClass(ns + "Researcher");

    // ** TASK 6.1: Create a new class named "University" **
    OntClass university = model.createClass(ns + "University");

    // ** TASK 6.2: Add "Researcher" as a subclass of "Person" **
    model.getOntClass(ns + "Person").addSubClass(researcher);

    // ** TASK 6.3: Create a new property named "worksIn" **
    Property worksIn = model.createProperty(ns + "worksIn");

    // ** TASK 6.4: Create a new individual of Researcher named "Jane Smith" **
    Individual jane = researcher.createIndividual(ns + "JaneSmith");

    // ** TASK 6.5: Add to the individual JaneSmith the fullName, given and family names **
    jane.addProperty(VCARD.FN, "Jane Smith");
    jane.addProperty(VCARD.Given, "Jane");
    jane.addProperty(VCARD.Family, "Smith");

    // ** TASK 6.6: Add UPM as the university where John Smith works **
    Individual john = model.getIndividual(ns + "JohnSmith");
    Individual upm = university.createIndividual(ns + "UPM");
    john.addProperty(worksIn, upm);

    model.write(System.out, "RDF/XML-ABBREV");
  }
  public void readTo(
      InputStream manifestResourceAsStream, Manifest manifest, URI manifestResourceBaseURI)
      throws IOException, RiotException {
    OntModel model = new RDFToManifest().getOntModel();
    model.add(jsonLdAsJenaModel(manifestResourceAsStream, manifestResourceBaseURI));

    // model.write(System.out, "TURTLE");
    // System.out.println();

    URI root = manifestResourceBaseURI.resolve("/");
    Individual ro = findRO(model, root);
    if (ro == null)
      throw new IOException("root ResearchObject not found - " + "Not a valid RO Bundle manifest");

    for (Individual manifestResource : listObjectProperties(ro, isDescribedBy)) {
      String uriStr = manifestResource.getURI();
      if (uriStr == null) {
        logger.warning("Skipping manifest without URI: " + manifestResource);
        continue;
      }
      // URI relative = relativizeFromBase(uriStr, root);
      Path path = manifest.getBundle().getFileSystem().provider().getPath(URI.create(uriStr));
      manifest.getManifest().add(path);
    }

    List<Agent> creators = getAgents(root, ro, createdBy);
    if (!creators.isEmpty()) {
      manifest.setCreatedBy(creators.get(0));
      if (creators.size() > 1) logger.warning("Ignoring additional createdBy agents");
    }

    RDFNode created = ro.getPropertyValue(createdOn);
    manifest.setCreatedOn(literalAsFileTime(created));

    List<Path> history = new ArrayList<Path>();
    for (Individual histItem : listObjectProperties(ro, hasProvenance))
      history.add(
          Bundles.uriToBundlePath(
              manifest.getBundle(), relativizeFromBase(histItem.getURI(), root)));
    manifest.setHistory(history);

    List<Agent> authors = getAgents(root, ro, authoredBy);
    if (!authors.isEmpty()) manifest.setAuthoredBy(authors);
    RDFNode authored = ro.getPropertyValue(authoredOn);
    manifest.setAuthoredOn(literalAsFileTime(authored));

    for (Individual aggrResource : listObjectProperties(ro, aggregates)) {
      String uriStr = aggrResource.getURI();
      // PathMetadata meta = new PathMetadata();
      if (uriStr == null) {
        logger.warning("Skipping aggregation without URI: " + aggrResource);
        continue;
      }

      PathMetadata meta = manifest.getAggregation(relativizeFromBase(uriStr, root));

      Set<Individual> proxies = listObjectProperties(aggrResource, hasProxy);
      if (!proxies.isEmpty()) {
        // We can only deal with the first one
        Individual proxy = proxies.iterator().next();

        String proxyUri = null;
        if (proxy.getURI() != null) proxyUri = proxy.getURI();
        else if (proxy.getSameAs() != null) proxyUri = proxy.getSameAs().getURI();
        if (proxyUri != null) setPathProxy(meta, relativizeFromBase(proxyUri, root));
      }

      creators = getAgents(root, aggrResource, createdBy);
      if (!creators.isEmpty()) {
        meta.setCreatedBy(creators.get(0));
        if (creators.size() > 1) logger.warning("Ignoring additional createdBy agents for " + meta);
      }
      meta.setCreatedOn(literalAsFileTime(aggrResource.getPropertyValue(createdOn)));

      for (Individual standard : listObjectProperties(aggrResource, conformsTo))
        if (standard.getURI() != null)
          meta.setConformsTo(relativizeFromBase(standard.getURI(), root));

      RDFNode mediaType = aggrResource.getPropertyValue(format);
      if (mediaType != null && mediaType.isLiteral())
        meta.setMediatype(mediaType.asLiteral().getLexicalForm());
    }

    for (Individual ann : listObjectProperties(ro, hasAnnotation)) {
      /*
       * Normally just one body per annotation, but just in case we'll
       * iterate and split them out (as our PathAnnotation can only keep a
       * single setContent() at a time)
       */
      for (Individual body : listObjectProperties(model.getOntResource(ann), hasBody)) {
        if (body.getURI() == null) {
          logger.warning("Can't find annotation body for anonymous " + body);
          continue;
        }
        PathAnnotation pathAnn = new PathAnnotation();
        pathAnn.setContent(relativizeFromBase(body.getURI(), root));

        if (ann.getURI() != null) pathAnn.setUri(relativizeFromBase(ann.getURI(), root));
        else if (ann.getSameAs() != null && ann.getSameAs().getURI() != null)
          pathAnn.setUri(relativizeFromBase(ann.getSameAs().getURI(), root));

        // Handle multiple about/hasTarget
        for (Individual target : listObjectProperties(ann, hasTarget))
          if (target.getURI() != null)
            pathAnn.getAboutList().add(relativizeFromBase(target.getURI(), root));
        manifest.getAnnotations().add(pathAnn);
      }
    }
  }