if (rule.isImplication()) {
for (final IExpression expr : rule.getHeadExpressions()) {
// Tripel mit variablen Praedikat wird generiert
if (expr instanceof RulePredicate) {
final RulePredicate pred = (RulePredicate) expr;
final BasicOperator pattern = this.generatePattern(pred, arg);
final KEY key = (pattern instanceof TriplePattern)?
new KeyTriplePattern((TriplePattern)pattern):
new KeyPredicatePattern((PredicatePattern)pattern);
this.tripleProducer.put(key, new LinkedHashSet<BasicOperator>());
} else if (expr instanceof Equality) {
this.tripleProducer.put(BuildOperatorGraphRuleVisitor.keyEquality, new LinkedHashSet<BasicOperator>());
this.usesEqualities = true;
}
}
}
}
// 3. Operatorgraphen fuer einzelne Regeln berechnen
final List<BasicOperator> subOperators = new ArrayList<BasicOperator>();
for (final Rule rule : obj.getRules()) {
if (rule.isImplication()) {
final BasicOperator result = (BasicOperator) rule.accept(this, arg);
subOperators.add(result);
}
}
// 4. Rekursive Verbindungen aufloesen
for (final Entry<KEY, Set<BasicOperator>> entry : this.tripleProducer.entrySet()) {
boolean consumerExists = false;
// find all matching consumers by just getting the previous determined tripleConsumers...
final Set<BasicOperator> consumers = this.tripleConsumer.get(entry.getKey());
if(consumers!=null){
consumerExists = true;
// Kreuzverbindungen zwischen Produzenten und Konsumenten
// herstellen
for (final BasicOperator producer : entry.getValue()) {
for (final BasicOperator consumer : consumers) {
producer.addSucceedingOperator(new OperatorIDTuple(consumer, producer.getSucceedingOperators().size()));
consumer.addPrecedingOperator(producer);
// Sonderfall: Falls PredicatePattern ->
// Dann: PredicatePattern -> Distinct ->
// -----> should now be unnecessary with our new joins with duplicate elimination integrated! <----
// if (consumer instanceof PredicatePattern) {
// boolean distinctFound = false;
// for (OperatorIDTuple opid : consumer
// .getSucceedingOperators())
// if (opid.getOperator() instanceof Distinct)
// distinctFound = true;
// if (!distinctFound) {
// final Distinct distinct = new Distinct();
// for(OperatorIDTuple opID: consumer.getSucceedingOperators()){
// distinct.getSucceedingOperators().add(new OperatorIDTuple(opID));
// }
// consumer.setSucceedingOperator(new OperatorIDTuple(distinct, 0));
// }
// }
}
}
}
// Wenn keine Konsumenten, dann Produzenten entfernen
if (!consumerExists) {
for (final BasicOperator producer : entry.getValue()) {
if (producer instanceof Generate) {
producer.removeFromOperatorGraph();
}
}
}
}
// 5. Ergebniss aller Regeln in einem Result zusammenfuehren
BasicOperator[] finalResults;
if (obj.getConclusion() == null) {
finalResults = new BasicOperator[1];
finalResults[0] = new Result();
} else {
finalResults = this.patternFromConclusion(obj.getConclusion());
}
for(final BasicOperator finalResult: finalResults){
// Verbindungen zum Endergebniss herstellen
for (final BasicOperator subOperator : subOperators) {
// Result immer auf linker Seite, damit keine Linksrekursion
// auftreten kann
if(!(finalResult instanceof TriplePattern && subOperator instanceof ConstructPredicate)
&&!(finalResult instanceof PredicatePattern && (subOperator instanceof Construct || subOperator instanceof Generate))){
if (!subOperator.getSucceedingOperators().isEmpty()) {
final OperatorIDTuple temp = subOperator.getSucceedingOperators().get(0);
subOperator.getSucceedingOperators().set(0,new OperatorIDTuple(finalResult, 0));
finalResult.addPrecedingOperator(subOperator);
subOperator.addSucceedingOperator(temp);
} else {
subOperator.setSucceedingOperator(new OperatorIDTuple(finalResult, 0));
finalResult.addPrecedingOperator(subOperator);
}
}
}
}
for(int i=0; i<finalResults.length; i++){
BasicOperator finalResult = finalResults[i];
if (subOperators.isEmpty()) {
// Root verweist auf EmptyIndex und der direkt auf Result
if (finalResult instanceof PredicatePattern || finalResult instanceof TriplePattern) {
finalResult.removeFromOperatorGraph();
finalResult = null;
}
final EmptyIndexScan empty = new EmptyIndexScan(finalResult == null ? null : new OperatorIDTuple(finalResult, 0));
this.indexScanCreator.getRoot().addSucceedingOperator(new OperatorIDTuple(empty, this.indexScanCreator.getRoot().getSucceedingOperators().size()));
empty.addPrecedingOperator(this.indexScanCreator.getRoot());
if (finalResult == null) {
finalResults[i] = empty;
}
}
}
if (this.booleanIndex != null
&& this.booleanIndex.getSucceedingOperators().isEmpty()){
this.indexScanCreator.getRoot().removeSucceedingOperator(this.booleanIndex);
this.booleanIndex.removePrecedingOperator(this.indexScanCreator.getRoot());
}
if(finalResults.length==1 && (finalResults[0] instanceof Result)){
return finalResults[0];
}
// Falls Conclusion vorhanden, noch Result anhaengen, zum Sammeln der Ergebnisse
final Result result = new Result();
final BasicOperator makeBooleanResultOrResult;
if (obj.getConclusion() != null && obj.getConclusion().getVariables().isEmpty()) {
makeBooleanResultOrResult = new MakeBooleanResult();
makeBooleanResultOrResult.addSucceedingOperator(result);
result.addPrecedingOperator(makeBooleanResultOrResult);
} else {
makeBooleanResultOrResult = result;
}
for(final BasicOperator finalResult: finalResults){
// DEBUG
//finalResult.addSucceedingOperator(finalResult = new Distinct());
finalResult.addSucceedingOperator(makeBooleanResultOrResult);
makeBooleanResultOrResult.addPrecedingOperator(finalResult);
}
return result;
}