Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions jena-serviceenhancer/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@
</dependency>

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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
*
* https://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.
*
* SPDX-License-Identifier: Apache-2.0
*/

package org.apache.jena.sparql.service.enhancer.algebra;

import org.apache.jena.sparql.algebra.Op;
import org.apache.jena.sparql.algebra.TransformCopy;
import org.apache.jena.sparql.algebra.op.OpAssign;
import org.apache.jena.sparql.algebra.op.OpExtend;

/**
* Transform OpAssign to OpExtend.
* Rationale: Execution of OpLateral in Jena 5.0.0 inserts OpAssign operations. Attempting to execute those remote results in
* SPARQL LET syntax elements which are usually not understood by remote endpoints.
*/
@Deprecated // Should no longer be necessary with https://github.com/apache/jena/pull/3029
public class TransformAssignToExtend
extends TransformCopy
{
private static TransformAssignToExtend INSTANCE = null;

public static TransformAssignToExtend get() {
if (INSTANCE == null) {
synchronized (TransformAssignToExtend.class) {
if (INSTANCE == null) {
INSTANCE = new TransformAssignToExtend();
}
}
}
return INSTANCE;
}

@Override
public Op transform(OpAssign opAssign, Op subOp) {
return OpExtend.create(subOp, opAssign.getVarExprList());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.apache.jena.sparql.algebra.TransformCopy;
import org.apache.jena.sparql.algebra.op.OpService;
import org.apache.jena.sparql.service.enhancer.impl.ServiceOpts;
import org.apache.jena.sparql.service.enhancer.impl.ServiceOptsSE;

/**
* Detects options on SERVICE and materializes them.
Expand All @@ -49,7 +50,7 @@ public class TransformSE_EffectiveOptions
@Override
public Op transform(OpService opService, Op subOp) {
OpService tmp = new OpService(opService.getService(), subOp, opService.getSilent());
ServiceOpts so = ServiceOpts.getEffectiveService(tmp);
ServiceOpts so = ServiceOptsSE.getEffectiveService(tmp);
OpService result = so.toService();
return result;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
*
* SPDX-License-Identifier: Apache-2.0
*/

package org.apache.jena.sparql.service.enhancer.algebra;

import java.util.HashMap;
Expand All @@ -45,6 +44,7 @@
import org.apache.jena.sparql.graph.NodeTransform;
import org.apache.jena.sparql.graph.NodeTransformLib;
import org.apache.jena.sparql.service.enhancer.impl.ServiceOpts;
import org.apache.jena.sparql.service.enhancer.impl.ServiceOptsSE;

/**
* Checks for the presence of <code>SERVICE &lt;loop:&gt; { }</code>
Expand All @@ -66,11 +66,22 @@ public Op transform(OpJoin opJoin, Op left, Op right)
Op effectiveRight = right;
if (right instanceof OpService) {
OpService op = (OpService)right;
ServiceOpts opts = ServiceOpts.getEffectiveService(op);
canDoLinear = opts.containsKey(ServiceOpts.SO_LOOP);
ServiceOpts opts = ServiceOptsSE.getEffectiveService(op);
canDoLinear = opts.containsKey(ServiceOptsSE.SO_LOOP);
if (canDoLinear) {
NodeTransform joinVarRename = renameForImplicitJoinVars(left);
effectiveRight = NodeTransformLib.transform(joinVarRename, right);
String loopMode = opts.getFirstValue(ServiceOptsSE.SO_LOOP, "", null);
switch (loopMode) {
case "":
NodeTransform joinVarRename = renameForImplicitJoinVars(left);
effectiveRight = NodeTransformLib.transform(joinVarRename, right);
break;
case ServiceOptsSE.SO_LOOP_MODE_SCOPED:
// Nothing to do
effectiveRight = right;
break;
default:
throw new RuntimeException("Unsupported loop mode: " + loopMode);
}
}
}

Expand All @@ -92,11 +103,21 @@ public Op transform(OpSequence opSequence, List<Op> elts) {
Op newOp = right;
if (right instanceof OpService) {
OpService op = (OpService)right;
ServiceOpts opts = ServiceOpts.getEffectiveService(op);
boolean isLoop = opts.containsKey(ServiceOpts.SO_LOOP);
ServiceOpts opts = ServiceOptsSE.getEffectiveService(op);
boolean isLoop = opts.containsKey(ServiceOptsSE.SO_LOOP);
if (isLoop) {
NodeTransform joinVarRename = renameForImplicitJoinVars(visibleVarsLeft);
newOp = NodeTransformLib.transform(joinVarRename, right);
String loopMode = opts.getFirstValue(ServiceOptsSE.SO_LOOP, "", null);
switch (loopMode) {
case "":
NodeTransform joinVarRename = renameForImplicitJoinVars(visibleVarsLeft);
newOp = NodeTransformLib.transform(joinVarRename, right);
break;
case ServiceOptsSE.SO_LOOP_MODE_SCOPED:
// Nothing to do
break;
default:
throw new RuntimeException("Unsupported loop mode: " + loopMode);
}
}
}

Expand All @@ -110,33 +131,44 @@ public Op transform(OpSequence opSequence, List<Op> elts) {
return result;
}

@Override
public Op transform(OpDisjunction opSequence, List<Op> elts) {
// Accumulated visible vars
Set<Var> visibleVarsLeft = new LinkedHashSet<>();

OpDisjunction result = OpDisjunction.create();
for (Op right : elts) {
Op newOp = right;
if (right instanceof OpService) {
OpService op = (OpService)right;
ServiceOpts opts = ServiceOpts.getEffectiveService(op);
boolean isLoop = opts.containsKey(ServiceOpts.SO_LOOP);
if (isLoop) {
NodeTransform joinVarRename = renameForImplicitJoinVars(visibleVarsLeft);
newOp = NodeTransformLib.transform(joinVarRename, right);
}
}

// Add the now visible vars as new ones
Set<Var> visibleVarsRight = OpVars.visibleVars(newOp);
visibleVarsLeft.addAll(visibleVarsRight);

result.add(newOp);
}

return result;
}
// @Override
// public Op transform(OpDisjunction opSequence, List<Op> elts) {
// // Accumulated visible vars
// Set<Var> visibleVarsLeft = new LinkedHashSet<>();
//
// OpDisjunction result = OpDisjunction.create();
// for (Op right : elts) {
// Op newOp = right;
// if (right instanceof OpService) {
// OpService op = (OpService)right;
// ServiceOpts opts = ServiceOptsSE.getEffectiveService(op);
// boolean isLoop = opts.containsKey(ServiceOptsSE.SO_LOOP);
// if (isLoop) {
// String loopMode = opts.getFirstValue(ServiceOptsSE.SO_LOOP, "", null);
// switch (loopMode) {
// case "":
// NodeTransform joinVarRename = renameForImplicitJoinVars(visibleVarsLeft);
// newOp = NodeTransformLib.transform(joinVarRename, right);
// break;
// case ServiceOptsSE.SO_LOOP_MODE_SCOPED:
// // Nothing to do
// newOp = right;
// break;
// default:
// throw new RuntimeException("Unsupported loop mode: " + loopMode);
// }
// }
// }
//
// // Add the now visible vars as new ones
// Set<Var> visibleVarsRight = OpVars.visibleVars(newOp);
// visibleVarsLeft.addAll(visibleVarsRight);
//
// result.add(newOp);
// }
//
// return result;
// }

@Override
public Op transform(OpLeftJoin opLeftJoin, Op left, Op right)
Expand All @@ -145,16 +177,26 @@ public Op transform(OpLeftJoin opLeftJoin, Op left, Op right)
Op effectiveRight = right;
if (right instanceof OpService) {
OpService op = (OpService)right;
ServiceOpts opts = ServiceOpts.getEffectiveService(op);
canDoLinear = opts.containsKey(ServiceOpts.SO_LOOP);
ServiceOpts opts = ServiceOptsSE.getEffectiveService(op);
canDoLinear = opts.containsKey(ServiceOptsSE.SO_LOOP);
if (canDoLinear) {
NodeTransform joinVarRename = renameForImplicitJoinVars(left);
effectiveRight = NodeTransformLib.transform(joinVarRename, right);

ExprList joinExprs = opLeftJoin.getExprs();
if (joinExprs != null) {
ExprList effectiveExprs = NodeTransformLib.transform(joinVarRename, joinExprs);
effectiveRight = OpFilter.filterBy(effectiveExprs, effectiveRight);
String loopMode = opts.getFirstValue(ServiceOptsSE.SO_LOOP, "", null);
switch (loopMode) {
case "":
NodeTransform joinVarRename = renameForImplicitJoinVars(left);
effectiveRight = NodeTransformLib.transform(joinVarRename, right);

ExprList joinExprs = opLeftJoin.getExprs();
if (joinExprs != null) {
ExprList effectiveExprs = NodeTransformLib.transform(joinVarRename, joinExprs);
effectiveRight = OpFilter.filterBy(effectiveExprs, effectiveRight);
}
break;
case ServiceOptsSE.SO_LOOP_MODE_SCOPED:
// Nothing to do
break;
default:
throw new RuntimeException("Unsupported loop mode: " + loopMode);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.apache.jena.sparql.algebra.op.OpService;
import org.apache.jena.sparql.algebra.optimize.Rewrite;
import org.apache.jena.sparql.service.enhancer.impl.ServiceOpts;
import org.apache.jena.sparql.service.enhancer.impl.ServiceOptsSE;
import org.apache.jena.sparql.service.enhancer.init.ServiceEnhancerConstants;

/** It seems that preemtive optimization before execution does not work with property
Expand All @@ -44,17 +45,17 @@ public TransformSE_OptimizeSelfJoin(Rewrite selfRewrite) {
@Override
public Op transform(OpService opService, Op subOp) {
Op result;
ServiceOpts so = ServiceOpts.getEffectiveService(
ServiceOpts so = ServiceOptsSE.getEffectiveService(
new OpService(opService.getService(), subOp, opService.getSilent()));

OpService targetService = so.getTargetService();
if (ServiceEnhancerConstants.SELF.equals(targetService.getService())) {
String optimizerOpt = so.getFirstValue(ServiceOpts.SO_OPTIMIZE, "on", "on");
String optimizerOpt = so.getFirstValue(ServiceOptsSE.SO_OPTIMIZE, "on", "on");

if (!optimizerOpt.equalsIgnoreCase("off")) {
Op newSub = selfRewrite.rewrite(targetService.getSubOp());

so.removeKey(ServiceOpts.SO_OPTIMIZE);
so.removeKey(ServiceOptsSE.SO_OPTIMIZE);
// so.add(ServiceOpts.SO_OPTIMIZE, "off");
// so.add(ServiceOpts.SO_OPTIMIZE, "on");
result = new ServiceOpts(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,9 @@

import java.util.Objects;

import com.google.common.base.Preconditions;

import org.apache.commons.lang3.function.TriFunction;
import org.apache.jena.assembler.Assembler;
import org.apache.jena.assembler.exceptions.AssemblerException;
import org.apache.jena.atlas.logging.Log;
import org.apache.jena.graph.Node;
import org.apache.jena.query.ARQ;
import org.apache.jena.query.Dataset;
Expand All @@ -39,14 +36,20 @@
import org.apache.jena.sparql.core.DatasetGraph;
import org.apache.jena.sparql.core.DatasetGraphWrapper;
import org.apache.jena.sparql.core.assembler.DatasetAssembler;
import org.apache.jena.sparql.core.assembler.DatasetAssemblerVocab;
import org.apache.jena.sparql.service.enhancer.impl.ChainingServiceExecutorBulkCache;
import org.apache.jena.sparql.service.enhancer.impl.ServiceResponseCache;
import org.apache.jena.sparql.service.enhancer.impl.util.GraphUtilsExtra;
import org.apache.jena.sparql.service.enhancer.impl.util.Lazy;
import org.apache.jena.sparql.service.enhancer.init.ServiceEnhancerConstants;
import org.apache.jena.sparql.service.enhancer.init.ServiceEnhancerInit;
import org.apache.jena.sparql.util.Context;
import org.apache.jena.sparql.util.Symbol;
import org.apache.jena.sparql.util.graph.GraphUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.Preconditions;

/**
* Assembler that sets up a base dataset's context with the service enhancer machinery.
Expand All @@ -55,9 +58,26 @@
public class DatasetAssemblerServiceEnhancer
extends DatasetAssembler
{
private static final Logger logger = LoggerFactory.getLogger(DatasetAssemblerServiceEnhancer.class);

@SuppressWarnings("deprecation")
@Override
public DatasetGraph createDataset(Assembler a, Resource root) {
Resource baseDatasetRes = GraphUtils.getResourceValue(root, ServiceEnhancerVocab.baseDataset);
if (baseDatasetRes != null) {
if (logger.isWarnEnabled()) {
logger.warn("Use of {} is deprecated. Please use {} instead.", ServiceEnhancerVocab.baseDataset.getURI(), DatasetAssemblerVocab.pDataset.getURI() );
}
}

Resource tmp = GraphUtils.getResourceValue(root, DatasetAssemblerVocab.pDataset);
if (tmp != null) {
if (baseDatasetRes != null) {
throw new AssemblerException(root, "Both " + DatasetAssemblerVocab.pDataset.getURI() + " and " + ServiceEnhancerVocab.baseDataset.getURI() + " specified. Please only use the former.");
}
baseDatasetRes = tmp;
}

Objects.requireNonNull(baseDatasetRes, "No ja:baseDataset specified on " + root);
Object obj = a.open(baseDatasetRes);

Expand Down Expand Up @@ -92,7 +112,7 @@ public DatasetGraph createDataset(Assembler a, Resource root) {
Preconditions.checkArgument(maxPageCount > 0, ServiceEnhancerVocab.cacheMaxPageCount.getURI() + " requires a value greater than 0");

ServiceResponseCache cache = new ServiceResponseCache(maxEntryCount, pageSize, maxPageCount);
ServiceResponseCache.set(cxt, cache);
ServiceResponseCache.set(cxt, Lazy.ofInstance(cache));
}

// Transfer values from the RDF model to the context
Expand All @@ -113,7 +133,9 @@ public DatasetGraph createDataset(Assembler a, Resource root) {
result = DatasetFactory.wrap(new DatasetGraphWrapper(result.asDatasetGraph(), cxt));
}

Log.info(DatasetAssemblerServiceEnhancer.class, "Dataset self id set to " + selfId);
if (logger.isInfoEnabled()) {
logger.info("Dataset self id set to {}", selfId);
}
} else {
Class<?> cls = obj == null ? null : obj.getClass();
throw new AssemblerException(root, "Expected ja:baseDataset to be a Dataset but instead got " + Objects.toString(cls));
Expand All @@ -122,7 +144,6 @@ public DatasetGraph createDataset(Assembler a, Resource root) {
return result.asDatasetGraph();
}


/** Transfer a resource's property value to a context symbol's value */
private static <T> void configureCxt(Resource root, Property property, Context cxt, Symbol symbol, boolean applyDefaultValueIfPropertyAbsent, T defaultValue, TriFunction<Resource, Property, T, T> getValue) {
if (root.hasProperty(property) || applyDefaultValueIfPropertyAbsent) {
Expand Down
Loading
Loading