/*
* Copyright 2012 Research Studios Austria Forschungsges.m.b.H.
*
* 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 won.protocol.util.linkeddata;
import org.apache.jena.graph.Node;
import org.apache.jena.query.Dataset;
import org.apache.jena.rdf.model.*;
import org.apache.jena.shared.PrefixMapping;
import org.apache.jena.sparql.path.Path;
import org.apache.jena.sparql.path.PathParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import won.protocol.util.RdfUtils;
import won.protocol.vocabulary.WON;
import java.net.URI;
import java.util.Iterator;
/**
* Utilitiy functions for common linked data lookups.
*/
public class WonLinkedDataUtils
{
private static final Logger logger = LoggerFactory.getLogger(WonLinkedDataUtils.class);
public static URI getRemoteConnectionURIforConnectionURI(URI connectionURI, LinkedDataSource linkedDataSource) {
assert linkedDataSource != null : "linkedDataSource must not be null";
Dataset dataset = getDatalForResource(connectionURI, linkedDataSource);
Path propertyPath = PathParser.parse("<" + WON.HAS_REMOTE_CONNECTION + ">", PrefixMapping.Standard);
return RdfUtils.getURIPropertyForPropertyPath(dataset, connectionURI, propertyPath);
}
public static URI getRemoteNeedURIforConnectionURI(URI connectionURI, LinkedDataSource linkedDataSource) {
assert linkedDataSource != null : "linkedDataSource must not be null";
Dataset dataset = getDatalForResource(connectionURI, linkedDataSource);
Path propertyPath = PathParser.parse("<" + WON.HAS_REMOTE_NEED + ">", PrefixMapping.Standard);
return RdfUtils.getURIPropertyForPropertyPath(dataset, connectionURI, propertyPath);
}
public static Dataset getDatalForResource(final URI connectionURI, final LinkedDataSource linkedDataSource) {
assert linkedDataSource != null : "linkedDataSource must not be null";
assert connectionURI != null : "connection URI must not be null";
Dataset dataset = null;
logger.debug("loading model for connection {}", connectionURI);
dataset = linkedDataSource.getDataForResource(connectionURI);
if (dataset == null) {
throw new IllegalStateException("failed to load model for Connection " + connectionURI);
}
return dataset;
}
public static Iterator<Dataset> getModelForURIs(final Iterator<URI> uriIterator,
final LinkedDataSource linkedDataSource) {
assert linkedDataSource != null : "linkedDataSource must not be null";
return new ModelFetchingIterator(uriIterator, linkedDataSource);
}
public static URI getWonNodeURIForNeedOrConnectionURI(final URI resourceURI, LinkedDataSource linkedDataSource) {
assert linkedDataSource != null : "linkedDataSource must not be null";
logger.debug("fetching WON node URI for resource {} with linked data source {}", resourceURI, linkedDataSource);
return getWonNodeURIForNeedOrConnection(resourceURI, linkedDataSource.getDataForResource(resourceURI));
}
public static URI getWonNodeURIForNeedOrConnection(final URI resURI, final Model resourceModel) {
assert resourceModel != null : "model must not be null";
//we didnt't get the queue name. Check if the model contains a triple <baseuri> won:hasWonNode
// <wonNode> and get the information from there.
logger.debug("getting WON node URI from model");
Resource baseResource = resourceModel.getResource(resURI.toString());
logger.debug("resourceModel: {}",RdfUtils.toString(resourceModel));
StmtIterator wonNodeStatementIterator = baseResource.listProperties(WON.HAS_WON_NODE);
if (! wonNodeStatementIterator.hasNext()){
//no won:hasWonNode triple found. we can't do anything.
logger.debug("base resource {} has no won:hasWonNode property", baseResource);
return null;
}
Statement stmt = wonNodeStatementIterator.nextStatement();
RDFNode wonNodeNode = stmt.getObject();
if (!wonNodeNode.isResource()) {
logger.debug("won:hasWonNode property of base resource {} is not a resource", baseResource);
return null;
}
URI wonNodeUri = URI.create(wonNodeNode.asResource().getURI().toString());
logger.debug("obtained WON node URI: {}",wonNodeUri);
if (wonNodeStatementIterator.hasNext()) {
logger.warn("multiple WON node URIs found for resource {}, using first one: {} ", baseResource, wonNodeUri );
}
return wonNodeUri;
}
public static URI getWonNodeURIForNeedOrConnection(final URI resourceURI, final Dataset resourceDataset) {
return RdfUtils.findFirst(resourceDataset, new RdfUtils.ModelVisitor<URI>(){
@Override
public URI visit(final Model model) {
return getWonNodeURIForNeedOrConnection(resourceURI, model);
}
});
}
/**
* For the specified need or connection URI, the model is fetched, the WON node URI found there is also
* de-referenced, and the specified property path is evaluated in that graph, starting at the WON node URI.
*
* @param resourceURI
* @param propertyPath
* @param linkedDataSource
* @return
*/
public static Node getWonNodePropertyForNeedOrConnectionURI(URI resourceURI, Path propertyPath, LinkedDataSource linkedDataSource) {
assert linkedDataSource != null : "linkedDataSource must not be null";
URI wonNodeUri = WonLinkedDataUtils.getWonNodeURIForNeedOrConnectionURI(resourceURI, linkedDataSource);
Dataset nodeDataset = linkedDataSource.getDataForResource(wonNodeUri);
return RdfUtils.getNodeForPropertyPath(
nodeDataset,
wonNodeUri,
propertyPath
);
}
/**
* For the specified URI, the model is fetched and the specified property path is evaluated in that graph,
* starting at the specified URI.
*
* @param resourceURI
* @param propertyPath
* @param linkedDataSource
* @return
*/
public static Node getPropertyForURI(URI resourceURI, Path propertyPath, LinkedDataSource linkedDataSource) {
assert linkedDataSource != null : "linkedDataSource must not be null";
Dataset dataset = linkedDataSource.getDataForResource(resourceURI);
return RdfUtils.getNodeForPropertyPath(
dataset,
resourceURI,
propertyPath
);
}
/**
* Iterator implementation that fetches linked data lazily for the specified iterator of URIs.
*/
private static class ModelFetchingIterator implements Iterator<Dataset> {
private Iterator<URI> uriIterator = null;
private LinkedDataSource linkedDataSource = null;
private ModelFetchingIterator(final Iterator<URI> uriIterator, final LinkedDataSource linkedDataSource) {
this.uriIterator = uriIterator;
this.linkedDataSource = linkedDataSource;
}
@Override
public Dataset next() {
URI uri = uriIterator.next();
return linkedDataSource.getDataForResource(uri);
}
@Override
public boolean hasNext() {
return uriIterator.hasNext();
}
@Override
public void remove() {
throw new UnsupportedOperationException("this iterator cannot remove");
}
}
}