Insert Keyword in Decision Table - insert

I am new to Drools, and going through an existing use case where the action contains the insert($param) or insert(new Object($param)), i could not find the functionality of this keyword and the scope of this and how this is getting utilized further conditions.
Any response or documentation on this would help. I could not find this on any documentation.

I strongly recommend you to read the official documentation here: https://docs.drools.org/8.32.0.Final/drools-docs/docs-website/drools/rule-engine/index.html
The conditions of the rules in Drools are applied to "Facts" present in a KieSession. These "Facts" are nothing but Java objects. If you want to make an object a "Fact" then you have to insert it into the KieSession. Otherwise Drools will not know about its presence and no rules will be applied to it.
So, for example, if you have the following rule in your KieSession:
rule "Adult Person"
Person(age >= 18)
then
//do something
end
The Person pattern is making reference to a Java class named "Person". In Java, if you want to make a Person instance available to the KieSession you will need to do something like this:
Person person = new Person();
person.setAge(33); // up to this point, Drools is not aware of this object
kieSession.insert(person); //here we are telling Drools that the `person` object is a Fact and that the rules have to be evaluated for it.
In you case, the insert function is being called as part of the action of you rules and not straight from Java, but the idea is the same.

Related

What is the name of the design pattern to avoid chained field access?

There is a pattern or term that is used to avoid codes like
myObject.fieldA.fieldB.fieldC
something like this. I forgot what this term is called. Can anyone let me know about it?
It violates the Law of Demeter, which states that code should only access its own local variables, parameters, and instance members.
It could be a case of of feature envy, where a class calls a lot of getters or accesses a lot of data from another class.
If these are really fields, they are poorly encapsulated (i.e., not behind a function), and any change to these fields forces you to modify all code that's using them.
Testing such code becomes hard, as you will have to mock not only fieldA, but also that's fieldB, and in turn that's fieldC.
I think you are trying to create a new object and add certain properties to that object. If that is the case then it's Builder design patten where you seperate the construction and representation.
If you are trying to call a certain field with the above shown code then your design is very poor. An object should store only it's own properties.

'Existing Entity' constraint

I'm reading some data from an excel file, and hydrating it into an object of class A. Now I have to make sure that one of the fields of the data corresponds to the Id of a specific Entity. i.e:
class A{
protected $entityId;
}
I have to make sure that $entityId is an existing id of a specific entity (let's call it Foo). Now this can be achieved using the choice constraint, by supplying the choices option as all of the existing ids of Foo. However this will obviously cause a performance overhead. Is there a standard/better way to do this?
I'm a bit confused about what you are doing, since you seem to talk about Excel parsing, but at the same time you mention choices, which in my opinion relate to Forms.
IMO you should handle directly the relationship to your entity, instead of only its id. Most of the time it is always better to have directly the related entity as attribute of your class A than only the id, and Symfony manipulates such behaviours pretty well.
Then just have your Excel parser do something like this:
$relatedEntity = $this->relatedEntityRepository->find($entityId);
if (!$relatedEntity) {
throw new \Exception();
}
$entity->setRelatedEntity($relatedEntity);
After doing this, since you were talking about Forms, you can then use an EntityType field which will automatically perform the request in database. Use query_builder if you need to filter the results.

Trouble with complex routing rule

I have a lookup table called BlockCustomer. I also have an FTP Adapter that picks up files from multiple customers. I need to be able to determine the customer from the source of the file and do a lookup on the table. If BlockCustomer.Customer1 = 0 then it will send it to it's target, otherwise it will do nothing.
If I could use javascript I would do something like this:
WHEN Lookup(BlockCustomer,HL7.Source.split("/incoming/")[1].split("/")[0]),1) = 0
But obviously I can't. I found $ZSTRIP but I'm not sure if or how it will work. Is this possible or am I going to have to create a custom class?
In Cache we use function $piece if needs to get some parts of string by delimiter. For rule you could use the same function called Piece, with the same arguments. So you conditions should looks like:
Lookup(BlockCustomer,Piece(HL7.Source,"/incoming/",2),1)=0
By the way if you think, that you need some specific functions for you, you can do it by developing it. Just extend the class Ens.Rule.FunctionSet and add a method. And function will appear with the same name. As an example you can see at Ens.Util.FunctionSet class, which contains almost all available functions.

Linq To Sql Where does not call overridden Equals

I'm currently working on a project where I'm going to do a lot of comparison of similar non-database (service layer objects for this discuss) objects and objects retrieved from the database via LinqToSql. For the sake of this discussion, assume I have a service layer Product object with a string field that is represented in the database. However, in the database, there is also a primary key Id that is not represented in the service layer.
Accordingly (as I often do for unit testing etc), I overrode Equals(Object), Equals(Product), and GetHashCode and implemented IEquatable with the expectation that I would be able to write code like this:
myContext.Products.Where(p => p.Equals(passedInProduct).SingleOrDefault();
And so forth.
The Equals override is tested and works. The objects are mutable so the usual caveats apply to the GetHashCode override. However, for the purposes of this example, the objects are not modified except by LtS and could be made readonly.
Here's the simple test:
Create a test object in memory and commit to the LtS context. By committing, the test object is populated with a few auto-generated fields.
Create another identical test object in memory (separate reference)
Attempt to retrieve the first object from the database using the second object as the criteria. (see code line above).
// Setup
string productDesc = "12A";
Product testProduct1 = _CreateTestProductInDatabase(productDesc);
Product testProduct2 = _CreateTestProduct(productDesc);
// check setup
Product retrievedProduct1 = ProductRepo.Retrieve(testProduct1);
//Assert.IsNotNull(retrievedProduct1);
// execute - try to retrieve the 'equivalent' product object
Product retrievedProduct2 = ProductRepo.Retrieve(testProduct2);
A simplified version of Retrieve (cruft removed is just parameter checks etc):
using (var dbContext = new ProductDataContext()) {
Product retrievedProduct = dbContext.Products
.Where(p => p.Equals(product)).SingleOrDefault();
NB: The overridden Equals method knows not to care about the auto-generated fields from the database and only looks at the string that is represented in the service layer.
Here's what I observed:
Retrieve on testProduct1 succeeds (no surprise, equal by reference)
Retrieve on testProduct2 fails (null)
The overridden Equals method called in the Retrieve method is never hit during either Retrieve calls
However, the overridden Equals method is called multiple times by the context on SubmitChanges (called when creating the first test object in the database) (works as expected).
Statically, the compiler knows that the type of the objects being emitted and is able to resolve the type.
So my specific questions:
Am I trying to do something ill-advised? Seems like a straightforward use of Equals.
Corollary to first question: alternate suggestions to deal with linq to sql equality checking while keeping comparison details inside the objects rather than the repository
Why might I have observed the Equals method being resolved in SubmitChanges but not in the Where clause?
I'm as much interested in understanding as making my Equals calls work. But I also would love to learn how to make this 'pattern' work rather than just understand why it appears to be an 'anti-pattern' in the contest of LtS and C#.
Please don't suggest I just filter directly on the context with Where statements. Obviously, I can remove the Equals call and do that. However, some of the other objects (not presented here) are large and a bit complicated. For the sake of maintenance and clarity, I want to keep knowledge of how to compare itself to another of its own type in one place and ideally as part of the object in question.
Some other things I tried that didn't change the behavior:
Overloaded and used == instead
Casting the lambda variable to the type p => (Product)p
Getting an IQueryable object first and calling Equals in the Where clause
Some other things I tried that didn't work:
Creating a static ProductEquals(Product first, Product second) method: System.NotSupportedException:has no supported translation to SQL.
Thanks StackOverflow contributors!
Re Possible dups: I've read ~10 other questions. I'd love a pointer to an exact duplicate but most don't seem to directly address what seems to be an oddity of LinqToSql.
Am I trying to do something ill-advised?
Absolutely. Consider what LINQ to SQL does: it creates a SQL representation of your query. It doesn't know what your overridden Equals method does, so can't translate that logic into SQL.
Corollary to first question: alternate suggestions to deal with linq to sql equality checking while keeping comparison details inside the objects rather than the repository
You'd need to do something with expression trees to represent the equality that way - and then build those expression trees up into a full query. It won't be fun, but it should be possible. It will affect how you build all your queries though.
I would have expected most database representations to be ID-based though, so you should be able to just compare IDs for equality. Usually when I've seen attempts to really model data in an OO fashion but store it in a database, the leakiness of the abstraction has caused a lot of pain.
Why might I have observed the Equals method being resolved in SubmitChanges but not in the Where clause?
Presumably SubmitChanges is working against a set of in-memory objects to work out what's changed - it doesn't have to do any conversion to SQL to do that part.

How to validate in domain layer

I often see people validating domain objects by creating rule objects which take in a delegate to perform the validation. Such as this example": http://www.codeproject.com/KB/cs/DelegateBusinessObjects.aspx
What I don't understand is how is this advantageous to say just making a method?
For example, in that particular article there is a method which creates delegates to check if the string is empty.
But is that not the same as simply having something like:
Bool validate()
{
Result = string.IsNullOrEmpty(name);
}
Why go through the trouble of making an object to hold the rule and defining the rule in a delegate when these rules are context sensitive and will likely not be shared. the exact same can be achieved with methods.
There are several reasons:
SRP - Single Responsibility Principle. An object should not be responsible for its own validation, it has its own responsibility and reasons to exist.
Additionally, when it comes to complex business rules, having them explicitly stated makes validation code easier to write and understand.
Business rules also tend to change quite a lot, more so than other domain objects, so separating them out helps with isolating the changes.
The example you have posted is too simple to benefit from a fully fledged validation object, but it is very handy one systems get large and validation rules become complex.
The obvious example here is a webapp: You fill in a form and click "submit". Some of your data is wrong. What happens?
Something throws an exception. Something (probably higher up) catches the exception and prints it (maybe you only catch UserInputInvalidExceptions, on the assumption that other exceptions should just be logged). You see the first thing that was wrong.
You write a validate() function. It says "no". What do you display to the user?
You write a validate() function which returns (or throws an exception with, or appends to) a list of messages. You display the messages... but wouldn't it be nice to group by field? Or to display it beside the field that was wrong? Do you use a list of tuple or a tuple of lists? How many lines do you want a rule to take up?
Encapsulating rules into an object lets you easily iterate over the rules and return the rules that were broken. You don't have to write boilerplate append-message-to-list code for every rule. You can stick broken rules next to the field that broke them.

Resources