Package com.esri.gpt.catalog.lucene

Source Code of com.esri.gpt.catalog.lucene.TimeperiodProperty$MetaTermsTokenStream

/* 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 com.esri.gpt.catalog.schema.indexable.tp.TpInterval;
import com.esri.gpt.catalog.schema.indexable.tp.TpIntervals;
import com.esri.gpt.framework.util.Val;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.tokenattributes.TermAttribute;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.Fieldable;
import org.apache.lucene.document.NumericField;

/**
* Represents the time periods associated with a document.
*/
public class TimeperiodProperty extends Storeable {
 
  /** class variables ========================================================= */
   
  /** The Logger */
  private static Logger LOGGER = Logger.getLogger(TimeperiodProperty.class.getName());
 
  /** instance variables ====================================================== */
  private String intervalMetaFieldName;
  private String multiplicityFieldName;
  private String summaryMetaFieldName;
  private int    precisionStep = 4;
 
  /** constructors ============================================================ */
 
  /**
   * Constructs with a supplied name.
   * @param name the property name
   */
  public TimeperiodProperty(String name) {
    super(name);
    this.intervalMetaFieldName = this.getName()+".imeta";
    this.multiplicityFieldName = this.getName()+".num";
    this.summaryMetaFieldName = this.getName()+".meta";
  }
     
  /** methods ================================================================= */
 
  /**
   * Appends underlying fields to a document prior to writing the
   * document to the index.
   * @param document the Lucene document
   */
  @Override
  public void appendForWrite(Document document) {
   
    // get the analyzed time period intervals
    boolean bWasInvalid = false;
    TpIntervals intervals = null;
    Object value = null;
    if ((getValues() != null) && (getValues().length == 1)) {
      value = getValues()[0];
      if (value instanceof TpIntervals) {
        intervals = (TpIntervals)value;
      }
    }
    if (intervals == null) {
      intervals = new TpIntervals();
      bWasInvalid = true;
    }
    if (intervals.size() > 1) intervals.sort();

    long nNow = System.currentTimeMillis();
    long nLower = Long.MAX_VALUE;
    long nUpper = Long.MIN_VALUE;
    int nInterval = 0;
    boolean bHasUnknown = false;
    boolean bHasNow = false;
    boolean bHasLowerNow = false;
    boolean bHasUpperNow = false;
    boolean bHasDeterminate = false;
    boolean bLastWasUpperNow = false;
    TpInterval firstInterval = null;
    List<String> lIMetaTerms = new ArrayList<String>();
    List<String> lSMetaTerms = new ArrayList<String>();
    ArrayList<Fieldable> lFields = new ArrayList<Fieldable>();
   
    int nIntervals = intervals.size();
    int nLastInterval = (nIntervals - 1);
    for (int i=0;i<nIntervals;i++) {
      boolean bLastInterval = (i == nLastInterval);
      TpInterval interval = intervals.get(i);     
      String sCurInd = Val.chkStr(interval.getIndeterminate());
     
      if (sCurInd.equals("unknown")) {
        bHasUnknown = true;
      } else {
       
        nInterval++;
        String sLowerField = this.getLowerFieldName(nInterval);
        String sUpperField = this.getUpperFieldName(nInterval);
        long nCurLower = interval.getLower().longValue();
        long nCurUpper = interval.getUpper().longValue();
        lFields.add(this.makeBoundaryField(sLowerField,nCurLower));
        lFields.add(this.makeBoundaryField(sUpperField,nCurUpper));
        if (firstInterval == null) {
          firstInterval = interval;
        }
       
        if (sCurInd.equals("now")) {
          bHasNow = true;
          lIMetaTerms.add(this.getMetaValue("now",nInterval));
        } else if (sCurInd.equals("now.lower")) {
          bHasLowerNow = true;
          lIMetaTerms.add(this.getMetaValue("now.l",nInterval));
          if (nCurUpper > nUpper) {
            nUpper = nCurUpper;
          }
        } else if (sCurInd.equals("now.upper")) {
          bHasUpperNow = true;
          if (bLastInterval) bLastWasUpperNow = true;
          lIMetaTerms.add(this.getMetaValue("now.u",nInterval));
          if (nCurLower < nLower) {
            nLower = nCurLower;
          }
        } else {
          bHasDeterminate = true;
          lIMetaTerms.add(this.getMetaValue("determinate",nInterval));
          if (nCurLower < nLower) {
            nLower = nCurLower;
          }
          if (nCurUpper > nUpper) {
            nUpper = nCurUpper;
          }
        }
      }
    } 
   
    int nMultiplicity = lFields.size() / 2;
    boolean bIsUnknown = bHasUnknown && (nMultiplicity == 0);
    boolean bIsDeterminate = bHasDeterminate && !bHasUnknown &&
                             !bHasNow && !bHasLowerNow && !bHasUpperNow;
    boolean bIs1Determinate = bIsDeterminate && (nMultiplicity == 1);
    boolean bIsIndeterminate = bHasNow || bHasLowerNow || bHasUpperNow;
    boolean bIs1Indeterminate = bIsIndeterminate && (nMultiplicity == 1);
    boolean bWasEmpty = !bWasInvalid && (nIntervals == 0);
    if (bIsDeterminate)    lSMetaTerms.add("isDeterminate");
    if (bIs1Determinate)   lSMetaTerms.add("is1Determinate");
    if (bIsIndeterminatelSMetaTerms.add("isIndeterminate");
    if (bIs1Indeterminate) lSMetaTerms.add("is1Indeterminate");
    if (bIsUnknown)        lSMetaTerms.add("isUnknown");
    if (bHasDeterminate)   lSMetaTerms.add("hasDeterminate");
    if (bHasUnknown)       lSMetaTerms.add("hasUnknown");
    if (bHasNow)           lSMetaTerms.add("hasNow");
    if (bHasLowerNow)      lSMetaTerms.add("hasLowerNow");
    if (bHasUpperNow)      lSMetaTerms.add("hasUpperNow");
    if (bWasInvalid)       lSMetaTerms.add("wasInvalid");
    if (bWasEmpty)         lSMetaTerms.add("wasEmpty");
   
    // make the summary interval (for the document minLower->maxUpper)
    nInterval = 0;
    String sLowerField = this.getLowerFieldName(nInterval);
    String sUpperField = this.getUpperFieldName(nInterval);
    if (bIsDeterminate) {
      String sMeta = "determinate";
      lFields.add(0,this.makeBoundaryField(sUpperField,nUpper));
      lFields.add(0,this.makeBoundaryField(sLowerField,nLower));
      lIMetaTerms.add(0,this.getMetaValue(sMeta,nInterval));
    } else if (nMultiplicity == 1) {
      TpInterval interval = firstInterval;
      String sCurInd = Val.chkStr(interval.getIndeterminate());
      String sMeta = null;
      if (sCurInd.equals("now")) {
        sMeta = "now";
      } else if (sCurInd.equals("now.lower")) {
        sMeta = "now.l";
      } else if (sCurInd.equals("now.upper")) {
        sMeta = "now.u";
      }
      if (sMeta != null) {
        lFields.add(0,this.makeBoundaryField(sUpperField,nUpper));
        lFields.add(0,this.makeBoundaryField(sLowerField,nLower));
        lIMetaTerms.add(0,this.getMetaValue(sMeta,nInterval));
      }
    } else if (nMultiplicity > 1) {
                 
      // check for a sequential set of intervals ending with now
      // e.g. 2008-08-01..2009-08-31 , 2009-09-01..2010-04-15 , 2010-04-16..now
      boolean bUseUpperNowSummary = false;
      if (!bHasUnknown && !bHasNow && !bHasLowerNow &&
           bHasUpperNow && bLastWasUpperNow) {
        if ((nLower != Long.MIN_VALUE) && (nLower != Long.MAX_VALUE)) {
          if ((nUpper != Long.MIN_VALUE) && (nUpper != Long.MAX_VALUE)) {
            if (nUpper < nNow) {
              bUseUpperNowSummary = true;
            }
          }
        }
      }
     
      if (!bUseUpperNowSummary) {
        // not sure how to generate the summary interval here,
        // without a summary the document cannot fall "within"
      } else {
        lFields.add(0,this.makeBoundaryField(sUpperField,Long.MAX_VALUE));
        lFields.add(0,this.makeBoundaryField(sLowerField,nLower));
        lIMetaTerms.add(0,this.getMetaValue("now.u",nInterval));
      }
    }
   
    // add the multiplicity field
    boolean bIndexMultiplicity = true;
    if (bIndexMultiplicity) {
      String sName = this.multiplicityFieldName;
      NumericField f = new NumericField(sName,this.precisionStep,Field.Store.YES,true);
      f.setLongValue(nMultiplicity);
      lFields.add(0,f);
    }
   
    // add the interval meta terms field
    if (lIMetaTerms.size() > 0) {
      String sName = this.intervalMetaFieldName;
      String sValue = "meta-terms";
      Field f = new Field(sName,sValue,Field.Store.YES,Field.Index.ANALYZED,Field.TermVector.NO);
      String[] aMetaTerms = lIMetaTerms.toArray(new String[lIMetaTerms.size()]);
      f.setTokenStream(new MetaTermsTokenStream(aMetaTerms));
      lFields.add(0,f);
    }
   
    // add the summary meta terms field
    if (lSMetaTerms.size() > 0) {
      String sName = this.summaryMetaFieldName;
      String sValue = "meta-terms";
      Field f = new Field(sName,sValue,Field.Store.YES,Field.Index.ANALYZED,Field.TermVector.NO);
      String[] aMetaTerms = lSMetaTerms.toArray(new String[lSMetaTerms.size()]);
      f.setTokenStream(new MetaTermsTokenStream(aMetaTerms));
      lFields.add(0,f);
    }
   
    // add the interval fields
    for (Fieldable fld: lFields) {
      if (LOGGER.isLoggable(Level.FINER)) {
        StringBuffer sb = new StringBuffer();
        sb.append("Appending field:\n ");
        sb.append(" name=\"").append(fld.name()).append("\"");
        sb.append(" storageOption=\"").append(fld.isStored()).append("\"");
        sb.append("\n  storeValue=\"").append(fld.stringValue()).append("\"");
        LOGGER.finer(sb.toString());
      }
      document.add(fld);
    }
  }
 
  /**
   * Appends underlying fields to a document prior to writing the
   * document to the index.
   * @param document the Lucene document
   * @param value the input value to write
   */
  @Override
  public void appendForWrite(Document document, Object value) {
    // Not applicable
  }
 
  /**
   * Makes the lower boundary field name associated with an interval index.
   * <br/>Interval 0 is the summary interval for the document.
   * @param interval the interval index
   * @return the name
   */
  private String getLowerFieldName(int interval) {
    //if (interval == 0) return this.getName()+".l.d";
    //else return this.getName()+".l."+interval;
    return this.getName()+".l."+interval;
  }
 
  /**
   * Makes the meta value associated with an interval index.
   * <br/>Interval 0 is the summary interval for the document.
   * @param type the value predicate
   * @param interval the interval index
   * @return the name
   */
  private String getMetaValue(String type, int interval) {
    //if (interval == 0) return type+".d";
    //else return type+"."+interval;
    return type+"."+interval;
  }

  /**
   * Makes the upper boundary field name associated with an interval index.
   * <br/>Interval 0 is the summary interval for the document.
   * @param interval the interval index
   * @return the name
   */
  private String getUpperFieldName(int interval) {
    return this.getName()+".u."+interval;
    //String s = this.getName()+".bnd.u";
    //if (interval == 0) return s;
    //else return s+"."+interval;
    //if (interval == 0) return this.getName()+".u.d";
    //else return this.getName()+".u."+interval;
  }
 
  /**
   * Makes an interval boundary field.
   * @param name the field name
   * @param value the field value
   * @return the field
   */
  private NumericField makeBoundaryField(String name, Long value) {
    NumericField f = new NumericField(name,this.precisionStep,Field.Store.YES,true);
    f.setLongValue(value);
    return f;
  }
 
  /**
   * A stream to provide the meta terms for a time period.
   */
  private class MetaTermsTokenStream extends TokenStream  {
    private int           currentIndex = -1;
    private TermAttribute termAttribute = addAttribute(TermAttribute.class);
    private int           termCount = 0;
    private String[]      terms;
   
    public MetaTermsTokenStream(String[] terms) {
      this.terms = terms;
      this.termCount = this.terms.length;
    }

    @Override
    public boolean incrementToken() throws IOException {
      this.currentIndex++;
      if (this.currentIndex < this.termCount) {
        String sTerm = this.terms[this.currentIndex];
        this.termAttribute.setTermBuffer(sTerm.toLowerCase());
        return true;
      }
      return false;
    }

    @Override
    public void reset() throws IOException {
      this.currentIndex = -1;
    }
  }
  
}
TOP

Related Classes of com.esri.gpt.catalog.lucene.TimeperiodProperty$MetaTermsTokenStream

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.