"${fn:escapeXml(parameter)!=null}" is always true - jstl

I am checking a parameter!=null by using ${fn:escapeXml},
but it always returns true for me.
e.g <c:set var="isABC" value="${fn:escapeXml(param.isABC)!=null}"/>
When the exscape function is removed, it will return false if the parameter is null.
e.g <c:set var="isABC" value="${param.isABC!=null}"/>
I would like to know the reason, thanks a lot.

The reason is simple: escapeXml() returns an empty string when called with null. And an empty string is not null.
public static String escapeXml(String input) {
if (input == null) return "";
return Util.escapeXml(input);
}

Related

SPeL - set a value of an object which should be in an empty list

I have the following SPel expression:
custData.address[0].postcode
The custData is an existing object but the address is an empty list. It is an existing object but it is empty. When I try to set a the post code on this path then I got the
org.springframework.expression.spel.SpelEvaluationException: EL1007E: Property or field 'postcode' cannot be found on null
What I'd need that a new address object will be put to the list and set its postcode attribute.
Is it something that can be done in the SPel expression?
Thanks,
V.
So this basically is a NullPointerException. You need to make sure the object from which you are trying to get a field value exists. SPeL has the special operator '?' to check if the object has value, though I'm not sure if it works for an array, but definitely worth a try. In general expression where some object might be null looks like this:
object?.anotherObject?.field
This makes sure that "object" is not null and if it has value gets "anotherObject" and check if it's not null either, and then gets "field". So try something like this:
custData.address[0]?.postcode
Eventually I ended up using a custom function in spel expression.
#addIfNecessary(custData.address, 0, "uk.co.acme.AddressType").postcode
The user defined function is
import org.springframework.util.ReflectionUtils;
import java.util.List;
public class CustomFunc {
public static Object addIfNecessary(List<Object> list, Integer index, String className) throws IllegalAccessException, InstantiationException, ClassNotFoundException {
Object o = null;
if (list != null) {
if (list.size() <= index || list.get(index) == null) {
list.set(index, Class.forName(className).newInstance());
}
o = list.get(index);
}
return o;
}
}
It is neither nice nor elegant but it works.
Please let me know if you have a more elegant one!

How to search exact record by asp.net web api with help of lamda expresion

I am facing a problem in searching a exact record by LINQ query method in ASP.NET Web API my controller. This is my code:
[HttpGet]
[Route("api/tblProducts/AllProductbySearch/{SearchText}")]
[ResponseType(typeof(IEnumerable<tblProduct>))]
public IHttpActionResult AllProductbySearch(string SearchText)
{
IEnumerable<tblProduct> tblProduct = db.tblProducts.Where(x=>x.PrdKeyword.Contains(SearchText)).AsEnumerable();
if (tblProduct == null)
{
return NotFound();
}
return Ok(tblProduct);
}
In this I am searching the record with value have keyword column and getting the result but problem is that it is not giving exact result for example if in database two record have keyword column value like shirt and another have Tshirt
Then if I pass shirt in SearchText or pass tshirt in SearchText it is giving both record while I want one record which exact match with SearchText. Please help me
My updated action method code is:
[HttpGet]
[Route("api/tblProducts/AllProductbySearch/{SearchText}")]
[ResponseType(typeof(IEnumerable<tblProduct>))]
public IHttpActionResult AllProductbySearch(string SearchText)
{
IEnumerable<tblProduct> tblProduct = db.tblProducts.Where(x => CheckWord(x.PrdKeyword, SearchText)).AsEnumerable();
if (tblProduct == null)
{
return NotFound();
}
return Ok(tblProduct);
}
private bool CheckWord(string source, string searchWord)
{
var punctuation = source.Where(Char.IsPunctuation).Distinct().ToArray();
var words = source.Split().Select(x => x.Trim(punctuation));
return words.Contains(searchWord, StringComparer.OrdinalIgnoreCase);
}
But is throwing the same error - http 500
EDITED 2
Added ToList() - db.tblProducts.ToList().... In this case we retrieve all data from Data Base and filter them in memory. If we don't retrieve all data before filtering .Net tries to create request to SQL with filtration and can't because there are .Net methods as CheckWord().
I think we can get required data without retrieving all table into memory, but don't know how. As variant we should write specific Stored Procedure and use it. Get all into memory is a simplest way (but not faster)
Please, look at this post Get only Whole Words from a .Contains() statement
Actually, for your case solution can be:
IEnumerable<tblProduct> tblProduct = db.tblProducts.ToList()
.Where(x => Regex.Match(x.PrdKeyword, $#"\b{SearchText}\b", RegexOptions.IgnoreCase).Success)
.AsEnumerable();
Option 2. Without regexp:
public static bool CheckWord(string source, string searchWord)
{
if (source == null)
return false;
var punctuation = source.Where(Char.IsPunctuation).Distinct().ToArray();
var words = source.Split().Select(x => x.Trim(punctuation));
return words.Contains(searchWord, StringComparer.OrdinalIgnoreCase);
}
[HttpGet]
[Route("api/tblProducts/AllProductbySearch/{SearchText}")]
[ResponseType(typeof(IEnumerable<tblProduct>))]
public IHttpActionResult AllProductbySearch(string SearchText)
{
IEnumerable<tblProduct> tblProduct = db.tblProducts.ToList()
.Where(x => CheckWord(x.PrdKeyword, SearchText)).AsEnumerable();
if (tblProduct == null)
{
return NotFound();
}
return Ok(tblProduct);
}
Sorry, I'm from phone now, there can be mistakes here. Will try it in 3-4 hour
You are making a simple mistake. You just need to use .Equals instead of .Contains.
When you use Contains .Net will check if the input string is part of the main string. Whereas Equals will check for exact match.
var mainStr = “long string with Hello World”;
var inputStr = “Hello”;
var status = mainStr.Contains(inputStr);
// Value of status is `true`
status = mainStr.Equals(inputStr);
// Value of status is `false`
So your code should look like this:
IEnumerable<tblProduct> tblProduct = db.tblProducts.Where(x=>x.PrdKeyword.Equals(SearchText)).AsEnumerable();
.Equals can also help you find exact match with or without having case-sensitive check in force. The single-parameterised method does a Case-Sensitive check whereas the other overridden methods of .Equals gives you an opportunity to ignore it.
Hope this helps!

java 8 method reference to: either `equals` or `equalsIgnoreCase`

I tried to convert the body of a method boolean exists(String value, boolean isCaseSensitive) :
for(String str : existingNames){
if(isCaseSensitive ? str.equals(name) : str.equalsIgnoreCase(name)){
return true;
}
}
return false;
to a solution that utilises java8 method references:
Predicate<String> equalityPred = isCaseSensitive ?
name::equals :
name::equalsIgnoreCase;
return existingNames.stream().anyMatch(equalityPred);
Then I saw that this way the equality is performed in the opposite direction (e.g. value.equals(str) ).
Is there a way to fix this and still use method references, and if no what would be the java8 way.
There is no “opposite direction” for equality. The only issue might be the behavior for null values. Your loop might fail, if the collection contains null, your method references will fail, if name is null.
You may achieve the original behavior using lambda expressions:
boolean check(Collection<String> existingNames, String name, boolean isCaseSensitive) {
Predicate<String> equalityPred = isCaseSensitive?
s -> s.equals(name):
s -> s.equalsIgnoreCase(name);
return existingNames.stream().anyMatch(equalityPred);
}
but it makes little sense to consider null for the name parameter, when it will never be equal, as the code will fail with a NullPointerException, if the collection contains null.
To get a sensible behavior for null, you may use
boolean check(Collection<String> existingNames, String name, boolean isCaseSensitive) {
Predicate<String> equalityPred = name==null? Objects::isNull:
isCaseSensitive? name::equals: name::equalsIgnoreCase;
return existingNames.stream().anyMatch(equalityPred);
}
or just
boolean check(Collection<String> existingNames, String name, boolean isCaseSensitive) {
return name==null || isCaseSensitive?
existingNames.contains(name):
existingNames.stream().anyMatch(name::equalsIgnoreCase);
}
If you know that the Collection will never contain null, but want to support null for the name parameter, you could also use
boolean check(Collection<String> existingNames, String name, boolean isCaseSensitive) {
return name!=null && existingNames.stream()
.anyMatch(isCaseSensitive? name::equals: name::equalsIgnoreCase);
}
Well don't use a method reference then and write your lambda directly:
static boolean existsJDK8(List<String> existingNames, String value, boolean isCaseSensitive) {
Predicate<String> equalityPred = isCaseSensitive ? s -> value.equals(s) : s -> value.equalsIgnoreCase(s);
Predicate<String> equalityPredReversed = isCaseSensitive ? s -> s.equals(value) : s -> s.equalsIgnoreCase(value);
// return existingNames.stream().anyMatch(equalityPredReversed);
return existingNames.stream().anyMatch(equalityPred);
}

LINQ Statement dictionary first key's value

I have a dictionary
private Dictionary<string, string> ScannerMessages;
and then I have a call for this
public bool equalMessages()
{
lock (lockObj)
{
return (ScannerMessages.Values.ToList().Distinct().Count() < ScannerMessages.Values.ToList().Count) ? true : false;
}
}
And it returns if the messages are equal. I also need to add to the end of that clause a second check to verify that the values are not null or empty. I was trying to do something like this but I am not sure where to go with the LINQ statement (not the greatest at LINQ)...
public bool equalMessages()
{
lock (lockObj)
{
return ((ScannerMessages.Values.ToList().Distinct().Count() < ScannerMessages.Values.ToList().Count) && (ScannerMessages.Keys.First() *get the value here and check it !null or string.empty) ? true : false;
}
}
To verify all the values are not null or empty:
ScannerMessages.Values.All(s => !string.IsNullOrEmpty(s))
It will return true if all values are not null and not empty.
If you want to get the non-null values you can do this:
ScannerMessages.Values.Where(v=>!string.IsNullOrEmpty(v)).ToList()
or just to get the count
ScannerMessages.Values.Where(v=>!string.IsNullOrEmpty(v)).Count()
or
ScannerMessages[ScannerMessages.Keys.First()].Where(v=>!string.IsNullOrEmpty(v)).Count()

ASP.NET MVC3 using Redirect To Action

I want to use the Redirect to Action result on this code which gives a null but i have several if statements and the code is becoming more complex to build need a solution on how i could use the Redirect to Action which outputs null, help please?
public ActionResult Convert(double temperature, string convertTo)
{
ViewBag.Temperature = temperature;
ViewBag.ConvertTo = convertTo;
if (convertTo.Equals("Celsius"))
{ ViewBag.ConvertedTemperature = this.FahrenheitToCelsius(temperature); }
else
{ ViewBag.ConvertedTemperature = this.CelsiusToFahrenheit(temperature); }
return View("Convert");
}
The error message would really help. But it seems like you'd need to make your temperature parameter nullable, like so:
public ActionResult Convert(double? temperature, string convertTo)
Then you could check for null and return RedirectToAction:
if (temperature == null)
return RedirectToAction("ActionName", "ControllerName");
You'll also need to do the following to get the temperature value in your conversion methods:
temperature.Value
Hope this helps.

Resources