All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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