/** \file filterbuilder.cpp .
-----------------------------------------------------------------------------


 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF 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.

-----------------------------------------------------------------------------

   Description:

-----------------------------------------------------------------------------


-------------------------------------------------------------------------- */


/* ----------------------------------------------------------------------- */
/*       Include dependencies                                              */
/* ----------------------------------------------------------------------- */
#include "uima/fsfilterbuilder.hpp"
#include "uima/fsindex.hpp"
#include "uima/internal_fspromoter.hpp"
/* ----------------------------------------------------------------------- */
/*       Constants                                                         */
/* ----------------------------------------------------------------------- */

/* ----------------------------------------------------------------------- */
/*       Forward declarations                                              */
/* ----------------------------------------------------------------------- */

/* ----------------------------------------------------------------------- */
/*       Types / Classes                                                   */
/* ----------------------------------------------------------------------- */

/*
Here are straightforward implementations of FSFilters.
Nothing exciting.
*/

namespace uima {
  namespace internal {

    //////////////////////////////////////////////////////
    class NOTFilter : public FSFilter {
    private:
      FSFilter * iv_pFilter;
    public:
      NOTFilter(FSFilter* pFilter)
          : iv_pFilter(pFilter) {
        assert(EXISTS(iv_pFilter));
      }

      bool isFiltered(FeatureStructure const & fs) const {
        assert(EXISTS(iv_pFilter));
        return ! iv_pFilter->isFiltered(fs);
      }

      void deInit() {
        assert(EXISTS(iv_pFilter));
        iv_pFilter->deInit();
        delete iv_pFilter;
      }
    };

    //////////////////////////////////////////////////////
    class BoolBinaryOperationFilter : public FSFilter {
    protected:
      FSFilter * iv_pFilter1;
      FSFilter * iv_pFilter2;

      BoolBinaryOperationFilter(FSFilter * pFilter1, FSFilter * pFilter2)
          : iv_pFilter1(pFilter1),
          iv_pFilter2(pFilter2) {
        assert(EXISTS(iv_pFilter1));
        assert(EXISTS(iv_pFilter2));
      }
    public:
      void deInit() {
        assert(EXISTS(iv_pFilter1));
        iv_pFilter1->deInit();
        delete iv_pFilter1;
        assert(EXISTS(iv_pFilter2));
        iv_pFilter2->deInit();
        delete iv_pFilter2;
      }
    };

    //////////////////////////////////////////////////////
    class ANDFilter : public BoolBinaryOperationFilter {
    public:
      ANDFilter(FSFilter * pFilter1, FSFilter * pFilter2)
          : BoolBinaryOperationFilter(pFilter1, pFilter2) {}

      bool isFiltered(FeatureStructure const & fs) const {
        assert(EXISTS(iv_pFilter1));
        assert(EXISTS(iv_pFilter2));
        // ensure that filter 2 is not used when filter 1 already returns false
        bool bResult1 = iv_pFilter1->isFiltered(fs);
        if (!bResult1) {
          return false;
        }
        //            cerr << __FILE__ << ", " << __LINE__ << ": value of filter1: " << iv_pFilter1->isFiltered(fs) << ", value of filter2: " << iv_pFilter2->isFiltered(fs) << endl;
        return iv_pFilter2->isFiltered(fs);
      }
    };

    //////////////////////////////////////////////////////
    class ORFilter : public BoolBinaryOperationFilter {
    public:
      ORFilter(FSFilter * pFilter1, FSFilter * pFilter2)
          : BoolBinaryOperationFilter(pFilter1, pFilter2) {}

      bool isFiltered(FeatureStructure const & fs) const {
        assert(EXISTS(iv_pFilter1));
        assert(EXISTS(iv_pFilter2));
        bool bResult1 = iv_pFilter1->isFiltered(fs);
        if (bResult1) {
          return true;
        }
        return iv_pFilter2->isFiltered(fs);
      }
    };

    //////////////////////////////////////////////////////
    class TypeFilter : public FSFilter {
    private:
      Type iv_type;
      bool iv_bUseSusumption;
    public:
      TypeFilter(Type const & crType, bool bUseSubsumption)
          : iv_type(crType),
          iv_bUseSusumption(bUseSubsumption) {}

      bool isFiltered(FeatureStructure const & fs) const {
        if (iv_bUseSusumption) {
          return iv_type.subsumes(fs.getType());
        }
        return iv_type == fs.getType();
      }

    };

    //////////////////////////////////////////////////////
    FeatureStructure getPath(FeatureStructure const & crFS, vector<Feature> const & crFeatures, size_t uiStep) {
      FeatureStructure result = crFS;
      size_t i;
      for (i=0; i<uiStep; ++i) {
        result = result.getFSValue(crFeatures[i]);
      }
      return result;
    }

    //////////////////////////////////////////////////////
    template<class T>
    class BuiltinFeatureValueFilter : public FSFilter {
    private:
      vector<Feature> iv_features;
      FSFilterBuilder::EnComparisonOperator iv_enOp;
      T iv_val;

      bool compare(FSFilterBuilder::EnComparisonOperator enOp, T val1, T val2) const {
        switch (enOp) {
        case FSFilterBuilder::EQUALS:
          return val1 == val2;
        case FSFilterBuilder::GREATER:
          return val1 > val2;
        case FSFilterBuilder::LESS:
          return val1 < val2;
        };
        assert(false);
        return false;
      }

    protected:
      virtual T getFeature(FeatureStructure const &, Feature const &) const = 0;
    public:
      BuiltinFeatureValueFilter(vector<Feature> const & crFeatures, FSFilterBuilder::EnComparisonOperator enOp, T val)
          : iv_features(crFeatures),
          iv_enOp(enOp),
        iv_val(val) {}

      bool isFiltered(FeatureStructure const & crFS) const {
        size_t uiLast = iv_features.size() - 1;
        FeatureStructure fs = getPath(crFS, iv_features, uiLast);
        T val = getFeature(fs, iv_features[uiLast]);
        return compare(iv_enOp, val, iv_val);
      }

    };

    //////////////////////////////////////////////////////
    class IntFeatureFilter : public BuiltinFeatureValueFilter<int> {
    protected:
      int getFeature(FeatureStructure const & crFS, Feature const & crFeat) const {
        return crFS.getIntValue(crFeat);
      }
    public:
      IntFeatureFilter(vector<Feature> const & crFeatures, FSFilterBuilder::EnComparisonOperator enOp, int val)
          : BuiltinFeatureValueFilter<int>(crFeatures, enOp, val) {}
    };

    //////////////////////////////////////////////////////
    class FloatFeatureFilter : public BuiltinFeatureValueFilter<float> {
    protected:
      float getFeature(FeatureStructure const & crFS, Feature const & crFeat) const {
        return crFS.getFloatValue(crFeat);
      }
    public:
      FloatFeatureFilter(vector<Feature> const & crFeatures, FSFilterBuilder::EnComparisonOperator enOp, float val)
          : BuiltinFeatureValueFilter<float>(crFeatures, enOp, val) {}
    };
    /////////////////////////////////////////////////////////////
    class UnicodeStringRefFeatureFilter : public BuiltinFeatureValueFilter<UnicodeStringRef> {
    protected:
      UnicodeStringRef getFeature(FeatureStructure const & crFS, Feature const & crFeat) const {
        return crFS.getStringValue(crFeat);
      }
    public:
      UnicodeStringRefFeatureFilter(vector<Feature> const & crFeaturePath, UnicodeStringRef const & crUStr)
          : BuiltinFeatureValueFilter<UnicodeStringRef>(crFeaturePath, FSFilterBuilder::EQUALS, crUStr ) {}
    };

    class StringFeatureFilter : public FSFilter {
    private:
      UnicodeStringRefFeatureFilter * iv_pUnicodeStringRefFeatureFilter;
      icu::UnicodeString iv_string;
    public:
      StringFeatureFilter(vector<Feature> const & crFeaturePath, UChar const * cpUTFBuffer, size_t uiLength)
          : iv_pUnicodeStringRefFeatureFilter(NULL) {
        iv_string = icu::UnicodeString( cpUTFBuffer, uiLength );
        UnicodeStringRef up(iv_string.getBuffer(), iv_string.length() );
        iv_pUnicodeStringRefFeatureFilter = new UnicodeStringRefFeatureFilter(crFeaturePath, up);
        assert( EXISTS( iv_pUnicodeStringRefFeatureFilter ) );
      }

      ~StringFeatureFilter() {
        if (iv_pUnicodeStringRefFeatureFilter != NULL) {
          delete iv_pUnicodeStringRefFeatureFilter;
          iv_pUnicodeStringRefFeatureFilter = NULL;
        }
      }

      virtual bool isFiltered(FeatureStructure const &crFS) const {
        assert( EXISTS( iv_pUnicodeStringRefFeatureFilter ) );
        return iv_pUnicodeStringRefFeatureFilter->isFiltered(crFS);
      }

      virtual void deInit() {
        assert( EXISTS( iv_pUnicodeStringRefFeatureFilter ) );
        iv_pUnicodeStringRefFeatureFilter->deInit();
      }

    };


    //////////////////////////////////////////////////////
    class MatchFilter : public FSFilter {
    private:
      vector<Feature> iv_features;
      FSFilter * iv_pFilter;
    public:
      MatchFilter(vector<Feature> const & crFeaturePath, FSFilter * pFilter)
          : iv_features(crFeaturePath),
          iv_pFilter(pFilter) {
        assert(EXISTS(iv_pFilter));
      }

      bool isFiltered(FeatureStructure const & crFS) const {
        FeatureStructure fs = getPath(crFS, iv_features, iv_features.size());
        assert(EXISTS(iv_pFilter));
        return iv_pFilter->isFiltered(fs);
      }

      void deInit() {
        assert(EXISTS(iv_pFilter));
        iv_pFilter->deInit();
        delete iv_pFilter;
      }
    };


  }
} // namespace uima

/* ----------------------------------------------------------------------- */
/*       Implementation                                                    */
/* ----------------------------------------------------------------------- */

namespace uima {

  FSFilterBuilder::FSFilterBuilder() {}

  FSFilterBuilder::~FSFilterBuilder() {}

  FSFilter * FSFilterBuilder::createNOTFilter(FSFilter * pFilter) const {
    return new internal::NOTFilter(pFilter);
  }

  FSFilter * FSFilterBuilder::createANDFilter(FSFilter * pFilter1, FSFilter * pFilter2) const {
    return new internal::ANDFilter(pFilter1, pFilter2);
  }

  FSFilter * FSFilterBuilder::createORFilter(FSFilter * pFilter1, FSFilter * pFilter2) const {
    return new internal::ORFilter(pFilter1, pFilter2);
  }

  FSFilter * FSFilterBuilder::createTypeFilter(Type const & crType, bool bUseSubsumption) const {
    return new internal::TypeFilter(crType, bUseSubsumption);
  }

  FSFilter * FSFilterBuilder::createIntFeatureFilter(vector<Feature> const & crFeatures, EnComparisonOperator enOp, int iVal) const {
    return new internal::IntFeatureFilter(crFeatures, enOp, iVal);
  }

  FSFilter * FSFilterBuilder::createFloatFeatureFilter(vector<Feature> const & crFeatures, EnComparisonOperator enOp, float fVal) const {
    return new internal::FloatFeatureFilter(crFeatures, enOp, fVal);
  }

  FSFilter * FSFilterBuilder::createMatchFilter(vector<Feature> const & crFeaturePath, FSFilter * pFilter) const {
    return new internal::MatchFilter(crFeaturePath, pFilter);
  }

  FSFilter * FSFilterBuilder::createStringFeatureFilter(vector<Feature> const & crFeaturePath, UChar const * cpUTFBuffer, size_t uiLength) const {
    return new internal::StringFeatureFilter(crFeaturePath, cpUTFBuffer, uiLength);
  }


} // namespace uima

/* ----------------------------------------------------------------------- */



