在 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 实例。
我有下面的枚举结构,我必须更改第二个参数的值 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 实例。