具有不同实体源的CustomVariableListener - 监听器的参数化

时间:2017-05-19 13:16:59

标签: optaplanner

最近,有人问here如何实现一个监听器,其中源变量位于不同的计划实体类上,例如

@PlanningEntity
class FirstPlanningEntityClass{

  @PlanningVariable
  int a;
}

@PlanningEntity
class SecondPlanningEntityClass{

  @PlanningVariable
  int b;
}

在我的第三个(影子)计划实体中,我想在ab更改时更新我的​​影子规划变量(即ab作为来源) ,例如:

@PlanningEntity //shadow planning entity
class ShadowEntityClass{
  @CustomShadowVariable(variableListenerClass = MyListener.class,
        sources = {@CustomShadowVariable.Source(entityClass = FirstEntityClass.class, variableName = "a"),
                @CustomShadowVariable.Source(entityClass = SecondEntityClass.class, variableName = "b")})
  public local int getMyShadowVariable(){...}

但是,MyListenerClass必须使用一个类型参数实现参数化VariableListener,其中type参数对应于源变量所在的实体类:

public class MyListenerClass implements VariableListener<Entity_>{...}

但源变量位于两个计划实体类上。

为了解决这个问题,我尝试了几件事:

  • 我无法将FirstPlanningEntityClassFirstPlanningEntityClass与{一个共同的CommonPlanningEntityInferface因为两个实体类完全不同。此公共接口可以用作VariableListener的类型参数。
  • 我也无法在@CustomShadowVariable参数列表中指定两个不同的侦听器类,例如

    @CustomShadowVariable(variableListenerClass = MyFirstListener.class,
    sources = {@CustomShadowVariable.Source(entityClass = FirstPlanningEntity.class, variableName = "a")}, 
    variableListenerClass = MySecondListener.class, 
    sources = {@CustomShadowVariable.Source(entityClass = SecondPlanningEntity.class, variableName = "b")})
    
  • 或两个相互重叠的注释,例如

    @CustomShadowVariable(variableListenerClass = MyFirstListener.class,
    sources = {@CustomShadowVariable.Source(entityClass = FirstPlanningEntity.class, variableName = "a")})
    @CustomShadowVariable(variableListenerClass = MySecondListener.class,
    sources = {@CustomShadowVariable.Source(entityClass = SEcondPlanningEntity.class, variableName = "b")})
    

手册仅涉及同一类的许多计划变量或不同类的一个计划变量(第4.3.6.4节,6.5.0)。

那么我如何实现一个影子变量,它具有来自不同规划实体类的两个规划变量作为源?给出的答案here主要涵盖一个计划实体类中两个影子变量的变化。

2 个答案:

答案 0 :(得分:0)

很抱歉打扰每个人 - 这是一个多么愚蠢的问题。

我需要做的就是分别在ShadowEntityClass上创建两个临时阴影变量,分别收听ab。然后,我在getMyShadowVariable上创建一个监听器,其中包含这些临时阴影变量,它们现在位于同一个规划实体类中,作为源。

(但是,我仍然认为注释签名不应允许来自多个计划实体类的阴影变量。)

答案 1 :(得分:0)

使用通用接口或普通旧java.lang.Object作为通用参数类型:

public class MyListenerClass implements VariableListener<Object>{...}

您的实现可能需要对源实例进行instanceof检查,并相应地转换为第一或第二类。