use of org.apache.stanbol.entityhub.servicesapi.query.ValueConstraint in project stanbol by apache.
the class SparqlQueryUtils method addFieldConstraint.
/**
* Adds the WHERE clause of the SPARQL query.
* <p>
* If the {@link SparqlEndpointTypeEnum SPARQL endpoint} supports SPARQL 1.1 subqueries, than this adds also the
* LIMIT and OFFSET to in inner SELECT that only selects the id.
*
* @param queryString
* the SPARQL query string to add the WHERE
* @param query
* the query
* @param selectedFields
* the selected fields
* @param endpointType
* The type of the endpoint (used to write optimised queries for endpoint type specific
* extensions
*/
private static void addFieldConstraint(final StringBuilder queryString, SparqlFieldQuery query, Map<String, String> selectedFields, SparqlEndpointTypeEnum endpointType) {
// we need temporary variables with unique names
String varPrefix = "tmp";
int[] varNum = new int[] { 1 };
// used to open brackets for the select part of the constraints
boolean first = true;
// determine if sub-selects are supported and if we need a sub-select
// (more than the id is selected)
boolean subSelectState = isSubSelectState(endpointType, selectedFields);
log.trace("add field constraints is in a sub-select-state [{}].", (subSelectState ? "yes" : "no"));
// if we uses a sub query to select the ids, we need to add the graph
// pattern
// of all selected fields outside of the sub query
Map<String, String> tmpSelectedFields = subSelectState ? new HashMap<String, String>(selectedFields) : null;
String intend;
if (subSelectState) {
// additional intend because of sub query (3*2)
intend = " ";
} else {
// normal intend (2*2)
intend = " ";
}
Iterator<Entry<String, Constraint>> constraintIterator = query.iterator();
while (constraintIterator.hasNext()) {
Entry<String, Constraint> fieldConstraint = constraintIterator.next();
if (first) {
queryString.append(" { \n");
if (subSelectState) {
String rootVarName = selectedFields.get(null);
queryString.append(" SELECT ?").append(rootVarName).append(" \n");
queryString.append(" WHERE { \n");
}
first = false;
}
String field = fieldConstraint.getKey();
Constraint constraint = fieldConstraint.getValue();
log.trace("adding a constraint [type :: {}][field :: {}][prefix :: {}][intent :: {}].", new Object[] { constraint.getType(), field, varPrefix, intend });
boolean added = true;
switch(constraint.getType()) {
case value:
addValueConstraint(queryString, field, (ValueConstraint) constraint, selectedFields, varPrefix, varNum, intend);
break;
case text:
String var = addFieldGraphPattern(queryString, field, selectedFields, varPrefix, varNum, intend);
addTextConstraint(queryString, var, (TextConstraint) constraint, endpointType, intend);
break;
case range:
var = addFieldGraphPattern(queryString, field, selectedFields, varPrefix, varNum, intend);
addRangeConstriant(queryString, var, (RangeConstraint) constraint, intend);
break;
default:
log.warn("Constraint Type '{}' not supported in SPARQL! Constriant {} " + "will be not included in the query!", fieldConstraint.getValue().getType(), fieldConstraint.getValue());
added = false;
break;
}
if (added) {
queryString.append(" . \n");
}
}
// rank the graph selected by the query
if (subSelectState) {
addRankingConstraints(endpointType, queryString, selectedFields.get(null));
}
if (!first) {
if (subSelectState) {
queryString.append(" } \n");
// re-add all selected fields to be added as selects because in
// the sub-query we only select the ID!
selectedFields = tmpSelectedFields;
// ranking needs also to be added to the sub-query (to correctly
// process LIMIT and OFFSET
addRankingOrder(endpointType, queryString, selectedFields.get(null), " ");
// add LIMIT and OFFSET to the sub-query!
// TODO: add link to the email
queryString.append(" ");
addLimit(query.getLimit(), queryString);
queryString.append(" ");
addOffset(query, queryString);
queryString.append(" ");
}
queryString.append(" } \n");
}
// if no subqueries are used we need now to add the ranking constraints
if (!subSelectState) {
addRankingConstraints(endpointType, queryString, selectedFields.get(null));
}
// root variable
while (selectedFields.size() > 1) {
// if this is the only left element
// we are done
Iterator<String> it = selectedFields.keySet().iterator();
// we need to get a non null value from the map
String actField;
do {
// the outer while ensures an non null value so we need not to
// use hasNext
actField = it.next();
} while (actField == null);
queryString.append(" OPTIONAL { ");
// NOTE the following Method removes the written mapping from the
// Map
addFieldGraphPattern(queryString, actField, selectedFields, varPrefix, varNum, "");
queryString.append(". } \n");
}
}
use of org.apache.stanbol.entityhub.servicesapi.query.ValueConstraint in project stanbol by apache.
the class BaseGoogleRefineReconcileResource method addPropertyConstraints.
/**
* @param rQuery
* @param query
*/
private void addPropertyConstraints(ReconcileQuery rQuery, FieldQuery query) {
Collection<String> ids = new HashSet<String>();
// keep order for texts
List<String> texts = new ArrayList<String>();
Collection<Object> values = new HashSet<Object>();
// hold all references for @references special property
HashSet<String> references = new HashSet<String>();
// holds all texts for @fullText special property
List<String> fullText = null;
// holds the context for the @similarity special property
Collection<String> similarityContext = null;
// the field used for the @similarity special property
HashSet<String> similarityFields = new LinkedHashSet<String>();
for (Entry<ReconcileProperty, Collection<ReconcileValue>> propertyEntry : rQuery.getProperties()) {
ReconcileProperty property = propertyEntry.getKey();
// collect the properties
for (ReconcileValue value : propertyEntry.getValue()) {
if (value.getId() != null) {
ids.add(value.getId());
}
if (value.getValue() instanceof String) {
texts.add((String) value.getValue());
} else {
values.add(value.getValue());
}
}
// handle supported special properties
if (property.isSpecial()) {
if (property.getName().equalsIgnoreCase("references")) {
// if Users do parse parameters - so we need to collect all values
if (property.getParameter() != null) {
log.warn("parameters are not supported for @references -> ignore '{}'", property.getParameter());
}
if (ids.isEmpty()) {
log.warn("No URI values present for parsed @references property! (values: " + propertyEntry.getValue());
}
for (String id : ids) {
references.add(id);
}
} else if (property.getName().equalsIgnoreCase("fulltext")) {
// if Users do parse parameters - so we need to collect all values
if (property.getParameter() != null) {
log.warn("parameters are not supported for @fullText -> ignore '{}'", property.getParameter());
}
fullText = texts;
} else if (property.getName().equalsIgnoreCase("similarity")) {
String propUri = property.getParameter() != null ? nsPrefixService.getFullName(property.getParameter()) : SpecialFieldEnum.fullText.getUri();
if (propUri != null) {
similarityFields.add(propUri);
} else {
// TODO: maybe throw an Exception instead
log.warn("Unknown prefix '{}' used by Google Refine query parameter of property '{}'! " + "Will use the full text field as fallback", NamespaceMappingUtils.getPrefix(property.getParameter()), property);
similarityFields.add(SpecialFieldEnum.fullText.getUri());
}
similarityContext = texts;
} else {
// TODO: implement LDPATH support
log.warn("ignore unsupported special property {}", property);
}
} else {
// * non Reference | Text | Datatype values are ignored
if (!ids.isEmpty()) {
// only references -> create reference constraint
query.setConstraint(property.getName(), new ReferenceConstraint(ids));
if (ids.size() != propertyEntry.getValue().size()) {
log.info("Only some of the parsed values of the field {} contain" + "references -> will ignore values with missing references");
}
} else if (!texts.isEmpty()) {
// NOTE: This will use OR over all texts. To enforce AND one
// would need to parse a single string with all values e.g. by
// using StringUtils.join(texts," ")
query.setConstraint(property.getName(), new TextConstraint(texts));
if (ids.size() != propertyEntry.getValue().size()) {
log.info("Only some of the parsed values of the field {} are" + "of type String -> will ignore non-string values");
}
} else if (!values.isEmpty()) {
query.setConstraint(property.getName(), new ValueConstraint(values));
}
// else no values ... ignore property
}
// clean up
ids.clear();
values.clear();
}
// now add constraints for the collected special properties
if (!references.isEmpty()) {
// add references constraint
ReferenceConstraint refConstraint = new ReferenceConstraint(references, MODE.all);
query.setConstraint(SpecialFieldEnum.references.getUri(), refConstraint);
}
if (fullText != null && !fullText.isEmpty()) {
TextConstraint textConstraint = new TextConstraint(fullText);
query.setConstraint(SpecialFieldEnum.fullText.getUri(), textConstraint);
// add full text constraint
}
if (similarityContext != null && !similarityContext.isEmpty()) {
// add similarity constraint
Iterator<String> fieldIt = similarityFields.iterator();
String field = fieldIt.next();
SimilarityConstraint simConstraint;
if (fieldIt.hasNext()) {
List<String> addFields = new ArrayList<String>(similarityFields.size() - 1);
while (fieldIt.hasNext()) {
addFields.add(fieldIt.next());
}
simConstraint = new SimilarityConstraint(similarityContext, DataTypeEnum.Text, addFields);
} else {
simConstraint = new SimilarityConstraint(similarityContext, DataTypeEnum.Text);
}
query.setConstraint(field, simConstraint);
}
}
use of org.apache.stanbol.entityhub.servicesapi.query.ValueConstraint in project stanbol by apache.
the class AbstractBackend method listSubjects.
@Override
public Collection<Object> listSubjects(Object property, Object object) {
FieldQuery query = createQuery();
if (this.isURI(object)) {
query.setConstraint(property.toString(), new ReferenceConstraint(object.toString()));
} else if (object instanceof Text) {
Text text = (Text) object;
TextConstraint constraint;
if (text.getLanguage() == null) {
constraint = new TextConstraint(text.getText(), PatternType.none, true);
} else {
constraint = new TextConstraint(text.getText(), PatternType.none, true, text.getLanguage());
}
query.setConstraint(property.toString(), constraint);
} else {
Set<DataTypeEnum> dataTypes = DataTypeEnum.getPrimaryDataTypes(object.getClass());
if (dataTypes == null || dataTypes.isEmpty()) {
query.setConstraint(property.toString(), new ValueConstraint(object));
} else {
Collection<String> types = new ArrayList<String>(dataTypes.size());
for (DataTypeEnum type : dataTypes) {
types.add(type.getUri());
}
query.setConstraint(property.toString(), new ValueConstraint(object, types));
}
}
query.setLimit(Integer.valueOf(DEFAULT_MAX_SELECT));
QueryResultList<String> results;
try {
results = query(query);
} catch (EntityhubException e) {
throw new IllegalStateException("Unable to query for resources with value '" + object + "' on property '" + property + "'!", e);
}
Collection<Object> references;
if (results.isEmpty()) {
references = Collections.emptySet();
} else if (results.size() == 1) {
// assuming that a single result is a likely case
references = Collections.singleton((Object) getValueFactory().createReference(results.iterator().next()));
} else {
int offset = 0;
references = new HashSet<Object>(results.size());
for (String result : results) {
references.add(getValueFactory().createReference(result));
}
while (results.size() >= DEFAULT_MAX_SELECT && references.size() <= DEFAULT_MAX_RESULTS - DEFAULT_MAX_SELECT) {
offset = offset + results.size();
query.setOffset(offset);
try {
results = query(query);
} catch (EntityhubException e) {
throw new IllegalStateException("Unable to query for resources with value '" + object + "' on property '" + property + "'!", e);
}
for (String result : results) {
references.add(getValueFactory().createReference(result));
}
}
}
return references;
}
use of org.apache.stanbol.entityhub.servicesapi.query.ValueConstraint in project stanbol by apache.
the class YardTest method testFindMultipleConstraints.
/**
* Tests simple {@link RangeConstraint}
*/
@Test
public void testFindMultipleConstraints() {
// init the test data
FieldQueryTestData data = getFieldQueryTestData();
// Integer Range and reference query
FieldQuery query = getYard().getQueryFactory().createFieldQuery();
// selects r2, r2en, r2de, r5
query.setConstraint(data.intField, new RangeConstraint(data.intValue2, data.intValue5, true));
// selects r1, r1en, r1de, r5
query.setConstraint(data.refField, new ReferenceConstraint(data.refValue1.getReference()));
query.addSelectedField(data.intField);
query.addSelectedField(data.refField);
validateQueryResults(query, getYard().find(query), Arrays.asList(data.r5.getId()), Arrays.asList(data.intField, data.refField));
// text and reference
query = getYard().getQueryFactory().createFieldQuery();
// selects r1en and r2en
String wildcard = data.textValue1.getText();
wildcard = wildcard.substring(0, wildcard.length() - 1) + "*";
query.setConstraint(data.textField, new TextConstraint(wildcard, PatternType.wildcard, false, "en"));
// selects r1, r1en, r1de, r5
query.setConstraint(data.refField, new ReferenceConstraint(data.refValue1.getReference()));
query.addSelectedField(data.refField);
query.addSelectedField(data.textField);
validateQueryResults(query, getYard().find(query), Arrays.asList(data.r1en.getId()), Arrays.asList(data.refField, data.textField));
// text and value
query = getYard().getQueryFactory().createFieldQuery();
// selects r1de and r2de
query.setConstraint(data.textField, new TextConstraint(wildcard, PatternType.wildcard, false, "de"));
// selects r2, r2en, r2de
query.setConstraint(data.intField, new ValueConstraint(data.intValue2));
query.addSelectedField(data.refField);
query.addSelectedField(data.textField);
validateQueryResults(query, getYard().find(query), Arrays.asList(data.r2de.getId()), Arrays.asList(data.refField, data.textField));
}
use of org.apache.stanbol.entityhub.servicesapi.query.ValueConstraint in project stanbol by apache.
the class SolrQueryFactory method initValueConstraint.
/**
* @param indexConstraint
* @param refConstraint
*/
private void initValueConstraint(IndexConstraint indexConstraint) {
ValueConstraint valueConstraint = (ValueConstraint) indexConstraint.getConstraint();
if (valueConstraint.getValues() == null) {
indexConstraint.setInvalid(String.format("ValueConstraint without a value - that check only any value for " + "the parsed datatypes %s is present - can not be supported by a Solr query!", valueConstraint.getDataTypes()));
} else {
// first process the parsed dataTypes to get the supported types
List<IndexDataType> indexDataTypes = new ArrayList<IndexDataType>();
List<String> acceptedDataTypes = new ArrayList<String>();
if (valueConstraint.getDataTypes() != null) {
for (String dataType : valueConstraint.getDataTypes()) {
IndexDataTypeEnum indexDataTypeEnumEntry = IndexDataTypeEnum.forUri(dataType);
if (indexDataTypeEnumEntry != null) {
indexDataTypes.add(indexDataTypeEnumEntry.getIndexType());
acceptedDataTypes.add(dataType);
} else {
// TODO: Add possibility to add warnings to indexConstraints
log.warn("A Datatype parsed for a ValueConstraint is not " + "supported and will be ignored (dataTypeUri={})", dataType);
}
}
}
// we support only a single dataType ...
// ... therefore remove additional data types from the ValueConstraint
IndexDataType indexDataType = null;
if (!indexDataTypes.isEmpty()) {
indexDataType = indexDataTypes.get(0);
if (indexDataTypes.size() > 1) {
log.warn("Only a single DataType is supported for ValueConstraints!");
while (acceptedDataTypes.size() > 1) {
String ignored = acceptedDataTypes.remove(acceptedDataTypes.size() - 1);
log.warn(" > ignore parsed dataType {}", ignored);
}
}
}
// else empty we will initialise based on the first parsed value!
ConstraintValue constraintValue = new ConstraintValue(valueConstraint.getMode());
// init the boost
addBoost(constraintValue, valueConstraint);
for (Object value : valueConstraint.getValues()) {
IndexValue indexValue;
if (indexDataType == null) {
// get the dataType based on the type of the value
try {
indexValue = indexValueFactory.createIndexValue(value);
} catch (NoConverterException e) {
// if not found use the toString() and string as type
log.warn("Unable to create IndexValue for value {} (type: {}). Create IndexValue manually by using the first parsed IndexDataType {}", new Object[] { value, value.getClass(), IndexDataTypeEnum.STR.getIndexType() });
indexValue = new IndexValue(value.toString(), IndexDataTypeEnum.STR.getIndexType());
}
// initialise the IndexDataType for this query based on the first parsed value
indexDataType = indexValue.getType();
} else {
indexValue = new IndexValue(value.toString(), indexDataType);
}
// add the constraint
constraintValue.getValues().add(indexValue);
}
// indexConstraint.setFieldConstraint(IndexConstraintTypeEnum.DATATYPE, indexDataType);
IndexField indexField;
if (IndexDataTypeEnum.TXT.getIndexType().equals(indexDataType)) {
// NOTE: in case of TEXT we need also to add the language to create a valid
// query!
// * We take the language of the first parsed element
indexField = new IndexField(indexConstraint.getPath(), indexDataType, constraintValue.getValues().iterator().next().getLanguage());
} else {
indexField = new IndexField(indexConstraint.getPath(), indexDataType);
}
// set FIELD, DATATYPE and LANGUAGE constraint by using the indexField
indexConstraint.setIndexFieldConstraints(indexField);
// set the VALUE
// TODO: We need to somehow pass the MODE so that the encoder knows how
// to encode the values
indexConstraint.setFieldConstraint(IndexConstraintTypeEnum.EQ, constraintValue);
// update this constraint!
if (valueConstraint instanceof ReferenceConstraint) {
indexConstraint.setFieldQueryConstraint(valueConstraint);
} else {
indexConstraint.setFieldQueryConstraint(new ValueConstraint(valueConstraint.getValues(), Arrays.asList(indexDataType.getId())));
}
}
}
Aggregations