is it possible to do something like
criteria.add(Expression.eq("product", " * "))
for it to match everything ?
It would be handy in case that you get a variable that can have many values and a special value "all" that matches against everything. So you can call a method like this and if the variable had a value of "all", then the expression would match everything.
public void someFunction(String variable) {
criteria.add(Expression.eq("product", variable))
}
EDITED: If I had 2 select fields with Source Language & Destination Language and a table listing entries based on which language combination it contains, with IF STATEMENTS it would look like this: (DynamicQuery is an abstraction for Criteria)
private DynamicQuery addCriteria(DynamicQuery dq, String languageFrom, String languageTo){
if (null != languageFrom && !languageFrom.isEmpty() && null != languageTo && !languageTo.isEmpty()){
if(languageFrom.equals("All") && languageTo.equals("All")) {
return dq;
} else if (!languageFrom.equals("All") && !languageTo.equals("All")) {
dq.add(PropertyFactoryUtil.forName("languageFrom").eq(languageFrom));
dq.add(PropertyFactoryUtil.forName("languageTo").eq(languageTo));
return dq;
} else if (languageFrom.equals("All") && !languageTo.equals("All")) {
dq.add(PropertyFactoryUtil.forName("languageTo").eq(languageTo));
return dq;
} else if (!languageFrom.equals("All") && languageTo.equals("All")) {
dq.add(PropertyFactoryUtil.forName("languageFrom").eq(languageFrom));
return dq;
}
}
}
It's disgusting, consider there would be one more field, it would be even more disgusting...One simply must cover all the combinations that might occur ... That's why I would like to have something like REGEX, because I would assign variable the reqex "*" value and I would add two lines like this
dq.add(PropertyFactoryUtil.forName("languageFrom").eq(languageFromVariable));
dq.add(PropertyFactoryUtil.forName("languageTo").eq(languageToVariable));
if (null != variable && !variable.isEmpty()){
criteria.add(Expression.eq("product", variable)) ;
}
If you only need it when it is selected. You may wanna add an if statement so criteria is added only when needed.
Edit 1:
You can define a method if you are gonna use it for more than fields. Even you can define different criterias inside here. Easy maintance (as is used by all and centrilized), code reuse (change at one point at it will be effective to all)
addCriteria(Criteria criteria, String name, String value){
//you wanna handle special cases like null == name as well accordingly
if (null != value && !value.isEmpty() && null != name && !name.isEmpty()){
criteria.add(Expression.eq(name, value)) ;
}
}
Related
I am trying to convert a module of a java program into Scala. So far, I have been able to apply Scala's functional programming paradigm and its syntax in every module I converted. But I have come across a method that does some validations, use continue and finally yield the output.
Below is the code in Java:
public boolean checkColumn(String server, String database, String schema, String table, String column) {
boolean bServer, bDatabase, bSchema, bTable, bColumn, bRet = false;
for (int i = 0; i < columns.length; i++) {
if ((server == null) || (server.length() == 0)) {
bServer = true;
} else {
bServer = columns[i][0].equalsIgnoreCase(server);
}
if (!bServer) continue;
if ((database == null) || (database.length() == 0)) {
bDatabase = true;
} else {
bDatabase = columns[i][1].equalsIgnoreCase(database);
}
if (!bDatabase) continue;
if ((schema == null) || (schema.length() == 0)) {
bSchema = true;
} else {
bSchema = columns[i][2].equalsIgnoreCase(schema);
}
if (!bSchema) continue;
bTable = columns[i][3].equalsIgnoreCase(table);
if (!bTable) continue;
bColumn = columns[i][4].equalsIgnoreCase(column);
if (!bColumn) continue;
bRet = true;
break;
}
return bRet;
}
While I understand there is no continue in recent versions of Scala I am able to understand how to write the same code in Scala. I tried to construct a for loop as below:
val finalReturn = for {i <- 0 until columns.length
} yield bRet
But couldn't think of a way to form the logic of all the if-conditions & continue inside the for-loop. Could anyone let me know how can I write the same code in Scala ?
You are checking that (at least) one of the columns matches all the tests. This is the exists operation:
def checkColumn(server: String, database: String, schema: String, table: String, column: String) = {
columns.exists { col =>
(server.isEmpty || col(0).equalsIgnoreCase(server)) &&
(database.isEmpty || col(1).equalsIgnoreCase(database)) &&
(schema.isEmpty || col(2).equalsIgnoreCase(schema)) &&
col(3).equalsIgnoreCase(table) &&
col(4).equalsIgnoreCase(column)
}
This will check each element in turn until one of the columns passes all the tests (which will return true) or the list is exhausted, which will return false.
There is no way to write exactly the same algorithm with a functional approach because in java code this is a very imperative style with mutability and manual control over the flow of evaluation.
So you should think what this code does, what is the logic in the code. And then implement this logic with functional primitives and patterns.
Let's go step by step
if ((server == null) || (server.length() == 0)) {
bServer = true;
} else {
bServer = columns[i][0].equalsIgnoreCase(server);
}
if (!bServer) continue;
it checks that if there is the defined server string - you should check that 1st field of the column
should be equal to that defined server string (i don't know what columns exactly are, but I try to guess that columns[i] is column and column[j] is a field of the column).
Otherway it calls continue and skips the iteration.
Same for other fields with the exception that table and schema doesn't being checked for emptiness.
If we looked at the end, the skipping results in "not setting bRet to true". So if all checks passed for some column, bRet would be true and the loop breaks after that.
So we can say that "if there exists at least one column that passes the checks - the result of that method should be true". Good for you that in scala you have a special method of the collection exists with exactly that logic.
Also, it is better to have a dedicated helper function to deal with nullability and emptiness.
private def isEmpty(string: String) = string == null || string.isEmpty
def checkColumn(server: String, database: String, schema: String, table: String, column: String): Boolean = {
columns.exists { column =>
(isEmpty(server) || column(0).equalsIgnoreCase(server)) &&
(isEmpty(database) || column(1).equalsIgnoreCase(database)) &&
(isEmpty(schema) || column(2).equalsIgnoreCase(schema)) &&
column(3).equalsIgnoreCase(table) &&
column(4).equalsIgnoreCase(column)
}
}
In addition, I have to mention that in Scala dealing with nulls in business code is very bad practice, you should change nullable parameters to Option[String] and change a little bit expressions to deal with that type. I will show 3 ways of doing that:
def checkColumn(serverOpt: Option[String], databaseOpt: Option[String], schemaOpt: Option[String], String table, String column): Boolean =
columns.exists { column =>
serverOpt.filterNot(_.isEmpty).map(server => column(0).equalsIgnoreCase(server).getOrElse(true) &&
databaseOpt.filterNot(_.isEmpty).map(column(1).equalsIgnoreCase).getOrElse(true) &&
schemaOpt.filterNot(_.isEmpty).fold(true)(column(2).equalsIgnoreCase)&&
column(3).equalsIgnoreCase(table) &&
column(4).equalsIgnoreCase(column)
}
And when you call it, you should wrap your nullable strings with Option constructor like this:
checkColumn(Option(nullableServer), Option(nullableDatabase), Option(nullableshema), table, column)
Further improvements would be to use refinement types techniques and change the type of nullable and maybe empty strings from just Option[String] to Option[NonEmptyString].
I want to annotated 2 different methods and related them together in order to match the global variable and method which uses it
#FirstAnn(funcName = "foo")
def foo = {
val value = boo()
val checkValue = value > 2
return checkValue
}
#SecondAnn(funcName = "foo", paramName = "value")
def boo : Double = {
return B.getValue
}
#Pointcut("execution(* *(..)) && #annotation(firstAnn) && if()")
public static boolean execute(FirstAnn firstAnn){
return true;
}
#Pointcut("execution(* *(..)) && #annotation(secAnn) && if()")
public static boolean execute2(SecondAnn secAnn){
return true;
}
#Before("execute(firstAnn) && execute2(secAnn)")
public void before(FirstAnn firstAnn, SecondAnn secAnn, JoinPoint.StaticPart jps,JoinPoint jp){
if (firstAnn.funcName == secAnn.funcName){
print("value X is used in funcname Y" ) //here I will retrieve the value from signature like: value 3 is used in function foo
}
}
But the code doesn't get to this place...Any suggestion to make it work please?
thanks
Your usage of && implies you expect both methods to be executed at the same time. But of course they are not. Either the first or the second one is matched, they are two different joinpoints, thus combining the pointcuts with && will never make your advice method fire. You need to use || instead to match either one.
Looking at your source code, what you probably want is to trigger the advice when boo is called from within foo and possibly also the other way around. You are also trying to bleed context from the calling method into the called method. This is called a wormhole pattern, see also my answers here:
https://stackoverflow.com/a/12130175/1082681
https://stackoverflow.com/a/50577287/1082681
https://stackoverflow.com/a/25075051/1082681
So probably you want to use a pointcut like
execute2(secAnn) && cflow(execute(firstAnn))
for your example or the other way around if you have cases where the second method calls the first one:
cflow(execute2(secAnn)) && execute(firstAnn)
There is an Integer property called foo in a model. Now I need to know whether it equals 1 or 2. Usually I use:
if (null != model) {
Integer foo = model.getFoo();
if (foo != null) {
if (foo == 1) {
// do something...
}
if (foo == 2) {
// do something...
}
}
}
Is there any handier code to avoid the NullPointerException?
You can use Optional:
Optional.ofNullable(model)
.map(Model::getFoo)
.ifPresent(foo -> {
switch (foo) { // or if-else-if, the important thing is you skip the null check
case 1:
...
break;
case 2:
...
break;
...
}
});
You can use the null-safe java.util.Object.equals:
if(null != model) {
Integer foo = model.getFoo();
if(Objects.equals(foo, 1){
//do something
}
if(Objects.equals(foo, 2){
//do something
}
}
The method has this description:
Returns true if the arguments are equal to each other and false otherwise. Consequently, if both arguments are null, true is returned and if exactly one argument is null, false is returned. Otherwise, equality is determined by using the equals method of the first argument.
If you didn't return null sentinels values, and instead used Optionals, you could do:
Optional<Model> model = getModel();
Optional<Integer> foo = model.flatMap(Model::getFoo);
foo.filter(Integer.valueOf(1)::equals).ifPresent(this::doSomething);
foo.filter(Integer.valueOf(2)::equals).ifPresent(this::doSomethingElse);
You could do Integer.of(1).equals(foo), but this is a bit silly. Why save the one line? I'd just put it inside the same if/else-if chain (and if that gets long, conside a switch/case (which also is not null-safe, though).
if (foo == null)
else if (foo == 1)
else if (foo == 2)
Also note that comparing objects with == is a bit tricky because of how auto-boxing works (or does not work). I think that it works in this case, but I do not want to have to think about it too hard, so in my code I usually drop down to int (after the null check) to be on the safe side.
Assuming possible value is only 1 or 2
Of course the model the should be guarded with null check
Use ternary operator
Model theModel = model.getFoo() ;
if(model!=null && model.getFoo()!=null){
model.getFoo() == 1 ? callOne() : call2();
}
Edit the code to like this:
if (null != model) {
Integer foo = model.getFoo();
if (Integer.valueOf(1).equals(foo)) {
// do something...
}
if (Integer.valueOf(2).equals(foo)) {
// do something...
}
}
I hope to help you.
I need to know the "best" and safest way to get a value held within a Set if there is only one entry. methodToGetValues() is used extensively to read config files and return a list of values given a specific key, in this case "enabled". For the enabled key, there should only be one entry returned in the Set, obviously "true" or "false" but, mistakes happen. I have the following which seems a little convoluted:
Set<String> enabled = methodToGetValues("enabled");
if (!enabled.isEmpty() && enabled.size() < 2 && "true".equals(enabled.iterator().next())) {
...
}
Can anyone suggest a simpler yet still robust way of checking this?
Your question asks to get something from the Set. But your example just needs a check.
If you know what to expect in the Set, this works fine.
if (enabled != null && enabled.size() == 1 && enabled.contains("true")) {
...
}
Otherwise, if you just want to get the element but don't know what it is, the iterator you suggested works fine.
String getOnlyElement(Set<String> enabled, String default) {
return (enabled == null || enabled.size() != 1) ? default : enabled.iterator().next();
}
I like having null checks but it depends on what methodToGetValues returns.
Unsure of what the use case is that would drive using a Set<String> for this data but here is an option:
// check size = 1 over two checks, use contains rather than grabbing an iterator
if (set.size() == 1 && set.contains("true")) {
...
}
public Set<String> getValues(final String key){
.....
}
public String getValue(final String key) {
final Set<String> values = getValues(key);
if (values == null || values.size() != 1) {
throw new IllegalStateException("Invalid configuration for give key :" + key);
}
return values.iterator().next();
}
public Boolean getValueAsBoolean(final String key) {
return Boolean.valueOf(getValue(key));
}
You can modify method to have accept argument to return default value when keys are not found. You can add different methods to return specific type object like inte, boolean, this way code looks cleaner
How to implement a filter which in case of null returns all the data?
For example if name is null it should be excluded from the filter.
The only way in my head is to make 100k lines of code and test all of the combinations. It is very stupid. I dont want it like this. I am sure there is better way.
Collection<Ojects> filter(String name, Integer age, Integer number) ;
NOTE: your line of code is not correct:
To call the filter method:
Collection<Ojects> ojects = filter(String name, Integer age, Integer number);
Also there are a lot of details missing in your question, but to use as a guide: check if all the conditions to filter are null and return all elements else do the filter:
public Collection<Ojects> filter(String name, Integer age, Integer number) {
// return all object if no filter
if (name == null && age == null && number == null) {
Collection<Ojects> allOjects = // get all objects from where you wish
return allOjects;
}
// do the filters
Collection<Ojects> filteredOjects = new ....
// filter by name
if (name != null && name.lenght > 0) {
// do the filter and put the matching ones in filtered objects
}
// filter by age
if (age != null && age < 0) {
// do the filter and put the matching ones in filtered objects
}
// filter by number
if (name != null // conditions you need) {
// do the filter and put the matching ones in filtered objects
}
return filteredObjects
}
If you don't filter when parameters are not given you will return all objects...