// Copyright 2011 Google 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.google.enterprise.connector.util.filter; import com.google.common.base.Preconditions; import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; import com.google.enterprise.connector.spi.Document; import com.google.enterprise.connector.spi.Property; import com.google.enterprise.connector.spi.RepositoryException; import com.google.enterprise.connector.spi.SimpleProperty; import com.google.enterprise.connector.spi.Value; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.logging.Level; /** * A {@link Document} filter that adds a new {@link Property} * or adds values to an existing Property. * <p> * If the {@code overwrite} flag is {@code true}, the new * property values replace any existing values of the target property. * Otherwise, the new property values augment any existing values * of the target property. * <p> * <b>Example {@code documentFilters.xml} Configurations:</b> * <p> * The following example tags all fed documents with source department * identification meta-data. It adds a {@code DeptId} property, with * the single value {@code Finance} to all documents. * <pre><code> <!-- Tag all documents fed from this department with a source ID. --> <bean id="AddDeptId" class="com.google.enterprise.connector.util.filter.AddPropertyFilter"> <property name="propertyName" value="DeptId"/> <property name="propertyValue" value="Finance"/> <property name="overwrite" value="true"/> </bean> </code></pre> * The following example adds "Carlton Whitfield" to the list of {@code Authors} * for all documents. * <pre><code> <!-- Add myself as co-author of all documents. Gain citation notoriety. --> <bean id="AddAuthor" class="com.google.enterprise.connector.util.filter.AddPropertyFilter"> <property name="propertyName" value="Author"/> <property name="propertyValue" value="Carlton Whitfield"/> <property name="overwrite" value="false"/> </bean> </code></pre> * * @since 2.8 */ public class AddPropertyFilter extends AbstractDocumentFilter { /** The name of the new {@link Property}. */ protected String propertyName; /** The List of addtional {@link Value Values} for the {@link Property}. */ protected List<Value> additionalValues; /** * If {@code true}, overwrite any existing destination property values * with the new property values; otherwise augment the existing values * with the additional Values (like multi-valued Properties). */ protected boolean overwrite = false; /** * Sets the the name of the {@link Property} to add. If the property * already exists for this {@link Document}, either overwrite or * augment the existing property values with the additional values. * * @param propertyName the name of the {@link Property} to filter * @throws IllegalArgumentException if {@code propertyName} is {@code null} * or empty */ public void setPropertyName(String propertyName) { Preconditions.checkArgument(!Strings.isNullOrEmpty(propertyName), "propertyName may not be null or empty"); this.propertyName = propertyName; } /** * Sets the List of additional String values that will be returned for * the configured Property. * * @param values a List of String values. */ public void setPropertyValues(List<String> values) { Preconditions.checkNotNull(values, "values may not be null"); ImmutableList.Builder<Value> builder = ImmutableList.builder(); for (String value : values) { builder.add(Value.getStringValue(value)); } this.additionalValues = builder.build(); } /** * Sets the additional String value that will be returned for * the configured Property. * <p> * A convenience method that wraps the {@code value} in a single * item List and calls {@link #setPropertyValues}. * * @param value a String value. */ public void setPropertyValue(String value) { Preconditions.checkNotNull(value, "value may not be null"); this.additionalValues = ImmutableList.of(Value.getStringValue(value)); } /** * Sets the {@code overwrite} values flag. If {@code true}, any existing * values of the property are overwritten with the copied values. * If {@code false}, the copied values augment those of the * property. Default {@code overwrite} is {@code false}. * * @param overwrite the overwrite flag */ public void setOverwrite(boolean overwrite) { this.overwrite = overwrite; } /** * Finds a {@link Property} by {@code name}. If the requested property * is the filtered property, return that property with the configured * additional values. * <p> * If the {@code overwrite} flag is {@code true}, the new * property values replace any existing values of the target property. * Otherwise, the new property values augment any existing values * of the target property. */ @Override public Property findProperty(Document source, String name) throws RepositoryException { Preconditions.checkState(propertyName != null, "must set propertyName"); if (!propertyName.equals(name)) { // If not adding this property, pass on request. return source.findProperty(name); } if (LOGGER.isLoggable(Level.FINEST)) { LOGGER.finest("Adding property " + name); } if (overwrite) { // If overwrite, replace any existing values of named property // with the new values. return new SimpleProperty(additionalValues); } else { // If not overwrite, augment existing values of named property // with the addtional values. List<Value> values = super.getPropertyValues(source, name); values.addAll(additionalValues); return new SimpleProperty(values); } } /** * Gets the set of names of all {@link Property Properties} in the * {@link Document}, including any new Properties that might be * added. */ @Override public Set<String> getPropertyNames(Document source) throws RepositoryException { Preconditions.checkState(propertyName != null, "must set propertyName"); Set<String> superSet = new HashSet<String>(source.getPropertyNames()); superSet.add(propertyName); return superSet; } @Override public String toString() { return super.toString() + ": (" + propertyName + " , " + additionalValues.toString() + " , " + overwrite + ")"; } }