The expression of type List needs unchecked conversion to conform to List< CategoryTypes > - liferay-6

I have this code :
DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(OpenBoard.class);
DynamicQuery categoryQuery = DynamicQueryFactoryUtil.forClass(CategoryTypes.class);
User user=UserLocalServiceUtil.getUser(PortalUtil.getUserId(request));
List<CategoryTypes> category_list= null;
categoryQuery.add(RestrictionsFactoryUtil.eq("categoryTarget",String.valueOf("O")));
category_list=CategoryTypesLocalServiceUtil.dynamicQuery(categoryQuery);
the last line generates the warning
"The expression of type List needs unchecked conversion to conform to
List< CategoryTypes >"
How can I fix my code to remove this warning?

First add this method into your class:
public static <T> List<T> castList(Class<? extends T> clazz, Collection<?> c) {
List<T> r = new ArrayList<T>(c.size());
for(Object o: c)
r.add(clazz.cast(o));
return r;
}
Than try this:
DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(OpenBoard.class);
DynamicQuery categoryQuery = DynamicQueryFactoryUtil.forClass(CategoryTypes.class);
User user=UserLocalServiceUtil.getUser(PortalUtil.getUserId(request));
categoryQuery.add(RestrictionsFactoryUtil.eq("categoryTarget",String.valueOf("O")));
List<CategoryTypes> category_list = castList(CategoryTypes.class, CategoryTypesLocalServiceUtil.dynamicQuery(categoryQuery));
bibliography: https://stackoverflow.com/a/2848268/6676203

Related

C++ template member variable declaration error

I'm new to C++ and learning what Class is and related concept on it.
I faced some Error while practicing making code that contains class.
template <typename T>
class Node{
public:
T data;
Node<T> *link;
Node<T>(T element){
data = element;
link = 0;
}
};
template <typename T>
class LinkedList{
protected:
Node<T> *first;
int current_size;
public:
LinkedList(){
first = NULL;
current_size = 0;
};
T GetSize(){
return current_size;
};
void Insert(T element);
virtual bool Delete(T &element);
void Print();
};
template <typename T>
void LinkedList<T>::Insert(T element){
Node *newnode = new Node(element);
newnode -> link = first;
first = newnode;
current_size++;
}
template <typename T>
bool LinkedList<T>::Delete(T &element){
if (first == 0)
return false;
Node *current = first;
Node *previous = 0;
while(1){
if (current->link == 0){
if (previous)
previous -> link = current -> link;
else
first = first -> link;
break; // Point in which Error Occured
}
previous = current;
current = current -> link;
}
element = current -> data;
delete current;
current_size--;
return true;
}
In "delete" Function, "'current': undeclared identifier Error Occured.
I think I declared and defined it at the first of the function (Node* current = this->first).
I don't know why error happened.
Thanks for your help.
Just replace all Node usages with Node<T> and it should compile.
Explanation:
Each class that declares a template (template <typename T>) is familiar with it. Other classes aren't. Even if the template is declared with the same literal T, there isn't a conncetion between two different classes' templates.

Using Find from subclass not in DbContext

ASP .NET 5 MVC Core application.
Following method is used to find entity by key:
class MyStudents: Students { }
public TEntity FindNormalized<TEntity>(params object[] keyValues)
where TEntity : class
{
return Find<TEntity>(keyValues);
}
void FindNormalized<TEntity>(TEntity entity, params object[] keyValues)
where TEntity : class
{
var res = FindNormalized<TEntity>(keyValues);
if (res == null)
throw new KeyNotFoundException(entity.GetType().Name + " entity key not found " + keyValues[0]);
CopyPropertiesTo(res, entity);
}
static void CopyPropertiesTo<T, TU>(T source, TU dest)
{ // https://stackoverflow.com/questions/3445784/copy-the-property-values-to-another-object-with-c-sharp
var sourceProps = typeof(T).GetProperties().Where(x => x.CanRead).ToList();
var destProps = typeof(TU).GetProperties()
.Where(x => x.CanWrite)
.ToList();
foreach (var sourceProp in sourceProps)
if (destProps.Any(x => x.Name == sourceProp.Name))
{
var p = destProps.First(x => x.Name == sourceProp.Name);
p.SetValue(dest, sourceProp.GetValue(source, null), null);
}
}
Using it with subclass
FindNormalized<MyStudents>(1);
throws exception
Cannot create a DbSet for 'MyStudents' because this type is not
included in the model for the context.
FindNormalized<Students>(1);
works.
How to fix this so that it can used with subclass type also ?
For getting table attribute from subclass code from Dynamic Linq works:
string GetTableAttrib(Type t)
{
foreach (Type t2 in SelfAndBaseClasses(t))
{
IEntityType entityType = Model.FindEntityType(t2);
if (entityType == null)
continue;
return entityType.GetTableName();
}
throw new ApplicationException(t.FullName + " no table attribute");
}
/// <summary>
/// Enumerate inheritance chain - copied from DynamicLinq
/// </summary>
static IEnumerable<Type> SelfAndBaseClasses(Type type)
{
while (type != null)
{
yield return type;
type = type.BaseType;
}
}
Maybe this can used to implement Find also. Unfortunately Find throws exception. Is it reasonable to wrap Find using try/catch or is there better way ?
The EFCore Find method throws exception because the TEntity is not an entity type but a type deriving from the entity type. So to solve this, we need to first get the most derived type which is the ancestor type of the passed in TEntity type, so when passing in MyStudents you need to get type Students first to use as type argument for Find<> method. Because that type is not known at design time, so we need to use reflection to invoke that Find<> method or better use the other overload of Find that accepts the first argument of entity type (Type). Of course I understand that your Find<> method in your question is from DbContext.Find.
So the solution can be simple like this, firstly we need method to get the most derived entity type from the passed in type (which inherits from the entity type):
public static class DbContextExtensions {
public static Type GetMostDerivedEntityType(this DbContext dbContext, Type type){
while(type != null && dbContext.Model.FindEntityType(type) == null) {
type = type.BaseType;
}
return type;
}
}
Next just use that extension method in your FindNormalized method to find the most derived entity type first before using Find:
//I suppose that this is in the context (class) of your custom DbContext
void FindNormalized<TEntity>(TEntity entity, params object[] keyValues)
where TEntity : class
{
var actualEntityType = this.GetMostDerivedEntityType(typeof(TEntity)) ??
throw new InvalidOperationException($"The type {typeof(TEntity)} is not an entity type or a derive from an entity type");
//use the actualEntityType instead
var res = Find(actualEntityType, keyValues);
if (res == null)
throw new KeyNotFoundException(entity.GetType().Name + " entity key not found " + keyValues[0]);
//copy the properties
CopyPropertiesTo(res, entity);
}
Note that in the above code I use another overload (non-generic version) of Find which accepts the first argument of Type (entity type) directly instead of using your wrapper FindNormalized which is generic only (you can add your one overload of that wrapper which wraps the non-generic Find as used directly in my code above).
I've not tested the code at all. Just try it and let me know if there is any error.

How to construct Where Expression dynamically in Entity Framework?

I've taken a look at this answer on how to dynamically create an OrderBy expression in Entity Framework. But I'd like to also build a dynamic Where expression. Something along the lines of this:
public IEnumerable<InventoryItem> GetAll(string filterBy, object value)
{
var results = new List<InventoryItem>();
using (var db = new InventoryDb())
{
if (QueryHelper.PropertyExists<InventoryItem>(filterBy))
{
var query = db.rri_InventoryItems.WhereByProperty(filterBy, value);
foreach(var item in query.Where(expr))
{
results.Add(ConvertItem(item));
}
}
}
return results;
}
Passing in the property to filter by and a value as ab object. Queryable has two methods for Where that both take two parameters, so I am not even sure which is the proper one.
And it's at this point I get a little more lost. I'm not sure how to refactor the original OrderByProerty method to provide a WhereByProperty. I know what I have here is completely wrong. I'm not sure what to do with it.
Ideally, I'd want to extend this even more by providing a collection of objects that could be used to build a query with ands and or operators.
Queryable has two methods for Where that both take two parameters, so I am not even sure which is the proper one.
You need the one that receives Expression<Func<T, bool>> predicate.
Here is how you can build dynamically a predicate similar to (T item) => item.Property == value:
public static partial class QueryableExtensions
{
public static IQueryable<T> WhereEquals<T>(this IQueryable<T> source, string member, object value)
{
var item = Expression.Parameter(typeof(T), "item");
var memberValue = member.Split('.').Aggregate((Expression)item, Expression.PropertyOrField);
var memberType = memberValue.Type;
if (value != null && value.GetType() != memberType)
value = Convert.ChangeType(value, memberType);
var condition = Expression.Equal(memberValue, Expression.Constant(value, memberType));
var predicate = Expression.Lambda<Func<T, bool>>(condition, item);
return source.Where(predicate);
}
}
I've tried to write it in such a way so you can step over the code in order to understand what it does. The only line that might need some explanation is:
var memberValue = member.Split('.').Aggregate((Expression)item, Expression.PropertyOrField);
This is a simple way of handling nested properties like obj.Prop1.Prop2 etc. If you don't need such capability, you can simply use this instead:
var memberValue = Expression.PropertyOrField(item, member);
I didn't need nested properties (yet). I modified your code slightly and have this that is working:
public static IQueryable<T> WhereEquals<T>(
this IQueryable<T> source, string propertyName, object value)
{
if (typeof(T).GetProperty(propertyName, BindingFlags.IgnoreCase |
BindingFlags.Public | BindingFlags.Instance) == null)
{
return null;
}
ParameterExpression parameter = Expression.Parameter(typeof(T), "item");
Expression whereProperty = Expression.Property(parameter, propertyName);
Expression constant = Expression.Constant(value);
Expression condition = Expression.Equal(whereProperty, constant);
Expression<Func<T, bool>> lambda = Expression.Lambda<Func<T, bool>>(condition,parameter);
return source.Where(lambda);
}

How do you create a dynamic QueryDSL operator based on a quoted String value

I have a pojo that contains a property name, logic operator as String and the value of property. What I want to accomplish is create a Predicate or Expression etc dynamically from the pojo data. Below are my code:
public class QueryParam {
private String property = "acctType"; //can be any property of classname
private String operator = "eqic" //can be any logic operator !=, >, <, >=, <= etc
private Object value; //will store the value of
// getters/setters here
}
public interface CustomerRepository extends JpaRepository<Customer, Long>, QueryDslPredicateExecutor<Customer>{
}
#Service("CustomerService")
class MyCustomerServiceImpl {
#Resource
private CustomerRepository custRpstry;
//if classname is Customer, property is "acctType", operator is "eqic", and value is "Corporate"
//I want my findAll below to retrieve all Customers having acctType = "Corporate"
List<Customer> findAll(List<QueryParam> qryParam) {
QCustomer qcust = QCustomer.customer;
BooleanBuilder where = new BooleanBuilder();
for(QueryParam param : qryParam) {
//within this block, i want a BooleanBuilder to resolve to:
where.and(qcust.acctType.equalsIgnoreCase("Corporate"));
something like:
where.and(param.getClassname().param.getProperty().param.getOperator().param.getValue())
}
return custRpstry.findAll(where.getValue()).getContent();
}
}
I can't figure out to formulate my BooleanBuilder especially the portion that will convert
getOperator() into .equalIgnoreCase().
Any help would be greatly appreciated.
Thanks in advance,
Mario
After combining several answers to some related questions here in so, I was able to formulate a solution that works for me.
BooleanBuilder where = new BooleanBuilder();
for(QueryParam param: qryParam) {
//create: Expressions.predicate(Operator<Boolean> opr, StringPath sp, filter value)
//create an Operator<Boolean>
Operator<Boolean> opr = OperationUtils.getOperator(param.getOperator().getValue());
//create a StringPath to a class' property
Path<User> entityPath = Expressions.path(Customer.class, "customer");
Path<String> propPath = Expressions.path(String.class, entityPath, param.getProperty());
//create Predicate expression
Predicate predicate = Expressions.predicate(opr, propPath, Expressions.constant(param.getValue()));
where.and(predicate);
}
list = repository.findAll(where.getValue(), pageReq).getContent();
My OperationUtils.java
public class OperationUtils {
public static com.mysema.query.types.Operator<Boolean> getOperator(String key) {
Map<String, com.mysema.query.types.Operator<Boolean>> operators = ImmutableMap.<String, com.mysema.query.types.Operator<Boolean>>builder()
.put(Operator.EQ.getValue() ,Ops.EQ)
.put(Operator.NE.getValue() ,Ops.NE)
.put(Operator.GT.getValue() ,Ops.GT)
.put(Operator.GTE.getValue() ,Ops.GOE)
.put(Operator.LT.getValue() ,Ops.LT)
.put(Operator.LTE.getValue() ,Ops.LOE)
.build();
return operators.get(key);
}
}

Convert Method Group to Expression

I'm trying to figure out of if there is a simple syntax for converting a Method Group to an expression. It seems easy enough with lambdas, but it doesn't translate to methods:
Given
public delegate int FuncIntInt(int x);
all of the below are valid:
Func<int, int> func1 = x => x;
FuncIntInt del1 = x => x;
Expression<Func<int, int>> funcExpr1 = x => x;
Expression<FuncIntInt> delExpr1 = x => x;
But if i try the same with an instance method, it breaks down at the Expressions:
Foo foo = new Foo();
Func<int, int> func2 = foo.AFuncIntInt;
FuncIntInt del2 = foo.AFuncIntInt;
Expression<Func<int, int>> funcExpr2 = foo.AFuncIntInt; // does not compile
Expression<FuncIntInt> delExpr2 = foo.AFuncIntInt; //does not compile
Both of the last two fail to compile with "Cannot convert method group 'AFuncIntInt' to non-delegate type 'System.Linq.Expressions.Expression<...>'. Did you intend to invoke the method?"
So is there a good syntax for capturing a method grou in an expression?
thanks,
arne
How about this?
Expression<Func<int, int>> funcExpr2 = (pArg) => foo.AFuncIntInt(pArg);
Expression<FuncIntInt> delExpr2 = (pArg) => foo.AFuncIntInt(pArg);
It is also possible to do it using NJection.LambdaConverter a Delegate to LambdaExpression converter Library
public class Program
{
private static void Main(string[] args) {
var lambda = Lambda.TransformMethodTo<Func<string, int>>()
.From(() => Parse)
.ToLambda();
}
public static int Parse(string value) {
return int.Parse(value)
}
}
I use property instead of method.
public class MathLibrary
{
public Expression<Func<int, int>> AddOne {
get { return input => input + 1;}
}
}
Using above