Check if property is defined in jena rules - jena

In apache jena (using rules), how do I print when finding an instance that does not have a specified object property (in a single rule)?
Example (print people without a job):
[ruleNoJob: (?p rdf:type :Person) ... -> print(?p, 'does not have a job')]

You can use "noValue". Example code below:
[ruleNoJob: (?p rdf:type :Person), noValue(?p aa:job) -> print(?p, 'does not have a job')]

Related

Comprehension pattern and neo4j-embedded

I have a problem when using comprehension with a neo4j-embedded (version 3.5.3).
For exemple, this kind of query works perfectly fine with neo4j enterprise 3.5.3, but does not work with neo4j-embedded :
MATCH (myNode:MyNode {myId:'myid'})
MATCH path = ( (myNode) -[*0..]- (otherNode:MyNode) )
WHERE
ALL(n in nodes(path) where [ (n)<--(state:MyState) | state.isConnected ][0] = true)
RETURN myNode, otherNode
The error I get when using neo4j-embedded is difficult to understand, and looks like an internal error :
org.neo4j.driver.v1.exceptions.DatabaseException: This expression should not be added to a logical plan:
VarExpand(myNode, BOTH, OUTGOING, List(), otherNode, UNNAMED62, VarPatternLength(0,None), ExpandInto, UNNAMED62_NODES, UNNAMED62_RELS, Equals(ContainerIndex(PatternComprehension(None,RelationshipsPattern(RelationshipChain(NodePattern(Some(Variable( UNNAMED62_NODES)),List(),None,None),RelationshipPattern(Some(Variable( REL136)),List(),None,None,INCOMING,false,None),NodePattern(Some(Variable(state)),List(LabelName(MyState)),None,None))),None,Property(Variable(state),PropertyKeyName(isConnected))),Parameter( AUTOINT1,Integer)),True()), True(), List((Variable(n),Equals(ContainerIndex(PatternComprehension(None,RelationshipsPattern(RelationshipChain(NodePattern(Some(Variable(n)),List(),None,None),RelationshipPattern(Some(Variable( REL136)),List(),None,None,INCOMING,false,None),NodePattern(Some(Variable(state)),List(LabelName(MyState)),None,None))),None,Property(Variable(state),PropertyKeyName(isConnected))),Parameter( AUTOINT1,Integer)),True())))) {
LHS -> CartesianProduct() {
LHS -> Selection(Ands(Set(In(Property(Variable(myNode),PropertyKeyName(myId)),ListLiteral(List(Parameter( AUTOSTRING0,String))))))) {
LHS -> NodeByLabelScan(myNode, LabelName(MyNode), Set()) {}
}
RHS -> NodeByLabelScan(otherNode, LabelName(MyNode), Set()) {}
}
}
Any idea ?
It was quite a complicated issue but here is the full explanation.
First, I found that it was not specific to neo4j-embedded. The internal error exception was raised because of an assert in Neo4J, witch would trigger an exception only if the flag -ea (enable assertions) is set. And this flag is set only when running tests with maven or any IDE.
Drilling down Neo4J's code on github, I found also that this assert whas added because of some concerns on recursive comprehension pattern. (The commit is here : https://github.com/neo4j/neo4j/commit/dfbe8ce397f7b72cf7d9b9ff1500f24a5c4b70b0)
In my case, I do use comprehension pattern but not recursively, so I think everything should be fine, except when unit testing :)
I submitted the problem to Neo4J's support, and they will provide a fix in a future release.

XPath 2.0 Leading '/' cannot select the root node of the tree containing the context item: the context item is not a node

Trying to check that one value (once tokenized) doesn't match another value in my document:
/foo/bar/baz/tokenize(value,',')[not(. =(/foo/biz/value/string(),'bing'))]
Specifically here, checking that /foo/bar/baz/value (which is 'ding,dong,bing') doesn't match /foo/biz/value/string() or the value 'bong'.
But I'm getting "Leading '/' cannot select the root node of the tree containing the context item: the context item is not a node"
Is there any way that I can do this in XPath, or do I need to get out into XQuery and start to worry about variables?
Given that you're using Saxon, you can take advantage of the fact that XPath 3.0 allows you to bind variables:
let $foo := /foo return $foo/bar/baz/tokenize(value,',')
[not(. =($foo/biz/value/string(),'bing'))]
or you could pull the expression out of the predicate:
let $exceptions := (/foo/biz/value/string(),'bing')
return /foo/bar/baz/tokenize(value,',')[not(. = $exceptions)]
If you want pure XPath 2.0 you can achieve the same with an ugly "for" binding:
for $foo in /foo return $foo/bar/baz/tokenize(value,',')
[not(. =($foo/biz/value/string(),'bing'))]
If you're in XSLT, of course, you can use current().

R CMD Check non-S3-methods with dots in the name where part of name before dot coincides with a generic in utils

This question is related to but distinct from Exporting non-S3-methods with dots in the name using roxygen2 v4. From that post I learned that one needs to use #export function.name in order for the NAMESPACE to be written correctly by roxygen. I have done that and the NAMESPACE is correctly written.
My problem comes when I do R CMD Check. I have legacy code that has a function tail.g(). R CMD Check throws a NOTE noting that an apparent S3 method has been exported but not registered.
A reproducible example is below. Observe that xxxx.g doesn't have the NOTE, which leads me to believe that because tail is a generic in the utils package I need some special work-around. I'd prefer not to rename tail.g to tail_g because this is legacy code. I wish to eliminate all notes for a successful CRAN submission.
library(roxygen2)
package.skeleton("test")
writeLines(
"#' Check an argument
#'
#' Checks an argument.
#' #param ... Some arguments.
#' #return A value.
#' #export tail.g
tail.g <- function(...) 0",
"test/R/tail.g.R"
)
writeLines(
"#' Check an argument
#'
#' Checks an argument.
#' #param ... Some arguments.
#' #return A value.
#' #export xxxx.g
xxxx.g <- function(...) 0",
"test/R/xxxx.g.R"
)
roxygenise("test")
setwd("./test")
devtools::check(document=FALSE)
Gives the NOTE:
checking S3 generic/method consistency ... NOTE
Found the following apparent S3 methods exported but not registered:
tail.g
How do I eliminate the NOTE for tail.g() without renaming?
This is a dirty hack, but it works: just register the functions as methods, in addition to the export.
So your NAMESPACE could have two lines like this:
export(tail.g)
S3method(tail, g)
This appears to be enough to eliminate the warning and get a clean CRAN submission. The only negative side effect I can think of for regular users is a few bogus entries in the output of things like methods(class="g") or methods("tail"). Most regular users shouldn't even notice.
With roxygen2, you can use the #rawNamespace tag to include the required S3method directive in your NAMESPACE file:
writeLines(
"#' Check an argument
#'
#' Checks an argument.
#' #param ... Some arguments.
#' #return A value.
#' #export tail.g
#' #rawNamespace S3method(tail, g)
tail.g <- function(...) 0",
"test/R/tail.g.R"
)

Is it possible to add YAWS appmods config at runtime?

I embedded YAWS in my application at production environment, and I use the function yaws:start_embedded/4 to start YAWS.
Below is my code:
Id = "my_server",
GconfList = [{logdir, "./log"}, {id, Id}],
SconfList = [{docroot, Docroot},
{port, Port},
{listen, Listen},
{appmods, [
{"/rest", mod_rest, []},
{"/file", mod_file, []}
]}
],
yaws:start_embedded(Docroot, SconfList, GconfList, Id).
I'd like to add another appmod, e.g: {"/upload", mod_upload, []}
Is it possible to add appmods at runtime without restarting YAWS?
You can add appmods at runtime by first retrieving the current configuration, using it to create a new configuration containing your new appmods, and then setting the new configuration.
Call yaws_api:getconf/0 to get a 3-tuple {ok, GlobalConf, ServerConfs} where GlobalConf is the global Yaws configuration and ServerConfs is a list of lists of Yaws server configurations. The global conf is a record type named gconf, and the server conf is a record type named sconf; both of these record types are defined in the yaws.hrl header file.
Work through the server configurations to find the one containing the appmods you want to change. This is slightly tricky because you're dealing with a list of lists, and you need to keep the shape of the overall data structure unchanged.
Once you find the sconf, create a new sconf instance from it by adding your new appmod to its current list of appmods. Each element of the appmod list is a tuple consisting of a URL path for the appmod and the name of the appmod module. An appmod tuple can also optionally contain a third field consisting of a list of paths under the first path to be excluded; see the description of exclude_paths in the Yaws appmod documentation for more details.
Replace the existing sconf value in ServerConfs with your new value.
Call yaws_api:setconf/2 to set the new configuration, passing the existing GlobalConf as the first argument and the new ServerConfs containing your new sconf as the second argument.
The am_extend module below shows how to do this. It exports an add/1 function that takes a function that can identify and augment the appmods in the particular server you care about.
-module(am_extend).
-export([add/1]).
add(AppmodAdder) ->
{ok, GlobalConf, ServerConfs} = yaws_api:getconf(),
NewServerConfs = add_appmod(ServerConfs, AppmodAdder),
yaws_api:setconf(GlobalConf, NewServerConfs).
add_appmod(ServerConfs, AppmodAdder) ->
lists:foldl(fun(Val, Acc) ->
Acc ++ [AppmodAdder(A) || A <- Val]
end, [], ServerConfs).
An example of using this code is to pass the function below as the AppmodAdder argument for am_extend:add/1. For this example, we're looking for a server that has an appmod path "/sse" so we can add another appmod to that server for the path "/sse2". Any server conf we don't care about is just returned unchanged.
-include_lib("yaws/include/yaws.hrl").
add_sse2(#sconf{appmods=AM}=SC) ->
case lists:keyfind("/sse", 1, AM) of
false ->
SC;
_ ->
SC#sconf{appmods=[{"/sse2", my_sse_module}|AM]}
end.
Note that our add_sse2/1 function must be compiled with yaws.hrl included so it has the definition for the sconf record available.

How to rewrite URL in Yaws/Erlang

How can I access yaws file without including it's extension? Say,
www.domain.com/listen.yaws => www.domain.com/listen
I could not find any specific documentation for this from yaws documentation/appmod.
I think the question is ultimately clarified!
You can find one example of how to accomplish this in the "Arg Rewrite" section (7.1.2) of the Yaws PDF documentation. Set the variable arg_rewrite_mod in your server configuration to the name of an Erlang module supporting rewriting:
arg_rewrite_mod = my_rewriter
To support rewriting, the my_rewriter module must define and export an arg_rewrite/1 function, taking an #arg{} record as its argument:
-module(my_rewriter).
-export([arg_rewrite/1]).
-include_lib("yaws/include/yaws_api.hrl").
rewrite_pages() ->
["/listen"].
arg_rewrite(Arg) ->
Req = Arg#arg.req,
{abs_path, Path} = Req#http_request.path,
case lists:member(Path, rewrite_pages()) of
true ->
Arg#arg{req = Req#http_request{path = {abs_path, Path++".yaws"}}};
false ->
Arg
end.
The code includes yaws_api.hrl to pick up the #arg{} record definition.
The rewrite_pages/0 function returns a list of pages that must be rewritten to include ".yaws" suffixes; in this example, it's just the /listen page you mention in your question. If in arg_rewrite/1 we find the requested page in that list, we append ".yaws" to the page name and include it in a new #arg{} we return to Yaws, which then continues dispatching the request based on the new #arg{}.

Resources