beanshell beginner- how do I check if a variable.toString contains no value in it? - beanshell

In a beanshell program, I get a value in a variable. Now, if there was no value obtained for this variable, then I want to set this as "Missing"
In a very old version of Beanshell I used the command as shown below to do this--
contact.toString() != ''
However I updated the Beanshell library and now I am getting an error message that says that I cannot put a second apostrophe after the first one (i.e. '' is erroneous).
How do I check correctly for the above condition in Beanshell?

An apostrophe is used in the Java language to indicate a char. You cannot have a '' char value. However the earlier version of beanshell may have been doing some implicit conversion to an empty string that somehow is broken after upgrade.
Checking for a valid value using the toString() seems a bit wasteful to me, but if 'contact' be non-null, yet still not have a value in the toString() representation the you check the String value as follows:
if(contact != null) {
contactStr = contact.toString();
if(contactStr != null #and contactStr.length() > 0) {
/// value is something other than null or ""
}
}
and the toString() is the only way

If you want to check whether contact is defined then you do:
if (contact == void)
http://www.beanshell.org/manual/specialvarsvalues.html

Related

Kotlin "let{}" Doesn't Provide Smart Cast

Just learned Kotlin Nullable type and let{} function which replaces the if (xx != null) {} operation.
But one thing I am confused is that, we all know and I Think the Complier Should Know that when we use let{}, the variable/object who is calling this function is possiblly null, however the complier still requires me to add the safe call operator "?" after the variable name instead of providing Smart Cast like it does in if (xx != null) {}. Why?
My piece of code:
fun main() {
var number1: Int? = null
//val number2 = number1.let { it + 1 } ?: 10 //doesn't work, not quite "smart"
val number2 = number1?.let { it + 1 } ?: 10 //works, must have "?"
println(number1)
println(number2)
}
You've already got answers in the comments, but just to explain the ? thing...
Kotlin lets you make null-safe calls on nullable variables and properties, by adding ? before the call. You can chain this too, by doing
nullableObject?.someProperty?.someFunction()
which evaluates nullableObject, and if it's non-null it evaluates the next bit, otherwise the whole expression evaluates to null. If any part of the chain evaluates as null, the whole expression returns null.
So it has this short-circuiting effect, and you can use the elvis "if null" operator to create a default value if you can't evaluate the whole chain to a non-null result:
nullableObject?.nullableProperty?.someFunction() ?: defaultAction()
and once you introduce the null check in the chain, you have to add it for every call after that - it's basically propagating either the result of the previous bit, or the null it resolved to, so there's a null check at each step
The let block is just a scope function - you use it on a value, so you can run some code either using that value as a parameter or a receiver (a variable or this basically). It also has the side effect of creating a new temporary local variable holding that value, so if the original is a var it doesn't matter if that value changes, because your let code isn't referring to that variable anymore.
So it's useful for doing null checks one time, without worrying the underlying value could become null while you're doing stuff with it:
nullableVar?.let { it.definitelyIsNotNull() }
and the compiler will recognise that and smart cast it to a non-null type. An if (nullableVar != null) check can't guarantee that nullableVar won't be null by the time the next line is executed.

Instantiated class in Kotlin still possibly null. Why?

Question is simple:
In Kotlin, when I instantiate a fragments arguments with a Bundle(), the system still needs the arguments object to be reassured with !!. The arguments should be definitely not null by now, right? So why is that needed?
Here is the code:
private fun openPinCodeFragment(mode: PinView.Mode) {
currentFragment = PinCodeFragment()
currentFragment?.run {
arguments = Bundle()
arguments!!.putSerializable(MODE, mode)
}
openFragment(currentFragment)
}
If I remove the !! then:
You're setting the value of a variable which was defined outside of this scope (the declaration of arguments is not visible in your code).
No matter what you assign, it could have been changed by the time code execution reaches the next line to a null value by another Thread, that's why you have to use the !! here. I'd suggest defining arguments either in local scope with val or making it non-nullable in its definition.
This happens because arguments is of Bundle? type, this means that it can be either Bundle or null.
Instead of using an if to check whether it is null, like you would to in Java, the operators !! and ? were introduced.
For example if you want your code to be correct without using !! you could add:
if (arguments != null) {
arguments.putSerializable(MODE, mode)
}
Using these operators you have the following flexibility:
!! - you tell the compiler that the value cannot be null, it will throw error otherwise;
? - you don't care that much, if it is not null then it will access method and might return result, otherwise the result of such call is null and no action is made.

OOP static variable changing value

I recently came upon this code in a comic, which I did not understand. Can someone please explain this to me? Is there any reason why the variable should change it's value?
static bool isCrazyMurderingRobot = false;
void interact_with_humans(void) {
if (isCrazyMurderingRobot = true)
kill(humans);
else
be_nice_to(humans)
}
Here is the comic: http://oppressive-silence.com/comics/oh-no-the-robots
The reason might be that in many programming languages,
checking for equality is done by using ==, while using a single = sign would assign the value to the variable).
So the code
if (isCrazyMurderingRobot = true)
would assign trueto the variable and the first condition will always be satisfied (as the result of the assignment would be true).
The correct line would be:
// use '==' here instead of '=' to check if variable is set
// using a single '=' would assign the value instead
if (isCrazyMurderingRobot == true)
For more details, please check these descriptions (they are for the C# language, but the operators behave similar in other languages like Java etc...)
assignment (=) operator.
equality (==) operator.

Why does Javassist insist on looking for a default annotation value when one is explicitly specified?

I am using Javassist to add and modify annotations on a package-info "class".
In some cases, I need to deal with the following edge case. Someone has (incorrectly) specified an #XmlJavaTypeAdapters annotation on the package-info package, but has not supplied a value attribute (which is defined as being required). So it looks like this:
#XmlJavaTypeAdapters // XXX incorrect; value() is required, but javac has no problem
package com.foobar;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters;
In Javassist, this comes through slightly oddly.
The javassist.bytecode.annotation.Annotation representing the #XmlJavaTypeAdapters annotation does not have a member value (getMemberValue("value") returns null), as expected.
It is of course possible to add a value() member value, and that is what I've done:
if (adaptersAnnotation.getMemberValue("value") == null) {
final ArrayMemberValue amv = new ArrayMemberValue(new AnnotationMemberValue(constantPool), constantPool);
adaptersAnnotation.addMemberValue("value", amv);
annotationsAttribute.addAnnotation(adaptersAnnotation);
}
In the code snippet above, I've created a new member value to hold an array of annotations, because the value() attribute of #XmlJavaTypeAdapters is an array of #XmlJavaTypeAdapter. I've specified its array type by trying to divine the Zen-like documentation's intent—it seems that if you supply another MemberValue that this MemberValue will somehow serve as the array's type. In my case I want the type of the array to be #XmlJavaTypeAdapter, which is an annotation, so the only kind of MemberValue that seemed appropriate was AnnotationMemberValue. So I've created an empty one of those and set it as the array type.
This works fine as far as it goes, as long as you stay "within" Javassist.
However, something seems to have gone wrong. If I ask Javassist to convert all of its proprietary annotations into genuine Java java.lang.annotation.Annotations, then when I try to access the value() attribute of this #XmlJavaTypeAdapters annotation, Javassist tells me that there is no default value. Huh?
In other words, that's fine—indeed there is not—but I have specified what I had hoped was a zero-length array (that is, the default value shouldn't be used; my explicitly specified zero-length array should be used instead):
final List<Object> annotations = java.util.Arrays.asList(packageInfoClass.getAnnotations());
for (final Object a : annotations) {
System.out.println("*** class annotation: " + a); // OK; one of these is #XmlJavaTypeAdapters
System.out.println(" ...of type: " + a.getClass()); // OK; resolves to XmlJavaTypeAdapters
System.out.println(" ...assignable to java.lang.annotation.Annotation? " + java.lang.annotation.Annotation.class.isInstance(a)); // OK; returns true
if (a instanceof XmlJavaTypeAdapters) {
final XmlJavaTypeAdapters x = (XmlJavaTypeAdapters)a;
System.out.println(" ...value: " + java.util.Arrays.asList(x.value())); // XXX x.value() throws an exception
}
}
So why is Javassist looking for a default value in this case?
My larger issue is of course to handle this (unfortunately somewhat common) case where #XmlJavaTypeAdapters is specified with no further information on it. I need to add a value member value that can hold an array of #XmlJavaTypeAdapter annotations. I can't seem to figure out how to accomplish this with Javassist. As always, all help appreciated.
For posterity, it appears that in this particular case (to avoid a NullPointerException and/or a RuntimeException), you need to do this:
if (adaptersAnnotation.getMemberValue("value") == null) {
final ArrayMemberValue amv = new ArrayMemberValue(constantPool);
amv.setValue(new AnnotationMemberValue[0]);
adaptersAnnotation.addMemberValue("value", amv);
annotationsAttribute.addAnnotation(adaptersAnnotation);
}
Note in particular that I deliberately omit the array type when building the ArrayMemberValue (including one of any kind will result in an exception). Then I explicitly set its value to an empty array of type AnnotationMemberValue. Any other combination here will result in an exception.
Additionally, and very oddly, the last line in that if block is critical. Even though in this particular case the annotation itself was found, and so hence was already present in the AnnotationsAttribute, you must re-add it. If you do not, you will get a RuntimeException complaining about the lack of a default value.
I hope this helps other Javassist hackers.

Code contracts - Assume vs Requires

What's the diference between these two statements ?
Contract.Requires(string.IsNullOrWhiteSpace(userName));
Contract.Assume(string.IsNullOrWhiteSpace(userName));
Imagine you have a method like this:
bool ContainsAnX(string s)
{
return s.Contains("X");
}
Now, this method will always fail if you pass null to it, so you want to ensure this never happens. This is what Contract.Requires is for. It sets a precondition for the method, which must be true in order for the method to run correctly. In this case we would have:
bool ContainsAnX(string s)
{
Contract.Requires(s != null);
return s.Contains("X");
}
(Note: Requires and Ensures must always be at the start of a method, as they are information about the method as a whole. Assume is used in the code itself, as it is information about that point in the code.)
Now, in your code that calls the method "ContainsAnX", you must ensure that the string is not null. Your method might look like this:
void DoSomething()
{
var example = "hello world";
if (ContainsAnX(example))
Console.WriteLine("The string contains an 'X'.");
else
Console.WriteLine("The string does not contain an 'X'.");
}
This will work fine, and the static checker can prove that example is not null.
However, you might be calling into external libraries, which don't have any information about the values they return (i.e. they don't use Code Contracts). Let's change the example:
void DoSomething()
{
var example = OtherLibrary.FetchString();
if (ContainsAnX(example))
Console.WriteLine("The string contains an 'X'.");
else
Console.WriteLine("The string does not contain an 'X'.");
}
If the OtherLibrary doesn't use Code Contracts, the static checker will complain that example might be null.
Maybe their documentation for the library says that the method will never return null (or should never!). In this case, we know more than the static checker does, so we can tell it to Assume that the variable will never be null:
void DoSomething()
{
var example = OtherLibrary.FetchString();
Contract.Assume(example != null);
if (ContainsAnX(example))
Console.WriteLine("The string contains an 'X'.");
else
Console.WriteLine("The string does not contain an 'X'.");
}
Now this will be okay with the static checker. If you have runtime contracts enabled, the Assume will also be checked at run time.
Another case where you might need Assume is when your preconditions are very complex and the static checker is having a hard time proving them. In this case you can give it a bit of a nudge to help it along :)
In terms of runtime behavior there won't be much difference between using Assume and Requires. However, results with the static checker will differ greatly. The meaning of each is different as well, in terms of who is responsible for the error in case of failure:
Requires means that the code which calls this method must ensure the condition holds.
Assume means that this method is making an assumption which should always hold true.
It only differs design-time/static-analysis-time
Contract.Assume:
"Instructs code analysis tools to assume that the specified condition is true, even if it cannot be statically proven to always be true"
And:
At run time, using this method is equivalent to using the Assert(Boolean) method.
Contract.Requires will guarantee that the given predicate is true and static code analyzers might raise an error if they can't 'prove' that is not the case. On Contract.Assume the static analyzer will continue/issue a warning/whatever the tool will decide.
According to official documentation: pages 7 (preconditions) and 11 (assumes).
Requires:
Is a precondition ("preconditions are extressed by using Contract.Requires");
As a precondition will be executed on method invoke;
Assumes:
Not a precondition, not a postcondition, not an invariant;
Is executed at the point where it is specified;
p. 11 "Exist in a build only when the full-contract symbol or DEBUG symbol is defined";