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

com.hp.autonomy.searchcomponents.hod.parametricvalues.HodParametricValuesService 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.hod.parametricvalues;

import com.hp.autonomy.frontend.configuration.ConfigService;
import com.hp.autonomy.hod.caching.CachingConfiguration;
import com.hp.autonomy.hod.client.api.resource.ResourceIdentifier;
import com.hp.autonomy.hod.client.api.textindex.query.parametric.FieldNames;
import com.hp.autonomy.hod.client.api.textindex.query.parametric.GetParametricValuesRequestBuilder;
import com.hp.autonomy.hod.client.api.textindex.query.parametric.GetParametricValuesService;
import com.hp.autonomy.hod.client.api.textindex.query.parametric.ParametricSort;
import com.hp.autonomy.hod.client.error.HodErrorException;
import com.hp.autonomy.hod.sso.HodAuthenticationPrincipal;
import com.hpe.bigdata.frontend.spring.authentication.AuthenticationInformationRetriever;
import com.hp.autonomy.searchcomponents.core.caching.CacheNames;
import com.hp.autonomy.searchcomponents.core.fields.FieldsService;
import com.hp.autonomy.searchcomponents.core.parametricvalues.AbstractParametricValuesService;
import com.hp.autonomy.searchcomponents.core.parametricvalues.BucketingParams;
import com.hp.autonomy.searchcomponents.core.parametricvalues.ParametricRequest;
import com.hp.autonomy.searchcomponents.hod.configuration.HodSearchCapable;
import com.hp.autonomy.searchcomponents.hod.fields.HodFieldsRequest;
import com.hp.autonomy.types.idol.RecursiveField;
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.TagName;
import com.hp.autonomy.types.requests.idol.actions.tags.ValueDetails;
import com.hp.autonomy.types.requests.idol.actions.tags.params.FieldTypeParam;
import org.apache.commons.lang3.NotImplementedException;
import org.springframework.cache.annotation.Cacheable;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

public class HodParametricValuesService extends AbstractParametricValuesService {
    private final FieldsService fieldsService;
    private final GetParametricValuesService getParametricValuesService;
    private final ConfigService configService;
    private final AuthenticationInformationRetriever authenticationInformationRetriever;

    public HodParametricValuesService(
            final FieldsService fieldsService,
            final GetParametricValuesService getParametricValuesService,
            final ConfigService configService,
            final AuthenticationInformationRetriever authenticationInformationRetriever
    ) {
        this.fieldsService = fieldsService;
        this.getParametricValuesService = getParametricValuesService;
        this.configService = configService;
        this.authenticationInformationRetriever = authenticationInformationRetriever;
    }

    @Override
    @Cacheable(value = CacheNames.PARAMETRIC_VALUES, cacheResolver = CachingConfiguration.PER_USER_CACHE_RESOLVER_NAME)
    public Set getAllParametricValues(final HodParametricRequest parametricRequest) throws HodErrorException {
        final Collection fieldNames = new HashSet<>();
        fieldNames.addAll(parametricRequest.getFieldNames());
        if (fieldNames.isEmpty()) {
            fieldNames.addAll(lookupFieldIds(parametricRequest.getQueryRestrictions().getDatabases()));
        }

        final Set results;
        if (fieldNames.isEmpty()) {
            results = Collections.emptySet();
        } else {
            final FieldNames parametricFieldNames = getParametricValues(parametricRequest, fieldNames);
            final Set fieldNamesSet = parametricFieldNames.getFieldNames();

            results = new HashSet<>();
            for (final String name : fieldNamesSet) {
                final Set values = new HashSet<>(parametricFieldNames.getValuesAndCountsForFieldName(name));
                if (!values.isEmpty()) {
                    results.add(new QueryTagInfo(new TagName(name), values));
                }
            }
        }

        return results;
    }

    //TODO use the same method as IDOL for bucketing, once HOD-2784 and HOD-2785 are complete
    @Override
    @Cacheable(value = CacheNames.PARAMETRIC_VALUES_IN_BUCKETS, cacheResolver = CachingConfiguration.PER_USER_CACHE_RESOLVER_NAME)
    public List getNumericParametricValuesInBuckets(final HodParametricRequest parametricRequest, final Map bucketingParamsPerField) throws HodErrorException {
        if (parametricRequest.getFieldNames().isEmpty()) {
            return Collections.emptyList();
        } else {
            validateBucketingParams(parametricRequest, bucketingParamsPerField);

            final Set numericFieldInfo = getNumericParametricValues(parametricRequest);
            final List ranges = new ArrayList<>(numericFieldInfo.size());

            for (final QueryTagInfo queryTagInfo : numericFieldInfo) {
                final BucketingParams bucketingParams = bucketingParamsPerField.get(queryTagInfo.getId());
                ranges.add(parseNumericParametricValuesInBuckets(queryTagInfo, bucketingParams));
            }

            return ranges;
        }
    }

    private Collection lookupFieldIds(final Collection databases) throws HodErrorException {
        final List fields = fieldsService.getFields(new HodFieldsRequest.Builder().setDatabases(databases).build(), FieldTypeParam.Parametric).get(FieldTypeParam.Parametric);
        final Collection fieldIds = new ArrayList<>(fields.size());
        fieldIds.addAll(fields.stream().map(TagName::getId).collect(Collectors.toList()));

        return fieldIds;
    }

    // Parse a list of numeric parametric values into buckets specified by the min, max and number of buckets in the BucketingParams
    private RangeInfo parseNumericParametricValuesInBuckets(final QueryTagInfo queryTagInfo, final BucketingParams bucketingParams) {
        final List boundaries = calculateBoundaries(bucketingParams);

        // Map of bucket minimum to count
        final Map bucketCounts = new HashMap<>();

        // Boundaries includes the min and the max values, so has a minimum size of 2
        for (int i = 0; i < boundaries.size() - 1; i++) {
            bucketCounts.put(boundaries.get(i), 0);
        }

        int totalCount = 0;

        // The index of the min value for the bucket we are currently counting
        int currentBoundary = 0;

        final Iterator iterator = queryTagInfo.getValues().iterator();

        while (iterator.hasNext() && currentBoundary < boundaries.size()) {
            final QueryTagCountInfo valueAndCount = iterator.next();
            final double value = Double.parseDouble(valueAndCount.getValue());

            // Ignore values less than the lowest bucket boundary
            if (value >= boundaries.get(currentBoundary)) {
                while (currentBoundary < boundaries.size() - 1) {
                    // Check that the value is within the max boundary for the bucket, if not, check the next bucket
                    if (value < boundaries.get(currentBoundary + 1)) {
                        final Double min = boundaries.get(currentBoundary);
                        totalCount += valueAndCount.getCount();
                        bucketCounts.put(min, bucketCounts.get(min) + valueAndCount.getCount());

                        break;
                    } else {
                        currentBoundary++;
                    }
                }
            }
        }

        final List buckets = new ArrayList<>(bucketingParams.getTargetNumberOfBuckets());

        // Boundaries includes the min and the max values, so has a minimum size of 2
        for (int i = 0; i < boundaries.size() - 1; i++) {
            final double min = boundaries.get(i);
            buckets.add(new RangeInfo.Value(bucketCounts.get(min), min, boundaries.get(i + 1)));
        }

        // All buckets have the same size, so just use the value from the first one
        final double bucketSize = boundaries.get(1) - boundaries.get(0);
        return new RangeInfo(new TagName(queryTagInfo.getId()), totalCount, bucketingParams.getMin(), bucketingParams.getMax(), bucketSize, buckets);
    }

    // Get parametric values matching the given request from HOD and parse them as numeric CSVs
    private Set getNumericParametricValues(final ParametricRequest parametricRequest) throws HodErrorException {
        final Collection fieldNames = parametricRequest.getFieldNames();

        final Set results;
        if (fieldNames.isEmpty()) {
            results = Collections.emptySet();
        } else {
            final FieldNames parametricFieldNames = getParametricValues(parametricRequest, fieldNames);
            final Set fieldNamesSet = parametricFieldNames.getFieldNames();

            results = new LinkedHashSet<>();
            for (final String name : fieldNamesSet) {
                final Set values = new LinkedHashSet<>(parametricFieldNames.getValuesAndCountsForNumericField(name));
                if (!values.isEmpty()) {
                    results.add(new QueryTagInfo(new TagName(name), values));
                }
            }
        }

        return results;
    }

    @Override
    public List getDependentParametricValues(final HodParametricRequest parametricRequest) throws HodErrorException {
        throw new NotImplementedException("Dependent parametric values not yet implemented for hod");
    }

    @Override
    public Map getValueDetails(final HodParametricRequest parametricRequest) throws HodErrorException {
        if (parametricRequest.getFieldNames().isEmpty()) {
            return Collections.emptyMap();
        } else {
            final FieldNames response = getParametricValues(parametricRequest, parametricRequest.getFieldNames());
            final Map output = new LinkedHashMap<>();

            for (final String fieldName : response.getFieldNames()) {
                final List values = response.getValuesAndCountsForNumericField(fieldName);
                final double firstValue = Double.parseDouble(values.get(0).getValue());

                double min = firstValue;
                double max = firstValue;
                double sum = 0;
                double totalCount = 0;

                for (final QueryTagCountInfo countInfo : values) {
                    final double value = Double.parseDouble(countInfo.getValue());
                    totalCount += countInfo.getCount();
                    sum += value * countInfo.getCount();
                    min = Math.min(value, min);
                    max = Math.max(value, max);
                }

                final ValueDetails valueDetails = new ValueDetails.Builder()
                        .setMin(min)
                        .setMax(max)
                        .setSum(sum)
                        .setAverage(sum / totalCount)
                        .setTotalValues(values.size())
                        .build();

                output.put(new TagName(fieldName), valueDetails);
            }

            return output;
        }
    }

    private FieldNames getParametricValues(final ParametricRequest parametricRequest, final Collection fieldNames) throws HodErrorException {
        final ResourceIdentifier queryProfile = parametricRequest.isModified() ? getQueryProfile() : null;

        final GetParametricValuesRequestBuilder parametricParams = new GetParametricValuesRequestBuilder()
                .setQueryProfile(queryProfile)
                .setSort(ParametricSort.fromParam(parametricRequest.getSort()))
                .setText(parametricRequest.getQueryRestrictions().getQueryText())
                .setFieldText(parametricRequest.getQueryRestrictions().getFieldText())
                .setMaxValues(parametricRequest.getMaxValues())
                .setMinScore(parametricRequest.getQueryRestrictions().getMinScore())
                .setSecurityInfo(authenticationInformationRetriever.getPrincipal().getSecurityInfo());

        return getParametricValuesService.getParametricValues(fieldNames,
                new ArrayList<>(parametricRequest.getQueryRestrictions().getDatabases()), parametricParams);
    }

    private ResourceIdentifier getQueryProfile() {
        final String profileName = configService.getConfig().getQueryManipulation().getProfile();
        final String domain = authenticationInformationRetriever.getPrincipal().getApplication().getDomain();
        return new ResourceIdentifier(domain, profileName);
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy