Can i compare Set<Byte> with String in java and drools? - java

I have a Java class as below
public class Mart implements MartInterface {
private Set<Byte> visit;
private Set<Byte> type;
//
}
and to create Drools rule to compare the byte with
String REF_VISIT_RESULT = "1"
String REF_TYPE_RESULT = "2"
and the set of array for example [1, 2, 3]
something like
rule "rule 1"
dialect "java"
when
mart : Mart (visit == REF_VISIT_RESULT, type == REF_TYPE_RESULT)
then
System.out.println("//error");
end
Can i compare Set Byte with Lookup String in drools? Please help to create the .drl file

Related

Generating Enums Dynamically

Let's say I have a file whose format is basic XML, like so:
<?xml version="1.0"?>
<enum-set>
<enum>
<name>SomeEnum</name>
<values>
<value>
<name>SOMEVALUE</name>
<displayText>This is some value</displayText>
</value>
... more values ...
</values>
</enum>
... more enums ...
</enum-set>
and I wanted to turn SomeEnum into something like this at runtime:
public enum SomeEnum implements HasDisplayText {
SOMEVALUE("This is some value"),
... more values ...;
private String displayText;
SomeEnum(String displayText) {
this.displayText = displayText;
}
#Override
public String getDisplayText() {
return displayText;
}
}
... and then pass the newly created enum SomeEnum around my application. How might I achieve something like this? Is it doable?
What you're trying to do doesn't make a whole lot of sense. Enums are really only for the benefit of compile time, as they represent a fixed set of constants. At runtime, what would be the meaning of a dynamically generated enum - how would this be different from an plain object? For example:
public class Salutation implements HasDisplayText {
private String displayText;
private Salutation(String displayText) {
this.displayText = displayText;
}
#Override
public String getDisplayText() {
return displayText;
}
public static Collection<Salutation> loadSalutations(String xml) {
//parse, instantiate, and return Salutations
}
}
Your XML could be parsed into newly instantiated Salutation objects, which could be stored in some Collection or otherwise used by your program. Notice in my example, I've restricted the creation of Salutation by giving it a private constructor - in this case the only way to retrieve instances is by calling the factory method which takes your XML. I believe this achieves the behavior you're looking for.
Actually it is possible to create enum instances dynamically, but it's a total hack, I wouldn't advise it at all - maybe you're misunderstanding the nature of an enum, it's a compile-time feature of the language, and you're not supposed to add/remove instances from it at runtime.
Anyway, if you're interested in the hack for creating enum instances dynamically, take a look at this article.
Agree with Oscar Lopez. Here is what i did, a sort of hack.
public static enum Setter {
DYNAMIC_ENUM_EXAMPLE {
#Override
public String setGetValue(String yourValue) {
return "prefix " + yourValue + " postfix";
}
};
public abstract String setGetValue(String value);
}
You can get the value like this :
Setter.DYNAMIC_ENUM_EXAMPLE.setGetValue("namaste")
Output :
prefix namaste postfix
Dynamic Enums is the answer to your problem:
public abstract class DEnum<E extends DEnum<E>> implements Comparable<E>, Serializable {
This class has a signature similar to the standard Enum class. It has a protected constructor to allow instance creation in concrete Enum classes. For example:
public class YesNo extends DEnum<YesNo> {
public final static YesNo YES = new YesNo();
public final static YesNo NO = new YesNo();
The DEnum class knows the names of the members by introspection:
String name = YesNo.YES.getName();
YesNo yes = YesNo.get(YesNo.class, name);
assert (yes == YesNo.YES);
There is a typed getter that retrieves all the items:
YesNo[] items = yes.getItems();
assert (items.length == 2);
It allows to add members dynamically at run time with (from database or from file):
YesNo maybe = getOrCreateIfNotExists(YesNo.class, "MAYBE");
items = yes.getItems();
assert (items.length == 3);
Which have the same behavior as the static members:
YesNo unknown = YesNo.get(YesNo.class, "MAYBE");
assert (unknown == maybe);

Antlr4 create more meaningful/consistent type name

By default the token.getType() method returns an int, and is pretty useless to code based upon, without loading and parsing the *.tokens file that is generated.
How do ANTLR users usually go about making consistent use of the token types? What I mean by consistent is that if you change the grammar, the token numbers are very likely to change.
Do you typically create a Utility class that loads the *.tokens file and parses it?
My sample Search.tokens file:
LOCATION=8
TIME=5
AGE=3
WS=1
COMPARATIVE=9
GENDER=4
PHRASE=2
A sample token stream:
(token.getType(), token.getText())
9 [MegaBlocks vs Legos], -1 [<EOF>]
Currently I'm doing something like:
public class TokenMapper {
private HashMap<Integer, String> tokens;
public TokenMapper(String file) {
tokens = new HashMap<Integer, String>();
parse(file);
}
private void parse(String file) {
// trivial code that maps the Integer typeId to the String name
}
public Integer type(String type) {
for(Map.Entry<Integer, String> entry : tokens.entrySet()) {
if(entry.getValue().equals(type)) {
return entry.getKey();
}
}
return null;
}
public String type(Integer type) {
return tokens.get(type);
}
}
Then I can always refer to my tokens by names such as LOCATION or GENDER and don't have to worry about the Integer values that tend to change.
When you generate your lexer and/or parser, the generated class will contain constants for each token type declared in the grammar as well as the ones imported via a tokens file.
For example, if you have the following grammar:
lexer grammar SearchLexer;
options { tokenVocab = Search; }
...
Then the generated SearchLexer.java class will contain constants (public static final int) for LOCATION and GENDER because they were imported due to the tokenVocab option.

How to convert hardcoded enum to different language?

I have an enum that is autogenerated of a webservice I use, thus I cannot modify this enum class as further update would override it.
I would like to provide translation for the enum:
//I cannot modify this class
public enum Time {
PAST("Past"), PRESENT("Present"), FUTURE("Future");
private final String value;
}
//my code
Time time = getTimeFromWebservice();
String translation;
switch(time.value()) {
case: "Past": translation = "Vergangenheit"; break;
case: "Present": translation = "Gegenwart"; break;
case: "Future": translation = "Zukunft"; break;
}
How could I improve this?
You cannot dynamically extend/modify enums at runtime. They are treated like constants.
Usually if you want to do internationlization, all translations are loaded from a ResourceBundle. You can use the enum literal as key:
String translation = bundle.getString(time.name());
Or maybe you want to prefix the key:
String translation = bundle.getString("myprefix." + time.name());
// or use full qualified name:
String translation = bundle.getString(time.getClass().getCanonicalName() + "." + time.name());
See http://docs.oracle.com/javase/tutorial/i18n/resbundle/index.html for details.

Enum relating to a string array that was read from file

I've received a working code (in Java, 1.7) that does the following:
load an array of strings (a list of blood test names) from a file into a string array member (using Properties and FileInputStream). The file can change the strings but the meaning stays the same (for example: a test can be called "abc" and in another run it is called "zzz"). I've got an enum class that enumerates the test names. The enum strings aren't the same as the inputted strings (since the latter can change).
file bloodtest.names contains:
bloodTestNames=abc;def;123;
code:
public enum BloodTestNames {
AAA,BBB,CCC;
}
Properties props = new Properties();
FileInputStream fis = new FileInputStream("bloodtest.names");
props.load(fis);
String testName[]=props.getProperty("bloodTestNames").toString().split(";");
Now to the questions:
Question 1:
I need to return the string that was set in the file when I know the test name (for instance: return "def" for value BBB). What's the best of doing that?
the best way I've come up with is:
return testName[BloodTestNames.BBB.ordinal()]
Question 2: if BBB is not known in compile time - how do I accomplish the same target?
Three points:
* I'm a veteran at C but a newbie with Java. Any Do's and Don't are welcome. Assume my Java knowledge is zero.
* I don't total re-factoring is that's what's needed here.
* I've probably forgot to mention important details, please ask and I'll feel the missing gaps
I'll first assume you do need enum constants for modeling this use-case because you have some sort of specific code to be executed for each kind of blood test (otherwise, a simple set of strings would be enough and more flexible, since you don't need to know the number of tests upfront or care about their names).
Q1: Since Java enums are a little more than a sequence of values, you can make full use of their object oriented nature.
public enum BloodTest {
AAA, BBB, CCC;
private static String[] names;
public static void setNames(String[] names) {
if (BloodTest.names != null)
throw new IllegalStateException("You can only set the names once");
if (names.length != values().length)
throw new IllegalArgumentException("Wrong number of names");
BloodTest.names = names;
}
#Override
public String toString() {
return names[ordinal()];
}
}
Now all you need to do is to initialize your enum by calling BloodTest.setNames(namesFromConfiguration) and then you can get the string representation of each constant by calling the standard toString() method on it: BloodTest.BBB.toString().
Since the initial assumption was that you have some specific logic for each of the test types, I would suggest that logic (as well as the required properties) will also be encapsulated in the enum itself or the enum constants; e.g.:
public enum BloodTest {
AAA(10) {
#Override
public boolean isRequired(MedicalRecord medicalRecord) {
return medicalRecord.includes("someDisease");
}
},
BBB(15) {
#Override
public boolean isRequired(MedicalRecord medicalRecord) {
return ! medicalRecord.hasTakenBloodTestsLately();
}
},
CCC(20) { // ... also implements the abstract method and so on
private final int threshold;
private BloodTest(int threshold) {
this.threshold = threshold;
}
public boolean hasPassed(int value) {
return value <= threshold;
}
public abstract boolean isRequired(MedicalRecord medicalRecord);
// ... same as above
}
Now, once you get a reference to some BloodTest, you can check whether that specific test passed by invoking the corresponding method without switching and having the logic spread around the client code:
BloodTest bloodTest = BloodTest.valueOf(someString); // someString can be "AAA", "BBB" or "CCC"
// no matter which constant this is, you use it as an object and rely on polymorphism
if (bloodTest.hasPassed(someValue)) { // ... do something
Q2: Your question 2 kind of "questions" my initial assumption regarding your actual need for an enum. If there's a chance you'll need to dynamically handle blood tests that you don't know about yet, then you can't use an enum.
In other words, if your code does not have any switch or if/else if blocks to handle each blood test, an enum is a really bad choice for your use case.
However, if it does, than I'd recommend refactoring the code to include the logic in the enum itself as in the above example, rather than in switch/if blocks; moreover, if your switch has a default case (or your if has a final else block), this can still be modeled in the enum itself, for instance by adding a DEFAULT constant as a fallback.
Make the whole thing settings driven: Add a statuc method to load in settings of what string maps to what enum and add a factory method that uses these settings:
public enum BloodTestNames {
AAA,BBB,CCC;
private static Map<String, BloodTestNames> map = new HashMap<String, BloodTestNames>();
public static void addAlias(String alias, String name) {
map.put(alias, valueOf(name));
}
public static BloodTestNames getByAluas(String alias) {
if (map.containsKey(alias))
return map.get(alias);
// own name assumed to be mapped
return valueOf(alias);
}
}
On startup, repeatedly call BloodTestNames.addAlias() based on some settings file to load the mappings.
When you're reading the saved file, use BloodTestNames.getByAlias() to return the enum for a given string value.
You would do well to name your class in the singular, and drop "Name", ie BloodTest - name the class for what each enum is (all enums have a "name" which is the coded instance name).
A short extract from one of my enum class :
public enum TypesStructurelsE {
SOURCE("SRC"),
COLONNE("COL");
private String code;
TypesStructurelsE(final String code1) {
code = code1;
}
/** #return String */
public String getCode() {
return code;
}
public void setCode(final String newCode) {
code = newCode;
}
}
. . In other class
if(TypesStructurelsE.SOURCE.getCode().equal(testName[i])){ // can be "COL" or "SRC"
//
;
}
... changing value :
TypesStructurelsE.SOURCE.setCode("SOURCE_NEW");
So, if your properties file change, you have just to compile with the new symbole (SRC --> SOURCE) no more

Inserting objects containing collections in MongoDB

I am fairly new to MongoDB / JSON so this might be very simple but I can't find a satisfactory answer.
Let's say I have 2 classes defined below (in reality much more complex):
public class Instrument {
public String name;
public List<Identifier> identifiers;
}
public class Identifier {
public String type;
public String value;
}
So one Instrument can have several Identifiers.
Now I have a List<Instrument> that I would like to store in a Mongo collection called "instruments".
The only way I have found so far is to create each document manually by inserting their fields one by one (see the getDocFromInstrument method in the full working example below). This is very cumbersome and error prone + completely coupled with the underlying classes.
Is there a better way to do that?
And as I will need to get the information back at some stage, any ideas on how to "automatically" recreate the objects from the database is welcome too.
For information, the output of the code below is:
{ "_id" : { "$oid" : "4f44db111d8bc98c289b5d82"} , "name" : "inst1" , "identifiers" : [ { "type" : "type1" , "value" : "inst1_type1"} , { "type" : "type2" , "value" : "inst1_type2"}]}
{ "_id" : { "$oid" : "4f44db111d8bc98c289b5d83"} , "name" : "inst2" , "identifiers" : [ { "type" : "type1" , "value" : "inst2_type1"} , { "type" : "type2" , "value" : "inst2_type2"}]}
Full code:
public class TestMongo {
private final static String IP = "192.168.3.12";
private final static String DB_NAME = "test";
private final static int DEFAULT_PORT = 27017;
public static void main(String[] args) {
DB db = null;
try {
db = new Mongo(IP, DEFAULT_PORT).getDB(DB_NAME);
insertSomething(db);
printContent(db);
cleanDb(db);
} catch (Exception e) {
System.out.println(e);
} finally {
if (db != null) {
db.getMongo().close();
}
}
}
private static void insertSomething(DB db) {
Identifier idInst1_1 = new Identifier("type1", "inst1_type1");
Identifier idInst1_2 = new Identifier("type2", "inst1_type2");
Identifier idInst2_1 = new Identifier("type1", "inst2_type1");
Identifier idInst2_2 = new Identifier("type2", "inst2_type2");
Instrument inst1 = new Instrument("inst1", Arrays.asList(idInst1_1, idInst1_2));
Instrument inst2 = new Instrument("inst2", Arrays.asList(idInst2_1, idInst2_2));
BasicDBObject doc1 = getDocFromInstrument(inst1);
BasicDBObject doc2 = getDocFromInstrument(inst2);
DBCollection instrumentsCollection = db.getCollection("instruments");
instrumentsCollection.insert(doc1);
instrumentsCollection.insert(doc2);
}
private static void printContent(DB db) {
DBCollection instrumentsCollection = db.getCollection("instruments");
DBCursor cur = instrumentsCollection.find();
while(cur.hasNext()) {
System.out.println(cur.next());
}
}
private static void cleanDb(DB db) {
db.dropDatabase();
}
private static BasicDBObject getDocFromInstrument(Instrument instrument) {
BasicDBObject instrumentDoc = new BasicDBObject();
instrumentDoc.put("name", instrument.name);
List<BasicDBObject> identifiers = new ArrayList<>();
for (Identifier identifier : instrument.identifiers) {
BasicDBObject identifierDoc = new BasicDBObject();
identifierDoc.put("type", identifier.type);
identifierDoc.put("value", identifier.value);
identifiers.add(identifierDoc);
}
instrumentDoc.put("identifiers", identifiers);
return instrumentDoc;
}
static class Instrument {
public String name;
public List<Identifier> identifiers;
public Instrument(String name, List<Identifier> ids) {
this.name = name;
this.identifiers = ids;
}
}
static class Identifier {
public String type = "";
public String value = "";
public Identifier(String type, String values) {
this.type = type;
this.value = values;
}
}
}
Take a look at Morphia, it's the Java ORM for MongoDB:
Morphia - Java ORM to/from MongoDB
I use it for my Java code and my classes look very similar to yours. I have not had any trouble nesting lists of objects within other objects. Morphia uses reflection to convert your classes into JSON, so it'll handle a lot of your code for you (such as your getDocFromInstrument function). Hope that helps.
There are several ORM tools you can try.But Morphia is the most stable one among them.
Morphia
Spring Data - MongoDB
Mongo4j
Kundera
https://github.com/impetus-opensource/Kundera/wiki/Kundera-Mongo-performance
This a compiled performance comparision b/w Kundera, Spring Data, Morphia and Native API.
This should give you an idea which one is better. Kundera is providing client extension framework(a way to handle other mongodb requirements).
There is a list of Java POJO mappers on mongo's website.

Resources