@@ -140,6 +140,38 @@ def isjava(data) -> bool:
140140 return isinstance (data , jpype .JClass ) or isinstance (data , jpype .JObject )
141141
142142
143+ def is_jbyte (the_type : type ) -> bool :
144+ return _is_jtype (the_type , "java.lang.Byte" )
145+
146+
147+ def is_jshort (the_type : type ) -> bool :
148+ return _is_jtype (the_type , "java.lang.Short" )
149+
150+
151+ def is_jinteger (the_type : type ) -> bool :
152+ return _is_jtype (the_type , "java.lang.Integer" )
153+
154+
155+ def is_jlong (the_type : type ) -> bool :
156+ return _is_jtype (the_type , "java.lang.Long" )
157+
158+
159+ def is_jfloat (the_type : type ) -> bool :
160+ return _is_jtype (the_type , "java.lang.Float" )
161+
162+
163+ def is_jdouble (the_type : type ) -> bool :
164+ return _is_jtype (the_type , "java.lang.Double" )
165+
166+
167+ def is_jboolean (the_type : type ) -> bool :
168+ return _is_jtype (the_type , "java.lang.Boolean" )
169+
170+
171+ def is_jcharacter (the_type : type ) -> bool :
172+ return _is_jtype (the_type , "java.lang.Character" )
173+
174+
143175def is_jarray (data : Any ) -> bool :
144176 """Return whether the given data object is a Java array."""
145177 if mode == Mode .JEP :
@@ -246,3 +278,50 @@ def jarray(kind, lengths: Sequence):
246278 for i in range (len (arr )):
247279 arr [i ] = jarray (kind , lengths [1 :])
248280 return arr
281+
282+
283+ def numeric_bounds (the_type : type ) -> Union [Tuple [int , int ], Tuple [float , float ], Tuple [None , None ]]:
284+ """
285+ Get the minimum and maximum values for the given numeric type.
286+ For example, a Java long returns (int(Long.MIN_VALUE), int(Long.MAX_VALUE)),
287+ whereas a Java double returns (float("-inf"), float("inf")).
288+
289+ :param the_type: The type whose minimum and maximum values are needed.
290+ :return:
291+ The minimum and maximum values as a two-element tuple of int or float,
292+ or a two-element tuple of None if no known bounds.
293+ """
294+ if is_jbyte (the_type ):
295+ Byte = jimport ("java.lang.Byte" )
296+ return int (Byte .MIN_VALUE ), int (Byte .MAX_VALUE )
297+
298+ if is_jshort (the_type ):
299+ Short = jimport ("java.lang.Short" )
300+ return int (Short .MIN_VALUE ), int (Short .MAX_VALUE )
301+
302+ if is_jinteger (the_type ):
303+ Integer = jimport ("java.lang.Integer" )
304+ return int (Integer .MIN_VALUE ), int (Integer .MAX_VALUE )
305+
306+ if is_jlong (the_type ):
307+ Long = jimport ("java.lang.Long" )
308+ return int (Long .MIN_VALUE ), int (Long .MAX_VALUE )
309+
310+ if is_jfloat (the_type ) or is_jdouble (the_type ):
311+ return float ("-inf" ), float ("inf" )
312+
313+ return None , None
314+
315+
316+ def _is_jtype (the_type : type , class_name : str ) -> bool :
317+ """
318+ Test if the given type object is *exactly* the specified Java type.
319+
320+ :param the_type: The type object to check.
321+ :param class_name: The fully qualified Java class name in string form.
322+ :returns: True iff the type is exactly that Java type.
323+ """
324+ # NB: Stringify the type to support both bridge modes. Ex:
325+ # * JPype: <java class 'java.lang.Integer'>
326+ # * Jep: <class 'java.lang.Integer'>
327+ return f"class '{ class_name } '" in str (the_type )
0 commit comments