1
package org.apache.lucene.facet.index;
3
import java.io.IOException;
4
import java.io.ObjectInputStream;
5
import java.io.ObjectOutputStream;
6
import java.io.Serializable;
7
import java.util.HashMap;
8
import java.util.Iterator;
12
import org.apache.lucene.util.Attribute;
14
import org.apache.lucene.facet.FacetException;
15
import org.apache.lucene.facet.index.attributes.CategoryAttribute;
16
import org.apache.lucene.facet.index.attributes.CategoryAttributeImpl;
17
import org.apache.lucene.facet.index.attributes.CategoryProperty;
18
import org.apache.lucene.facet.taxonomy.CategoryPath;
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
* A container to add categories which are to be introduced to
39
* {@link CategoryDocumentBuilder#setCategories(Iterable)}. Categories can be
40
* added with Properties.
42
* @lucene.experimental
44
public class CategoryContainer implements Iterable<CategoryAttribute>, Serializable {
46
protected transient Map<CategoryPath, CategoryAttribute> map;
51
public CategoryContainer() {
52
map = new HashMap<CategoryPath, CategoryAttribute>();
59
* The path of the category.
60
* @return The {@link CategoryAttribute} of the category.
62
public CategoryAttribute addCategory(CategoryPath categoryPath) {
63
return mapCategoryAttribute(categoryPath);
67
* Add a category with a property.
70
* The path of the category.
72
* The property to associate to the category.
73
* @return The {@link CategoryAttribute} of the category.
75
public CategoryAttribute addCategory(CategoryPath categoryPath,
76
CategoryProperty property) {
78
* This method is a special case of addCategory with multiple
79
* properties, but it is kept here for two reasons: 1) Using the array
80
* version has some performance cost, and 2) it is expected that most
81
* calls will be for this version (single property).
83
CategoryAttribute ca = mapCategoryAttribute(categoryPath);
84
ca.addProperty(property);
89
* Add a category with multiple properties.
92
* The path of the category.
94
* The properties to associate to the category.
95
* @return The {@link CategoryAttribute} of the category.
96
* @throws FacetException
97
* When the category already has a property of the same type as
98
* one of the new properties, and merging for this property type
101
public CategoryAttribute addCategory(CategoryPath categoryPath,
102
CategoryProperty... properties) throws FacetException {
103
CategoryAttribute ca = mapCategoryAttribute(categoryPath);
104
for (CategoryProperty attribute : properties) {
105
ca.addProperty(attribute);
111
* Add an entire {@link CategoryAttribute}.
113
* @param categoryAttribute
114
* The {@link CategoryAttribute} to add.
115
* @return The {@link CategoryAttribute} of the category (could be different
116
* from the one provided).
117
* @throws FacetException
119
public CategoryAttribute addCategory(CategoryAttribute categoryAttribute)
120
throws FacetException {
121
CategoryAttribute ca = mapCategoryAttribute(categoryAttribute
123
Set<Class<? extends CategoryProperty>> propertyClasses = categoryAttribute
124
.getPropertyClasses();
125
if (propertyClasses != null) {
126
for (Class<? extends CategoryProperty> propertyClass : propertyClasses) {
127
ca.addProperty(categoryAttribute.getProperty(propertyClass));
134
* Get the {@link CategoryAttribute} object for a specific
135
* {@link CategoryPath}, from the map.
137
private final CategoryAttribute mapCategoryAttribute(
138
CategoryPath categoryPath) {
139
CategoryAttribute ca = map.get(categoryPath);
141
ca = new CategoryAttributeImpl(categoryPath);
142
map.put(categoryPath, ca);
148
* Get the {@link CategoryAttribute} this container has for a certain
149
* category, or {@code null} if the category is not in the container.
151
* @param categoryPath
152
* The category path of the requested category.
154
public CategoryAttribute getCategoryAttribute(CategoryPath categoryPath) {
155
return map.get(categoryPath);
158
public Iterator<CategoryAttribute> iterator() {
159
return map.values().iterator();
163
* Remove all categories.
165
public void clear() {
170
* Add the categories from another {@link CategoryContainer} to this one.
173
* The {@link CategoryContainer} to take categories from.
174
* @throws FacetException
175
* If any prohibited merge of category properties is attempted.
177
public void merge(CategoryContainer other) throws FacetException {
178
for (CategoryAttribute categoryAttribute : other.map.values()) {
179
addCategory(categoryAttribute);
184
* Get the number of categories in the container.
186
* @return The number of categories in the container.
193
public String toString() {
194
StringBuilder builder = new StringBuilder("CategoryContainer");
195
for (CategoryAttribute ca : map.values()) {
196
builder.append('\n');
197
builder.append('\t');
198
builder.append(ca.toString());
200
return builder.toString();
204
* Serialize object content to given {@link ObjectOutputStream}
206
private void writeObject(ObjectOutputStream out) throws IOException {
207
out.defaultWriteObject();
208
// write the number of categories
209
out.writeInt(size());
210
// write the category attributes
211
for (CategoryAttribute ca : this) {
212
serializeCategoryAttribute(out, ca);
217
* Serialize each of the {@link CategoryAttribute}s to the given
218
* {@link ObjectOutputStream}.<br>
219
* NOTE: {@link CategoryProperty}s are {@link Serializable}, but do not
220
* assume that Lucene's {@link Attribute}s are as well
221
* @throws IOException
223
protected void serializeCategoryAttribute(ObjectOutputStream out,
224
CategoryAttribute ca) throws IOException {
225
out.writeObject(ca.getCategoryPath());
226
Set<Class<? extends CategoryProperty>> propertyClasses = ca.getPropertyClasses();
227
if (propertyClasses != null) {
228
out.writeInt(propertyClasses.size());
229
for (Class<? extends CategoryProperty> clazz : propertyClasses) {
230
out.writeObject(ca.getProperty(clazz));
238
* Deserialize object from given {@link ObjectInputStream}
240
private void readObject(ObjectInputStream in) throws IOException,
241
ClassNotFoundException {
242
in.defaultReadObject();
243
map = new HashMap<CategoryPath, CategoryAttribute>();
244
int size = in.readInt();
245
for (int i = 0; i < size; i++) {
246
deserializeCategoryAttribute(in);
251
* De-Serialize each of the {@link CategoryAttribute}s from the given
252
* {@link ObjectInputStream}.
254
protected void deserializeCategoryAttribute(ObjectInputStream in)
255
throws IOException, ClassNotFoundException {
256
CategoryPath cp = (CategoryPath) in.readObject();
257
int nProperties = in.readInt();
258
if (nProperties == 0) {
261
for (int j = 0; j < nProperties; j++) {
262
CategoryProperty property = (CategoryProperty) in.readObject();
263
addCategory(cp, property);
269
public boolean equals(Object o) {
270
if (! (o instanceof CategoryContainer)) {
274
CategoryContainer that = (CategoryContainer)o;
275
return this.map.equals(that.map);
279
public int hashCode() {
280
return map.hashCode();