Class ObjectUtils
This class includes methods for:
- Evaluating object truthiness and emptiness
- Determining and converting between Java and Naftah types
- Applying arithmetic and logical operations to objects
- Handling arrays, collections, maps, and primitive wrappers
- Converting objects to their Naftah string representations
This class is not instantiable.
- Author:
- Chakib Daii
-
Constructor Summary
ConstructorsModifierConstructorDescriptionprivatePrivate constructor to prevent instantiation. -
Method Summary
Modifier and TypeMethodDescriptionstatic ObjectapplyOperation(Object left, Object right, BinaryOperation operation) Applies a binary operation to two values.static ObjectapplyOperation(Object a, UnaryOperation operation) Applies a unary operation to a value.static intbooleanToInt(boolean aBoolean) Converts a boolean to an integer (1 fortrue, 0 forfalse).static StringbooleanToString(boolean b) Converts a boolean value to its Naftah string representation ("صحيح" or "خطأ").static intCompares twoComparableobjects in a null-safe manner.static <T> booleanequals(T left, T right, boolean safe) Safely compares two objects for equality using custom dynamic operations.static JavaTypegetJavaType(DefaultContext currentContext, NaftahParser.QualifiedNameTypeContext qualifiedNameTypeContext) Resolves aJavaTypefrom a qualified-name type context.static JavaTypegetJavaType(NaftahParser.BuiltInContext builtInContext) Resolves aJavaTypefrom a built-in Naftah type.static JavaTypegetJavaType(NaftahParserBaseVisitor<?> naftahParserBaseVisitor, DefaultContext currentContext, org.antlr.v4.runtime.ParserRuleContext naftahTypeContext) Resolves aJavaTypefrom a Naftah parser type context.static JavaTypegetJavaType(NaftahParserBaseVisitor<?> naftahParserBaseVisitor, NaftahParser.ComplexBuiltInContext complexBuiltInContext) Resolves aJavaTypefrom a complex built-in type context.static StringgetNaftahType(org.antlr.v4.runtime.Parser parser, JavaType javaType) Maps aJavaTypeto its corresponding Naftah language type using theVocabularyassociated with the given ANTLRParser.static StringgetNaftahType(org.antlr.v4.runtime.Vocabulary vocabulary, JavaType javaType) Maps aJavaTypeto its equivalent Naftah language type representation using the supplied ANTLRVocabulary.static StringConverts a Naftah value into its string representation, using language-specific formatting.static booleaninstanceOf(Object obj, JavaType targetType) Checks whether the given object is an instance of the specifiedJavaType.static booleanintToBoolean(int i) Converts an integer to a boolean (true if odd, false if even).static booleanisBuiltinType(Object obj) Checks if the object is a Naftah built-in type.static booleanDetermine whether the given object is empty.static booleanChecks whether the object or its components are simple, built-in, or collections/maps/tuple of such types.static booleanisSimpleType(Object obj) Checks if the object is a "simple" type (primitive wrapper, string, number, etc.).static booleanDetermines whether the given object is considered "truthy".static ObjectNegates the given value.static StringnumberToString(Number number) Converts the givenNumberinto a localized string representation using Arabic locale formatting rules.static StringPads the given string with leading zeros to ensure it reaches the specified length.static StringReplaces all "null" occurrences in the given string with the localizedNULLconstant.static NumberReturns the size or length of the given object, depending on its type.static voidvalidateType(String name, Object value, JavaType type, int line, int column) Validates that a runtime value conforms to the expectedJavaType.
-
Constructor Details
-
ObjectUtils
private ObjectUtils()Private constructor to prevent instantiation. Always throws aNaftahBugErrorwhen called.
-
-
Method Details
-
isTruthy
Determines whether the given object is considered "truthy".The following objects are considered falsy (return
false):nullBoolean.FALSE- Numeric zero or
NaNvalues - Blank strings (empty or only whitespace)
- Empty arrays
- Empty collections or maps
true.- Parameters:
obj- the object to evaluate for truthiness- Returns:
trueif the object is considered truthy;falseotherwise
-
compare
Compares twoComparableobjects in a null-safe manner.Rules for comparison:
- If both
leftandrightare the same object (including bothnull), returns 0. - A
nullvalue is considered less than any non-null value (nulls-first). - If both values are non-null, their natural ordering (via
Comparable.compareTo(T)) is used.
Examples:
compare(null, null) = 0 compare(null, "abc") = -1 compare("abc", null) = 1 compare("abc", "def") = "abc".compareTo("def")- Parameters:
left- the first object to compare, may benullright- the second object to compare, may benull- Returns:
- a negative integer, zero, or a positive integer if
leftis less than, equal to, or greater thanright, respectively
- If both
-
equals
public static <T> boolean equals(T left, T right, boolean safe) Safely compares two objects for equality using custom dynamic operations.This method attempts to evaluate
leftandrightusing the internalBinaryOperation.EQUALSoperation and checks that all results aretrue. If an internalNaftahBugErroroccurs, it falls back toleft.equals(right), unless the error matches a known empty-arguments condition andsafeistrue, in which case it returnstrue.- Type Parameters:
T- the type of the objects being compared- Parameters:
left- the first object to compareright- the second object to comparesafe- whether to treat certain internal evaluation errors as equality- Returns:
trueif the objects are considered equal;falseotherwise- Throws:
NaftahBugError- if a comparison fails andsafeisfalsefor certain internal errors
-
not
Negates the given value.Tries arithmetic negation using
NumberUtils.negate(Object). If that fails, it performs logical negation usingisTruthy(Object).- Parameters:
value- the value to negate- Returns:
- the negated value
-
isEmpty
Determine whether the given object is empty.This method supports the following object types.
Optional: considered empty if notOptional.isPresent()Array: considered empty if its length is zeroCharSequence: considered empty if its length is zeroCollection: delegates toCollection.isEmpty()Map: delegates toMap.isEmpty()
If the given object is non-null and not one of the aforementioned supported types, this method returns
false.- Parameters:
obj- the object to check- Returns:
trueif the object isnullor empty
-
getJavaType
public static JavaType getJavaType(NaftahParserBaseVisitor<?> naftahParserBaseVisitor, DefaultContext currentContext, org.antlr.v4.runtime.ParserRuleContext naftahTypeContext) Resolves aJavaTypefrom a Naftah parser type context.This method inspects the supplied
ParserRuleContextand maps Naftah language type constructs to their corresponding Java types. It supports return types, built-in types, complex built-ins, variable types, and qualified names, delegating to specialized resolvers where appropriate.Qualified names are resolved against the current
DefaultContext, including import matching. If a type cannot be resolved, the result defaults toObject.Resolution behavior
- Parameters:
naftahParserBaseVisitor- the active parser visitor, used to resolve complex built-in typescurrentContext- the current semantic context, used for import and type resolutionnaftahTypeContext- the parser rule context representing a Naftah type- Returns:
- the resolved
JavaType;JavaType.ofObject()if the type cannot be resolved
-
getJavaType
public static JavaType getJavaType(DefaultContext currentContext, NaftahParser.QualifiedNameTypeContext qualifiedNameTypeContext) Resolves aJavaTypefrom a qualified-name type context.The type name is extracted either from a fully-qualified name or a simple identifier and is then resolved against the current
DefaultContext, including import matching.If a matching import is found, the imported type is used. Otherwise, the resolved name is looked up directly. If resolution fails, the result defaults to
Object.- Parameters:
currentContext- the current semantic context used for import resolutionqualifiedNameTypeContext- the parser context representing a qualified-name type- Returns:
- the resolved
JavaType, orJavaType.ofObject()if unresolved
-
getJavaType
Resolves aJavaTypefrom a built-in Naftah type.Built-in types are mapped to their corresponding boxed Java types:
boolean,char,byte,short,int,long,float,double, andstring.If the built-in type is not recognized, this method returns
JavaType.ofObject().- Parameters:
builtInContext- the parser context representing a built-in type- Returns:
- the corresponding
JavaType
-
getJavaType
public static JavaType getJavaType(NaftahParserBaseVisitor<?> naftahParserBaseVisitor, NaftahParser.ComplexBuiltInContext complexBuiltInContext) Resolves aJavaTypefrom a complex built-in type context.Complex built-in types represent parameterized or structured constructs and are resolved recursively using the provided parser visitor.
Supported complex built-ins
struct→Map<String, DeclaredVariable>implementation→Map<String, DeclaredFunction>pair<T, U>→Pair<T, U>triple<T, U, V>→Triple<T, U, V>list<T>→List<T>set<T>→Set<T>map<K, V>→Map<K, V>tuple→Tuple
Generic type arguments are resolved by visiting nested
typecontexts via the supplied visitor.- Parameters:
naftahParserBaseVisitor- the active parser visitor used to resolve nested type parameterscomplexBuiltInContext- the parser context representing a complex built-in type- Returns:
- the resolved
JavaType, orJavaType.ofObject()if unresolved
-
getNaftahType
Maps aJavaTypeto its equivalent Naftah language type representation using the supplied ANTLRVocabulary.Primitive wrapper types and
Stringare mapped to their corresponding Naftah built-in type keywords (e.g.int,boolean,string).Parameterized and structured Java types are mapped as follows:
Map<String, DeclaredVariable>→structMap<String, DeclaredFunction>→implementationMap<K, V>→map<K, V>Pair<A, B>→pair<A, B>Triple<A, B, C>→triple<A, B, C>List<T>→list<T>Set<T>→set<T>Tuple→tuple
Generic type parameters are resolved recursively to produce fully-formed Naftah type expressions.
If
javaTypeisnullor cannot be mapped explicitly, the fallback typevaris returned.- Parameters:
vocabulary- the ANTLRVocabularyused to resolve token symbolsjavaType- the Java type to map- Returns:
- the formatted Naftah type representation
-
getNaftahType
Maps aJavaTypeto its corresponding Naftah language type using theVocabularyassociated with the given ANTLRParser.This is a convenience overload that delegates to
getNaftahType(Vocabulary, JavaType).- Parameters:
parser- the ANTLRParserproviding the vocabularyjavaType- the Java type to map- Returns:
- the formatted Naftah type representation
-
isBuiltinType
Checks if the object is a Naftah built-in type.- Parameters:
obj- the object to check- Returns:
trueif the object is a built-in type
-
instanceOf
Checks whether the given object is an instance of the specifiedJavaType.This method behaves similarly to the Java
instanceofoperator, but works withJavaTypeto support runtime inspection of generic type parameters.Unlike strict type equality checks, this method uses assignability semantics. This means that an object whose type is more specific may still be considered an instance of a more general target type.
Examples:
JavaType objectType = JavaType.of(Object.class); JavaType numberType = JavaType.of(Number.class); JavaType listOfObjects = JavaType.of(new TypeReference<List<Object>>() {}); instanceOf("hello", objectType); // true instanceOf(42, numberType); // true instanceOf(List.of("a"), listOfObjects); // trueIf either the object or the target type is
null, this method returnsfalse.- Parameters:
obj- the object to check; may be nulltargetType- theJavaTypeto check against; may be null- Returns:
trueif the object is an instance of the specified type according to assignability rules;falseotherwise
-
validateType
Validates that a runtime value conforms to the expectedJavaType.If the provided value is non-null and does not match the expected type, this method throws a Naftah type-mismatch error. Type matching is performed using
instanceOf(Object, JavaType), which supports raw types, generic parameters, and wildcard assignability.This method is typically used to validate function arguments, variable assignments, and return values at runtime.
Null values are considered valid for any type and will not trigger a validation error.
Example usage:
JavaType expectedType = JavaType.of(new TypeReference<List<String>>() {}); validateType("items", List.of("a", "b"), expectedType); // valid validateType("items", List.of(1, 2), expectedType); // throws type mismatch error- Parameters:
name- the name of the variable, parameter, or value being validated; used for error reportingvalue- the runtime value to validate; may benulltype- the expectedJavaTypeof the value- Throws:
NaftahBugError- if the value is non-null and does not conform to the expected type
-
isSimpleType
Checks if the object is a "simple" type (primitive wrapper, string, number, etc.).- Parameters:
obj- the object to check- Returns:
trueif the object is a simple type
-
isSimpleOrBuiltinOrCollectionOrMapOfSimpleType
Checks whether the object or its components are simple, built-in, or collections/maps/tuple of such types.- Parameters:
obj- the object to evaluate- Returns:
trueif the object is simple or composed only of simple/builtin types
-
applyOperation
Applies a binary operation to two values.- Parameters:
left- the left operandright- the right operandoperation- the binary operation to apply- Returns:
- the result of the operation
- Throws:
NaftahBugError- if operands are incompatible
-
applyOperation
Applies a unary operation to a value.- Parameters:
a- the operandoperation- the unary operation to apply- Returns:
- the result of the operation
- Throws:
NaftahBugError- if the operand type is unsupported
-
booleanToInt
public static int booleanToInt(boolean aBoolean) Converts a boolean to an integer (1 fortrue, 0 forfalse).- Parameters:
aBoolean- the boolean to convert- Returns:
- 1 if
true, 0 iffalse
-
intToBoolean
public static boolean intToBoolean(int i) Converts an integer to a boolean (true if odd, false if even).- Parameters:
i- the integer to convert- Returns:
trueif the integer is odd;falseotherwise
-
booleanToString
Converts a boolean value to its Naftah string representation ("صحيح" or "خطأ").- Parameters:
b- the boolean value- Returns:
- "صحيح" if
true, "خطأ" iffalse
-
getNaftahValueToString
Converts a Naftah value into its string representation, using language-specific formatting.- Parameters:
o- the value to convert- Returns:
- the string representation
-
replaceAllNulls
Replaces all "null" occurrences in the given string with the localizedNULLconstant.- Parameters:
s- the string to process- Returns:
- the string with "null" replaced
-
numberToString
Converts the givenNumberinto a localized string representation using Arabic locale formatting rules.When the system property
arabic.number.formatistrue, this method uses a preconfiguredNumberFormatinstance for the Arabic locale. This includes Arabic-style decimal and grouping separators and may render digits in Arabic-Indic form, depending on JVM and font support.The method synchronizes on
ScriptUtils.NUMBER_FORMATsinceNumberFormatis not thread-safe.If the system property is not set to
true, the method falls back to a custom digit conversion viaScriptUtils.numberToString(Number).- Parameters:
number- the number to format; must not benull- Returns:
- the number formatted as a string using Arabic locale or Arabic digits
- Throws:
NullPointerException- ifnumberisnull- See Also:
-
padZero
Pads the given string with leading zeros to ensure it reaches the specified length.If the input string is shorter than the desired length, zeros are added at the beginning. If the string is already equal to or longer than the specified length, it is returned unchanged.
Example:
padZero("5", 2) // returns "05" padZero("123", 5) // returns "00123" padZero("42", 1) // returns "42"- Parameters:
str- the input string to padlength- the desired minimum length of the resulting string- Returns:
- the input string left-padded with zeros to the specified length
-
size
Returns the size or length of the given object, depending on its type.This method provides a unified way to determine the "size" of various types of objects commonly encountered in Java, including arrays, collections, maps, strings, and arbitrary objects. The definition of size depends on the object's runtime type as follows:
- Arrays: Returns the array's length via
Array.getLength(Object). - Collections: Returns the number of elements using
Collection.size(). - Maps: Returns the number of key-value mappings using
Map.size(). - Strings: Returns the number of characters using
String.length(). - Boxed primitives: Returns 1 because primitives are considered as a single value counts.
- Other objects: Returns the count of non-static declared fields in the object's class.
If the provided object is
null, this method returns0.- Parameters:
obj- the object whose size is to be determined; may benull- Returns:
- the size or length of the given object, or
0ifnull
- Arrays: Returns the array's length via
-