在 Drools 中更新现有枚举常量的值

Updating value for an existing enum constant on the go in Drools

我有下面的枚举结构,我必须更改第二个参数的值 THREAT。该应用程序几乎已开发并且非常依赖枚举类型并且无法更改类型(由于大量枚举变量)。当应用程序重新启动时,我需要那里的默认值。有什么方法可以即时更改 THREAT 的值吗?

enum TraceLevel {
   APP_DOS("as", ""),
   APP_DOS1("as", ""),
   APP_DOS2("as", ""),
   APP_DOS3("as", ""),
   APP_DOS4("as", "");
   String NAME;
   String THREAT;

   private TraceLevel(String name, String threat) {
      this.NAME = name;
      this.THREAT = threat;
   }
}

更新 1
根据评论,我想我应该多更新一下问题。我基本上是在使用枚举常量的 drools 规则引擎工作。那里的声明并不像 Java。所以,我不知道该怎么做。这是流口水的特定模式。

declare enum AttackCategory
APP_DOS("as", ""),
APP_DOS1("as", ""),
APP_DOS2("as", ""),
APP_DOS3("as", ""),
APP_DOS4("as", "");
value : String
threat: String

end

正如很多问题评论所说,您正试图以一种非设计或非预期的方式使用枚举。对于发生这种情况的大多数情况,您可能可以强制它工作,但您将遇到其他问题。正如他们所说,正确的答案是回到绘图板,并提出一个不试图强制枚举具有 class 行为的解决方案。


(错误的)枚举方式

要更改枚举的值,请将设置器添加到您的声明中。在 Java 中,这样做是这样的:

enum TraceLevel {
   APP_DOS("as", ""), ...;
   String NAME;
   String THREAT;

   private TraceLevel(String name, String threat) {
      this.NAME = name;
      this.THREAT = threat;
   }

  public String getThreat() { return this.NAME; }
  public void setThreat(String name) { this.NAME = name; }
}

(还有一点小意见——'name' 和 'threat' 的变量不应完全大写。它们应遵循常规变量的命名约定。)

另一方面,如果您使用的是 Drools type declarations,则不会在这些结构上创建方法,而是 Drools 会按照 bean 约定生成 getter 和 setter。正如您所指出的,这些约定不会在枚举上生成此类方法(这应该是一种暗示,表明您试图以错误的方式使用它们。)

因此,如果您必须使用枚举,则必须在 Java 中声明它们。


替代方法:classes

您的用例似乎只是美化常量,那么为什么不将其用作替代方法呢?使用三个字符串变量(名称、线程、id)声明一个 class。然后,在规则中将它们全部插入到工作内存中,并应用默认值。当您确实需要使用它们时,您可以根据需要在内存中更新它们。

declare TraceLevel
  id: String
  name: String
  threat: String
end

rule "Prepare default trace levels"
when
  not( TraceLevel() )
then
  insert( new TraceLevel("APP_DOS", "as", "") ) // equivalent to TraceLevel.APP_DOS
  insert( new TraceLevel("APP_DOS2", "as", "") )
  // etc.
end

rule "Example rule which needs to update a Threat value"
when
  $traceLevel: TraceLevel( id == "APP_DOS" )
then
  modify( $traceLevel ) { threat = "new threat value" }
end

第一条规则“准备默认跟踪级别”将默认级别插入到工作内存中。此时,工作内存包含一组这些对象,它们在功能上与您的枚举值相同。由于它们在工作记忆中,因此它们现在可用于任何随后评估的规则。

请注意,此规则的条件非常简单,并验证工作内存中没有 pre-existing TraceLevel 实例——如果由于某种原因您触发了一个完整的re-evaluation.

第二个示例规则显示了如何使用 modify rule action.

更新“威胁”值

在所有情况下,我都添加了一个“id”字段,以便您可以识别特定的 TraceLevel 实例。这些是 TraceLevel 枚举名称的等效项(例如 TraceLevel.APP_DOS -> id = "APP_DOS")。第二个示例展示了如何利用此 ID 获取特定的 TraceLevel 实例。