Предоставление массива в качестве параметра для встроенного Jena
Мне нужно создать новый встроенный для Йены. С этим я хотел бы быть в состоянии извлечь минимальную дату, где это находится. Мне просто интересно, можно ли дать класс данных встроенному, а не только одному параметру.
Вот bodyCall моей функции:
@Override
public boolean bodyCall(Node[] args, int length, RuleContext context) {
System.out.println("Entra");
checkArgs(length, context);
BindingEnvironment env = context.getEnv();
Node n1 = getArg(0, args, context);
Node n2 = getArg(1, args, context);
//int count = 0;
//do{
//System.out.println("RULE"+context.getEnv().getGroundVersion(n2).getLiteralLexicalForm()); count ++;}while(count <2);
System.out.println("Date 1: " + n1 + " and Date 2: " + n2);
if (n1.isLiteral() && n2.isLiteral()) {
Object v1 = n1.getLiteralValue();
Object v2 = n2.getLiteralValue();
Node max = null;
if (v1 instanceof XSDDateTime && v2 instanceof XSDDateTime) {
XSDDateTime nv1 = (XSDDateTime) v1;
XSDDateTime nv2 = (XSDDateTime) v2;
Calendar data1 = new GregorianCalendar (nv1.getYears(), nv1.getMonths(), nv1.getDays());
Calendar data2 = new GregorianCalendar (nv2.getYears(), nv2.getMonths(), nv2.getDays());
SimpleDateFormat df = new SimpleDateFormat();
df.applyPattern("yyyy-dd-MM");
if (data1.compareTo(data2) > 0)
{
System.out.println("la data piu' grande e' DATA1: " +df.format(data1.getTime()));
max = args[0];
}
else
{
max = args[1];
System.out.print("la data piu' grande e' DATA1: " +df.format(data1.getTime()));
}
return env.bind(args[2], max);
}
}
// Doesn't (yet) handle partially bound cases
return false;
}
});
Это мое простое правило:
@prefix ex: http://www.semanticweb.org/prova_rules_M#
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
[maxDate:
(?p rdf:type ex:Persona)
(?p http://www.semanticweb.org/prova_rules_M/persona#data_nascita ?c)
(?p http://www.semanticweb.org/prova_rules_M/persona#data_nascita ?d)
maxDate(?c,?d,?x)
-> print(?x)
]
Я даю встроенным три параметра. Два для ввода и один для вывода. Моя идея заключается в использовании двух переменных:? C и? D. У них обоих есть дата рождения. Я хотел бы получить первую запись от? C и следующую запись от? D. Но, похоже, что Йена снимает каждый раз первую запись.
Возможно ли с помощью Java сказать, что я хочу вторую запись и прокрутить результаты?
Например, моя онтология состоит из двух дат: 1)1992-04-13T00:00:00.0; 2)1988-04-25T00:00:00,0
Я хочу иметь 1) in? C и 2) in? D, а затем создать алгоритм для получения минимума между ними.
PS: в "bodyCall" выше есть моя попытка получить максимум между датами, которые я даю правилу. Это прекрасно работает для этой цели.
Спасибо вам всем.
1 ответ
Когда вы реализуете bodyCall(Node[], int, RuleContext)
или же headAction(Node[], int, RuleContext)
как часть реализации Builtin
Вам дан массив аргументов, который представляет аргументы для встроенной функции. Как правило, во встроенную функцию можно передать любое количество переменных (не только одну).
Похоже, (и вы можете исправить меня, если я неверно истолковал ваш вопрос), что вы хотите поработать над некоторым выражением класса, чтобы получить необходимые данные. Если вашей общей целью является работа с "классом данных", то для этого есть несколько способов.
(самый простой) Сформулируйте выражение своего класса как операторы в теле правила. Это гарантирует, что ваш встроенный будет передан только лицам соответствующего класса. Объединение нескольких предварительных условий может позволить вам работать только с определенными лицами ("класс данных").
(потенциально нетривиально) Если вы хотите, чтобы ваша встроенная программа работала с классом, используйте
RuleContext
перешел к вашемуbodyCall(...)
или жеheadAction(...)
для того, чтобы найти людей, которые удовлетворяют вашему выражению класса (вызываяRuleContext#find(...)
или какой-то другой метод).
В качестве примера, скажем, что мы хотели действовать на каждого члена класса urn:ex:Question
, В первом решении мы сформулируем правило, подобное следующему:
[eachIndividual: (?x rdf:type urn:ex:Question) -> builtin(?x)]
Это гарантирует, что мы будем работать на каждом экземпляре urn:ex:Question
, Примером второго решения может быть передача выражения класса вашей встроенной программе напрямую. В вашем вопросе не указано, как бы вы определили класс, о котором идет речь, поэтому я произвольно предположу, что вы заинтересованы в классах, которые rdfs:subClassOf
urn:ex:Question
,
[eachSubclass: (x? rdfs:subClassof urn:ex:Question) -> builtin(?x)]
В этом случае вам нужно будет как-то оперировать вашим "классом данных" в вашей встроенной программе. Как упоминалось ранее, вы могли бы потенциально использовать RuleContext
сделать это.
РЕДАКТИРОВАТЬ
Давайте предположим, что у вас есть 40 человек типа urn:ex:Question
и каждый человек имеет свойство urn:ex:dateSubmitted
это указывает, когда он был представлен. Это можно довольно просто решить с помощью запроса SPARQL:
SELECT ?post WHERE {
?post a urn:ex:Question .
?post urn:ex:dateSubmitted ?date .
}
ORDER BY ?date
LIMIT 1
Редактировать 2 На основании новой информации в вашем обновлении, вы, вероятно, можете просто изменить свой вызов телосложения, чтобы он выглядел следующим образом:
@Override
public boolean bodyCall( final Node[] args, final int length, final RuleContext context )
{
checkArgs(length, context);
final Node n1 = getArg(0, args, context);
final Node n2 = getArg(1, args, context);
if (n1.isLiteral() && n2.isLiteral()) {
final Node max = Util.compareTypedLiterals(n1, n2) < 0 ? n2 : n1;
return context.getEnv().bind(args[2], max);
}
return false;
}