Rhino: Java numbers don't behave like Javascript numbers - java

I have an instance of this Java class accessible in my Javascript program
public class ContentProvider {
public Object c(int n) {
switch (n) {
case 1: return 1.1;
case 2: return 2.2;
case 3: return 3.3;
case 4: return "4";
case 5: return new java.util.Date();
}
return null;
}
}
This is the code inside main():
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName("JavaScript");
engine.put("ctx", new ContentProvider());
res = engine.eval("ctx.c(1)");
System.out.printf("rhino:> %s (%s)%n"
, res
, res != null ? res.getClass().getName() : null
);
The simple expression ctx.c(1) prints:
rhino:> 1.1 (java.lang.Double)
Now here is what happens with ctx.c(1) + ctx.c(2):
rhino:> 1.12.2 (java.lang.String)
And finally (ctx.c(1) + ctx.c(2)) * ctx.c(3):
rhino:> nan (java.lang.Double)
Rhino is performing string concatenation instead of number arithmetics! The following program works as expected instead:
engine.put("a", 1.1);
engine.put("b", 2.2);
engine.put("c", 3.3);
res = engine.eval("(a + b) * c");
Outputs:
rhino:> 10,89 (java.lang.Double)

This is a strange feature of Rhino: a Java Number set with engine.put("one", new Double(1)) works as expected, while the result of a Java method depends on the return type declared by the method itself, which is read with the reflection API:
if it's a primitive, like double, it's converted to a Javascript number
otherwise it's handled like other host objects and the + means concatenation, either Object like in your sample as well as Double
You can configure this behavior with wrapFactory.setJavaPrimitiveWrap(false) on the WrapFactory in the current Context. This way the Rhino code can be kept in the bootstrap lines of your program and doesn't clutter ContentProvider (which I guess is some sort of configuration proxy)
From the live Javadoc of WrapFactory.isJavaPrimitiveWrap()
By default the method returns true to indicate that instances of
String, Number, Boolean and Character should be wrapped as any other
Java object and scripts can access any Java method available in these
objects
So you can set this flag to false to indicate that Java Number's should be converted to Javascript numbers. It takes just two lines of code
Context ctx = Context.enter();
ctx.getWrapFactory().setJavaPrimitiveWrap(false);
Here is the Gist with the full code I used to test

I created a value wrapper:
public static class JSValue extends sun.org.mozilla.javascript.internal.ScriptableObject
{
Object value;
public JSValue(Object value) {
this.value = value;
}
public String getClassName() {
return value != null? value.getClass().getName(): null;
}
#Override
public Object getDefaultValue(Class typeHint) {
if (typeHint == null || Number.class.isAssignableFrom(typeHint)) {
if (value instanceof Number)
return ((Number) value).doubleValue();
}
return toString();
}
#Override
public String toString() {
return value != null? value.toString(): null;
}
}
and an edit function:
public static class ContentProvider {
public Object c(int n) {
... return new JSValue(1.1);
Now the expression works as expected. Thanks all.

Related

Performance penalty when using Java varargs method with no arguments

Suggest the following Java class:
/** Utility class for working with DOM nodes.
*/
public class DomNodes {
public static boolean isElement(Node pNode, String pElementName, String... pAttributes) {
if (pNode.getNodeType() == Node.ELEMENT_NODE) {
final Element e = (Element) pNode;
final String uri = e.getNamespaceURI();
if (uri == null || uri.length() == 0) {
if (pElementName.equals(e.getLocalPart())) {
if (pAttributes == null || areAttributesMatching(pNode, pAttributes)) {
return true;
}
}
}
}
}
}
Now, suggest the following two uses of that class:
isElement(node, "foo");
isElement(node, "foo", "attribute0", value0, "attribute1", value1, "attribute2", value2);
It is obvious to me, that the second invocation depends on the construction of a string array. In other words, there is a small performance penalty for the construction of that array.
The first invocation, however, isn't obvious: The compiler could implement this by passing a newly constructed array with no elements. However, it might just as well pass the value null, or a constant array.
In the former case, I could help the compiler by adding a method
isElement(Node pNode, String pElementName). Question: Would you recommend that?

If condition is true even then else is executing

I have an enum defined as below, which contains a static function fromString(String s) which is like valueOf(String s) but case insensitive.
enum Platform {
TWITTER("TWITTER"), INSTAGRAM("INSTAGRAM"), UNKNOWN;
private String value;
Platform(String value) {
this.value = value;
}
private static final Map<String, Platform> stringToEnumMap = new HashMap<>();
static {
for (Platform platform : values()) {
stringToEnumMap.put(platform.toString().toLowerCase(), platform);
}
}
public static Platform fromString(String symbol) {
Platform platform = stringToEnumMap.get(symbol.toLowerCase());
if (platform != null) {
return platform;
} else {
return UNKNOWN;
}
}
public String getValue() {
return value;
}
#Override
public String toString() {
return getValue();
}
}
but when I execute the following code
Platform platform = Platform.fromString("twitter");
I get Platform.UNKNOWN returned on few devices on production.
Any Idea?
Update
symbol.toString() gives twitter
stringToEnumMap.toString() gives this
Platform StringToEnumMap: {
twıtter=TWITTER, ınstagram=INSTAGRAM,
unknown=UNKNOWN}
If you look closely, the letter i is different in the keys of HashMap and thats why string comparison fails.
the hexvalue of letter ı in stringToEnumMap is 0131, whereas the it should be 0069
Why is this happening on only few devices? How to avoid it?
It seems to be a dirty ide issue, try to clean up your project, build and run again.
UPDATE
Try replacing your if statement by getOrDefault method:
public static Letter fromString(String symbol) {
return stringToEnumMap.getOrDefault(symbol.toLowerCase(), UNKNOWN);
}
In my Opinion, there is no need for a map.... nor a new method for doing something that valueOf() is able to do...
look this implemetation..
enum ECase {
A, B, UNK;
public static ECase resolveEnumFromString(final String string) {
ECase r = null;
try {
r = ECase.valueOf(string.toUpperCase());
} catch (final IllegalArgumentException e) {
r = ECase.UNK;
}
return r;
}
}
you can verify the results doing:
ECase d = null;
d = ECase.resolveEnumFromString("a");
System.out.println(d);
d = ECase.resolveEnumFromString("A");
System.out.println(d);
d = ECase.resolveEnumFromString("0");
System.out.println(d);
I am able to find what the issue was. After some careful logging I found the issue was this http://mattryall.net/blog/2009/02/the-infamous-turkish-locale-bug.
Apparently toLowerCase() and toUpperCase() functions are locale dependent due to which you can't use them safely for case insensitive string comparison.
So all you need to do is pass the english locale in the parameter of these functions like this -
toLowerCase(Locale.ENGLISH).

Retrieving value of a method with Predicate return type in java

I am working on a pre-existing java program, one of its classes calculates some Boolean features. Some private methods do this. Their return type is Predicate. For example :
private Predicate<ChunkedBinaryExtraction> startArg1() {
return new Predicate<ChunkedBinaryExtraction>() {
public boolean apply(ChunkedBinaryExtraction e) {
return e.getArgument1().getRange().getStart() == 0;
}
};
}
I want to retrieve this feature value, I used this simple statements:
Predicate<ChunkedBinaryExtraction> ftr1=startArg1();
System.out.print("Feature1 is: "+ftr1);
The result should return a Boolean value :true or false, but it shows:
Feature1 is: edu.washington.cs.knowitall.extractor.conf.ReVerbFeatures$3#1eb44e46
I'm new to Java programming, please help:( Thanks.
You are returning an object. So the print will call toString() on the predicate object. I guess you want the result of the apply method, so you need to do sth. like this
ChunkedBinaryExtraction someObject = ...
Predicate<ChunkedBinaryExtraction> ftr1 = startArg1();
System.out.print("Feature1 is: " + ftr1.apply(someObject));
Where the ChunkedBinaryExtraction object comes from, you have to know.

Does java have some convention to indicate that object is in empty state?

Of course, empty definition can differ. I'm used to PHP's empty though, which calls empty everything that evaluates to false. I'd like to call these things empty in my Java application:
null
String of zero length
0 Integer, Float or Double
false
Any array of zero length
Empty ArrayList or HashMap
Java has, for example, toString convention. Every object is granted to give you some string representation. In my Settings class I operate with HashMap<String, Object>. My empty method looks now like this:
public boolean empty(String name) {
Object val = settings.get(name);
if(val!=null) {
return false;
}
return true;
}
I'd like to extend it in a conventional manner, rather than if(val instanceof XXX) chain.
No, there is no standard convention for this in Java. Also, in Java there is no such thing as "evaluate to false" (except for booleans and Booleans, of course).
You will have to write a method (or rather, a series of overloaded methods for each type you need it for) which implements your notion of "empty". For example:
public static boolean isEmpty(String s) {
return (s == null) || (s.isEmpty());
}
public static boolean isEmpty(int i) {
return i == 0;
}
...
You could use overloading to describe all the "empty" objects:
public static boolean empty(Object o) {
return o == null;
}
public static boolean empty(Object[] array) {
return array == null || array.length == 0;
}
public static boolean empty(int[] array) { //do the same for other primitives
return array == null || array.length == 0;
}
public static boolean empty(String s) {
return s == null || s.isEmpty();
}
public static boolean empty(Number n) {
return n == null || n.doubleValue() == 0;
}
public static boolean empty(Collection<?> c) {
return c == null || c.isEmpty();
}
public static boolean empty(Map<?, ?> m) {
return m == null || m.isEmpty();
}
Examples:
public static void main(String[] args) {
Object o = null;
System.out.println(empty(o));
System.out.println(empty(""));
System.out.println(empty("as"));
System.out.println(empty(new int[0]));
System.out.println(empty(new int[] { 1, 2}));
System.out.println(empty(Collections.emptyList()));
System.out.println(empty(Arrays.asList("s")));
System.out.println(empty(0));
System.out.println(empty(1));
}
AFAIK there is no such convention. It's fairly common to see project specific utility classes with methods such as:
public static boolean isEmpty(String s) {
return s == null || s.isEmpty();
}
However I personally think its use is a bit of a code smell in Java. There's a lot of badly written Java around, but well written Java shouldn't need null checks everywhere, and you should know enough about the type of an object to apply type-specific definitions of "empty".
The exception would be if you were doing reflection-oriented code that worked with Object variables who's type you don't know at compile time. That code should be so isolated that it's not appropriate to have a util method to support it.
Python's duck-typing means the rules are sort of different.
How about creating an interface EmptinessComparable or something similar, and having all your classes implement that? So you can just expect that, and not have to ask instanceof every time.
Java does not, but Groovy does. Groovy runs on the Java VM alongside Java code and provides many shortcuts and convenient conventions such as this. A good approach is write foundation and crital project components in Java and use Groovy for less critical higher level components.
If you want to use the one approach, I would overload a utility method:
public class MyUtils {
public static boolean isEmpty(String s) {
return s == null || s.isEmpty();
}
public static boolean isEmpty(Boolean b) {
return b == null || !b;
}
// add other versions of the method for other types
}
Then your code always looks like:
if (MyUtils.isEmpty(something))
If the type you're checking isn't supported, you'll get a compiler error, and you can implement another version as you like.
There are ways to establish the notion of emptiness but it's not standardized across all Java classes. For example, the Map (implementation) provides the Map#containsKey() method to check if a key exists or not. The List and String (implementations) provide the isEmpty() method but the List or String reference itself could be null and hence you cannot avoid a null check there.
You could however come up with a utility class of your own that takes an Object and using instanceof adapts the empty checks accordingly.
public final class DataUtils {
public static boolean isEmpty(Object data) {
if (data == null) {
return false;
}
if (data instanceof String) {
return ((String) data).isEmpty();
}
if (data instanceof Collection) {
return ((Collection) data).isEmpty();
}
}
}
The Guava Libraries already contains Defaults class that do just that.
Calling defaultValue will return the default value for any primitive type (as specified by the JLS), and null for any other type.
You can use it like shown below:
import com.google.common.base.Defaults;
Defaults.defaultValue(Integer.TYPE); //will return 0
Below is example code on how to use it:
import com.google.common.base.Defaults;
public class CheckingFieldsDefault
{
public static class MyClass {
private int x;
private int y = 2;
}
public static void main() {
MyClass my = new MyClass();
System.out.println("x is defualt: " + (my.x == Defaults.defaultValue(box(my.x).TYPE)));
System.out.println("y is defualt: " + (my.y == Defaults.defaultValue(box(my.y).TYPE)));
}
private static <T extends Object> T box(T t) {
return t;
}
}

In Java, it is possible to take a line of code as a method argument?

I can't seem to find anything on google for this and I'm not sure it's possible. What I want to do, is pass a line of Java code as an argument to a method. Google only turns up results for passing cmd line arguments to methods, but I want to pass an actual line of code.
Basically I want to pass methodA to methodB except methodA isn't a method, but a line of code. Below is a full example of passing a method to a method using reflection.
public class Relation<T> {
protected Set<Pair<T,T>> pairs = null;
public Relation() {
this.pairs = new LinkedHashSet<Pair<T,T>>();
}
/* Next 2 methods are methods for sending methods to methods useing java.lang.reflect.Method */
public Method getMethod(String name) {
try { return Relation.class.getDeclaredMethod(name);
} catch (Exception e) {}
return null;
}
public boolean execute(Method method, Object... params) {
try { return (Boolean) method.invoke(this, params);
} catch (Exception e) {}
return false;
}
/* The method I reuse several times so I just put methods inside of it */
public boolean pairsTFIterator(Method method) {
for(Pair<T,T> x : pairs) {
boolean bool = false;
for(Pair<T,T> y : pairs) {
if(execute(method, x,y))
bool = true; break;
}
if(!bool) return false;
}
return true;
}
/* To be replaced by the line of code*/
public static <T> boolean isSymmetricPairs(Pair<T,T> a, Pair<T,T> b) {
return a.getFirst().equals(b.getSecond()) && a.getSecond().equals(b.getFirst()) ? true :false;
}
/* Method that calls others */
public boolean isSymmetric() {
return pairsTFIterator(getMethod("isSymmetricPairs"));
}
}
The above works fine and all, but I want to take it a step further and just forego methods like the "isSymmetricPairs" method by just putting that methods logic line directly in the "pairsTFIterator", like so:
public boolean isReflexive() {
return baseSetTFIterator(
a.getFirst().equals(b.getSecond()) && a.getSecond().equals(b.getFirst()) ? true :false
);
}
I'm pretty sure this is impossible, but if there is someway to do it, that would be great.
It sounds like what you are looking for are "first-class functions". Some languages treat functions just like a variable, in the sense that you can assign them to variables and pass them as arguments to other functions. Java 8 will be introducing the concept of lambda expressions which will support this type of functionality.
Also there are other JVM languages that provide this already, including Scala and Groovy to name two of the more popular ones.
Just to give you a flavor of what it looks like, in Groovy you can execute arbitrary functions on each element of a collection by calling the each() method and passing it a closure (a function essentially).
def list = [1, 2, 3, 4]
def printer = { x -> println x } // defines a closure that takes one arg and prints it
list.each(printer) // prints out the elements
def sum = 0
def summer = { x -> sum += x } // defines a closure that takes one arg and adds it to the sum variable
list.each(summer)
println sum // should be 1 + 2 + 3 + 4
Put you code in an anonymos inner class may satisfy your requirement:
interface PairFilter<T>{
boolean filter(Pair<T, T> a, Pair<T,T> b);
}
And in you iterator method:
public boolean pairsTFIterator(PairFilter filter) {
for(Pair<T,T> x : pairs) {
boolean bool = false;
for(Pair<T,T> y : pairs) {
if(filter.filter(x,y))
bool = true; break;
}
if(!bool) return false;
}
return true;
}
then call it:
pairsTFIterator(new PairFilter<T>(){
public boolean filter(Pair<T, T> a, Pair<T,T> b){
return a.getFirst().equals(b.getSecond()) && a.getSecond().equals(b.getFirst()) ? true :false;
}
});

Categories

Resources