1 package org.apache.lucene.facet.index.streaming;
3 import java.io.IOException;
4 import java.util.HashSet;
5 import java.util.LinkedList;
9 import org.apache.lucene.analysis.TokenFilter;
11 import org.apache.lucene.facet.index.attributes.CategoryAttribute;
12 import org.apache.lucene.facet.index.attributes.CategoryProperty;
13 import org.apache.lucene.facet.index.attributes.OrdinalProperty;
14 import org.apache.lucene.facet.index.categorypolicy.OrdinalPolicy;
15 import org.apache.lucene.facet.index.categorypolicy.PathPolicy;
16 import org.apache.lucene.facet.index.params.FacetIndexingParams;
17 import org.apache.lucene.facet.taxonomy.CategoryPath;
18 import org.apache.lucene.facet.taxonomy.TaxonomyWriter;
21 * Licensed to the Apache Software Foundation (ASF) under one or more
22 * contributor license agreements. See the NOTICE file distributed with
23 * this work for additional information regarding copyright ownership.
24 * The ASF licenses this file to You under the Apache License, Version 2.0
25 * (the "License"); you may not use this file except in compliance with
26 * the License. You may obtain a copy of the License at
28 * http://www.apache.org/licenses/LICENSE-2.0
30 * Unless required by applicable law or agreed to in writing, software
31 * distributed under the License is distributed on an "AS IS" BASIS,
32 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
33 * See the License for the specific language governing permissions and
34 * limitations under the License.
38 * This class adds parents to a {@link CategoryAttributesStream}. The parents
39 * are added according to the {@link PathPolicy} and {@link OrdinalPolicy} from
40 * the {@link FacetIndexingParams} given in the constructor.<br>
41 * By default, category properties are removed when creating parents of a
42 * certain category. However, it is possible to retain certain property types
43 * using {@link #addRetainableProperty(Class)}.
45 * @lucene.experimental
47 public class CategoryParentsStream extends TokenFilter {
50 * A {@link TaxonomyWriter} for adding categories and retrieving their
53 protected TaxonomyWriter taxonomyWriter;
55 /** An attribute containing all data related to the category */
56 protected CategoryAttribute categoryAttribute;
58 /** A category property containing the category ordinal */
59 protected OrdinalProperty ordinalProperty;
62 * A set of property classes that are to be retained when creating a parent
65 private Set<Class<? extends CategoryProperty>> retainableProperties;
67 /** A {@link PathPolicy} for the category's parents' category paths. */
68 private PathPolicy pathPolicy;
70 /** An {@link OrdinalPolicy} for the category's parents' ordinals. */
71 private OrdinalPolicy ordinalPolicy;
77 * The input stream to handle, must be derived from
78 * {@link CategoryAttributesStream}.
79 * @param taxonomyWriter
80 * The taxonomy writer to use for adding categories and
81 * retrieving their ordinals.
82 * @param indexingParams
83 * The indexing params used for filtering parents.
85 public CategoryParentsStream(CategoryAttributesStream input,
86 TaxonomyWriter taxonomyWriter, FacetIndexingParams indexingParams) {
88 this.categoryAttribute = this.addAttribute(CategoryAttribute.class);
89 this.taxonomyWriter = taxonomyWriter;
90 this.pathPolicy = indexingParams.getPathPolicy();
91 this.ordinalPolicy = indexingParams.getOrdinalPolicy();
92 this.ordinalPolicy.init(taxonomyWriter);
93 this.ordinalProperty = new OrdinalProperty();
98 public final boolean incrementToken() throws IOException {
99 if (this.categoryAttribute.getCategoryPath() != null) {
100 // try adding the parent of the current category to the stream
101 clearCategoryProperties();
102 boolean added = false;
103 // set the parent's ordinal, if illegal set -1
104 int ordinal = this.ordinalProperty.getOrdinal();
106 ordinal = this.taxonomyWriter.getParent(ordinal);
107 if (this.ordinalPolicy.shouldAdd(ordinal)) {
108 this.ordinalProperty.setOrdinal(ordinal);
110 this.categoryAttribute.addProperty(ordinalProperty);
111 } catch (UnsupportedOperationException e) {
112 throw new IOException(e.getLocalizedMessage());
116 this.ordinalProperty.setOrdinal(-1);
119 // set the parent's category path, if illegal set null
120 CategoryPath cp = this.categoryAttribute.getCategoryPath();
123 // if ordinal added, must also have category paths
124 if (added || this.pathPolicy.shouldAdd(cp)) {
125 this.categoryAttribute.setCategoryPath(cp);
128 this.categoryAttribute.clear();
132 // a legal parent exists
136 // no more parents - get new category
137 if (input.incrementToken()) {
138 int ordinal = taxonomyWriter.addCategory(this.categoryAttribute.getCategoryPath());
139 this.ordinalProperty.setOrdinal(ordinal);
141 this.categoryAttribute.addProperty(this.ordinalProperty);
142 } catch (UnsupportedOperationException e) {
143 throw new IOException(e.getLocalizedMessage());
151 * Clear the properties of the current {@link CategoryAttribute} attribute
152 * before setting the parent attributes. <br>
153 * It is possible to retain properties of certain types the parent tokens,
154 * using {@link #addRetainableProperty(Class)}.
156 protected void clearCategoryProperties() {
157 if (this.retainableProperties == null
158 || this.retainableProperties.isEmpty()) {
159 this.categoryAttribute.clearProperties();
161 List<Class<? extends CategoryProperty>> propertyClassesToRemove =
162 new LinkedList<Class<? extends CategoryProperty>>();
163 for (Class<? extends CategoryProperty> propertyClass : this.categoryAttribute
164 .getPropertyClasses()) {
165 if (!this.retainableProperties.contains(propertyClass)) {
166 propertyClassesToRemove.add(propertyClass);
169 for (Class<? extends CategoryProperty> propertyClass : propertyClassesToRemove) {
170 this.categoryAttribute.remove(propertyClass);
176 * Add a {@link CategoryProperty} class which is retained when creating
180 * The property class to retain.
182 public void addRetainableProperty(Class<? extends CategoryProperty> toRetain) {
183 if (this.retainableProperties == null) {
184 this.retainableProperties = new HashSet<Class<? extends CategoryProperty>>();
186 this.retainableProperties.add(toRetain);