
com.hp.autonomy.searchcomponents.idol.parametricvalues.IdolParametricValuesService Maven / Gradle / Ivy
/*
* Copyright 2015 Hewlett-Packard Development Company, L.P.
* Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License.
*/
package com.hp.autonomy.searchcomponents.idol.parametricvalues;
import com.autonomy.aci.client.services.AciErrorException;
import com.autonomy.aci.client.services.AciService;
import com.autonomy.aci.client.services.Processor;
import com.autonomy.aci.client.util.AciParameters;
import com.hp.autonomy.aci.content.ranges.Range;
import com.hp.autonomy.aci.content.ranges.Ranges;
import com.hp.autonomy.idolutils.processors.AciResponseJaxbProcessorFactory;
import com.hp.autonomy.searchcomponents.core.caching.CacheNames;
import com.hp.autonomy.searchcomponents.core.fields.FieldsService;
import com.hp.autonomy.searchcomponents.core.parametricvalues.AdaptiveBucketSizeEvaluatorFactory;
import com.hp.autonomy.searchcomponents.core.parametricvalues.BucketSizeEvaluator;
import com.hp.autonomy.searchcomponents.core.parametricvalues.BucketingParams;
import com.hp.autonomy.searchcomponents.core.parametricvalues.ParametricRequest;
import com.hp.autonomy.searchcomponents.core.parametricvalues.ParametricValuesService;
import com.hp.autonomy.searchcomponents.core.search.QueryRestrictions;
import com.hp.autonomy.searchcomponents.idol.fields.IdolFieldsRequest;
import com.hp.autonomy.searchcomponents.idol.search.HavenSearchAciParameterHandler;
import com.hp.autonomy.types.idol.FlatField;
import com.hp.autonomy.types.idol.GetQueryTagValuesResponseData;
import com.hp.autonomy.types.idol.RecursiveField;
import com.hp.autonomy.types.idol.TagValue;
import com.hp.autonomy.types.requests.idol.actions.tags.QueryTagCountInfo;
import com.hp.autonomy.types.requests.idol.actions.tags.QueryTagInfo;
import com.hp.autonomy.types.requests.idol.actions.tags.RangeInfo;
import com.hp.autonomy.types.requests.idol.actions.tags.TagActions;
import com.hp.autonomy.types.requests.idol.actions.tags.TagName;
import com.hp.autonomy.types.requests.idol.actions.tags.params.FieldTypeParam;
import com.hp.autonomy.types.requests.idol.actions.tags.params.GetQueryTagValuesParams;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import javax.xml.bind.JAXBElement;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
@SuppressWarnings("WeakerAccess")
@Service
public class IdolParametricValuesService implements ParametricValuesService {
static final String VALUE_NODE_NAME = "value";
static final String VALUES_NODE_NAME = "values";
static final String VALUE_MIN_NODE_NAME = "valuemin";
static final String VALUE_MAX_NODE_NAME = "valuemax";
private final HavenSearchAciParameterHandler parameterHandler;
private final FieldsService fieldsService;
private final AciService contentAciService;
private final AdaptiveBucketSizeEvaluatorFactory bucketSizeEvaluatorFactory;
private final Processor queryTagValuesResponseProcessor;
@Autowired
public IdolParametricValuesService(final HavenSearchAciParameterHandler parameterHandler,
final FieldsService fieldsService,
final AciService contentAciService,
final AciResponseJaxbProcessorFactory aciResponseProcessorFactory,
final AdaptiveBucketSizeEvaluatorFactory bucketSizeEvaluatorFactory) {
this.parameterHandler = parameterHandler;
this.fieldsService = fieldsService;
this.contentAciService = contentAciService;
this.bucketSizeEvaluatorFactory = bucketSizeEvaluatorFactory;
queryTagValuesResponseProcessor = aciResponseProcessorFactory.createAciResponseProcessor(GetQueryTagValuesResponseData.class);
}
@Override
public Set getAllParametricValues(final IdolParametricRequest parametricRequest) throws AciErrorException {
final Collection fieldNames = new HashSet<>();
fieldNames.addAll(parametricRequest.getFieldNames());
if (fieldNames.isEmpty()) {
fieldNames.addAll(lookupFieldIds());
}
final Set results;
if (fieldNames.isEmpty()) {
results = Collections.emptySet();
} else {
final List fields = getFlatFields(parametricRequest, fieldNames);
results = new LinkedHashSet<>(fields.size());
for (final FlatField field : fields) {
final List> valueElements = field.getValueAndSubvalueOrValues();
final LinkedHashSet values = new LinkedHashSet<>(valueElements.size());
for (final JAXBElement> element : valueElements) {
if (VALUE_NODE_NAME.equals(element.getName().getLocalPart())) {
final TagValue tagValue = (TagValue) element.getValue();
values.add(new QueryTagCountInfo(tagValue.getValue(), tagValue.getCount()));
}
}
if (!values.isEmpty()) {
final TagName tagName = new TagName(field.getName().get(0));
results.add(new QueryTagInfo(tagName, values));
}
}
}
return results;
}
@Override
@Cacheable(CacheNames.PARAMETRIC_VALUES_IN_BUCKETS)
public List getNumericParametricValuesInBuckets(final IdolParametricRequest parametricRequest, final Map bucketingParamsPerField) throws AciErrorException {
final int numberOfFields = bucketingParamsPerField.size();
final List results = new ArrayList<>(numberOfFields);
final Map bucketSizeEvaluators = new HashMap<>(numberOfFields);
final Map fieldsNeedingMetadata = new HashMap<>(numberOfFields);
for (final Map.Entry entry : bucketingParamsPerField.entrySet()) {
final int targetNumberOfBuckets = entry.getValue().getTargetNumberOfBuckets();
if ((entry.getValue().getMin() == null || entry.getValue().getMax() == null) && targetNumberOfBuckets > 0) {
fieldsNeedingMetadata.put(entry.getKey(), entry.getValue());
} else if (targetNumberOfBuckets > 0) {
bucketSizeEvaluators.put(entry.getKey(), bucketSizeEvaluatorFactory.getBucketSizeEvaluator(entry.getValue()));
}
}
if (!fieldsNeedingMetadata.isEmpty()) {
getMissingValueBounds(parametricRequest, fieldsNeedingMetadata, bucketSizeEvaluators);
}
if (!bucketSizeEvaluators.isEmpty()) {
final List ranges = generateRanges(bucketSizeEvaluators);
queryForRanges(results, parametricRequest, bucketSizeEvaluators, ranges);
}
return results;
}
@Override
public List getDependentParametricValues(final IdolParametricRequest parametricRequest) throws AciErrorException {
final Collection fieldNames = new ArrayList<>();
fieldNames.addAll(parametricRequest.getFieldNames());
if (fieldNames.isEmpty()) {
fieldNames.addAll(lookupFieldIds());
}
final List results;
if (fieldNames.isEmpty()) {
results = Collections.emptyList();
} else {
final AciParameters aciParameters = createAciParameters(parametricRequest.getQueryRestrictions(), parametricRequest.isModified());
aciParameters.add(GetQueryTagValuesParams.DocumentCount.name(), true);
aciParameters.add(GetQueryTagValuesParams.FieldName.name(), StringUtils.join(fieldNames.toArray(), ','));
aciParameters.add(GetQueryTagValuesParams.FieldDependence.name(), true);
aciParameters.add(GetQueryTagValuesParams.FieldDependenceMultiLevel.name(), true);
final GetQueryTagValuesResponseData responseData = contentAciService.executeAction(aciParameters, queryTagValuesResponseProcessor);
results = responseData.getValues() == null ? Collections.emptyList() : responseData.getValues().getField();
}
return results;
}
private AciParameters createAciParameters(final QueryRestrictions queryRestrictions, final boolean modified) {
final AciParameters aciParameters = new AciParameters(TagActions.GetQueryTagValues.name());
parameterHandler.addSearchRestrictions(aciParameters, queryRestrictions);
if (modified) {
parameterHandler.addQmsParameters(aciParameters, queryRestrictions);
}
return aciParameters;
}
private Collection lookupFieldIds() {
final List fields = fieldsService.getFields(new IdolFieldsRequest.Builder().build(), FieldTypeParam.Parametric).get(FieldTypeParam.Parametric);
final Collection fieldIds = new ArrayList<>(fields.size());
for (final TagName field : fields) {
fieldIds.add(field.getId());
}
return fieldIds;
}
private void getMissingValueBounds(final ParametricRequest parametricRequest, final Map fieldsNeedingMetadata, final Map bucketSizeEvaluators) {
final AciParameters aciParameters = createAciParameters(parametricRequest.getQueryRestrictions(), parametricRequest.isModified());
aciParameters.add(GetQueryTagValuesParams.MaxValues.name(), 1);
aciParameters.add(GetQueryTagValuesParams.FieldName.name(), StringUtils.join(fieldsNeedingMetadata.keySet().toArray(), ','));
aciParameters.add(GetQueryTagValuesParams.ValueDetails.name(), true);
final GetQueryTagValuesResponseData responseData = contentAciService.executeAction(aciParameters, queryTagValuesResponseProcessor);
final Collection fields = responseData.getField();
for (final FlatField field : fields) {
final List> valueElements = field.getValueAndSubvalueOrValues();
final TagName tagName = new TagName(field.getName().get(0));
double minValue = 0.0;
double maxValue = 0.0;
for (final JAXBElement> element : valueElements) {
final String elementLocalName = element.getName().getLocalPart();
if (VALUE_MIN_NODE_NAME.equals(elementLocalName)) {
minValue = (Float) element.getValue();
} else if (VALUE_MAX_NODE_NAME.equals(elementLocalName)) {
maxValue = (Float) element.getValue();
}
}
final BucketingParams bucketingParams = fieldsNeedingMetadata.get(tagName.getId());
final BucketSizeEvaluator bucketSizeEvaluator = bucketSizeEvaluatorFactory.getBucketSizeEvaluator(new BucketingParams(bucketingParams, minValue, maxValue));
bucketSizeEvaluators.put(tagName.getId(), bucketSizeEvaluator);
}
}
private List generateRanges(final Map bucketSizeEvaluators) {
final List ranges = new ArrayList<>(bucketSizeEvaluators.size());
for (final Map.Entry entry : bucketSizeEvaluators.entrySet()) {
final BucketSizeEvaluator bucketSizeEvaluator = entry.getValue();
double value = bucketSizeEvaluator.getMin();
final List boundaries = new ArrayList<>(bucketSizeEvaluator.getTargetNumberOfBuckets());
boundaries.add(value);
while ((value += bucketSizeEvaluator.getBucketSize()) < bucketSizeEvaluator.getMax()) {
boundaries.add(value);
}
if (!bucketSizeEvaluator.unboundedMax()) {
boundaries.add(bucketSizeEvaluator.getMax());
}
ranges.add(new Range(entry.getKey(), ArrayUtils.toPrimitive(boundaries.toArray(new Double[boundaries.size()])), bucketSizeEvaluator.unboundedMax()));
}
return ranges;
}
private void queryForRanges(final List results, final ParametricRequest parametricRequest, final Map bucketSizeEvaluators, final List ranges) {
final IdolParametricRequest bucketingRequest = new IdolParametricRequest.Builder()
.setFieldNames(new ArrayList<>(bucketSizeEvaluators.keySet()))
.setMaxValues(null)
.setSort(parametricRequest.getSort())
.setRanges(ranges)
.setQueryRestrictions(parametricRequest.getQueryRestrictions())
.setModified(parametricRequest.isModified())
.build();
final List flatFields = getFlatFields(bucketingRequest, parametricRequest.getFieldNames());
for (final FlatField field : flatFields) {
final TagName tagName = new TagName(field.getName().get(0));
final BucketSizeEvaluator bucketSizeEvaluator = bucketSizeEvaluators.get(tagName.getId());
final List> valueElements = field.getValueAndSubvalueOrValues();
final Map values = new TreeMap<>();
int count = 0;
for (final JAXBElement> element : valueElements) {
final String elementLocalName = element.getName().getLocalPart();
if (VALUE_NODE_NAME.equals(elementLocalName)) {
final TagValue tagValue = (TagValue) element.getValue();
final String[] rangeValues = tagValue.getValue().split(",");
final double min = NumberUtils.toDouble(rangeValues[0], bucketSizeEvaluator.getMin());
final double max = rangeValues.length > 1 ? Double.parseDouble(rangeValues[1]) : bucketSizeEvaluator.getMax();
values.put(min, new RangeInfo.Value(tagValue.getCount(), min, max));
} else if (VALUES_NODE_NAME.equals(elementLocalName)) {
count = (Integer) element.getValue();
}
}
for (double d = bucketSizeEvaluator.getMin(); d < bucketSizeEvaluator.getMax(); d += bucketSizeEvaluator.getBucketSize()) {
if (!values.containsKey(d)) {
values.put(d, new RangeInfo.Value(0, d, d + bucketSizeEvaluator.getBucketSize()));
}
}
results.add(new RangeInfo(tagName, count, bucketSizeEvaluator.getMin(), bucketSizeEvaluator.getMax(), bucketSizeEvaluator.getBucketSize(), new ArrayList<>(values.values())));
}
}
private List getFlatFields(final ParametricRequest parametricRequest, final Collection fieldNames) {
final AciParameters aciParameters = new AciParameters(TagActions.GetQueryTagValues.name());
parameterHandler.addSearchRestrictions(aciParameters, parametricRequest.getQueryRestrictions());
if (parametricRequest.isModified()) {
parameterHandler.addQmsParameters(aciParameters, parametricRequest.getQueryRestrictions());
}
aciParameters.add(GetQueryTagValuesParams.DocumentCount.name(), true);
aciParameters.add(GetQueryTagValuesParams.MaxValues.name(), parametricRequest.getMaxValues());
aciParameters.add(GetQueryTagValuesParams.FieldName.name(), StringUtils.join(fieldNames.toArray(), ','));
aciParameters.add(GetQueryTagValuesParams.Sort.name(), parametricRequest.getSort());
aciParameters.add(GetQueryTagValuesParams.Ranges.name(), new Ranges(parametricRequest.getRanges()));
aciParameters.add(GetQueryTagValuesParams.ValueDetails.name(), true);
final GetQueryTagValuesResponseData responseData = contentAciService.executeAction(aciParameters, queryTagValuesResponseProcessor);
return responseData.getField();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy