Reading RDF in Apache Jena states that,
A resource name with no URI scheme is assumed to be a local file name.
This assumption can be overridden by providing a base URI to the various read methods of RDFDataMgr. But is there a way to treat relative URIs as errors, i.e. throw an exception if a relative URI is encountered in a given RDF document?
The question is similar to Jena adds path/url to URIs but in my case relative URIs represent an error condition.
Yes there is, it is possible to override the URI resolution behaviour. Thereby allowing you to substitute a resolver that refuses relative URIs. We use this in our production software which is built upon Apache Jena.
Our code does not apply to the code path you are interested in because we use this in SPARQL parsing which is a different API from parsing, and I can't share proprietary code anyway. However I think what you want to do is entirely achievable.
With recent versions of Jena there is a RDFParserBuilder class introduced which provides for constructing parsers with detailed control over parser behaviour. Converting terms in data into Jena Node objects is handled by the FactoryRDF Interface that can be set on the parser builder. So you should be able to override that to implement your logic to reject relative URIs.
Here is an implementation of the answer by #RobV using FactoryRDF.
static final String BASE = "null://null/";
static final FactoryRDF FACTORY = new FactoryRDFStd() {
#Override
public Node createURI(String uriStr) {
if (uriStr.startsWith(BASE))
throw new IllegalArgumentException("URI is not absolute: " + uriStr.substring(BASE.length()));
return super.createURI(uriStr);
}
};
public static void main(String... args) {
Model output = ModelFactory.createDefaultModel();
RDFParser.create()
.fromString("<foo> <bar> <baz> .")
.lang(Lang.TURTLE)
.base(BASE)
.factory(FACTORY)
.parse(output.getGraph());
}
A resource name with no URI scheme is assumed to be a local file name.
To expand on that documentation: This means
RDFDataMgr.read(Model, "mydata.ttl", ...)
will read file "mydata.ttl"
The base URI argument applies to the process parsing the data, not to choosing which data to read. Equivalently, the base URI for resource finding is the current working directory of the process.
Related
I am loading a JSON-LD document using Jena:
Model mj = RDFDataMgr.loadModel([filename]);
The actual content being loaded is here: http://build.fhir.org/account-example.jsonld
Jena goes off and resolves the context, and returns an error (LOADING_REMOTE_CONTEXT_FAILED - lovely suppression of the actual cause in the Jena code :-(). But I need to override the context anyway, and use a different source, because I am doing the build for what will be posted at build.fhir.org, and I need to use my local versions instead. I can't see how to override the context resolution
Alternatively, I could use the loading method documented here: https://github.com/jsonld-java/jsonld-java#code-example - but I have no idea how to get to a Jena graph from there (and I haven't figured out how make the custom resolution work in my Eclipse context either)
How can I get to a Jena graph using a context defined in code somewhere?
I think Jena devs are subscribed to the relevant tag RSS streams. They might weigh in on the clarity of LOADING_REMOTE_CONTEXT_FAILED error. But it seems pretty clear to me.
In order to override the context, you can use read(Model model, String uri, Context context) method. ModelFactory.createDefaultModel() will create a intance of a Model that you can pass as a first argument. See more examples here: https://github.com/apache/jena/tree/master/jena-arq/src-examples/arq/examples/riot
Alternative library is not Jena-compatible (nor RDF4J, which strikes me as rather silly), so there is no easy way to use it with Jena-dependent code.
Finally, you provided the code example for getting a model but now mention a graph – there is a method for that as well: read(Graph graph, String uri, Context context).
One of my recent projects involved sending reminder e-mails based on some reminder configuration. E-mail sending is implemented in an asynchronous job using Quartz.net. and it requires to include a permalink to a entity in the application.
However, in order to get this permalink, I have to be able to compute the full URL, based on the identifier stored in the queue used for the job. The answer is not straightforward, since HttpContext is not available in the thread's context.
One solution is to store application root path in the queue and use it from there. Another way is to use a function like the following:
public static String GetCurrentBasePath(String prefix = "http://")
{
return String.Format("{0}{1}{2}",
prefix, // protocol
System.Net.Dns.GetHostEntry("").HostName, // host
System.Web.HttpRuntime.AppDomainAppVirtualPath // virtual application path
);
}
However, this has (severe) limitations, since the protocol must be provided and also returns the hostname, not the domain name, thus rendering it useless when having multiple Web applications bound to the same host.
The question: is Web application base path available in another thread/task?. I think the other thread/task context is somehow connected to the ApplicationPool, rather than the WebApp and since multiple WebApps can use the same ApplicationPool, there is not a direct connection between thread context and the WebApp.
I'm not sure how you're invoking this. But from my experience, parallelism (as you've mentioned) loses the HttpContext. That said, there is nothing to stop you from using a config variable with the string value(s) that you need. Of course, depending how dynamic this value is this might not be the best course of action. But remember that the computation you're making above is expensive, so remember to store the value locally.
I believe the best solution here (assuming you know the context values, which I don't see why you couldn't/wouldn't) would be to set some variables and avoid the computation altogether.
static readonly string hostName = "your-host";
static readonly string virtualPath = "your-virtual-path";
public static String GetCurrentBasePath(String prefix = "http://")
{
return String.Format("{0}{1}{2}",
prefix, // protocol
hostName, // host
virtualPath // virtual application path
);
}
We have an OpenRasta service, and we'd like to use media types to version our resources. We'll have a different set of DTOs for each new version, distinguishable by namespace. For each version of the DTOs, we have a corresponding media type.
So DTOs will be mapped to media types like this:
Namespace.Dto.V1.MyResource -> application/vnd.Namespace.Dto.V1.MyResource+json
Namespace.Dto.V2.MyResource -> application/vnd.Namespace.Dto.V2.MyResource+json
The repository implementation will be specific to the version of the DTOs, but the interface is generic. I would like my handler and codec to be generic as well, so I don't need to copy/paste them for each version of the DTOs. So I want my routes to look like this:
ResourceSpace.Has.ResourcesOfType<V1.MyResource>()
.AtUri("MyResource/{resourceID}")
.HandledBy<MyResourceHandler<Dto.V1.MyResource>>()
.TranscodedBy<MyResourceCodec<Dto.V1.MyResource>>()
.ForMediaType(mediaTypeMapper.GetMediaType(typeof(Dto.V1.MyResource)));
//V2 of DTOs
ResourceSpace.Has.ResourcesOfType<V2.MyResource>()
.AtUri("MyResource/{resourceID}")
.HandledBy<MyResourceHandler<Dto.V2.MyResource>>()
.TranscodedBy<MyResourceCodec<Dto.V2.MyResource>>()
.ForMediaType(mediaTypeMapper.GetMediaType(typeof(Dto.V2.MyResource)));
Should this work? Right now, it appears that my service is handling requests with MyResourceHandler<Dto.V1.MyResource> regardless of the Accept header on a GET request, for example.
Any thoughts? We could change our scheme to use URIs like /v1/MyResource/ instead of using the accept header, but it would be great to get this working.
EDIT:
I should add that part of the reason we are using media types for versioning is because this is a service for internal use, not meant to be accessible on the public web.
You're registering two resource types on the same URI, only one will get selected, there's no way to do the distinction at request time.
I don't think versioning in URIs or media types is a good idea on the web. That said, for what you want (different mediatypes), then use the same resource type and use your codec to fill-in the same type from the incoming / outgoing data. That's teh responsibility of a codec in OR, making the junction between a DTO and a media type format.
On incoming requests, we need to know what resource type you want based on the URI. If you have two different types it ought to be different resources. that said if you do the following that'll work too:
ResourceSpace.Has.ResourcesNamed("myResource").AtUri("/myResource").HandledBy<ResourceV1Handler>().And.HandledBy<ResourceV2Handler>();
ResourceSpace.Has.ResourcesOfType<MyV1Resource>().WithoutUri.TranscodedBy<V1Codec>();
ResourceSpace.Has.ResourcesOfType<MyV2Resource>().WithoutUri.TranscodedBy<V2Codec>();
you can then write
public class handler {
public object Post(MyV1Resource resource) {}
public object Post(MyV2Resource resource) {}
}
and that'll work. What you won't be able to do is implement the get in that way, as OR assumes one resource type == one URI in most instances.
As for generics, if you use an IoC container, you can register your handlers in a generic fashion (aka register typeof(IHandler<>) with typeof(Handler<>)). This means any IHandler will get resolved to Handler. You can then simply register HandledBy>() in your registration and you're done. Same applies to codecs (but then again, codecs in OR are there to deal with media type issues, not just as serialization mechanisms, as serialization in itself is evil for the web and should be used seldomly).
I'm using an interpreter for my domain specific language rather than a compiler (despite the performance). I'm struggling to understand some of the concepts though:
Suppose I have a DSL (in XML style) for a game so that developers can make building objects easily:
<building>
<name> hotel </name>
<capacity> 10 </capacity>
</building>
The DSL script is parsed, then what happens?
Does it execute an existing method for creating a new building? As I understand it does not simply transform the DSL into a lower level language (as this would then need to be compiled).
Could someone please describe what an interpreter would do with the resulting parsed tree?
Thank you for your help.
Much depends on your specific application details. For example, are name and capacity required? I'm going to give a fairly generic answer, which might be a bit overkill.
Assumptions:
All nested properties are optional
There are many nested properties, possibly of varying depth
This invites 2 ideas: structuring your interpreter as a recursive descent parser and using some sort of builder for your objects. In your specific example, you'd have a BuildingBuilder that looks something like (in Java):
public class BuildingBuilder {
public BuildingBuilder() { ... }
public BuildingBuilder setName(String name) { ... return this; }
public BuildingBuilder setCapacity(int capacity) { ... return this; }
...
public Building build() { ... }
}
Now, when your parser encounters a building element, use the BuildingBuilder to build a building. Then add that object to whatever context the DSL applies to (city.addBuilding(building)).
Note that if the name and capacity are exhaustive and are always required, you can just create a building by passing the two parameters directly. You can also construct the building and set the properties directly as encountered instead of using the builder (the Builder Pattern is nice when you have many properties and said properties are both immutable and optional).
If this is in a non-object-oriented context, you'll end up implementing some sort of buildBuilding function that takes the current context and the inner xml of the building element. Effectively, you are building a recursive descent parser by hand with an xml library providing the actual parsing of individual elements.
However you implement it, you will probably appreciate having a direct semantic mapping between xml elements in your DSL and methods/objects in your interpreter.
There are at least two types of URIs in Java:
java.net.URI
org.eclipse.emf.common.util.URI
I have java.net.URI and need to use the EMF URI. How can I convert the former to the latter?
If I try new URI uri = profileUrl.toURI() I will get a message like this:
Type mismatch: cannot convert from java.net.URI to org.eclipse.emf.common.util.URI
I tried also some kind of workaround that will create a string from the java.net.URI and with the new string a new EMF URI... this lead to a file-not-found exception.
First things first, there are not "two types of URIs in Java": there is only one in Java, and one in EMF which is a framework built for modeling. They have their own implementation of URI because this reflects one of their own concepts, or they needed more than Java's URI allows, or... there can be a number of reasons for such a choice, and many frameworks provide their own version of such or such class (in Eclipse, use ctrl + shift + T and type "List" or "Array" for examples).
As for the actual question, there is no way to go directly from a java.net.URI to org.eclipse.emf.common.util.URI: you need to convert the Java URI to a string, then create a new URI around this string. Something like this:
java.net.URI javaURI = profileUrl.toURI();
org.eclipse.emf.common.util.URI emfURI = org.eclipse.emf.common.util.URI.createURI(javaURI.toString());
You need to use the fully qualified name of at least one of the two URIs: the one you did not import in your Java class. Judging by your question, I'd say you have imported org.eclipse.emf.common.util.URI, and thus can simply use this:
java.net.URI javaURI = profileUrl.toURI();
URI emfURI = URI.createURI(javaURI.toString());