_jcollection.py 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. #*****************************************************************************
  2. # Copyright 2004-2008 Steve Menard
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. #
  16. #*****************************************************************************
  17. import collections
  18. from . import _jclass
  19. class _WrappedIterator(object):
  20. """
  21. Wraps a Java iterator to respect the Python 3 iterator API
  22. """
  23. def __init__(self, iterator):
  24. self.iterator = iterator
  25. def __iter__(self):
  26. return self.iterator
  27. def __next__(self):
  28. return next(self.iterator)
  29. # Compatibility name
  30. next = __next__
  31. def _initialize():
  32. _jclass.registerClassCustomizer(CollectionCustomizer())
  33. _jclass.registerClassCustomizer(ListCustomizer())
  34. _jclass.registerClassCustomizer(MapCustomizer())
  35. _jclass.registerClassCustomizer(IteratorCustomizer())
  36. _jclass.registerClassCustomizer(EnumerationCustomizer())
  37. def isPythonSequence(v):
  38. if isinstance(v, collections.Sequence):
  39. if not hasattr(v.__class__, '__metaclass__') \
  40. or v.__class__.__metaclass__ is _jclass._JavaClass:
  41. return True
  42. return False
  43. def _colLength(self):
  44. return self.size()
  45. def _colIter(self):
  46. return _WrappedIterator(self.iterator())
  47. def _colDelItem(self, i):
  48. return self.remove(i)
  49. def _colAddAll(self, v):
  50. if isPythonSequence(v):
  51. r = False
  52. for i in v:
  53. r = self.add(i) or r
  54. return r
  55. else:
  56. return self._addAll(v)
  57. def _colRemoveAll(self, v):
  58. if isPythonSequence(v):
  59. r = False
  60. for i in v:
  61. r = self.remove(i) or r
  62. return r
  63. else:
  64. return self._removeAll(v)
  65. def _colRetainAll(self, v):
  66. if isPythonSequence(v):
  67. r = _jclass.JClass("java.util.ArrayList")(len(v))
  68. for i in v:
  69. r.add(i)
  70. else:
  71. r = v
  72. return self._retainAll(r)
  73. class CollectionCustomizer(object):
  74. _METHODS = {
  75. '__len__': _colLength,
  76. '__iter__': _colIter,
  77. '__delitem__': _colDelItem,
  78. }
  79. def canCustomize(self, name, jc):
  80. if name == 'java.util.Collection':
  81. return True
  82. return jc.isSubclass('java.util.Collection')
  83. def customize(self, name, jc, bases, members):
  84. if name == 'java.util.Collection':
  85. members.update(CollectionCustomizer._METHODS)
  86. else:
  87. # AddAll is handled by List
  88. if (not jc.isSubclass("java.util.List")) and 'addAll' in members:
  89. members['_addAll'] = members['addAll']
  90. members['addAll'] = _colAddAll
  91. if 'removeAll' in members:
  92. members['_removeAll'] = members['removeAll']
  93. members['removeAll'] = _colRemoveAll
  94. if 'retainAll' in members:
  95. members['_retainAll'] = members['retainAll']
  96. members['retainAll'] = _colRetainAll
  97. def _listGetItem(self, ndx):
  98. if isinstance(ndx, slice):
  99. start = ndx.start
  100. stop = ndx.stop
  101. if start < 0:
  102. start = self.size() + start
  103. if stop < 0:
  104. stop = self.size() + stop
  105. return self.subList(start, stop)
  106. else:
  107. if ndx < 0:
  108. ndx = self.size() + ndx
  109. return self.get(ndx)
  110. def _listSetItem(self, ndx, v):
  111. if isinstance(ndx, slice):
  112. start = ndx.start
  113. stop = ndx.stop
  114. if start < 0:
  115. start = self.size() + start
  116. if stop < 0:
  117. stop = self.size() + stop
  118. for i in range(start, stop):
  119. self.remove(start)
  120. if isinstance(v, collections.Sequence):
  121. ndx = start
  122. for i in v:
  123. self.add(ndx, i)
  124. ndx += 1
  125. else:
  126. if ndx < 0:
  127. ndx = self.size() + ndx
  128. self.set(ndx, v)
  129. def _listAddAll(self, v, v2=None):
  130. if isPythonSequence(v):
  131. r = False
  132. if v2 is not None: # assume form (int, values)
  133. for i in range(len(v2)):
  134. r = r or self.add(v + i, v2[i])
  135. else:
  136. for i in v:
  137. r = self.add(i) or r
  138. return r
  139. else:
  140. return self._addAll(v)
  141. class ListCustomizer(object):
  142. _METHODS = {
  143. '__setitem__': _listSetItem,
  144. '__getitem__': _listGetItem,
  145. }
  146. def canCustomize(self, name, jc):
  147. if name == 'java.util.List':
  148. return True
  149. return jc.isSubclass('java.util.List')
  150. def customize(self, name, jc, bases, members):
  151. if name == 'java.util.List':
  152. members.update(ListCustomizer._METHODS)
  153. else:
  154. if 'addAll' in members:
  155. members['_addAll'] = members['addAll']
  156. members['addAll'] = _listAddAll
  157. def isPythonMapping(v):
  158. if isinstance(v, collections.Mapping):
  159. if not hasattr(v.__class__, '__metaclass__') or \
  160. v.__class__.__metaclass__ is _jclass._JavaClass:
  161. return True
  162. return False
  163. def _mapLength(self):
  164. return self.size()
  165. def _mapIter(self):
  166. return _WrappedIterator(self.keySet().iterator())
  167. def _mapDelItem(self, i):
  168. return self.remove(i)
  169. def _mapGetItem(self, ndx):
  170. return self.get(ndx)
  171. def _mapSetItem(self, ndx, v):
  172. self.put(ndx, v)
  173. def _mapPutAll(self, v):
  174. if isPythonMapping(v):
  175. for i in v:
  176. self.put(i, v[i])
  177. else:
  178. # do the regular method ...
  179. self._putAll(v)
  180. class MapCustomizer(object):
  181. _METHODS = {
  182. '__len__': _mapLength,
  183. '__iter__': _mapIter,
  184. '__delitem__': _mapDelItem,
  185. '__getitem__': _mapGetItem,
  186. '__setitem__': _mapSetItem,
  187. }
  188. def canCustomize(self, name, jc):
  189. if name == 'java.util.Map':
  190. return True
  191. return jc.isSubclass('java.util.Map')
  192. def customize(self, name, jc, bases, members):
  193. if name == 'java.util.Map':
  194. members.update(MapCustomizer._METHODS)
  195. else:
  196. if "putAll" in members:
  197. members["_putAll"] = members["putAll"]
  198. members["putAll"] = _mapPutAll
  199. def _iterCustomNext(self):
  200. if self.hasNext():
  201. return self._next()
  202. raise StopIteration
  203. def _iterIteratorNext(self):
  204. if self.hasNext():
  205. return next(self)
  206. raise StopIteration
  207. def _iterIter(self):
  208. return self
  209. class IteratorCustomizer(object):
  210. _METHODS = {
  211. '__iter__': _iterIter,
  212. '__next__': _iterCustomNext,
  213. }
  214. def canCustomize(self, name, jc):
  215. if name == 'java.util.Iterator':
  216. return True
  217. return jc.isSubclass('java.util.Iterator')
  218. def customize(self, name, jc, bases, members):
  219. if name == 'java.util.Iterator':
  220. members.update(IteratorCustomizer._METHODS)
  221. elif jc.isSubclass('java.util.Iterator'):
  222. __next__ = 'next' if 'next' in members else '__next__'
  223. members['_next'] = members[__next__]
  224. members[__next__] = _iterCustomNext
  225. def _enumNext(self):
  226. if self.hasMoreElements():
  227. return self.nextElement()
  228. raise StopIteration
  229. def _enumIter(self):
  230. return self
  231. class EnumerationCustomizer(object):
  232. _METHODS = {
  233. 'next': _enumNext,
  234. '__next__': _enumNext,
  235. '__iter__': _enumIter,
  236. }
  237. def canCustomize(self, name, jc):
  238. return name == 'java.util.Enumeration'
  239. def customize(self, name, jc, bases, members):
  240. members.update(EnumerationCustomizer._METHODS)