Package com.flaptor.indextank.index.scorer

Source Code of com.flaptor.indextank.index.scorer.DynamicDataFacetingManager$DynamicDataFacetFilter

/*
* Copyright (c) 2011 LinkedIn, Inc
*
* Licensed 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 com.flaptor.indextank.index.scorer;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import com.flaptor.indextank.index.DocId;
import com.flaptor.indextank.index.scorer.CategoryMaskManager.CategoryInfo;
import com.flaptor.indextank.index.scorer.DynamicDataManager.DynamicData;
import com.flaptor.indextank.index.scorer.DynamicDataManager.FacetsCollector;
import com.flaptor.indextank.query.QueryVariables;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multiset;
import com.google.common.collect.ObjectArrays;

public class DynamicDataFacetingManager extends FacetingManager {
  private final DynamicDataManager dynamicDataManager;
 
  public class DynamicDataFacetFilter implements MatchFilter {
    private List<CategoryFilter> matchingCategories = new ArrayList<CategoryFilter>();
    private int dataOffset;
    //TODO: optimize to avoid searching the index when true
    private boolean isNoneMatchingFilter = false;
   
    private class CategoryFilter {
      public int[] bitmask;
      public int[][] values;
     
      public CategoryFilter(int[] bitmask, int[][] values) {
        this.bitmask = bitmask;
        this.values = values;
      }
    }
   
    public DynamicDataFacetFilter(Multimap<String, String> filteringFacets) {
      CategoryMaskManager maskManager = dynamicDataManager.getMaskManager();
      int maxMaskSize = maskManager.getMaxMaskSize();
      dataOffset = dynamicDataManager.getNumberOfBoosts() + 1;
     
      if (maxMaskSize == 0) {
        if (filteringFacets.size() == 0) {
          return;
        } else {
          isNoneMatchingFilter = true;
          return;
          //throw new IllegalArgumentException("Facets can't be filtered if no facets are defined");
        }
      }
     
      if (filteringFacets.values().size() == filteringFacets.keySet().size()) {
        // Only one value per category optimization
        int[] totalMask = new int[maxMaskSize];
        int[] totalValue = new int[maxMaskSize];
       
        for (Entry<String, String> entry : filteringFacets.entries()) {
          CategoryInfo categoryInfo = maskManager.getCategoryInfos().get(entry.getKey());

          if (categoryInfo == null) {
            isNoneMatchingFilter = true;
            return;
          }

          int[] bitmask = categoryInfo.getBitmask();
          Integer valueCode = categoryInfo.getValueCode(entry.getValue());
         
          if (valueCode == null) {
            isNoneMatchingFilter = true;
            return;
          }
         
          CategoryEncoder.encode(totalValue, 0, bitmask, valueCode);
         
          orArrays(bitmask, totalMask);
        }
       
        matchingCategories.add(new CategoryFilter(totalMask, new int[][] { totalValue } ));
      } else {
       
        for (String categoryKey : filteringFacets.keySet()) {
          CategoryInfo categoryInfo = maskManager.getCategoryInfos().get(categoryKey);
          if (categoryInfo == null) {
            isNoneMatchingFilter = true;
            return;
          }
          int[] bitmask = categoryInfo.getBitmask();

          Collection<String> values = filteringFacets.get(categoryKey);
          List<int[]> valuesBitmaps = Lists.newArrayList();
         
          for (String value : values) {
            Integer valueCode = categoryInfo.getValueCode(value);
            if (valueCode != null) {
              int[] encodedValue = CategoryEncoder.encode(new int[0], 0, bitmask, valueCode);
              valuesBitmaps.add(encodedValue);
            }
          }
         
          if (valuesBitmaps.isEmpty()) {
            isNoneMatchingFilter = true;
            return;
          }
         
          matchingCategories.add(new CategoryFilter(bitmask, valuesBitmaps.toArray(new int[valuesBitmaps.size()][])));
        }
      }
    }
   
    private void orArrays(int[] source, int[] target) {
      for (int i = 0; i < source.length; i++) {
        target[i] |= source[i];
      }
    }
   
    @Override
    public boolean matches(DocId documentId, double textualScore, int now, QueryVariables queryVars) {
      if (isNoneMatchingFilter) {
        return false;
      }
     
      DynamicData dynamicData = dynamicDataManager.getDynamicData(documentId);
     
      int[] data = dynamicData.getData();
     
      /*
       * For every category we checked that at least one of the
       * values matches.
       */
      for (CategoryFilter categoryFilter : matchingCategories) {
        int[][] values = categoryFilter.values;
        boolean matched = false;
       
        for (int i = 0; i < values.length; i++) {
          if (CategoryEncoder.matches(data, dataOffset, categoryFilter.bitmask, values[i])) {
            matched = true;
            break;
          }
        }
        if (!matched) {
          return false;
        }
      }
     
      return true;
    }
   
  }
 
  public DynamicDataFacetingManager(DynamicDataManager dynamicDataManager) {
    this.dynamicDataManager = dynamicDataManager;
  }

  public class DynamicDataFaceter implements Faceter, FacetsCollector {
    private Map<String, int[]> rawFacets = Maps.newHashMap();
   
    @Override
    public void computeDocument(DocId documentId) {
      dynamicDataManager.populateCollector(documentId, this);
    }

    @Override
    public Map<String, Multiset<String>> getFacets() {
      CategoryMaskManager maskManager = dynamicDataManager.getMaskManager();
      Map<String, Multiset<String>> results = Maps.newHashMap();
     
      for (Entry<String, int[]> entry : rawFacets.entrySet()) {
        Multiset<String> counts = HashMultiset.create();
        String category = entry.getKey();
        CategoryInfo categoryInfo = maskManager.getCategoryInfos().get(category);         
        int[] rawCounts = entry.getValue();
        for (int i = 0; i < rawCounts.length; i++) {
          String value = categoryInfo.getValue(i+1);
          counts.add(value, rawCounts[i]);
        }
        results.put(category, counts);
      }
     
      return results;
    }

    @Override
    public void addCategoryValue(String category, Integer valueCode) {
      int[] categorySet = rawFacets.get(category);
      if (categorySet == null) {
        categorySet = new int[dynamicDataManager.getMaskManager().getCategoryInfos().get(category).getSize()];
        rawFacets.put(category, categorySet);
      }
      categorySet[valueCode - 1]++;
    }
   
  }
 
  @Override
  public Faceter createFaceter() {
    return new DynamicDataFaceter();
  }

  @Override
  public MatchFilter getFacetFilter(Multimap<String, String> filteringFacets) {
    return new DynamicDataFacetFilter(filteringFacets);
  }
 
}

TOP

Related Classes of com.flaptor.indextank.index.scorer.DynamicDataFacetingManager$DynamicDataFacetFilter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.