/* * 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.addthis.hydra.data.filter.bundle; import java.util.ArrayList; import java.util.HashSet; import com.addthis.bundle.core.Bundle; import com.addthis.bundle.core.BundleField; import com.addthis.bundle.util.AutoField; import com.addthis.bundle.util.ValueUtil; import com.addthis.bundle.value.ValueArray; import com.addthis.bundle.value.ValueFactory; import com.addthis.bundle.value.ValueObject; import com.addthis.bundle.value.ValueString; import com.addthis.codec.annotations.FieldConfig; import com.addthis.hydra.data.filter.value.ValueFilter; import com.fasterxml.jackson.annotation.JsonIgnore; /** * This {@link BundleFilter BundleFilter} <span class="hydra-summary">appends a value to an array</span>. * <p/> * <p>Add the injected value to a {@link ValueArray ValueArray} if the * array already exists or it creates a new array with the provided value if the * array does not already exist. * <p/> * <p>The {@link #to to} field is required and it specifies both the start of the * input array and the output destination. Next any values in the {@link #values values} * field are appended to the array, and in the final step any values in the {@link #from from} * field are appended to the array. The output is stored in the {@link #to to} field. * <p/> * <p>NOTE: if the {@link #to to} or {@link #from from} fields has an existing value * that is not a ValueArray then this filter will convert the field * to a ValueArray. * <p>Example:</p> * <pre> * {append {to:"INPUT", values:{"a", "b", "c"}} * </pre> * * @user-reference */ public class BundleFilterAppend implements BundleFilter { @JsonIgnore public BundleFilterAppend setValues(ArrayList<String> values) { this.values = values; return this; } @JsonIgnore public BundleFilterAppend setValues(HashSet<String> values) { this.values = new ArrayList<>(values.size()); for (String val : values) { this.values.add(val); } return this; } public BundleFilterAppend setToField(AutoField field) { this.to = field; return this; } public BundleFilterAppend setFilter(ValueFilter filter) { this.filter = filter; return this; } public BundleFilterAppend setNullFail(boolean nullFail) { this.nullFail = nullFail; return this; } public BundleFilterAppend setSize(int size) { this.size = size; return this; } /** * Both the start of the array and the destination field. Required field. */ @FieldConfig(required = true) private AutoField to; /** * A field to append at the end of the array. */ @FieldConfig(codable = true) private AutoField from; /** * A list of values to append in between the 'to' and 'from' fields. */ @FieldConfig(codable = true) private ArrayList<String> values; /** * An optional filter to apply on the 'values' field. */ @FieldConfig(codable = true) private ValueFilter filter; /** * If true, then return a value of false if the 'to' field is null. Default is false. */ @FieldConfig(codable = true) private boolean nullFail; /** * If true, then append only values that are not already a members of the array. Default is * false. */ @FieldConfig(codable = true) private boolean unique; /** * Optional param to hint at expected array size. Default is 5. */ @FieldConfig(codable = true) private int size = 5; @Override public boolean filter(Bundle bundle) { ValueObject toVal = to.getValue(bundle); ValueArray arr = null; if (toVal == null) { if (nullFail) { return false; } arr = ValueFactory.createArray(size); } else { if (toVal.getObjectType() == ValueObject.TYPE.ARRAY) { arr = toVal.asArray(); } else { arr = ValueUtil.asArray(toVal); } } // append constants if (values != null) { for (String value : values) { ValueString str = ValueFactory.create(value); if (!unique || !arr.contains(str)) { arr.add(str); } } } // append from if set if (from != null) { ValueObject fromVal = from.getValue(bundle); if (filter != null) { fromVal = filter.filter(fromVal, bundle); } if (fromVal != null) { if (fromVal.getObjectType() == ValueObject.TYPE.ARRAY) { for (ValueObject element : fromVal.asArray()) { if (!unique || !arr.contains(element)) { arr.add(element); } } } else if (!unique || !arr.contains(fromVal)) { arr.add(fromVal); } } } to.setValue(bundle, arr); return true; } }