/* * Copyright 2012 NGDATA nv * * 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 org.lilyproject.indexer.model.indexerconf.formatter; import java.util.ArrayList; import java.util.Collection; import java.util.List; import com.google.common.base.Splitter; import org.lilyproject.indexer.model.indexerconf.Formatter; import org.lilyproject.indexer.model.indexerconf.IndexValue; import org.lilyproject.repository.api.LRepository; import org.lilyproject.repository.api.ValueType; /** * Formatter which formats values suitable for hierarchical faceting in Solr. * * <p>More information on hierarchical faceting in Solr can be found at * https://wiki.apache.org/solr/HierarchicalFaceting</p> * * <p>To take the example for the Solr wiki page, the following hierarchies:</p> * * <pre> * Doc#1: NonFic > Law * Doc#2: NonFic > Sci * Doc#3: NonFic > Hist, NonFic > Sci > Phys * </pre> * * <p>are by this formatter translated to multiple tokens, prefixed with the * depth of each path:</p> * * <pre> * Doc#1: 0/NonFic, 1/NonFic/Law * Doc#2: 0/NonFic, 1/NonFic/Sci * Doc#3: 0/NonFic, 1/NonFic/Hist, * 0/NonFic, 1/NonFic/Sci, 2/NonFic/Sci/Phys * </pre> * * <p>So the resulting value of this formatter will (in most cases) be * a multi-value. The input can be single or multi-valued. The inputs * should be slash-separated strings.</p> * */ public class HierarchicalFacetPrefixFormatter implements Formatter { @Override public List<String> format(List<IndexValue> indexValues, LRepository repository) throws InterruptedException { List<String> result = new ArrayList<String>(); for (IndexValue indexValue : indexValues) { ValueType valueType = indexValue.fieldType.getValueType(); if (valueType.getBaseName().equals("LIST")) { // The values of the first list-level are supplied as individual IndexValues valueType = valueType.getNestedValueType(); } if (!valueType.getName().equals("STRING")) { throw new RuntimeException(this.getClass().getSimpleName() + " only supports string values, but got: " + valueType.getName()); } processPath((String)indexValue.value, result); } return result; } private void processPath(String path, Collection<String> result) { final Iterable<String> splitted = Splitter.on("/").omitEmptyStrings().trimResults().split(path); int level = 0; final StringBuilder entry = new StringBuilder(); for (String split : splitted) { entry.append("/").append(split); result.add(level + entry.toString()); level++; } } }