/**
* 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
*
* http://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.
*/
package org.apache.jena.query.text.assembler;
import static org.apache.jena.query.text.assembler.TextVocab.NS ;
import java.util.Collection ;
import java.util.HashMap;
import java.util.List ;
import java.util.Map;
import org.apache.jena.assembler.Assembler ;
import org.apache.jena.assembler.Mode ;
import org.apache.jena.assembler.assemblers.AssemblerBase ;
import org.apache.jena.atlas.lib.StrUtils ;
import org.apache.jena.atlas.logging.Log ;
import org.apache.jena.ext.com.google.common.collect.HashMultimap;
import org.apache.jena.ext.com.google.common.collect.Multimap;
import org.apache.jena.graph.Node ;
import org.apache.jena.query.* ;
import org.apache.jena.query.text.EntityDefinition ;
import org.apache.jena.query.text.TextIndexException ;
import org.apache.jena.rdf.model.* ;
import org.apache.jena.vocabulary.RDF ;
import org.apache.lucene.analysis.Analyzer;
public class EntityDefinitionAssembler extends AssemblerBase implements Assembler
{
/*
<#entMap> a text:EntityMap ;
text:entityField "uri" ;
text:defaultField "text" ;
text:map (
[ text:field "text" ; text:predicate rdfs:label ]
[ text:field "type" ; text:predicate rdfs:type ]
) .
*/
@Override
public EntityDefinition open(Assembler a, Resource root, Mode mode)
{
String prologue = "PREFIX : <"+NS+"> PREFIX list: <http://jena.apache.org/ARQ/list#> " ;
Model model = root.getModel() ;
String qs1 = StrUtils.strjoinNL(prologue,
"SELECT * {" ,
" ?eMap :entityField ?entityField ;" ,
" :map ?map ;",
" :defaultField ?dftField ." ,
" OPTIONAL {" ,
" ?eMap :graphField ?graphField" ,
" }",
" OPTIONAL {" ,
" ?eMap :langField ?langField" ,
" }",
" OPTIONAL {" ,
" ?eMap :uidField ?uidField" ,
" }",
"}") ;
ParameterizedSparqlString pss = new ParameterizedSparqlString(qs1) ;
pss.setIri("eMap", root.getURI()) ;
Query query1 = QueryFactory.create(pss.toString()) ;
QueryExecution qexec1 = QueryExecutionFactory.create(query1, model) ;
ResultSet rs1 = qexec1.execSelect() ;
List<QuerySolution> results = ResultSetFormatter.toList(rs1) ;
if ( results.size() == 0 ) {
Log.warn(this, "Failed to find a valid EntityMap for : "+root) ;
throw new TextIndexException("Failed to find a valid EntityMap for : "+root) ;
}
if ( results.size() !=1 ) {
Log.warn(this, "Multiple matches for EntityMap for : "+root) ;
throw new TextIndexException("Multiple matches for EntityMap for : "+root) ;
}
QuerySolution qsol1 = results.get(0) ;
String entityField = qsol1.getLiteral("entityField").getLexicalForm() ;
String graphField = qsol1.contains("graphField") ? qsol1.getLiteral("graphField").getLexicalForm() : null;
String langField = qsol1.contains("langField") ? qsol1.getLiteral("langField").getLexicalForm() : null;
String defaultField = qsol1.contains("dftField") ? qsol1.getLiteral("dftField").getLexicalForm() : null ;
String uniqueIdField = qsol1.contains("uidField") ? qsol1.getLiteral("uidField").getLexicalForm() : null;
Multimap<String, Node> mapDefs = HashMultimap.create() ;
Map<String, Analyzer> analyzerDefs = new HashMap<>();
Statement listStmt = root.getProperty(TextVocab.pMap);
while (listStmt != null) {
RDFNode n = listStmt.getObject();
if (! n.isResource()) {
throw new TextIndexException("Text list node is not a resource : " + n);
}
Resource listResource = n.asResource();
if (listResource.equals(RDF.nil)) {
break; // end of the list
}
Statement listEntryStmt = listResource.getProperty(RDF.first);
if (listEntryStmt == null) {
throw new TextIndexException("Text map list is not well formed. No rdf:first property");
}
n = listEntryStmt.getObject();
if (! n.isResource()) {
throw new TextIndexException("Text map list entry is not a resource : " + n);
}
Resource listEntry = n.asResource();
Statement fieldStatement = listEntry.getProperty(TextVocab.pField);
if (fieldStatement == null) {
throw new TextIndexException("Text map entry has no field property");
}
n = fieldStatement.getObject();
if (! n.isLiteral()) {
throw new TextIndexException("Text map entry field property has no literal value : " + n);
}
String field = n.asLiteral().getLexicalForm();
Statement predicateStatement = listEntry.getProperty(TextVocab.pPredicate);
if (predicateStatement == null) {
throw new TextIndexException("Text map entry has no predicate property");
}
n = predicateStatement.getObject();
if (! n.isURIResource()) {
throw new TextIndexException("Text map entry predicate property has non resource value : " + n);
}
mapDefs.put(field, n.asNode()) ;
Statement analyzerStatement = listEntry.getProperty(TextVocab.pAnalyzer);
if (analyzerStatement != null) {
n = analyzerStatement.getObject();
if (! n.isResource()) {
throw new TextIndexException("Text map entry analyzer property is not a resource : " + n);
}
Resource analyzerResource = n.asResource();
Analyzer analyzer = (Analyzer) a.open(analyzerResource);
analyzerDefs.put(field, analyzer);
}
// move on to the next element in the list
listStmt = listResource.getProperty(RDF.rest);
}
// Primary field/predicate
if ( defaultField != null ) {
Collection<Node> c = mapDefs.get(defaultField) ;
if ( c.isEmpty() )
throw new TextIndexException("No definition of primary field '"+defaultField+"'") ;
}
EntityDefinition docDef = new EntityDefinition(entityField, defaultField);
docDef.setGraphField(graphField);
docDef.setLangField(langField);
docDef.setUidField(uniqueIdField);
for ( String f : mapDefs.keys() ) {
for ( Node p : mapDefs.get(f))
docDef.set(f, p) ;
}
for (String f : analyzerDefs.keySet()) {
docDef.setAnalyzer(f, analyzerDefs.get(f));
}
return docDef ;
}
}