#*****************************************************************************
#   Copyright 2004-2008 Steve Menard
#
#   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.
#   
#*****************************************************************************
import operator
import _jclass

def _initialize() :
    _jclass.registerClassCustomizer(CollectionCustomizer())
    _jclass.registerClassCustomizer(ListCustomizer())
    _jclass.registerClassCustomizer(MapCustomizer())
    _jclass.registerClassCustomizer(IteratorCustomizer())
    _jclass.registerClassCustomizer(EnumerationCustomizer())

def isPythonSequence(v):       
    if operator.isSequenceType(v) :
        if not hasattr(v.__class__, '__metaclass__') or v.__class__.__metaclass__ is _jclass._JavaClass :
            return True
    return False

def _colLength(self) :
    return self.size()
    
def _colIter(self) :    
    return self.iterator()

def _colDelItem(self, i) :
    return self.remove(i)

def _colAddAll(self, v):
    if isPythonSequence(v) :
        r = False
        for i in v :
            r = self.add(i) or r
        return r
    else:
        return self._addAll(v)

def _colRemoveAll(self, v):
    if isPythonSequence(v) :
        r = False
        for i in v :
            r = self.remove(i) or r
        return r
    else:
        return self._removeAll(v)

def _colRetainAll(self, v):
    if isPythonSequence(v) :
        r = _jclass.JClass("java.util.ArrayList")(len(v))
        for i in v :
            r.add(i)
    else:
        r = v
                
    return self._retainAll(r)

class CollectionCustomizer(object) :
    _METHODS = {
        '__len__' : _colLength,
        '__iter__' : _colIter,
        '__delitem__' : _colDelItem,
    }
    
    def canCustomize(self, name, jc) :
        if name == 'java.util.Collection' :
            return True
        return jc.isSubclass('java.util.Collection')
        
    def customize(self, name, jc, bases, members) :
        if name == 'java.util.Collection' :
            members.update(CollectionCustomizer._METHODS)
        else:
            # AddAll is handled by List  
            if (not jc.isSubclass("java.util.List")) and 'addAll' in members :
                members['_addAll'] = members['addAll']
                members['addAll'] = _colAddAll
            if 'removeAll' in members :
                members['_removeAll'] = members['removeAll']
                members['removeAll'] = _colRemoveAll
            if 'retainAll' in members :
                members['_retainAll'] = members['retainAll']
                members['retainAll'] = _colRetainAll

def _listGetItem(self, ndx) :
    if isinstance(ndx, slice) :
        start = ndx.start
        stop = ndx.stop
        if start < 0 :
            start = self.size() + start
        if stop < 0 :
            stop = self.size() + stop
        return self.subList(start, stop)
    else:
        if ndx < 0 :
            ndx = self.size() + ndx
        return self.get(ndx)
        
def _listSetItem(self, ndx, v) :
    if isinstance(ndx, slice) :
        start = ndx.start
        stop = ndx.stop
        if start < 0 :
            start = self.size() + start
        if stop < 0 :
            stop = self.size() + stop
        for i in range(start, stop) :
            self.remove(start)
        if operator.isSequenceType(v) :
            ndx = start
            for i in v :
                self.add(ndx, i)
                ndx += 1
    else:
        if ndx < 0 :
            ndx = self.size() + ndx
        self.set(ndx, v)

def _listAddAll(self, v, v2=None):
    if isPythonSequence(v) :
        r = False
        if v2 is not None : # assume form (int, values)
            for i in range(len(v2)) :
                r = r or self.add(v+i, v2[i])
                ndx +=1
        else:    
            for i in v :
                r = self.add(i) or r
        return r
    else:
        return self._addAll(v)

class ListCustomizer(object) :
    _METHODS = {
        '__setitem__' : _listSetItem,
        '__getitem__' : _listGetItem,
    }
    
    def canCustomize(self, name, jc) :
        if name == 'java.util.List' :
            return True
        return jc.isSubclass('java.util.List')
        
    def customize(self, name, jc, bases, members) :
        if name == 'java.util.List' :
            members.update(ListCustomizer._METHODS)
        else:
            if 'addAll' in members :
                members['_addAll'] = members['addAll']
                members['addAll'] = _listAddAll            
       
def isPythonMapping(v):       
    if operator.isMappingType(v) :
        if not hasattr(v.__class__, '__metaclass__') or v.__class__.__metaclass__ is _jclass._JavaClass :
            return True
    return False
        
def _mapLength(self) :
    return self.size()
    
def _mapIter(self) :
    return self.keySet().iterator()

def _mapDelItem(self, i) :
    return self.remove(i)

def _mapGetItem(self, ndx) :
    return self.get(ndx)
        
def _mapSetItem(self, ndx, v) :
    self.put(ndx, v)

def _mapPutAll(self, v):
    if isPythonMapping(v) :
        for i in v :
            self.put(i, v[i])
    else:        
        #do the regular method ...    
        self._putAll(v)
    
class MapCustomizer(object) :
    _METHODS = {
        '__len__' : _mapLength,
        '__iter__' : _mapIter,
        '__delitem__' : _mapDelItem,
        '__getitem__' : _mapGetItem,
        '__setitem__' : _mapSetItem,
    }
    
    def canCustomize(self, name, jc) :
        if name == 'java.util.Map' :
            return True
        return jc.isSubclass('java.util.Map')
        
    def customize(self, name, jc, bases, members) :
        if name == 'java.util.Map' :
            members.update(MapCustomizer._METHODS)
        else:
            if "putAll" in members :
                   members["_putAll"] = members["putAll"]
                   members["putAll"] = _mapPutAll

def _iterNext(self) :
    if self.hasNext() :
        return self._next()
    raise StopIteration
    
def _iterIter(self) :
    return self
    
class IteratorCustomizer(object) :
    _METHODS = {
        '__iter__' : _iterIter,
    }
    
    def canCustomize(self, name, jc) :
        if name == 'java.util.Iterator' :
            return True
        return jc.isSubclass('java.util.Iterator')
        
    def customize(self, name, jc, bases, members) :
        if name == 'java.util.Iterator' :
            members.update(IteratorCustomizer._METHODS)
        elif jc.isSubclass('java.util.Iterator') and 'next' in members:
            members['_next'] = members['next']
            members['next'] = _iterNext

def _enumNext(self) :
    if self.hasMoreElements() :
        return self.nextElement()
    raise StopIteration
    
def _enumIter(self) :
    return self
    

class EnumerationCustomizer(object) :
    _METHODS = {
        'next' : _enumNext,
        '__iter__' : _enumIter,
    }
    
    def canCustomize(self, name, jc) :
        return name == 'java.util.Enumeration'
        
    def customize(self, name, jc, bases, members) :
        members.update(EnumerationCustomizer._METHODS)
        
