MapStruct: Map two sources and return null if one of them is null - mapstruct

I could not find an answer and I believe this is not possible with MapStruc. I would like to ask anyway, maybe I missed something.
I have a mapping method that takes two sources and maps to one target, let's say
#Mapping(...)
#Mapping(...)
...
Target mapToTarget(SourceA a, SourceB b);
The generated code does the following null check to return null:
if (a == null && b == null) return null;
I wish to have
if (a == null || b == null) return null;
For the moment I filter beforehand so that I won't give null as input. I wish to skip that part and simply return null in the mapper if an argument is null.
Does MapStruct support this?
P.S.: We use MapStruct 1.3.1

This is not possible with MapStruct. However, you can achieve this by providing a default method.
e.g.
#Mapper
public abstract class CustomerMapper {
public Target mapToTarget(SourceA a, SourceB b) {
if (a == null || b == null) {
return null;
}
return mapToTargetWithMapStruct(a, b);
}
#Named("ignore") // #Named in order for MapStruct not to consider this as a candidate
protected abstract mapToTargetWithMapStruct(SourceA a, SourceB b);
}

Related

Merging Entity Framework Expression Trees

I'm looking for a way to merge multiple expression trees in order to build selectors for an Entity Framework query. The query knows which columns to select based on user-provided parameters. For example, a basic query returns ID/Name columns of an entity. If a parameter is explicitly set to also retrieve the Description column, then the query will return ID/Name/Description.
So, what I need it the code for the MergeExpressions method in the following code.
Expression<Func<T, TDto>> selector1 = x => new TDto
{
Id = x.Id,
Name = x.Name
}
Expression<Func<T, TDto>> selector2 = x => new TDto
{
Description = x.Description
}
var selector = selector1;
if (includeDescription)
selector = MergeExpressions(selector1, selector2);
var results = repo.All().Select(selector).ToList();
Thank you.
Not sure for general case, but merging MemberInitExpression bodied lambdas like in your sample is relatively easy. All you need is to create another MemberInitExpression with combined Bindings:
static Expression<Func<TInput, TOutput>> MergeExpressions<TInput, TOutput>(Expression<Func<TInput, TOutput>> first, Expression<Func<TInput, TOutput>> second)
{
Debug.Assert(first != null && first.Body.NodeType == ExpressionType.MemberInit);
Debug.Assert(second != null && second.Body.NodeType == ExpressionType.MemberInit);
var firstBody = (MemberInitExpression)first.Body;
var secondBody = (MemberInitExpression)second.Body.ReplaceParameter(second.Parameters[0], first.Parameters[0]);
var body = firstBody.Update(firstBody.NewExpression, firstBody.Bindings.Union(secondBody.Bindings));
return first.Update(body, first.Parameters);
}
Note that the lambda expressions must be bound to one and the same parameters, so the above code uses the following parameter replacer helper to rebind second lambda body to the first lambda parameter:
public static partial class ExpressionUtils
{
public static Expression ReplaceParameter(this Expression expression, ParameterExpression source, Expression target)
{
return new ParameterReplacer { Source = source, Target = target }.Visit(expression);
}
class ParameterReplacer : ExpressionVisitor
{
public ParameterExpression Source;
public Expression Target;
protected override Expression VisitParameter(ParameterExpression node)
{
return node == Source ? Target : base.VisitParameter(node);
}
}
}
Check out PredicateBuilder.
Example:
Expression<Func<Customer, bool>> expr1 = (Customer c) => c.CompanyName.StartsWith("A");
Expression<Func<Customer, bool>> expr2 = (Customer c) => c.CompanyName.Contains("B");
var expr3 = PredicateBuilder.And(expr1, expr2);
var query = context.Customers.Where(expr3);
or
var expr3 = expr1.And(expr2);
var query = context.Customers.Where(expr3);
I do this kind of thing with extension methods. Its syntactically a bit nicer than using expression trees everywhere. I call this composable repositories.
I also wrote a tool (LinqExpander) to combine the expression trees of different extension methods togeather, which is especially useful for doing projection (selects) from your database. This is only nessacary when you are doing things with sub-entities. (see my post here: Composable Repositories - Nesting extensions)
usage would be something along the lines of:
var dtos = context.Table
.ThingsIWant() //filter the set
.ToDtos() //project from database model to something else (your Selector)
.ToArray();//enumerate the set
ToDtos might look something like:
public static IQueryable<DtoType> ToDtos(this IQueryable<DatabaseType> things)
{
return things.Select(x=> new DtoType{ Thing = x.Thing ... });
}
You want to merge two selects togeather (im assuming to avoid an underfetch but this seems a bit wierd). I would do this by using a projection like this:
context.Table
.AsExpandable()
.Select(x=>new {
Dto1 = x.ToDto1(),
Dto2 = x.ToDto2()
})
.ToArray();
if you really wanted it to return a single entity like this you could probably do something like:
context.Table
.AsExpandable()
.Select(x=> ToDto1(x).ToDto2(x));
but I havent ever tried this.
As this uses a sub projection you will need the .AsExpandable extensions.

How to force some customer to be serviced by a specific vehicle in VRP examples of the OptaPlanner?

In the VRP examples of Optaplanner, I would like to force some customer to be serviced by a specific vehicle in VRP.
How to do this? Can anyone help me?
There are several ways. The easiest is probably just to add a hard constraint
when
Customer(forcedVehicleIsNotVehicle == true)
then
scoreHolder.addHardConstraint...
end
class Customer {
public boolean isForcedVehicleIsNotVehicle() {
return forcedVehicle != null
&& vehicle != null && forcedVehicle != vehicle;
}
}

Querying against DbContext.Set(TypeVariable) in Entity Framework

I'm re-factoring an application to invert some dependencies. Part of the original code uses DbContext.Set<MyEntityType>() to obtain the set to query against.
With the inversion, the MyEntityType is no longer explicitly known to the code using DbContext.Set<MyEntityType>(), so now I'm using DbContext.Set(TypeVariable) instead.
The re-factoring works to the extent that the correct DbSet is being returned.
However, the type DbContext.Set(TypeVariable).Local is IList (contained type unknown) where-as the type of DbContext.Set<MyEntityType>().Local was ObservableCollection<MyEntityType>. This means that it's now impossible to do Linq against the DbSet.
The best workaround I've been able to achieve is to cast to an interface that MyEntityType and other entity types implement (some code omitted for clarity)
var set = Context.Set(targetType);
var entity = set.Local.OfType<IActionTarget>()
.FirstOrDefault(l => l.Id == key.Id && l.EffectiveDate == key.EffectiveDate);
var querables = set as IQueryable<IActionTarget>;
entity = querables.FirstOrDefault(e => e.Id == key.Id && e.EffectiveDate == key.EffectiveDate);
So, two questions:
Why doesn't DbContext.Set(TypeVariable) return a strongly typed set?
Is there a better way to do the dependency inversion?
Some further details as requested
It's all about dependencies. The Model contains POCO classes which are persisted via EF Code First in the typical way (but via a Repository). An ActionEvaluator takes some incoming data, and via Repository methods, determines what actions need to occur - hence the queries against the DbSets.
In the original code, there was only one type of incoming data (CSV of a particular format) and the ActionEvaluator had a tight dependency to this data and knew which POCO classes were applicable to which CSV records.
Now, we want to expand to use different CSV formats and web api messages. To do this, we need to invert the dependencies so that the DataSource tells the ActionEvaluator what POCO classes it's records apply to. This is done by way of a Type variable.
So, the ActionEvaluator can no longer use a generic type parameter, but it can pass the type variable to the Repository which uses it to find the correct DbSet.
The problem is the difference between the two ways of finding the DbSet - DbContext.Set<AnEntity>() and DbContext.Set(TypeVariable).
I guess I'm asking for an enhancement in EF to make these two functionally equivalent in their return values, but that may not be possible since the types of the second version are determined at runtime.
Here's the full method code as requested:
private IActionTarget DbContextGetEntity(Type targetType, IActionTarget key)
{
var set = Context.Set(targetType);
if (set == null)
{
throw new Exception("Unable to find DbSet for type '{0}'".F(targetType.Name));
}
// Look in the local cache first
var entity = set.Local.OfType<IActionTarget>()
.FirstOrDefault(l => l.Id == key.Id && l.EffectiveDate == key.EffectiveDate);
if (entity == null)
{
// If not found locally, hit the database
var querables = set as IQueryable<IActionTarget>;
if (querables != null)
{
entity = querables.FirstOrDefault(e => e.Id == key.Id && e.EffectiveDate == key.EffectiveDate);
}
}
return entity;
}
Ideally, I want to replace
var entity = set.Local.OfType<IActionTarget>()
.FirstOrDefault(l => l.Id == key.Id && l.EffectiveDate == key.EffectiveDate);
with
var entity = set.Local.OfType(targetType)
.FirstOrDefault(l => l.Id == key.Id && l.EffectiveDate == key.EffectiveDate);
I haven't compiled it so please excuse any formatting issues - can you use the dynamic type to achieve the same thing?
private IActionTarget DbContextGetEntity(Type targetType, IActionTarget key)
{
dynamic instance = Activator.CreateInstance(targetType);
return DbContextGetEntity(instance, key);
}
private IActionTarget DbContextGetEntity<T>(T instance, IActionTarget key)
where T : class, IActionTarget
{
var set = Context.Set<T>(targetType);
if (set == null)
{
throw new Exception();
}
// Look in the local cache first
var entity = set.Local
.FirstOrDefault(l => l.Id == key.Id && l.EffectiveDate == key.EffectiveDate);
if (entity == null)
{
// If not found locally, hit the database
entity = set
.FirstOrDefault(e => e.Id == key.Id && e.EffectiveDate == key.EffectiveDate);
}
return entity;
}

how to judge the abstract class with ICompilationUnit

I am working on the eclipse plugin development,so I find the api docs and google them,it only contains such method isClass() isInterface() with the ICompilationUnit,but I want to dig deep with the abstract class,the code like
public boolean isAbstract(ICompilationUnit icu) {
//TODO
}
can anybody help me?
First, you will need an instance of org.eclipse.jdt.core.IType, because one ICompilationUnit can contain several types. ICompilationUnit.getTypes() will provide you with list of all types in this unit. ICompilationUnit.findPrimaryType() will get you a primary type for this unit.
Your routine should look something like following:
public boolean isAbstract(ICompilationUnit icu) throws JavaModelException {
final IType type = icu.findPrimaryType();
return (type != null)
? Flags.isAbstract(type.getFlags())
: false;
}
where Flags is org.eclipse.jdt.core.Flags.

How to iterate an Entity Framework tree to find a specific item

I have loaded my product catalog using Entity Framework
I would like to iterate all items to find a specific item
the structure is
Category -> [Subcategory ->] Product -> options
Subcategory, product and options are EntityCollection of their specific type
All types derive from EntityObject
Let's say I'm looking for option 12 but I don't know in which product it is in.
How can I iterate all objects to find the option 12 ? I have this so far. in my EntityObject, I know it's not recursive yet but will eventually be once i know which properties are collections, I might be approaching it the wrong way ...
public T Find<T>(Type type, int id) where T : EntityObject
{
//get all properties
PropertyInfo[] properties = this.GetType().GetProperties();
// foreach property find the one
foreach (PropertyInfo oPropertyInfo in properties)
{
// check for type
if (oPropertyInfo.PropertyType == type)
{
PersistentEntity o = oPropertyInfo.GetValue(this, null) as EntityObject;
if (o != null && o.Id == id)
{
return (T)o;
}
}
// if property has childs, is IEnumerable -> recursive
}
return (T)new EntityObject();
}
How about this?
var query =
from c in categories
from sc in c.SubCategories
from from p in sc.Products
from o in p.Options
where o.Id == 2
select c /* or p?? */;