/* See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * Esri Inc. licenses this file to You 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.esri.gpt.catalog.lucene; import java.io.IOException; import java.util.ArrayList; import org.apache.lucene.index.IndexReader; import org.apache.lucene.index.Term; import org.apache.lucene.index.TermDocs; import org.apache.lucene.search.DocIdSet; import org.apache.lucene.search.Filter; import org.apache.lucene.util.OpenBitSet; import com.esri.gpt.framework.collection.StringAttributeMap; import com.esri.gpt.framework.context.RequestContext; import com.esri.gpt.framework.util.Val; /** * A filter that forces the query to restrict to one or more item collections. */ @SuppressWarnings("serial") public class IsPartOfFilter extends Filter { /** instance variables ====================================================== */ private Filter chained; private String fieldName; private long timeMillis = 0; private String[] values; /** constructors ============================================================ */ /** * Constructs with an associated field name, value array and a chained filter. * @param fieldName the field name * @param values set of values * @param chained a chained filter */ public IsPartOfFilter(String fieldName, String[] values, Filter chained) { this.fieldName = fieldName; this.values = values; this.chained = chained; } /** properties ============================================================== */ /** * Gets the execution time. * @return the execution time (in milliseconds) */ public long getTimeMillis() { return this.timeMillis; } /** * Sets the execution time. * @param millis the execution time (in milliseconds) */ protected void setTimeMillis(long millis) { this.timeMillis = millis; } /** methods ================================================================= */ /** * Applies the filter and returns a DocIdSet of matching documents. * @param reader the index reader * @return the DocIdSet (documents that are visible to the supplied user principals) * @throws IOException if an exception is encountered while reading the index */ public DocIdSet getDocIdSet(IndexReader reader) throws IOException { long t1 = System.currentTimeMillis(); OpenBitSet bitSet = this.queryValues(reader,this.fieldName,this.values); if (this.chained != null) { bitSet.and((OpenBitSet)this.chained.getDocIdSet(reader)); } setTimeMillis(System.currentTimeMillis() - t1); return bitSet; } /** * Makes the filter based upon the application configuration and active * request context. * @param context the request filter * @param chained a chained filter * @return the filter (null if not applicable) */ public static Filter make(RequestContext context, Filter chained) { StringAttributeMap params = context.getCatalogConfiguration().getParameters(); String s = Val.chkStr(params.getValue("lucene.force.isPartOf")); if (s.length() > 0) { if (s.indexOf(",") == -1) { String[] values = new String[]{s}; return new IsPartOfFilter("isPartOf",values,chained); } else { String[] tokens = s.split(","); ArrayList<String> al = new ArrayList<String>(); for (String token: tokens) { String s2 = Val.chkStr(token); if (s2.length() > 0) al.add(s2); } if (al.size() > 0) { String[] values = al.toArray(new String[0]); return new IsPartOfFilter("isPartOf",values,chained); } } } return chained; } /** * Queries for documents that match one or more of the supplied values. * @param reader the index reader * @return the OpenBitSet (documents with matches are set to true) * @throws IOException if an exception is encountered while reading the index */ private OpenBitSet queryValues(IndexReader reader, String field, String[] values) throws IOException { OpenBitSet bitSet = new OpenBitSet(reader.maxDoc()); if ((values != null) && (values.length > 0)) { TermDocs termDocs = null; try { Term baseTerm = new Term(field); termDocs = reader.termDocs(); for (String value: values) { termDocs.seek(baseTerm.createTerm(value.trim().toLowerCase())); while (termDocs.next()) { bitSet.set(termDocs.doc()); } } } finally { try {if (termDocs != null) termDocs.close();} catch (Exception ef) {} } } return bitSet; } }