_jarray.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  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. import sys
  19. import _jpype
  20. from . import _jclass
  21. from . import _jwrapper
  22. if sys.version > '3':
  23. unicode = str
  24. irange = range
  25. _CLASSES = {}
  26. _CUSTOMIZERS = []
  27. def _initialize():
  28. _jpype.setJavaArrayClass(_JavaArrayClass)
  29. _jpype.setGetJavaArrayClassMethod(_getClassFor)
  30. registerArrayCustomizer(CharArrayCustomizer())
  31. registerArrayCustomizer(ByteArrayCustomizer())
  32. def registerArrayCustomizer(c):
  33. _CUSTOMIZERS.append(c)
  34. class _JavaArrayClass(object):
  35. def __init__(self, jo):
  36. self.__javaobject__ = jo
  37. def __str__(self):
  38. return str(tuple(self))
  39. def __len__(self):
  40. return _jpype.getArrayLength(self.__javaobject__)
  41. def __iter__(self):
  42. return _JavaArrayIter(self)
  43. def __getitem__(self, ndx):
  44. if isinstance(ndx, slice):
  45. start, stop, step = ndx.indices(len(self))
  46. if step != 1:
  47. raise RuntimeError("Slicing with step unimplemented")
  48. return self.__getslice__(start, stop)
  49. return _jpype.getArrayItem(self.__javaobject__, ndx)
  50. def __setitem__(self, ndx, val):
  51. if isinstance(ndx, slice):
  52. start, stop, step = ndx.indices(len(self))
  53. if step != 1:
  54. # Iterate in python if we need to step
  55. indices = irange(start, stop, step)
  56. for index, value in zip(indices, val):
  57. self[index] = value
  58. else:
  59. self.__setslice__(start, stop, val)
  60. return
  61. _jpype.setArrayItem(self.__javaobject__, ndx, val)
  62. def __getslice__(self, i, j):
  63. if j == sys.maxsize:
  64. j = _jpype.getArrayLength(self.__javaobject__)
  65. return _jpype.getArraySlice(self.__javaobject__, i, j)
  66. def __setslice__(self, i, j, v):
  67. if j == sys.maxsize:
  68. j = _jpype.getArrayLength(self.__javaobject__)
  69. _jpype.setArraySlice(self.__javaobject__, i, j, v)
  70. def _jarrayInit(self, *args):
  71. if len(args) == 2 and args[0] == _jclass._SPECIAL_CONSTRUCTOR_KEY:
  72. _JavaArrayClass.__init__(self, args[1])
  73. elif len(args) != 1:
  74. raise TypeError(
  75. "Array classes only take 2 parameters, {0} given"
  76. .format(len(args) + 1))
  77. else:
  78. values = None
  79. if isinstance(args[0], collections.Sequence):
  80. sz = len(args[0])
  81. values = args[0]
  82. else:
  83. sz = args[0]
  84. _JavaArrayClass.__init__(
  85. self, _jpype.newArray(self.__class__.__javaclass__, sz))
  86. if values is not None:
  87. _jpype.setArraySlice(self.__javaobject__, 0, sz, values)
  88. class _JavaArrayIter(object):
  89. def __init__(self, a):
  90. self._array = a
  91. self._ndx = -1
  92. def __iter__(self):
  93. return self
  94. def __next__(self):
  95. self._ndx += 1
  96. if self._ndx >= len(self._array):
  97. raise StopIteration
  98. return self._array[self._ndx]
  99. next = __next__
  100. class _JavaArray(type):
  101. pass
  102. def _defineArrayClass(name, jt):
  103. members = {
  104. "__init__": _jarrayInit,
  105. "__javaclass__": jt,
  106. }
  107. bases = [_JavaArrayClass]
  108. for i in _CUSTOMIZERS:
  109. if i.canCustomize(name, jt):
  110. i.customize(name, jt, bases, members)
  111. return _JavaArray(name, tuple(bases), members)
  112. def _getClassFor(name):
  113. if name not in _CLASSES:
  114. jc = _jpype.findArrayClass(name)
  115. _CLASSES[name] = _defineArrayClass(name, jc)
  116. return _CLASSES[name]
  117. def JArray(t, ndims=1):
  118. if issubclass(t, _jwrapper._JWrapper):
  119. t = t.typeName
  120. elif isinstance(t, _JavaArray):
  121. t = t.typeName
  122. elif issubclass(t, _jclass._JAVAOBJECT):
  123. t = t.__name__
  124. elif not isinstance(t, str) and not isinstance(t, unicode):
  125. raise TypeError("Argument must be a java class, java array class, "
  126. "java wrapper or string representing a java class")
  127. arrayTypeName = t + ('[]' * ndims)
  128. return _getClassFor(arrayTypeName)
  129. def _charArrayStr(self):
  130. return ''.join(self)
  131. def _charArrayUnicode(self):
  132. return u''.join(self)
  133. class CharArrayCustomizer(object):
  134. def canCustomize(self, name, jc):
  135. if name == 'char[]':
  136. return True
  137. return False
  138. def customize(self, name, jc, bases, members):
  139. members['__str__'] = _charArrayStr
  140. members['__unicode__'] = _charArrayUnicode
  141. def _byteArrayStr(self):
  142. s = _jclass.JClass('java.lang.String')(self)
  143. return s.toString()
  144. class ByteArrayCustomizer(object):
  145. def canCustomize(self, name, jc):
  146. if name == 'byte[]':
  147. return True
  148. return False
  149. def customize(self, name, jc, bases, members):
  150. members['__str__'] = _byteArrayStr