Hi,
I have to add a comment to my previous mail:

> I'd preferred using this option (#2) in toArray (for both JavaList and
> JavaSet) as it does not require the wrapping into  Java Integer (etc.)
objects.
> However this method does not work with lucene.ArrayList:
> 
>  >> x=lucene. JArray ('int')([1,2])
>  JArray<int>[1, 2]
>  >>> y=lucene. ArrayList (x)
>  Traceback: lucene.InvalidArgsError:
>   (<type 'ArrayList'>, '__init__', (JArray<int>[1, 2],))
> 
Sorry - that's rubbish of course: ArrayList requires a collection in its
constructor and JArray isn't a collection. So this can't work! The
'challenge' was to be able to use JavaSet and/or JavaList (both are
collections) as an argument for ArrayList. (During init of ArrayList the
toArray() method is called however.)

So I gave it a quick try again, and tried the 2nd alternative:

> 1) return JArray(object)([<lucene.Integer()-object>*])
> or
> 2) return JArray(int)([<Python-int-literal>*])

but that option then fails (in the demo code) when using bool (or float)
types. Attached is a revised version of collections.py with the alternative
code (disabled) - if anyone's interested...

The mentioned issue with the created JArray containing the same objects
still remains. I'll have to look deeper into that, but as said I'm out of
office next week ...

BTW, sorry if this is out of scope of the PyLucene mailing list (it's more a
JCC related discussion) - we can continue with 'private' mail if that's
preferred. 

Regards,
Thomas
#   Licensed 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.

from lucene import JArray, Boolean, Float, Integer, Long, String, \
    PythonSet, PythonList, PythonIterator, PythonListIterator, JavaError, \
    NoSuchElementException, IllegalStateException, IndexOutOfBoundsException

# 1 wrap via lucene.Integer etc. (string not needed) - works (almost...)
_types = { bool: Boolean,
          float: Float,
            int: Integer,
           long: Long,
         }

# TODO: Remove this code ...
# 2 used typed JArray: works for string, but not float and bool
X_types = {  int: 'int',
           bool: 'bool',
          float: 'float',
           long: 'long',
            str: 'string'
         }


class JavaSet(PythonSet):
    """
    This class implements java.util.Set around a Python set instance it wraps.
    """

    def __init__(self, _set):
        super(JavaSet, self).__init__()
        self._set = _set

    def __contains__(self, obj):
        return obj in self._set

    def __len__(self):
        return len(self._set)

    def __iter__(self):
        return iter(self._set)

    def add(self, obj):
        if obj not in self._set:
            self._set.add(obj)
            return True
        return False

    def addAll(self, collection):
        size = len(self._set)
        self._set.update(collection)
        return len(self._set) > size

    def clear(self):
        self._set.clear()

    def contains(self, obj):
        return obj in self._set

    def containsAll(self, collection):
        for obj in collection:
            if obj not in self._set:
                return False
        return True

    def equals(self, collection):
        if type(self) is type(collection):
            return self._set == collection._set
        return False

    def isEmpty(self):
        return len(self._set) == 0

    def iterator(self):
        class _iterator(PythonIterator):
            def __init__(_self):
                super(_iterator, _self).__init__()
                _self._iterator = iter(self._set)
            def hasNext(_self):
                if hasattr(_self, '_next'):
                    return True
                try:
                    _self._next = _self._iterator.next()
                    return True
                except StopIteration:
                    return False
            def next(_self):
                if hasattr(_self, '_next'):
                    next = _self._next
                    del _self._next
                else:
                    next = _self._iterator.next()
                return next
        return _iterator()

    def remove(self, obj):
        try:
            self._set.remove(obj)
            return True
        except KeyError:
            return False

    def removeAll(self, collection):
        result = False
        for obj in collection:
            try:
                self._set.remove(obj)
                result = True
            except KeyError:
                pass
        return result

    def retainAll(self, collection):
        result = False
        for obj in list(self._set):
            if obj not in collection:
                self._set.remove(obj)
                result = True
        return result

    def size(self):
        return len(self._set)

    #1 wrap via lucene.Integer etc.
    def toArray(self):
        """
        convert the set to a lucene.JArray
        wrapping all elements into their Java 'counterpart'
        if the type is a primitive datatype (int, float, double, bool)
        note: we assume all elements have same type!
        """
        l = list(self._set)
        if l:
            t = type(l[0])
            if t in _types.keys():
                l = map(_types[t], l)
        return JArray(object)(l)

    # TODO: Remove this code ...
    #2 use typed JArray
    def XtoArray(self):  # JavaSet
        klass = object
        l = list(self._set)
        if l:
            t = type(l[0])
            if t in _types.keys():
                klass = _types[t]
        return JArray(klass)(l)




class JavaListIterator(PythonListIterator):
    """
    This class implements java.util.ListIterator for a Python list instance it
    wraps. (simple bidirectional iterator)
    """
    def __init__(self, _lst, index=0):
        super(JavaListIterator, self).__init__()
        self._lst = _lst
        self._lastIndex = -1 # keep state for remove/set
        self.index = index

    def next(self):
        if self.index >= len(self._lst):
            raise JavaError, NoSuchElementException(str(self.index))
        result = self._lst[self.index]
        self._lastIndex = self.index
        self.index += 1
        return result

    def previous(self):
        if self.index <= 0:
            raise JavaError, NoSuchElementException(str(self.index - 1))
        self.index -= 1
        self._lastIndex = self.index
        return self._lst[self.index]

    def hasPrevious(self):
        return self.index > 0

    def hasNext(self):
        return self.index < len(self._lst)

    def nextIndex(self):
        return min(self.index, len(self._lst))

    def previousIndex(self):
        return max(-1, self.index - 1)

    def add(self, element):
        """
        Inserts the specified element into the list.
        The element is inserted immediately before the next element
        that would be returned by next, if any, and after the next
        element that would be returned by previous, if any.
        """
        if self._lastIndex < 0:
            raise JavaError, IllegalStateException("add")
        self._lst.insert(self.index, element)
        self.index += 1
        self._lastIndex = -1 # invalidate state

    def remove(self):
        """
        Removes from the list the last element that
        was returned by next or previous.
        """
        if self._lastIndex < 0:
            raise JavaError, IllegalStateException("remove")
        del self._lst[self._lastIndex]
        self._lastIndex = -1 # invalidate state

    def set(self, element):
        """
        Replaces the last element returned by next or previous
        with the specified element.
        """
        if self._lastIndex < 0:
            raise JavaError, IllegalStateException("set")
        self._lst[self._lastIndex] = element

    def __iter__(self):
        return self


class JavaList(PythonList):
    """
    This class implements java.util.List around a Python list instance it wraps.
    """

    def __init__(self, _lst):
        super(JavaList, self).__init__()
        self._lst = _lst

    def __contains__(self, obj):
        return obj in self._lst

    def __len__(self):
        return len(self._lst)

    def __iter__(self):
        return iter(self._lst)

    def add(self, index, obj):
        self._lst.insert(index, obj)

    def addAll(self, collection):
        size = len(self._lst)
        self._lst.extend(collection)
        return len(self._lst) > size

    def addAll(self, index, collection):
        size = len(self._lst)
        self._lst[index:index] = collection
        return len(self._lst) > size

    def clear(self):
        del self._lst[:]

    def contains(self, obj):
        return obj in self._lst

    def containsAll(self, collection):
        for obj in collection:
            if obj not in self._lst:
                return False
        return True

    def equals(self, collection):
        if type(self) is type(collection):
            return self._lst == collection._lst
        return False

    def get(self, index):
        if index < 0 or index >= self.size():
            raise JavaError, IndexOutOfBoundsException(str(index))
        return self._lst[index]

    def indexOf(self, obj):
        try:
            return self._lst.index(obj)
        except ValueError:
            return -1

    def isEmpty(self):
        return len(self._lst) == 0

    def iterator(self):
        class _iterator(PythonIterator):
            def __init__(_self):
                super(_iterator, _self).__init__()
                _self._iterator = iter(self._lst)
            def hasNext(_self):
                if hasattr(_self, '_next'):
                    return True
                try:
                    _self._next = _self._iterator.next()
                    return True
                except StopIteration:
                    return False
            def next(_self):
                if hasattr(_self, '_next'):
                    next = _self._next
                    del _self._next
                else:
                    next = _self._iterator.next()
                return next
        return _iterator()

    def lastIndexOf(self, obj):
        i = len(self._lst)-1
        while (i>=0):
            if obj.equals(self._lst[i]):
                break
            i -= 1
        return i

    def listIterator(self, index=0):
        return JavaListIterator(self._lst, index)

    def remove(self, obj_or_index):
        if type(obj_or_index) is type(1):
            return removeAt(int(obj_or_index))
        return removeElement(obj_or_index)

    def removeAt(self, pos):
        """
        Removes the element at the specified position in this list.
        Note: private method called from Java via remove(int index)
        index is already checked (or IndexOutOfBoundsException thrown)
        """
        try:
            el = self._lst[pos]
            del self._lst[pos]
            return el
        except IndexError:
            # should not happen
            return None

    def removeObject(self, obj):
        """
        Removes the first occurrence of the specified object
        from this list, if it is present
        """
        try:
            self._lst.remove(obj)
            return True
        except ValueError:
            return False

    def removeAll(self, collection):
        result = False
        for obj in collection:
            if self.removeElement(obj):
                result = True
        return result

    def retainAll(self, collection):
        result = False
        for obj in self._lst:
            if obj not in collection and self.removeElement(obj):
                result = True
        return result

    def size(self):
        return len(self._lst)

    #1 wrap via lucene.Integer etc.
    def toArray(self): # JavaList
        """
        convert the list to a lucene.JArray
        wrapping all elements into their Java 'counterpart'
        if the type is a primitive datatype (int, float, double, bool)
        note: we assume all elements have same type!
        """
        l = self._lst
        if l:
            t = type(l[0])
            if t in _types.keys():
                l = map(_types[t], l)
        return JArray(object)(l)

    # TODO: Remove this code ...
    # 2 use typed JArray
    def XtoArray(self):  # JavaList
        klass = object
        l = self._lst
        if l:
            t = type(l[0])
            if t in _types.keys():
                klass = _types[t]
        return JArray(klass)(l)

    def subListChecked(self, fromIndex, toIndex):
        """
        Note: private method called from Java via subList()
        from/to index are already checked (or IndexOutOfBoundsException thrown)
        also IllegalArgumentException is thronw if the endpoint indices
        are out of order (fromIndex > toIndex)
        """
        sublst = self._lst[fromIndex:toIndex]
        return JavaList(sublst)

    def set(self, index, obj):
        if index < 0 or index >= self.size():
            raise JavaError, IndexOutOfBoundsException(str(index))
        self._lst[index] = obj

Reply via email to