!=========================================================================
! Copyright (C) VMware, Inc. 1986-2011.  All Rights Reserved.
!
! $Id: indexquery.gs,v 1.5 2008-01-09 22:50:12 stever Exp $
!
! Superclass Hierarchy:
!   IndexedQueryEvaluator, Object.
!
!=========================================================================

! class created in idxclasses.topaz

removeallmethods IndexedQueryEvaluator
removeallclassmethods IndexedQueryEvaluator

category: 'For Documentation Installation only'
classmethod: IndexedQueryEvaluator
installDocumentation

| doc txt |
doc := GsClassDocumentation newForClass: self.

txt := (GsDocText new) details:
'IndexedQueryEvaluator is an abstract class that implements the behavior used to 
 evaluate queries against UnordedCollections that have been indexed. This class is
 used in the internal implementation of indexing and should not be modified.'.
doc documentClassWith: txt.

self description: doc.
%

! ------------------- Class methods for IndexedQueryEvaluator
category: 'Instance Creation'
classmethod: IndexedQueryEvaluator
on: anIndex

  ^ self new index: anIndex
%
! ------------------- Instance methods for IndexedQueryEvaluator
category: 'Query Select'
method: IndexedQueryEvaluator
findAllValuesIdenticalTo: aValue

  ^IndexedQueryEvaluator subclassResponsibility: #findAllValuesIdenticalTo:
%
category: 'Query Select'
method: IndexedQueryEvaluator
findAllValuesNotIdenticalTo: aValue

"Returns a set of all values that satisfy the query."

| tmpHolder res |

self index isIndexOnRootNsc
    ifTrue: [ 
        tmpHolder := self nscRoot copy.
        tmpHolder removeAll: (self _allIdenticalTo: aValue in: self nscRoot).
        ^ tmpHolder
    ].

tmpHolder := NscBuilder for: self nscRoot speciesForSelect new max: self sizeForNscBuilder.

" get all objects identical to aValue and identical to nil "
tmpHolder _addAllNsc: (self findAllValuesIdenticalTo: aValue) _asIdentityBag.
tmpHolder _addAllNsc: (self _allIdenticalTo: nil in: self nscRoot).

" get all objects with nil along the path "
1 to: self index size - 1 do: [ :i |
    self index _addAllFor: nil
        into: tmpHolder
        offset: i
        pathTerm: (self index at: i)
].

res := self nscRoot _asIdentityBag - tmpHolder completeBag _asIdentityBag.
res _class == self nscRoot speciesForSelect
  ifFalse: [
    | finalRes |
    finalRes := self nscRoot speciesForSelect new.
    finalRes addAll: res.
    ^ finalRes
  ].
^ res
%
category: 'Query Detect'
method: IndexedQueryEvaluator
findFirstValueIdenticalTo: aValue

  ^IndexedQueryEvaluator subclassResponsibility: #findFirstValueIdenticalTo:
%
category: 'Query Detect'
method: IndexedQueryEvaluator
findFirstValueNotIdenticalTo: aValue

"Returns the first value that satisfies the query."

| key lastPathTerm |

lastPathTerm := self index lastPathTerm.
" optimize query for objects in the NSC itself "
self index isIndexOnRootNsc
  ifTrue: [
    1 to: index nscRoot size do: [ :i |
      ((self nscRoot _at: i) == aValue)
        ifFalse: [ ^ self nscRoot _at: i ]
    ].
    ^ #_incompletePathTraversal
  ].

key := self _findFirstKeyNotIdenticalTo: aValue atTerm: lastPathTerm.
(key == #_incompletePathTraversal)
  ifTrue: [ ^ #_incompletePathTraversal ].

^ self findFirstValueIdenticalTo: key
%
category: 'Accessing'
method: IndexedQueryEvaluator
index

  ^index
%
category: 'Updating'
method: IndexedQueryEvaluator
index: anIndex

  index := anIndex
%
category: 'Accessing'
method: IndexedQueryEvaluator
nscRoot

^self index nscRoot
%
category: 'Accessing'
method: IndexedQueryEvaluator
sizeForNscBuilder

"Returns the size to be used when an NscBuilder is collecting objects."

^ self nscRoot size
%
category: 'Support'
method: IndexedQueryEvaluator
_allIdenticalTo: anObject in: nsc

"Returns a new NSC containing the given object with the number of occurrences
 as in the root NSC."

| result tmp |
result := self _primAllIdenticalTo: anObject in: nsc _asIdentityBag.
nsc _isIdentityBag
  ifFalse: [
    tmp := nsc class new: result size.
    tmp addAll: result.
    result := tmp
  ].
^ result
%
category: 'Error Handling'
method: IndexedQueryEvaluator
_errorCannotInvokeRangeOperationOnIdentityIndex

"An attempt was made to use a range operation (< > = <= >=) on a path
 expression only supported by an identity index."

^ self index _errorCannotInvokeRangeOperationOnIdentityIndex
%
category: 'Searching'
method: IndexedQueryEvaluator
_findFirstKeyNotIdenticalTo: aValue atTerm: pathTerm

  ^IndexedQueryEvaluator subclassResponsibility: #_findFirstKeyNotIdenticalTo:atTerm:
%
category: 'Searching'
method: IndexedQueryEvaluator
_findFirstValueForKey: aKey

"Returns any root value for the given key by following the path terms in reverse
 order.  If none are found, returns aValue."

| startPt tmpVal incomplete |

nil == self index indexDictionary
  ifTrue: [ ^ aKey ].

tmpVal := aKey.
self index isIndexOnNscElements
    ifTrue: [ startPt := self index size ]
    ifFalse: [ startPt := self index lastPathComponentsDictionaryOffset ].

incomplete := #_incompletePathTraversal.
startPt downTo: 1 do: [ :i |
  tmpVal := self index indexDictionary
    firstAt: tmpVal
    term: (self index at: i)
    otherwise: incomplete.
  (tmpVal == incomplete)
    ifTrue: [ ^ incomplete ].
].
^ tmpVal
%
category: 'Support'
method: IndexedQueryEvaluator
_primAllIdenticalTo: anObject in: nsc

"Returns a new NSC containing the given object with the number of occurrences
 as in the root NSC."

<primitive: 340>

self _primitiveFailed: #_primAllIdenticalTo:in: .
self _uncontinuableError
%


