text: from __future__ import absolute_import
  from __future__ import print_function
  import json
  from ._geom import Polygon, Polyline, Point, MultiPoint
  #TODO: from arcgis.geom import Polygon, Polyline, Point, MultiPoint
  ########################################################################
  class StatisticFilter(object):
      """
      The definitions for one or more field-based statistics to be calculated
      """
      _json = None
      _array = []
  
      #----------------------------------------------------------------------
      def __init__(self):
          """Constructor"""
          pass
      #----------------------------------------------------------------------
      def add(self, statisticType, onStatisticField, outStatisticFieldName=None):
          """
          Adds the statistics group to the filter.
  
          outStatistics - is supported on only those layers/tables that
            indicate supportsStatistics is true.
          outStatisticFieldName is empty or missing, the map server assigns a
            field name to the returned statistic field. A valid field name
            can only contain alphanumeric characters and an underscore.
          outStatisticFieldName is a reserved keyword of the underlying DBMS,
            the operation can fail. Try specifying an alternative
            outStatisticFieldName. When using outStatistics, the only other
            parameters that can be used are groupByFieldsForStatistics,
            orderByFields, time, and where.
          """
          val = {
              "statisticType" : statisticType,
              "onStatisticField" : onStatisticField,
              "outStatisticFieldName" : outStatisticFieldName
          }
          if outStatisticFieldName is None:
              del val['outStatisticFieldName']
          self._array.append(val)
      #----------------------------------------------------------------------
      def remove(self, index):
          """removes the filter by index"""
          self._array.remove(index)
      #----------------------------------------------------------------------
      def clear(self):
          """removes all the filters"""
          self._array = []
      #----------------------------------------------------------------------
      @property
      def filter(self):
          """ returns the key/value pair of a geometry filter """
          return self._array
  ########################################################################
  class LayerDefinitionFilter(object):
      """
         Allows you to filter the features of individual layers in the
         query by specifying definition expressions for those layers. A
         definition expression for a layer that is published with the
         service will always be honored.
      """
      _ids = []
      _filterTemplate = {"layerId" : "", "where" : "", "outFields" : "*"}
      _filter = []
      #----------------------------------------------------------------------
      def __init__(self):
          """Constructor"""
          pass
      #----------------------------------------------------------------------
      def addFilter(self, layer_id, where=None, outFields="*"):
          """ adds a layer definition filter """
          import copy
          f = copy.deepcopy(self._filterTemplate)
          f['layerId'] = layer_id
          f['outFields'] = outFields
          if where is not None:
              f['where'] = where
          if f not in self._filter:
              self._filter.append(f)
      #----------------------------------------------------------------------
      def removeFilter(self, filter_index):
          """ removes a layer filter based on position in filter list """
          f = self._filter[filter_index]
          self._filter.remove(f)
      #----------------------------------------------------------------------
      def removeAll(self):
          """ removes all items from the filter """
          self._filter = []
      #----------------------------------------------------------------------
      @property
      def filter(self):
          """ returns the filter object as a list of layer defs """
          return self._filter
  ########################################################################
  class GeometryFilter(object):
      """ creates a geometry filter for queries
          Inputs:
             geomObject - a common.Geometry or arcpy.Geometry object
             spatialFilter - The spatial relationship to be applied on the
                             input geometry while performing the query. The
                             supported spatial relationships include
                             intersects, contains, envelope intersects,
                             within, etc. The default spatial relationship
                             is intersects (esriSpatialRelIntersects).
             bufferDistance - if filter type esriSpatialRelWithin is selected
                              and the service supports that select type, then
                              the geometry will be buffered at a given.
                              Can be of type integer or float.
             units - the value the distance units represents. Valid values
                     are: "esriSRUnit_Meter", "esriSRUnit_StatuteMile",
                          "esriSRUnit_Foot", "esriSRUnit_Kilometer",
                           "esriSRUnit_NauticalMile", and
                           "esriSRUnit_USNauticalMile"
         Raises:
            AttributeError for invalid inputs
      """
      _allowedFilters = ["esriSpatialRelIntersects",
                         "esriSpatialRelContains",
                         "esriSpatialRelCrosses",
                         "esriSpatialRelEnvelopeIntersects",
                         "esriSpatialRelIndexIntersects",
                         "esriSpatialRelOverlaps",
                         "esriSpatialRelTouches",
                         "esriSpatialRelWithin"]
      _geomObject = None
      _spatialAction = None
      _geomType = None
      _spatialReference = None
      _buffer = None
      _units = None
      _allowed_units = ["esriSRUnit_Meter", "esriSRUnit_StatuteMile",
                        "esriSRUnit_Foot", "esriSRUnit_Kilometer",
                        "esriSRUnit_NauticalMile", "esriSRUnit_USNauticalMile"]
      #----------------------------------------------------------------------
      def __init__(self,
                   geomObject,
                   spatialFilter="esriSpatialRelIntersects",
                   bufferDistance=None,
                   units="esriSRUnit_Meter"
                   ):
          """Constructor"""
          self.geometry = geomObject
          if spatialFilter in self._allowedFilters:
              self._spatialAction = spatialFilter
              self._spatialReference = self.geometry.spatialReference
          else:
              raise AttributeError("geomObject must be a geometry object and "+ \
                                   "spatialFilter must be of value: " + \
                                   "%s" % ", ".join(self._allowedFilters))
          if not bufferDistance is None and \
             isinstance(bufferDistance, (int, float)) and \
             not units is None and \
             units.lower() in [f.lower() for f in self._allowed_units]:
              self._buffer = bufferDistance
              self._units = units
  
      #----------------------------------------------------------------------
      @property
      def spatialRelation(self):
          """ gets the filter type """
          return self._spatialAction
      #----------------------------------------------------------------------
      @spatialRelation.setter
      def spatialRelation(self, value):
          if value.lower() in \
             [x.lower() for x in self._allowedFilters]:
              self._spatialAction = value
          else:
              raise AttributeError("spatialRelation must be values of " + \
                                   "%s" % ", ".join(self._allowedFilters))
      #----------------------------------------------------------------------
      @property
      def geometryType(self):
          """ returns the geometry type """
          return self._geomObject.type
      #----------------------------------------------------------------------
      @property
      def geometry(self):
          """ gets the geometry object used by the filter """
          return self._geomObject
      #----------------------------------------------------------------------
      @geometry.setter
      def geometry(self, geometry):
          """ sets the geometry value """
  
          if isinstance(geometry, (Polygon, Point, Polyline, MultiPoint)):
              self._geomObject = geometry
              self._geomType = geometry.type
          else:
              raise AttributeError("geometry must be a common.Geometry type.")
      #----------------------------------------------------------------------
      @property
      def filter(self):
          """ returns the key/value pair of a geometry filter """
  
          val = {"geometryType":self.geometryType,
                  "geometry": json.dumps(self._geomObject.asDictionary),
                  "spatialRel": self.spatialRelation,
                  "inSR" : self._geomObject.spatialReference['wkid']}
          if self._buffer is not None and \
             self._units is not None:
              val['buffer'] = self._buffer
              val['units'] = self._units
          return val
  ########################################################################
  class TimeFilter(object):
      """ Implements the time filter """
      _startTime = None
      _endTime = None
      #----------------------------------------------------------------------
      def __init__(self, start_time, time_zone="UTC", end_time=None):
          """Constructor"""
          self._startTime = start_time
          self._endTime = end_time
          self._tz = time_zone
      #----------------------------------------------------------------------
      @property
      def filter(self):
          if not self._endTime is None:
              val = "%s, %s" % (self._startTime, self._endTime)
              return val
          else:
              return "%s" % self._startTime