java.lang.Boolean is perfect to handle trinary logic, because it can exactly have three states: Boolean.TRUE (it is the case that), Boolean.FALSE (it is not the case that) and null (we don't know what the case is). It would be a nice design to handle this using switch statements, eg. in this constructor:
public class URN {
private String value = null;
public URN (String value, Boolean mode){
switch (mode){
case TRUE:
if(!isValidURN(value))
throw new MalformedURLException("The string could not be parsed.");
this.value = value;
break;
case FALSE:
this.value = value.concat(checkByteFor(value));
break;
case null:
if(isValidURN(value))
this.value = value;
else
this.value = value.concat(checkByteFor(value));
break;
}
return;
}
Unluckily, Java doesn't allow that, complaining "Cannot switch on a value of type Boolean." Implementing this results in an obfuscated control flow and unnice code:
public URN (String value, Boolean mode){
Boolean valid = null;
if (!Boolean.FALSE.equals(mode)){
valid = isValidURN(value);
if (Boolean.TRUE.equals(mode) && !valid)
throw new MalformedURLException("The string could not be parsed.");
if(Boolean.TRUE.equals(valid)) {
this.value = value;
return;
} }
this.value = value.concat(checkByteFor(value));
}
Doing it the nice way requires to implement an enum class (which, in real life, is more complex than in this example, because .equals() must be rewritten so that Trinary.NULL.equals(null) becomes true) and converting:
private enum Trinary {TRUE, FALSE, NULL};
public URN (String value, Boolean toConvert, String x){
Trinary mode;
if(toConvert == null)
mode = Trinary.NULL;
else
mode = toConvert.equals(Boolean.TRUE) ? Trinary.TRUE : Trinary.FALSE;
switch (mode){
case TRUE:
if(!isValidURN(value)) throw new MalformedURLException("The string could not be parsed.");
this.value = value;
break;
case FALSE:
this.value = value.concat(checkByteFor(value));
break;
case NULL:
if(isValidURN(value))
this.value = value;
else
this.value = value.concat(checkByteFor(value));
break;
}
return;
}
To my eyes, this is the better since more readable solution, but the another half of the origin method size of code just to convert is annoying, and in real life you have to care about two different nulls with the same semantic. Is there a better way to do it?
Using a null object to convey information like this is not optimal. Remember that you cannot do any method calls on a null object, which again would mean that if you in the future ever would want to call any .getClass, .equals, .compare etc., you would have to rewrite your code.
Your best option is definitely to go with the enum option.
enum Ternary {TRUE,FALSE,UNKNOWN}
You can furthermore expand the class to have a method of getting such object,
public Ternary getByValue(Boolean o) {
if(o == null)
return UNKNOWN;
if(o)
return TRUE;
return FALSE;
}
I agree that its annoying that switch does support null or treat it as default if not mentioned.
Note: Trinary can be NULL or null which might be confusing.
Instead of using true, false and null. I would suggest using meaningful names for the modes. e.g. use VALIDATING, CONCATENATING, MIXED or whatever is more appropriate.
The simplest solution is
public URN (String value, Boolean mode){
if (mode == null) {
this.value = isValidURN(value) ? values : value.concat(checkByteFor(value));
} else if (mode) {
if(!isValidURN(value))
throw new MalformedURLException("The string could not be parsed.");
this.value = value;
} else {
this.value = value.concat(checkByteFor(value));
}
return;
}
BTW Comparing with TRUE can be confusing.
Boolean b = new Boolean(true);
if (b == Boolean.TRUE) // is false !!!
Related
I have a utility function which convert parseDouble value to string.
public static BigDecimal setValue(Object o) {
BigDecimal value = new BigDecimal(0);
if(o!= Null){
value=BigDecimal.valueOf(Double.parseDouble(o.toString()));
}
return value;
}
I have tried with (o!=null && !isEmpty(o)) and (o!="" && o!=null) but it is still throwing same error.
Transaction amount which is processing this utility function contains empty value.
Firstly I don't understand why you are taking object type as an input, however to resolve your issue you can do something like this. But I would strongly advice you to change the method signature it is misleading.
public static BigDecimal setValue(Object o) {
var value = new BigDecimal(0);
if (o != null) {
if(o instanceof String) {
if (((String) o).trim().length()>0) {
value = new BigDecimal((String) o);
}
}
}
return value;
}
I would change the method signature to BigDecimal setValue(String s). Your null check and length check code should then work fine.
Also the method name is misleading. The method does not set anything. Something like convertToBigDecimal would be clearer.
Hi I am working with the Stack class in java, the problem that I have is that in this Stack I want to insert (to push) elements of type String, but i also want to insert a tree, the code is the following:
public static void Expression(Stack<String> exp)
{
boolean error = false;
String leftExp,rightExp = "";
Stack<String> stackOp = new Stack<String>();
while(!exp.empty() && (error == false))
{
switch(elementType(exp.peek())){
case 'I':
error = true;
break;
case 'O':
if(stackOp.size() < 2)
error = true;
else
{
rightExp = stackOp.pop();
leftExp = stackOp.pop();
Tree subTree = new Tree();
subTree.insertNode(exp.peek());
subTree.insertNode(rightExp);
subTree.insertNode(leftExp);
stackOp.push(subTree);//here is were I have the mistake
}
break;
default:
stackOp.push(exp.peek());
}
}
}
public static char elementType(String car){
char c = 'Z';
if(car.equals("("))
c = 'I';
else if(car.equals(")"))
c = 'D';
else if(car.equals("+") || car.equals("-") || car.equals("*") || car.equals("/"))
c = 'O';
return c;
}
This code basically transforms a math expression into a binary tree, for this I need an input, which is the expression, an output which is the binary tree, and another local stack that contains variables, numbers, and subtrees. But how can i make a Stack that contains elements of different types?
Create a class that can hold anything you want to put on the stack -- I think using a string to designate your operation is a bit clumsy, but suit yourself. If you have a class that is StackElement, it can contain a type indicator (look into Java enums) and methods to do or obtain whatever you want.
You could define StackElement to contain a reference to one of several types, then also define all the methods of all the types it might contain; the ones that apply would be pass-throughs (if the type is an operation, a pass-through for getOperationType()), and the others would throw illegalOperationException, or something. So if you try to call getOperationType() on a value, it throws an exception, same for calling getValue() on an operation, etc.
A nice thing about doing it this way is that you do not have to do any instanceof testing of the types you have stored. You can declare your FILO queue to hold StackElement objects, create them with the types you want, and use them, all without instanceof or otherwise breaking OO style.
public class StackElement
{
private StackElementType type;
private StackOperation operation;
private StackValue value;
public StackElementType getType() { return type; }
public StackOperation getOperation()
{
switch (type)
{
case StackElementType.OPERATION: return operation;
default: throw IllegalOperationException
("getOperation() on type " + type.toString());
}
}
public StackValue getValue()
{
switch (type)
{
case StackElementType.VALUE: return value;
default: throw IllegalOperationException
("getValue on type " + type.toString());
}
}
}
Spring Expression Language (SpEL) in Spring Security to compare object use equals() or ==?
For example(method equals () is not called!):
class SecurityObject {
public boolean equals(Object obj) {
//...
}
}
#PreAuthorize(" #secObject == #otherSecObject ")
public void securityMethod(SecurityObject secObject, SecurityObject otherSecObject) {
//...
}
This is normal!? I need to use #PreAuthorize(" #secObject.equals(#otherSecObject) ") everywhere?
UPDATE
Why in first case Spring Security calling .equals(), and the second not?
//TestObject
public class TestObject {
private static final Logger log = LoggerFactory.getLogger(TestObject.class);
private Long id;
public TestObject(Long id) {
this.id = id;
}
#Override
public int hashCode() {
int hash = 7;
hash = 71 * hash + Objects.hashCode(this.id);
return hash;
}
#Override
public boolean equals(Object obj) {
log.info("equals");
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final TestObject other = (TestObject) obj;
if (!Objects.equals(this.id, other.id)) {
return false;
}
return true;
}
}
//TestService
#PreAuthorize(" #one == #two ")
public String testEqualsInAnnotation(Long one, Long two) {
//...
}
#Override
#PreAuthorize(" #one == #two ")
public String testEqualsInAnnotation(TestObject one, TestObject two) {
//...
}
//Test
log.info("for Long");
Long one = new Long(500);
Long two = new Long(500);
log.info("one == two: {}", (one==two)? true : false); // print false
log.info("one equals two: {}", (one.equals(two))? true : false); // print true
testService.testEqualsInAnnotation(one, two); //OK
log.info("for TestObject");
TestObject oneObj = new TestObject(new Long(500));
TestObject twoObj = new TestObject(new Long(500));
log.info("oneObj == twoObj: {}", (oneObj==twoObj)? true : false); // print false
log.info("oneObj equals twoObj: {}", (oneObj.equals(twoObj))? true : false); // print true
testService.testEqualsInAnnotation(oneObj, twoObj); // AccessDeniedException: Access is denied
UPDATE 2
equals() never invoked at all
package org.springframework.expression.spel.ast;
import org.springframework.expression.EvaluationException;
import org.springframework.expression.spel.ExpressionState;
import org.springframework.expression.spel.support.BooleanTypedValue;
/**
* Implements equality operator.
*
* #author Andy Clement
* #since 3.0
*/
public class OpEQ extends Operator {
public OpEQ(int pos, SpelNodeImpl... operands) {
super("==", pos, operands);
}
#Override
public BooleanTypedValue getValueInternal(ExpressionState state) throws EvaluationException {
Object left = getLeftOperand().getValueInternal(state).getValue();
Object right = getRightOperand().getValueInternal(state).getValue();
if (left instanceof Number && right instanceof Number) {
Number op1 = (Number) left;
Number op2 = (Number) right;
if (op1 instanceof Double || op2 instanceof Double) {
return BooleanTypedValue.forValue(op1.doubleValue() == op2.doubleValue());
} else if (op1 instanceof Long || op2 instanceof Long) {
return BooleanTypedValue.forValue(op1.longValue() == op2.longValue());
} else {
return BooleanTypedValue.forValue(op1.intValue() == op2.intValue());
}
}
if (left!=null && (left instanceof Comparable)) {
return BooleanTypedValue.forValue(state.getTypeComparator().compare(left, right) == 0);
} else {
return BooleanTypedValue.forValue(left==right);
}
}
}
As per spEL documentation, You need to create ExpressionParser instance, create an Expression instance and get the value like below
String name = "Nikola Tesla";
Expression exp = parser.parseExpression("name == 'Nikola Tesla'");
boolean result = exp.getValue(Boolean.class);
result evaluates to 'true'. That says when we need to compare any two objects, then we need to override the equals() method and pass the two objects in to parser#parseExpression("obj1 == obj2") and then call the exp#getValue(Boolean.class) to evaluate. In the similar way, the Expression instance can also have expression string containing Obj1.equals(Obj2) for checking the equality. so, both the ways of checking equality are possible with spEL.
You may have discovered this already, since it is in the OpEq code in 'Update 2' of the original post, but...
The comparison operators lt < gt > le <= ge >= eq == ne != are based on java's Comparable interface.
So, if you've got a custom type that you want to be able to compare using == or != in SpEL expressions, then you could write it to implement Comparable.
Of course, then you'll have to figure out some sane rule to decide which object is before the other when they're not equivalent.
That said, I can't find anything in Spring's current documentation indicating this.
rdm, I think you have to use permission evaluator to evaluate the expressions. I don't think you have really injected/passed values for the objects in the following expression.
#Override
#PreAuthorize(" #one == #two ")
public String testEqualsInAnnotation(TestObject one, TestObject two) {
//...
I tried to do the same thing, but I failed to pass values, hence couldn't able to evaluate the expressions. My suggestion is to implement your custom permission evaluator for the above expression, and inject/pass values from the evaluator. To generalize my idea, my suspect is the objects are null, that is why you couldn't able to evaluate it. Please let us know if you can really pass values of the objects inside here : #PreAuthorize(" #one == #two ")
Added:
I am using permission evaluator to evaluate expressions under #PreAuthorize(...) annotation. Because I couldn't able to pass values to the parameters as I explained above. If it is possible to pass/inject values, it will be good to reduce complexity that can come from using permission evaluator.
rdm or others, can you point me how to pass the values for the parameters under #PreAuthorize(...) if possible?
Sorry for asking another question on rdm's post, and thank you in advance for your help!.
I tried different ways to fix this, but I am not able to fix it. I am trying to get the Boolean value of an Object passed inside this method of a checkBox:
public boolean onPreferenceChange(Preference preference, Object newValue)
{
final String key = preference.getKey();
referenceKey=key;
Boolean changedValue=!(((Boolean)newValue).booleanValue()); //ClassCastException occurs here
}
I get:
java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Boolean
Instead of casting it, you can do something like
Boolean.parseBoolean(string);
Here's some of the source code for the Boolean class in java.
// Boolean Constructor for String types.
public Boolean(String s) {
this(toBoolean(s));
}
// parser.
public static boolean parseBoolean(String s) {
return toBoolean(s);
}
// ...
// Here's the source for toBoolean.
// ...
private static boolean toBoolean(String name) {
return ((name != null) && name.equalsIgnoreCase("true"));
}
So as you can see, you need to pass a string with the value of "true" in order for the boolean value to be true. Otherwise it's false.
assert new Boolean( "ok" ) == false;
assert new Boolean( "True" ) == true;
assert new Boolean( "false" ) == false;
assert Boolean.parseBoolean( "ok" ) == false;
assert Boolean.parseBoolean( "True" ) == true;
assert Boolean.parseBoolean( "false" ) == false;
From the code you posted, and the result you are seeing, it doesn't look like newValue is a boolean. So you try to cast to a Boolean, but it's not one, so the error occurs.
It's not clear what you're trying to do. Ideally you'd make newValue a boolean. If you can't do that, this should work:
boolean newValue;
if (newValue instanceof Boolean) {
changedValue = newValue; // autoboxing handles this for you
} else if (newValue instanceof String) {
changedValue = Boolean.parseBoolean(newValue);
} else {
// handle other object types here, in a similar fashion to above
}
Note that this solution isn't really ideal, and is somewhat fragile. In some instances that is OK, but it is probably better to re-evaluate the inputs to your method to make them a little cleaner. If you can't, then the code above will work. It's really something only you can decide in the context of your solution.
If you know that your Preference is a CheckBoxPreference, then you can call isChecked(). It returns a boolean, not a Boolean, but that's probably close enough.
Here is some code from the APIDemos Device Administration sample (DeviceAdminSample.java).
private CheckBoxPreference mDisableCameraCheckbox;
public void onResume() {
...
mDPM.setCameraDisabled(mDeviceAdminSample, mDisableCameraCheckbox.isChecked());
...
}
public boolean onPreferenceChange(Preference preference, Object newValue) {
...
boolean value = (Boolean) newValue;
...
else if (preference == mDisableCameraCheckbox) {
mDPM.setCameraDisabled(mDeviceAdminSample, value);
reloadSummaries();
}
return true;
}
Situation: I am coming across a lot of checks in my code. And I would like to know of a way in which I can reduce them.
if(needle!=null && haystack!=null)
{
if(needle.length()==0)
return true;
else
{
if(haystack.length()==0)
return false;
else
{
// Do 2 for loops to check character by character comparison in a substring
}
}
}
else
return false;
Perhaps a different code style would increase the readability of your code and reduce the amount of nested if statements for all of your checks.:
if (needle == null || haystack == null || haystack.isEmpty())
return false;
if (needle.isEmpty())
return true;
// compare strings here and return result.
You could consolidate that logic into a single method on a singleton 'StringFunctions' class and update the usages to use the common method as you encounter them.
You can create a wrapper class for the strings, then add a function like isValid() to them that checks if the length == 0. Use a Null Object that always returns false on isValid() to eliminate the null checks.
If you can create classes that you tell what to do, rather than passing strings that have to be null checked throughout your code, you will get more resuseable results:
class Haystack {
private static final Haystack NULL_HAYSTACK = new Haystack("");
private final String value;
public Haystack(String value) {
this.value = value;
}
public boolean containsNeedle(String needle) {
return needle != null && value.contains(needle);
}
}