Commit ee492960 authored by acoburn's avatar acoburn
Browse files

add ore service

parent 37ed67fa
Repository ORE Object Handler
==============================
This module makes it easier to work with ORE resources.
It uses simple OWL inference to handle inverse properties.
Building
--------
To build this project use
gradle install
Deploying in OSGi
-----------------
Each of these projects can be deployed in an OSGi container. For example using
[Apache Karaf](http://karaf.apache.org) version 4.x and above, you can run the following
command from its shell:
feature:repo-add mvn:edu.amherst.acdc/acrepo-karaf/LATEST/xml/features
feature:install acrepo-services-ore
apply plugin: 'osgi'
description = 'ORE Object Bundle'
dependencies {
compile group: 'org.apache.jena', name: 'jena-osgi', version: jenaVersion
testCompile group: 'junit', name: 'junit', version: junitVersion
testCompile group: 'xerces', name: 'xercesImpl', version: xercesVersion
testCompile group: 'ch.qos.logback', name: 'logback-classic', version: logbackVersion
}
jar {
manifest {
description project.description
docURL project.docURL
vendor project.vendor
license project.license
instruction 'Import-Package', defaultOsgiImports
instruction 'Export-Package', "edu.amherst.acdc.services.ore;version=${projectOsgiVersion}"
}
}
/*
* Copyright 2016 Amherst College
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package edu.amherst.acdc.services.ore;
import java.io.InputStream;
import java.util.Set;
import org.apache.jena.rdf.model.Model;
/**
* @author acoburn
* @since 3/15/17
*/
public interface OreService {
/**
* Parse an InputStream into an existing model
*
* @param model the existing model or null for a new model
* @param input the input RDF graph
* @param contentType the mimeType of the input
* @return the RDF Model
*/
Model parseInto(final Model model, final InputStream input, final String contentType);
/**
* Get the object values for the ore:isAggregatedBy triples
*
* @param model The model
* @param subject the subject
* @return a set of object values
*/
Set<String> aggregatedBy(final Model model, final String subject);
/**
* Get the object values for the ore:aggregates triples
*
* @param model The model
* @param subject the subject
* @return a set of object values
*/
Set<String> aggregates(final Model model, final String subject);
/**
* Serialize this model as an InputStream
*
* @param model the model
* @param contentType the contentType
* @return the RDF serialization
*/
InputStream serialize(final Model model, final String contentType);
}
/*
* Copyright 2016 Amherst College
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package edu.amherst.acdc.services.ore;
import static java.util.Optional.ofNullable;
import static java.util.stream.Collectors.toSet;
import static org.apache.jena.atlas.iterator.Iter.asStream;
import static org.apache.jena.rdf.model.ModelFactory.createDefaultModel;
import static org.apache.jena.rdf.model.ModelFactory.createInfModel;
import static org.apache.jena.rdf.model.ResourceFactory.createProperty;
import static org.apache.jena.rdf.model.ResourceFactory.createResource;
import static org.apache.jena.reasoner.ReasonerRegistry.getOWLMicroReasoner;
import static org.slf4j.LoggerFactory.getLogger;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.Optional;
import java.util.Set;
import org.apache.jena.rdf.model.InfModel;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.RDFNode;
import org.apache.jena.rdf.model.Resource;
import org.apache.jena.riot.Lang;
import org.apache.jena.riot.RDFLanguages;
import org.slf4j.Logger;
/**
* @author acoburn
* @since 6/16/16
*/
public class OreServiceImpl implements OreService {
private static final Logger LOGGER = getLogger(OreServiceImpl.class);
private static final String ORE_NAMESPACE = "http://www.openarchives.org/ore/terms/";
private static final String DEFAULT_LANG = "TTL";
private final Model oreModel = createDefaultModel();
/**
* Create a ORE Service object
*/
public OreServiceImpl() {
oreModel.read(getClass().getResourceAsStream("/ore.rdf"), null, "RDF/XML");
}
@Override
public Model parseInto(final Model model, final InputStream input, final String contentType) {
if (model == null) {
return parseInto(createDefaultModel(), input, contentType);
}
LOGGER.debug("Parsing data into model");
model.read(input, null, getRdfLanguage(contentType).orElse(DEFAULT_LANG));
return model;
}
@Override
public Set<String> aggregatedBy(final Model model, final String subject) {
return getObjectsOfProperty(model, subject, ORE_NAMESPACE + "isAggregatedBy");
}
@Override
public Set<String> aggregates(final Model model, final String subject) {
return getObjectsOfProperty(model, subject, ORE_NAMESPACE + "aggregates");
}
@Override
public InputStream serialize(final Model model, final String contentType) {
final ByteArrayOutputStream os = new ByteArrayOutputStream();
model.write(os, getRdfLanguage(contentType).orElse(DEFAULT_LANG));
LOGGER.debug("Writing model as InputStream");
return new ByteArrayInputStream(os.toByteArray());
}
private Optional<String> getRdfLanguage(final String contentType) {
return ofNullable(contentType).map(RDFLanguages::contentTypeToLang).map(Lang::getName);
}
private Set<String> getObjectsOfProperty(final Model model, final String subject, final String property) {
final InfModel infModel = createInfModel(getOWLMicroReasoner(), createDefaultModel());
infModel.add(model.listStatements());
infModel.add(oreModel.listStatements());
return asStream(infModel.listObjectsOfProperty(createResource(subject), createProperty(property)))
.filter(RDFNode::isURIResource).map(RDFNode::asResource).map(Resource::getURI).collect(toSet());
}
}
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd"
default-activation="lazy">
<bean id="oreServiceBean" class="edu.amherst.acdc.services.ore.OreServiceImpl"/>
<service ref="oreServiceBean" interface="edu.amherst.acdc.services.ore.OreService">
<service-properties>
<entry key="osgi.jndi.service.name" value="acrepo/Ore"/>
</service-properties>
</service>
</blueprint>
<?xml version="1.0" encoding="UTF-8"?>
<!-- OAI-ORE terms vocabulary
See http://www.openarchives.org/ore/1.0/vocabulary for description
This work is licensed under a Creative Commons
Attribution-Noncommercial-Share Alike 3.0 Unported License.
http://creativecommons.org/licenses/by-sa/3.0/
-->
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
xmlns:owl="http://www.w3.org/2002/07/owl#"
xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:dcterms="http://purl.org/dc/terms/"
xmlns:dctype="http://purl.org/dc/dcmitype/"
xmlns:rdfg="http://www.w3.org/2004/03/trix/rdfg-1/"
xmlns:ore="http://www.openarchives.org/ore/terms/">
<rdf:Description rdf:about="http://www.openarchives.org/ore/terms/">
<dcterms:title>The OAI ORE terms vocabulary</dcterms:title>
<rdfs:label>The OAI ORE terms vocabulary</rdfs:label>
<rdfs:comment>The set of terms provided by the OAI ORE initiative</rdfs:comment>
<dcterms:publisher rdf:parseType="Resource"><rdfs:label>The Open Archives Initiative ORE Project</rdfs:label></dcterms:publisher>
<dcterms:license rdf:resource="http://creativecommons.org/licenses/by-sa/3.0/" />
<rdfs:seeAlso rdf:resource="http://www.openarchives.org/ore/toc" />
</rdf:Description>
<rdfs:Class rdf:about="http://www.openarchives.org/ore/terms/Aggregation">
<rdfs:label>Aggregation</rdfs:label>
<rdfs:comment>A set of related resources (Aggregated Resources), grouped together such that the set can be treated as a single resource. This is the entity described within the ORE interoperability framework by a Resource Map.</rdfs:comment>
<rdfs:subClassOf rdf:resource="http://purl.org/dc/dcmitype/Collection" />
<rdfs:isDefinedBy rdf:resource="http://www.openarchives.org/ore/terms/"/>
</rdfs:Class>
<rdfs:Class rdf:about="http://www.openarchives.org/ore/terms/AggregatedResource">
<rdfs:label>Aggregated Resource</rdfs:label>
<rdfs:comment>A resource which is included in an Aggregation. Note that asserting that a resource is a member of the class of Aggregated Resources does not imply anything other than that it is aggregated by at least one Aggregation.</rdfs:comment>
<rdfs:isDefinedBy rdf:resource="http://www.openarchives.org/ore/terms/"/>
</rdfs:Class>
<rdfs:Class rdf:about="http://www.openarchives.org/ore/terms/Proxy">
<rdfs:label>Proxy</rdfs:label>
<rdfs:comment>A Proxy represents an Aggregated Resource as it exists in a specific Aggregation. All assertions made about an entity are globally true, not only within the context of the Aggregation. As such, in order to make assertions which are only true of a resource as it exists in an Aggregation, a Proxy object is required. For example, one might want to cite an article as it appears in a specific journal, or assign aggregation-specific metadata to a Resource.</rdfs:comment>
<rdfs:isDefinedBy rdf:resource="http://www.openarchives.org/ore/terms/"/>
</rdfs:Class>
<rdfs:Class rdf:about="http://www.openarchives.org/ore/terms/ResourceMap">
<rdfs:label>Resource Map</rdfs:label>
<rdfs:comment>A description of an Aggregation according to the OAI-ORE data model. Resource Maps are serialised to a machine readable format according to the implementation guidelines.</rdfs:comment>
<rdfs:subClassOf rdf:resource="http://www.w3.org/2004/03/trix/rdfg-1/Graph" />
<rdfs:isDefinedBy rdf:resource="http://www.openarchives.org/ore/terms/"/>
</rdfs:Class>
<rdf:Property rdf:about="http://www.openarchives.org/ore/terms/aggregates">
<rdfs:label>Aggregates</rdfs:label>
<rdfs:comment>Aggregations, by definition, aggregate resources. The ore:aggregates relationship expresses that the object resource is a member of the set of Aggregated Resources of the subject (the Aggregation). This relationship between the Aggregation and its Aggregated Resources is thus more specific than a simple part/whole relationship, as expressed by dcterms:hasPart for example.</rdfs:comment>
<rdfs:subPropertyOf rdf:resource="http://purl.org/dc/terms/hasPart" />
<rdfs:domain rdf:resource="http://www.openarchives.org/ore/terms/Aggregation" />
<rdfs:range rdf:resource="http://www.openarchives.org/ore/terms/AggregatedResource" />
<owl:inverseOf rdf:resource="http://www.openarchives.org/ore/terms/isAggregatedBy" />
<rdfs:isDefinedBy rdf:resource="http://www.openarchives.org/ore/terms/"/>
</rdf:Property>
<rdf:Property rdf:about="http://www.openarchives.org/ore/terms/isAggregatedBy">
<rdfs:label>Is Aggregated By</rdfs:label>
<rdfs:comment>The inverse relationship of ore:aggregates, ore:isAggregatedBy asserts that an Aggregated Resource is aggregated by an Aggregation.</rdfs:comment>
<rdfs:subPropertyOf rdf:resource="http://purl.org/dc/terms/isPartOf" />
<rdfs:domain rdf:resource="http://www.openarchives.org/ore/terms/AggregatedResource" />
<rdfs:range rdf:resource="http://www.openarchives.org/ore/terms/Aggregation" />
<owl:inverseOf rdf:resource="http://www.openarchives.org/ore/terms/aggregates" />
<rdfs:isDefinedBy rdf:resource="http://www.openarchives.org/ore/terms/"/>
</rdf:Property>
<rdf:Property rdf:about="http://www.openarchives.org/ore/terms/describes">
<rdfs:label>Describes</rdfs:label>
<rdfs:comment>This relationship asserts that the subject (a Resource Map) describes the object (an Aggregation).</rdfs:comment>
<rdfs:domain rdf:resource="http://www.openarchives.org/ore/terms/ResourceMap" />
<rdfs:range rdf:resource="http://www.openarchives.org/ore/terms/Aggregation" />
<owl:inverseOf rdf:resource="http://www.openarchives.org/ore/terms/isDescribedBy" />
<rdfs:isDefinedBy rdf:resource="http://www.openarchives.org/ore/terms/"/>
</rdf:Property>
<rdf:Property rdf:about="http://www.openarchives.org/ore/terms/isDescribedBy">
<rdfs:label>Is Described By</rdfs:label>
<rdfs:comment>The inverse relationship of ore:describes, in this case the object of the relationship is the Resource Map and the subject is the Aggregation which it describes.</rdfs:comment>
<rdfs:domain rdf:resource="http://www.openarchives.org/ore/terms/Aggregation" />
<rdfs:range rdf:resource="http://www.openarchives.org/ore/terms/ResourceMap" />
<owl:inverseOf rdf:resource="http://www.openarchives.org/ore/terms/describes" />
<rdfs:isDefinedBy rdf:resource="http://www.openarchives.org/ore/terms/"/>
</rdf:Property>
<rdf:Property rdf:about="http://www.openarchives.org/ore/terms/lineage">
<rdfs:label>Lineage</rdfs:label>
<rdfs:comment>ore:lineage is a relationship between two Proxy objects, both of which MUST have the same Resource for which they are proxies. The meaning is that the Resource for which the subject of the relationship is a Proxy was discovered in the Aggregation in which the object Proxy's resource is aggregated.</rdfs:comment>
<rdfs:domain rdf:resource="http://www.openarchives.org/ore/terms/Proxy" />
<rdfs:range rdf:resource="http://www.openarchives.org/ore/terms/Proxy" />
<rdfs:isDefinedBy rdf:resource="http://www.openarchives.org/ore/terms/"/>
</rdf:Property>
<rdf:Property rdf:about="http://www.openarchives.org/ore/terms/proxyFor">
<rdfs:label>Proxy For</rdfs:label>
<rdfs:comment>Proxy objects are used to represent a Resource as it is aggregated in a particular Aggregation. The ore:proxyFor relationship is used to link the proxy to the Aggregated Resource it is a proxy for. The subject of the relationship is a Proxy object, and the object of the relationship is the Aggregated Resource.</rdfs:comment>
<rdfs:domain rdf:resource="http://www.openarchives.org/ore/terms/Proxy" />
<rdfs:range rdf:resource="http://www.openarchives.org/ore/terms/AggregatedResource" />
<rdfs:isDefinedBy rdf:resource="http://www.openarchives.org/ore/terms/"/>
</rdf:Property>
<rdf:Property rdf:about="http://www.openarchives.org/ore/terms/proxyIn">
<rdfs:label>Proxy In</rdfs:label>
<rdfs:comment>Proxy objects must link to the Aggregation in which the resource being proxied is aggregated. The ore:proxyIn relationship is used for this purpose. The subject of the relationship is a Proxy object, and the object of the relationship is the Aggregation.</rdfs:comment>
<rdfs:domain rdf:resource="http://www.openarchives.org/ore/terms/Proxy" />
<rdfs:range rdf:resource="http://www.openarchives.org/ore/terms/Aggregation" />
<rdfs:isDefinedBy rdf:resource="http://www.openarchives.org/ore/terms/"/>
</rdf:Property>
<rdf:Property rdf:about="http://www.openarchives.org/ore/terms/similarTo">
<rdfs:label>Similar To</rdfs:label>
<rdfs:comment>The subject of this relationship MUST be an Aggregation. This Aggregation should be considered an expression within the ORE context of the object of the relationship, as it is broadly equivalent to the resource. For example, the Aggregation may consist of the resources which, together, make up a journal article which has a DOI assigned to it. The Aggregation is not the article to which the DOI was assigned, but is a representation of it in some manner.</rdfs:comment>
<rdfs:domain rdf:resource="http://www.openarchives.org/ore/terms/Aggregation" />
<rdfs:isDefinedBy rdf:resource="http://www.openarchives.org/ore/terms/"/>
</rdf:Property>
</rdf:RDF>
/*
* Copyright 2016 Amherst College
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package edu.amherst.acdc.services.ore;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.Collections.emptyList;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.StringJoiner;
import org.apache.jena.rdf.model.Model;
import org.junit.Test;
/**
* @author acoburn
* @since 9/14/15
*/
public class OreServiceTest {
private final OreService svc = new OreServiceImpl();
private static InputStream getOreFile(final String uri) {
final String triples = "@prefix premis: <http://www.loc.gov/premis/rdf/v1#> .\n" +
"@prefix ore: <http://www.openarchives.org/ore/terms/> .\n" +
"@prefix ebucore: <http://www.ebu.ch/metadata/ontologies/ebucore/ebucore#> .\n" +
"@prefix fedora: <http://fedora.info/definitions/v4/repository#> .\n" +
"@prefix ldp: <http://www.w3.org/ns/ldp#> .\n" +
"@prefix iana: <http://www.iana.org/assignments/relation/> .\n" +
"<" + uri + "> a ldp:NonRDFSource ;\n" +
"premis:hasSize \"1565421\"^^<http://www.w3.org/2001/XMLSchema#long> ;\n" +
"premis:hasMessageDigest <urn:sha1:c9790c378f3589bfcfe092f834d212685f44fff9> ;\n" +
"ebucore:hasMimeType \"image/jpeg\" ;\n" +
"ebucore:filename \"image.jpg\" ;\n" +
"iana:describedby <" + uri + "/fcr:metadata> ;\n" +
"fedora:createdBy \"bypassAdmin\" ;\n" +
"fedora:created \"2016-06-28T00:21:22.621Z\"^^<http://www.w3.org/2001/XMLSchema#dateTime> ;\n" +
"fedora:lastModified \"2016-06-28T00:21:22.621Z\"^^<http://www.w3.org/2001/XMLSchema#dateTime> ;\n" +
"fedora:lastModifiedBy \"bypassAdmin\" ;\n" +
"fedora:writable \"true\"^^<http://www.w3.org/2001/XMLSchema#boolean> ;\n" +
"fedora:hasParent <http://localhost:8080/fcrepo/rest/> ;\n" +
"fedora:numberOfChildren \"0\"^^<http://www.w3.org/2001/XMLSchema#long> ;\n" +
"fedora:hasFixityService <" + uri + "/fcr:fixity> .";
return new ByteArrayInputStream(triples.getBytes(UTF_8));
}
private static InputStream getOreObject(final String uri, final List<String> members, final List<String> files) {
final StringJoiner joiner = new StringJoiner("",
"@prefix ore: <http://www.openarchives.org/ore/terms/> .\n" +
"@prefix fedora: <http://fedora.info/definitions/v4/repository#> .\n" +
"@prefix ldp: <http://www.w3.org/ns/ldp#> .\n" +
"<" + uri + "> a ldp:RDFSource , ldp:Container ;\n" +
"fedora:lastModifiedBy \"bypassAdmin\" ;\n" +
"fedora:createdBy \"bypassAdmin\" ;\n" +
"fedora:created \"2016-06-28T00:14:06.677Z\"^^<http://www.w3.org/2001/XMLSchema#dateTime> ;\n" +
"fedora:lastModified \"2016-06-28T00:16:25.55Z\"^^<http://www.w3.org/2001/XMLSchema#dateTime> ;\n" +
"fedora:writable \"true\"^^<http://www.w3.org/2001/XMLSchema#boolean> ;\n" +
"fedora:hasParent <http://localhost:8080/fcrepo/rest/> ;\n" +
"fedora:numberOfChildren \"2\"^^<http://www.w3.org/2001/XMLSchema#long> ;\n",
"ldp:contains <" + uri + "/files> , <" + uri + "/members> .\n");
members.forEach(member -> {
joiner.add("ore:aggregates <" + uri + "/members/" + member + "> ;\n");
});
files.forEach(file -> {
joiner.add("ore:aggregates <" + uri + "/files/" + file + "> ;\n");
});
return new ByteArrayInputStream(joiner.toString().getBytes(UTF_8));
}
private static InputStream getOreCollection(final String uri, final List<String> members) {
final StringJoiner joiner = new StringJoiner("",
"@prefix ore: <http://www.openarchives.org/ore/terms/> .\n" +
"@prefix fedora: <http://fedora.info/definitions/v4/repository#> .\n" +
"@prefix ldp: <http://www.w3.org/ns/ldp#> .\n" +
"<" + uri + "> a ldp:RDFSource , ldp:Container ;\n" +
"fedora:lastModifiedBy \"bypassAdmin\" ;\n" +
"fedora:createdBy \"bypassAdmin\" ;\n" +
"fedora:created \"2016-06-28T00:14:06.677Z\"^^<http://www.w3.org/2001/XMLSchema#dateTime> ;\n" +
"fedora:lastModified \"2016-06-28T00:16:25.55Z\"^^<http://www.w3.org/2001/XMLSchema#dateTime> ;\n" +
"fedora:writable \"true\"^^<http://www.w3.org/2001/XMLSchema#boolean> ;\n" +
"fedora:hasParent <http://localhost:8080/fcrepo/rest/> ;\n" +
"fedora:numberOfChildren \"1\"^^<http://www.w3.org/2001/XMLSchema#long> ;\n",
"ldp:contains <" + uri + "/members> .\n");
members.forEach(member -> {
joiner.add("ore:aggregates <" + uri + "/members/" + member + "> ;\n");
});
return new ByteArrayInputStream(joiner.toString().getBytes(UTF_8));
}
@Test
public void testParseFile() {
final String uri = "http://localhost:8080/fcrepo/rest/ore/file";
final Model m = svc.parseInto(null, getOreFile(uri), "text/turtle");
assertNotNull(m);
assertEquals(0, svc.aggregatedBy(m, uri).size());
assertEquals(0, svc.aggregates(m, uri).size());
assertNotNull(svc.serialize(m, "text/turtle"));
}
@Test
public void testParseObject() {
final String uri = "http://localhost:8080/fcrepo/rest/ore/object";
final List<String> members = new ArrayList<>();
members.add("page1");
members.add("page2");
members.add("page3");
final List<String> files = new ArrayList<>();
files.add("file1");
files.add("file2");
files.add("file3");
final Model m = svc.parseInto(null, getOreObject(uri, members, files), "text/turtle");
assertNotNull(m);
assertEquals(0, svc.aggregatedBy(m, uri).size(), 0);
assertEquals(members.size() + files.size(), svc.aggregates(m, uri).size());
assertNotNull(svc.serialize(m, "text/turtle"));
// test inference
members.forEach(member -> {
assertEquals(1, svc.aggregatedBy(m, uri + "/members/" + member).size());
svc.aggregatedBy(m, uri + "/members/" + member).forEach(parent -> {
assertEquals(uri, parent);
});
});
files.forEach(file -> {
assertEquals(1, svc.aggregatedBy(m, uri + "/files/" + file).size());
svc.aggregatedBy(m, uri + "/files/" + file).forEach(parent -> {
assertEquals(uri, parent);
});
});
}
@Test
public void testParseCollection() {
final String uri = "http://localhost:8080/fcrepo/rest/ore/collection";
final List<String> members = new ArrayList<>();
members.add("obj1");
members.add("obj2");
members.add("obj3");
final Model m = svc.parseInto(null, getOreCollection(uri, members), "text/turtle");
assertNotNull(m);
assertEquals(0, svc.aggregatedBy(m, uri).size());
assertEquals(members.size(), svc.aggregates(m, uri).size());
assertNotNull(svc.serialize(m, "text/turtle"));
// Test inference
members.forEach(member -> {
assertEquals(1, svc.aggregatedBy(m, uri + "/members/" + member).size());
svc.aggregatedBy(m, uri + "/members/" + member).forEach(parent -> {
assertEquals(uri, parent);
});
});
}
@Test
public void testSerializeTurtle() {
final String uri = "http://localhost:8080/fcrepo/rest/ore/collection";
final Model m = svc.parseInto(null, getOreObject(uri, emptyList(), emptyList()), "text/turtle");
assertNotNull(m);
assertNotNull(svc.serialize(m, "text/turtle"));
}
@Test
public void testSerializeNull() {
final String uri = "http://localhost:8080/fcrepo/rest/ore/collection";
final Model m = svc.parseInto(null, getOreObject(uri, emptyList(), emptyList()), "text/turtle");
assertNotNull(m);
assertNotNull(svc.serialize(m, null));
}
@Test
public void testSerializeBogus() {
final String uri = "http://localhost:8080/fcrepo/rest/ore/collection";
final Model m = svc.parseInto(null, getOreObject(uri, emptyList(), emptyList()), "text/turtle");
assertNotNull(m);
assertNotNull(svc.serialize(m, "amherst/cool"));
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%p %d{HH:mm:ss.SSS} \(%c{0}\) %m%n</pattern>
</encoder>
</appender>
<logger name="edu.amherst.acdc.services.ore" additivity="false" level="INFO">
<appender-ref ref="STDOUT"/>
</logger>
<root additivity="false" level="INFO">
<appender-ref ref="STDOUT"/>
</root>
</configuration>
...@@ -7,12 +7,14 @@ include ':acrepo-connector-triplestore' ...@@ -7,12 +7,14 @@ include ':acrepo-connector-triplestore'
include ':acrepo-exts-fits' include ':acrepo-exts-fits'
include ':acrepo-exts-image' include ':acrepo-exts-image'
include ':acrepo-exts-ldpath' include ':acrepo-exts-ldpath'
include ':acrepo-exts-ore'
include ':acrepo-exts-pcdm' include ':acrepo-exts-pcdm'
include ':acrepo-exts-serialize-xml' include ':acrepo-exts-serialize-xml'
include ':acrepo-exts-template' include ':acrepo-exts-template'
include ':acrepo-karaf' include ':acrepo-karaf'
include ':acrepo-services-inference' include ':acrepo-services-inference'
include ':acrepo-services-mint'