org.apache.jena.sparql.util.Context Java Examples

The following examples show how to use org.apache.jena.sparql.util.Context. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: ExpandPrefixFunction.java    From tarql with BSD 2-Clause "Simplified" License 6 votes vote down vote up
public NodeValue exec(NodeValue prefix, Context context) {
	if (prefix == null) {
		return null;
	}
	if (!prefix.isString()) {
		throw new ExprEvalException(NAME + ": not a string: " + prefix);
	}
	PrefixMapping prefixes = context.get(PREFIX_MAPPING);
	if (prefixes == null) {
		throw new ExprEvalException(NAME + ": no prefix mapping registered");
	}
	String iri = prefixes.getNsPrefixURI(prefix.asString());
	if (iri == null) {
		throw new ExprEvalException(NAME + ": prefix not defined: " + prefix);
	}
	return NodeValue.makeString(iri);
}
 
Example #2
Source File: SelectPlan.java    From sparql-generate with Apache License 2.0 6 votes vote down vote up
private Query createQuery(final SPARQLExtQuery select, final List<Var> variables,
		final List<Binding> values, final Context context) {
	// SPARQLExtQuery q = select.cloneQuery();
	Binding binding = !values.isEmpty() ? values.get(0) : null;
	SelectQueryPartialCopyVisitor cloner = new SelectQueryPartialCopyVisitor(binding, context);
	select.visit(cloner);
	Query q = cloner.getOutput();
	if (!isSelectType && !q.hasGroupBy() && !q.hasAggregators()) {
		variables.forEach(v -> {
			if (!q.getProjectVars().contains(v)) {
				q.getProject().add(v);
			}
		});
	}
	return q;
}
 
Example #3
Source File: TemplatePlan.java    From sparql-generate with Apache License 2.0 6 votes vote down vote up
public void exec(List<Var> variables, List<Binding> values, Context context) {
	final IndentedWriter writer = ContextUtils.getTemplateOutput(context);
	boolean first = true;
	final FunctionEnv env = new FunctionEnvBase(context);
	String result;
	for(Iterator<Binding> it=values.iterator(); it.hasNext();) {
		Binding binding = it.next();
		if (first && before != null) {
			result = getExprEval(before, binding, context, env);
			writer.print(result);
		}
		if (!first && separator != null) {
			result = getExprEval(separator, binding, context, env);
			writer.print(result);
		}
		result = getExprEval(expr, binding, context, env);
		writer.print(result);
		first = false;
		if (!it.hasNext() && after != null) {
			result = getExprEval(after, binding, context, env);
			writer.print(result);
		}
		writer.flush();
	}
}
 
Example #4
Source File: QueryExecutor.java    From sparql-generate with Apache License 2.0 6 votes vote down vote up
public void execSelectPlan(
        final RootPlan plan,
        final List<Binding> newValues,
        final Context context) {
    Objects.nonNull(ContextUtils.getSelectOutput(context));
    final ExecutionKey key = new ExecutionKey(plan, newValues);
    if (++nbselect % 2000 == 00) {
        CacheStats stats = selectExecutions.stats();

        LOG.info("call select " + nbselect + " count " + stats.loadCount() + " - hit count " + stats.hitCount() + " - rate " + stats.hitRate());
    }
    ResultSetRewindable resultSet = selectExecutions.getIfPresent(key);
    if (resultSet != null) {
        resultSet.reset();
    } else {
        ResultSet memResultSet = plan.execSelect(newValues, context);
        resultSet = ResultSetFactory.copyResults(memResultSet);
        selectExecutions.put(key, resultSet);
    }
    ContextUtils.getSelectOutput(context).accept(resultSet);
}
 
Example #5
Source File: ContextUtils.java    From sparql-generate with Apache License 2.0 6 votes vote down vote up
public static void loadGraph(Context context, String sourceURI, String baseURI, StreamRDF dest) {
	if(getDataset(context).containsNamedModel(sourceURI)) {
		final Model model = getDataset(context).getNamedModel(sourceURI);
		StreamRDFOps.sendGraphToStream(model.getGraph(), dest);
		return;
	}
	if(!isRootContext(context)) {
		Context parentContext = (Context) context.get(PARENT_CONTEXT);
		loadGraph(parentContext, sourceURI, baseURI, dest);
		return;
	}
	final SPARQLExtStreamManager sm = (SPARQLExtStreamManager) context.get(SysRIOT.sysStreamManager);
	final String acceptHeader = "text/turtle;q=1.0,application/rdf+xml;q=0.9,*/*;q=0.1";
	final LookUpRequest request = new LookUpRequest(sourceURI, acceptHeader);
	try (TypedInputStream tin = sm.open(request);) {
		if(tin == null) {
			LOG.warn("Could not locate graph " + request);
			return;
		}
		Lang lang = RDFLanguages.contentTypeToLang(tin.getMediaType());
		RDFParser.create().source(tin).base(baseURI).context(context).lang(lang).parse(dest);
	} catch (RiotException ex) {
		LOG.warn("Error while loading graph " + sourceURI, ex);
	}
}
 
Example #6
Source File: ITER_Call_Select.java    From sparql-generate with Apache License 2.0 6 votes vote down vote up
@Override
public void exec(
        final List<NodeValue> args,
        final Consumer<List<List<NodeValue>>> collectionListNodeValue) {
    if (args.isEmpty()) {
        LOG.debug("There should be at least one IRI parameter.");
        throw new ExprEvalException("There should be at least one IRI parameter.");
    }
    if (!args.get(0).isIRI()) {
        LOG.debug("The first parameter must be a IRI.");
        throw new ExprEvalException("The first parameter must be a IRI.");
    }
    String queryName = args.get(0).asNode().getURI();

    final List<List<Node>> callParameters = new ArrayList<>();
    callParameters.add(EvalUtils.eval(args.subList(1, args.size())));

    final Context context = ContextUtils.fork(getContext()).setSelectOutput((result) -> {
        List<List<NodeValue>> list = getListNodeValues(result);
        collectionListNodeValue.accept(list);
    }).fork();
    final QueryExecutor queryExecutor = ContextUtils.getQueryExecutor(context);
    queryExecutor.execSelectFromName(queryName, callParameters, context);
}
 
Example #7
Source File: SPARQLExtCli.java    From sparql-generate with Apache License 2.0 6 votes vote down vote up
private static void execGenerateStream(RootPlan plan, ContextUtils.Builder builder, CliRequest request) {
	final PrefixMapping pm = plan.getQuery().getPrefixMapping();
	final ConsoleStreamRDF consoleStreamRDF;
	if (request.output == null) {
		consoleStreamRDF = new ConsoleStreamRDF(System.out, pm);
	} else {
		try {
			consoleStreamRDF = new ConsoleStreamRDF(
					new PrintStream(new FileOutputStream(request.output, request.outputAppend)), pm);
		} catch (IOException ex) {
			LOG.error("Error while opening the output file.", ex);
			return;
		}
	}
	Context context = builder.setGenerateOutput(consoleStreamRDF).build();
	plan.execGenerateStream(context);
}
 
Example #8
Source File: JenaUtil.java    From shacl with Apache License 2.0 6 votes vote down vote up
private static Node invokeFunction(Resource function, ExprList args, Dataset dataset) {

		if (dataset == null) {
	        dataset = ARQFactory.get().getDataset(ModelFactory.createDefaultModel());
	    }
		
		E_Function expr = new E_Function(function.getURI(), args);
		DatasetGraph dsg = dataset.asDatasetGraph();
		Context cxt = ARQ.getContext().copy();
		cxt.set(ARQConstants.sysCurrentTime, NodeFactoryExtra.nowAsDateTime());
		FunctionEnv env = new ExecutionContext(cxt, dsg.getDefaultGraph(), dsg, null);
		try {
			NodeValue r = expr.eval(BindingRoot.create(), env);
			if(r != null) {
				return r.asNode();
			}
		}
		catch(ExprEvalException ex) {
		}
		return null;
	}
 
Example #9
Source File: DatasetDeclarationPlan.java    From sparql-generate with Apache License 2.0 6 votes vote down vote up
private void addNamedGraph(Binding binding, Context context, DatasetGraph dsg, Expr sourceExpr) {
	String sourceURI = evalSourceURI(binding, context, sourceExpr);
	final String absURI = baseURI(sourceURI, baseURI);
	Dataset dataset = ContextUtils.getDataset(context);
	Node n = NodeFactory.createURI(absURI);
	Graph g = dsg.getGraph(n);
	if (g == null) {
		g = GraphFactory.createJenaDefaultGraph();
		dsg.addGraph(n, g);
	}
	// default: check the dataset
	if (dataset.containsNamedModel(absURI)) {
		Graph dg = dataset.getNamedModel(absURI).getGraph();
		GraphUtil.addInto(g, dg);
		return;
	}
	// fallback: load as RDF graph
	StreamRDF dest = StreamRDFLib.graph(g);
	ContextUtils.loadGraph(context, sourceURI, absURI, dest);
}
 
Example #10
Source File: BindPlan.java    From sparql-generate with Apache License 2.0 6 votes vote down vote up
@Override
protected final Binding exec(Binding binding, Context context) {
    LOG.debug("Start " + this);
    context.set(ARQConstants.sysCurrentTime, NodeFactoryExtra.nowAsDateTime());
    final FunctionEnv env = new FunctionEnvBase(context);
    try {
        final NodeValue n = expr.eval(binding, env);
        if (LOG.isTraceEnabled()) {
            LOG.trace("New binding " + var + " = " + LogUtils.compress(n.asNode()));
        }
        return BindingFactory.binding(binding, var, n.asNode());
    } catch(ExprEvalException ex) {
        LOG.trace("No evaluation for " + this + " " + ex.getMessage());
        return binding;
    }
}
 
Example #11
Source File: DB2QueryExecutionImpl.java    From quetzal with Eclipse Public License 2.0 6 votes vote down vote up
private com.ibm.research.rdf.store.Context getNativeContext()
{

// if this context was never exercised, return the store's context
if (jenaContext == null)
   {
   return getStore().getContext();
   }

// convert the jenaContext back to native context
com.ibm.research.rdf.store.Context nativeCtx = new com.ibm.research.rdf.store.Context();
Iterator<Symbol> jkeys = jenaContext.keys().iterator();
while (jkeys.hasNext())
   {
   Symbol b = jkeys.next();
   // jenaContext.put(b,getStore().getContext().get(b) );
   nativeCtx.set(b, jenaContext.get(b));
   }

return nativeCtx;
}
 
Example #12
Source File: DatasetDeclarationPlan.java    From sparql-generate with Apache License 2.0 6 votes vote down vote up
protected final Context prepareDataset(Binding binding, Context context) {
	if (fromClauses == null || fromClauses.isEmpty()) {
		return context;
	}
	final DatasetGraph dsg = DatasetGraphFactory.createGeneral();
	fromClauses.forEach((fromClause) -> {
		if (fromClause.getGenerate() == null) {
			if (!fromClause.isNamed()) {
				addDefaultGraph(binding, context, dsg, fromClause.getName());
			} else {
				addNamedGraph(binding, context, dsg, fromClause.getName());
			}
		} else {
			SPARQLExtQuery generate = fromClause.getGenerate();
			if (!fromClause.isNamed()) {
				addDefaultGraph(binding, context, dsg, generate);
			} else {
				addNamedGraph(binding, context, dsg, generate, fromClause.getName());
			}
		}
	});
	Dataset newDataset = DatasetFactory.wrap(dsg);
	return ContextUtils.fork(context).setDataset(newDataset).fork();
}
 
Example #13
Source File: QueryExecutor.java    From sparql-generate with Apache License 2.0 5 votes vote down vote up
/**
 *
 * @param queryName
 * @param callParameters never null
 * @param context
 */
public void execGenerateFromQuery(
        final SPARQLExtQuery query,
        final Binding binding,
        final Context context) {
	Objects.nonNull(query);
    Objects.nonNull(binding);
    Objects.nonNull(context);
    final RootPlan plan = getPlan(query);
    final List<Binding> newValues = new ArrayList<>();
    newValues.add(binding);
    execGeneratePlan(plan, newValues, context);
}
 
Example #14
Source File: QueryExecutor.java    From sparql-generate with Apache License 2.0 5 votes vote down vote up
/**
 *
 * @param queryName the name of the query (needs to be fetched)
 * @param callParameters
 * @param context
 */
public void execSelectFromName(
        final String queryName,
        final List<List<Node>> callParameters,
        final Context context) {
    Objects.nonNull(queryName);
    Objects.nonNull(callParameters);
    Objects.nonNull(context);
    final RootPlan plan = getPlanFromName(queryName, context);
    final SPARQLExtQuery query = plan.getQuery();
    final List<Var> signature = getSignature(query);
    final List<Binding> newValues = getNewValues(queryName, query, signature, callParameters);
    execSelectPlan(plan, newValues, context);
}
 
Example #15
Source File: QueryExecutor.java    From sparql-generate with Apache License 2.0 5 votes vote down vote up
public void execGeneratePlan(
        final RootPlan plan,
        final List<Binding> values,
        final Context context) {
    Objects.nonNull(ContextUtils.getGenerateOutput(context));
    if (++nbgenerate % 2000 == 00) {
        LOG.info(String.format("Called generates %s times.", nbgenerate));
    }
    plan.execGenerateStream(values, context);
}
 
Example #16
Source File: QueryExecutor.java    From sparql-generate with Apache License 2.0 5 votes vote down vote up
/**
 *
 * @param queryName
 * @param callParameters never null
 * @param context
 */
public void execGenerateFromName(
        final String queryName,
        final List<List<Node>> callParameters,
        final Context context) {
    Objects.nonNull(queryName);
    Objects.nonNull(callParameters);
    Objects.nonNull(context);
    final RootPlan plan = getPlanFromName(queryName, context);
    final SPARQLExtQuery query = plan.getQuery();
    final List<Var> signature = getSignature(query);
    final List<Binding> newValues = getNewValues(queryName, query, signature, callParameters);
    execGeneratePlan(plan, newValues, context);
}
 
Example #17
Source File: SHACLCReader.java    From shacl with Apache License 2.0 5 votes vote down vote up
@Override
public void read(InputStream in, String baseURI, Lang lang, StreamRDF output, Context context) {
	try {
		SHACLCLexer lexer = new SHACLCLexer(new ANTLRInputStream(in));
		read(lexer, baseURI, output);
	}
	catch(IOException ex) {
		ExceptionUtil.throwUnchecked(ex);
	}
}
 
Example #18
Source File: QueryExecutor.java    From sparql-generate with Apache License 2.0 5 votes vote down vote up
/**
 *
 * @param queryName the query uri
 * @param callParameters
 * @param context
 * @param outputTemplate
 */
public void execTemplateFromName(
        final String queryName,
        final List<List<Node>> callParameters,
        final Context context) {
    Objects.nonNull(queryName);
    Objects.nonNull(callParameters);
    Objects.nonNull(context);
    final RootPlan plan = getPlanFromName(queryName, context);
    final SPARQLExtQuery query = plan.getQuery();
    final List<Var> signature = getSignature(query);
    final List<Binding> newValues = getNewValues(queryName, query, signature, callParameters);
    execTemplatePlan(plan, newValues, context);
}
 
Example #19
Source File: QueryExecutor.java    From sparql-generate with Apache License 2.0 5 votes vote down vote up
public void execTemplateFromQuery(
        final SPARQLExtQuery query,
        final List<List<Node>> callParameters,
        final Context context) {
    Objects.nonNull(query);
    Objects.nonNull(callParameters);
    Objects.nonNull(context);
    final String queryName = LogUtils.compress(query.toString());
    final RootPlan plan = getPlan(query);
    final List<Var> signature = getSignature(query);
    final List<Binding> newValues = getNewValues(queryName, query, signature, callParameters);
    execTemplatePlan(plan, newValues, context);
}
 
Example #20
Source File: QueryExecutor.java    From sparql-generate with Apache License 2.0 5 votes vote down vote up
/**
 *
 * @param queryString the query as a string
 * @param callParameters
 * @param context
 * @param outputSelect
 */
public void execSelectFromString(
        final String queryString,
        final List<List<Node>> callParameters,
        final Context context) {
    Objects.nonNull(queryString);
    final SPARQLExtQuery query = getQueryFromString(queryString, null);
    execSelectFromQuery(query, callParameters, context);
}
 
Example #21
Source File: SourcePlan.java    From sparql-generate with Apache License 2.0 5 votes vote down vote up
final protected Binding exec(
        final Binding binding,
        final Context context) {

    LOG.debug("Start " + this);
    Objects.nonNull(binding);
    // generate the source URI.
    final String sourceUri = getActualSource(binding);
    final String acceptHeader = getAcceptHeader(binding);
    LOG.trace("... resolved to SOURCE <" + sourceUri + "> ACCEPT " + acceptHeader + " AS " + var);
    final LookUpRequest request = new LookUpRequest(sourceUri, acceptHeader);
    final SPARQLExtStreamManager sm = (SPARQLExtStreamManager) context.get(SysRIOT.sysStreamManager);
    Objects.requireNonNull(sm);
    final TypedInputStream stream = sm.open(request);
    if (stream == null) {
        LOG.info("Exec SOURCE <" + sourceUri + "> ACCEPT " + acceptHeader + " AS " + var + " returned nothing.");
        return BindingFactory.binding(binding);
    }
    try (InputStream in = stream.getInputStream()) {
        final String literal = IOUtils.toString(in, "UTF-8");
        final RDFDatatype dt;
        if (stream.getMediaType() != null && stream.getMediaType().getContentType() != null) {
            dt = tm.getSafeTypeByName("http://www.iana.org/assignments/media-types/" + stream.getMediaType().getContentType());
        } else {
            dt = tm.getSafeTypeByName("http://www.w3.org/2001/XMLSchema#string");
        }
        final Node n = NodeFactory.createLiteral(literal, dt);
        LOG.debug("Exec " + this + " returned. "
                + "Enable TRACE level for more.");
        if (LOG.isTraceEnabled()) {
            LOG.trace("Exec " + this + " returned\n" + LogUtils.compress(n));
        }
        return BindingFactory.binding(binding, var, n);
    } catch (IOException | DatatypeFormatException ex) {
        LOG.warn("Exception while looking up " + sourceUri + ":", ex);
        return BindingFactory.binding(binding);
    }
}
 
Example #22
Source File: DatasetDeclarationPlan.java    From sparql-generate with Apache License 2.0 5 votes vote down vote up
private void addDefaultGraph(Binding binding, Context context, DatasetGraph dsg, Expr sourceExpr) {
		String sourceURI = evalSourceURI(binding, context, sourceExpr);
		final String absURI = baseURI(sourceURI, baseURI);
		// default: check the dataset
		Dataset dataset = ContextUtils.getDataset(context);
		if (dataset.containsNamedModel(absURI)) {
//			Node n = NodeFactory.createURI(absURI);
			Graph g = dataset.getNamedModel(absURI).getGraph();
			GraphUtil.addInto(dsg.getDefaultGraph(), g);
			return;
		}
		// fallback: load as RDF graph
		StreamRDF dest = StreamRDFLib.graph(dsg.getDefaultGraph());
		ContextUtils.loadGraph(context, sourceURI, absURI, dest);
	}
 
Example #23
Source File: QueryExecutor.java    From sparql-generate with Apache License 2.0 5 votes vote down vote up
public void execSelectFromQuery(
        final SPARQLExtQuery query,
        final List<List<Node>> callParameters,
        final Context context) {
    Objects.nonNull(query);
    Objects.nonNull(callParameters);
    Objects.nonNull(context);
    final String queryName = LogUtils.compress(query.toString());
    final RootPlan plan = getPlan(query);
    final List<Var> signature = getSignature(query);
    final List<Binding> newValues = getNewValues(queryName, query, signature, callParameters);
    execSelectPlan(plan, newValues, context);
}
 
Example #24
Source File: SHACLCWriter.java    From shacl with Apache License 2.0 5 votes vote down vote up
private void write(IndentedWriter out, Graph graph, PrefixMap prefixMap, String baseURI, Context context) {
	Model model = ModelFactory.createModelForGraph(graph);
	if(baseURI != null) {
		out.println("BASE <" + baseURI + ">");
		out.println();
	}
	writeImports(out, model.getResource(baseURI));
	writePrefixes(out, prefixMap);
	writeShapes(out, model);
	out.flush();
}
 
Example #25
Source File: IteratorPlan.java    From sparql-generate with Apache License 2.0 5 votes vote down vote up
public IteratorFunction getIterator(Context context) {
    if (iterator != null) {
        return iterator;
    }
    final IteratorFunctionRegistry sr = IteratorFunctionRegistry.get(context);
    IteratorFunctionFactory factory = sr.get(iri);
    if (factory == null) {
        throw new SPARQLExtException("Unknown Iterator Function: " + iri);
    }
    iterator = factory.create(iri);
    iterator.build(exprList);
    return iterator;
}
 
Example #26
Source File: SHACLPaths.java    From shacl with Apache License 2.0 5 votes vote down vote up
public static void addValueNodes(RDFNode focusNode, Path path, Collection<RDFNode> results) {
	Set<Node> seen = new HashSet<>();
	Iterator<Node> it = PathEval.eval(focusNode.getModel().getGraph(), focusNode.asNode(), path, Context.emptyContext);
	while(it.hasNext()) {
		Node node = it.next();
		if(!seen.contains(node)) {
			seen.add(node);
			results.add(focusNode.getModel().asRDFNode(node));
		}
	}
}
 
Example #27
Source File: RootPlan.java    From sparql-generate with Apache License 2.0 5 votes vote down vote up
private void execSelectPlan(final List<Var> variables, final List<Binding> values, final Context context) {
	if (selectPlan == null) {
		if (query.isSelectType()) {
			final List<String> listVar = variables.stream().map(Var::getVarName).collect(Collectors.toList());
			final Model model = ContextUtils.getDataset(context).getDefaultModel();
			final ResultSet resultSet = new ResultSetStream(listVar, model, values.iterator());
			ContextUtils.getSelectOutput(context).accept(resultSet);
		} else if(query.isGenerateType()) {
			generatePlan.exec(variables, values, context);
		} else if(query.isTemplateType()) {
			templatePlan.exec(variables, values, context);
		}
	} else {
		selectPlan.exec(variables, values, context, resultSet -> {
			if (query.isSelectType()) {
				ContextUtils.getSelectOutput(context).accept(resultSet);
			} else {
				final List<Var> newVariables = new ArrayList<>();
				newVariables.addAll(variables); // can we delete this?
				newVariables.addAll(selectPlan.getVars());
				final List<Binding> newValues = new ArrayList<>();
				while (resultSet.hasNext()) {
					final Binding p = EvalUtils.createBinding(resultSet.next());
					newValues.add(p);
				}
				if(query.isGenerateType()) {
					generatePlan.exec(newVariables, newValues, context);
				} else if(query.isTemplateType()) {
					templatePlan.exec(newVariables, newValues, context);
				}
			}
		});
	}
}
 
Example #28
Source File: DatasetDeclarationPlan.java    From sparql-generate with Apache License 2.0 5 votes vote down vote up
private void addNamedGraph(Binding binding, Context context, DatasetGraph dsg, SPARQLExtQuery generate, Expr name) {
	String sourceURI = evalSourceURI(binding, context, name);
	final String absURI = baseURI(sourceURI, baseURI);
	Node n = NodeFactory.createURI(absURI);
	Graph g = dsg.getGraph(n);
	if (g == null) {
		g = GraphFactory.createJenaDefaultGraph();
		dsg.addGraph(n, g);
	}
	loadGraph(binding, context, generate, g);
}
 
Example #29
Source File: DatasetDeclarationPlan.java    From sparql-generate with Apache License 2.0 5 votes vote down vote up
private String evalSourceURI(Binding binding, Context context, Expr sourceExpr) {
	if (binding == null) {
		throw new NullPointerException("No binding to evaluate the source expression " + sourceExpr);
	}
	try {
		FunctionEnv env = new FunctionEnvBase(context);
		NodeValue nodeValue = sourceExpr.eval(binding, env);
		if (!nodeValue.isIRI()) {
			throw new IllegalArgumentException("FROM source expression did not eval to a URI " + sourceExpr);
		}
		return nodeValue.asNode().getURI();
	} catch (ExprEvalException ex) {
		throw new IllegalArgumentException("Exception when evaluating the source expression " + sourceExpr, ex);
	}
}
 
Example #30
Source File: SHACLCReader.java    From shacl with Apache License 2.0 5 votes vote down vote up
@Override
public void read(Reader reader, String baseURI, ContentType ct, StreamRDF output, Context context) {
	try {
		SHACLCLexer lexer = new SHACLCLexer(new ANTLRInputStream(reader));
		read(lexer, baseURI, output);
	}
	catch(IOException ex) {
		ExceptionUtil.throwUnchecked(ex);
	}
}