I am working with a project with nested objects.
I have 3 questions.
1). I have a rule in which I need to make use of a function. If I use this function on a variable in a nested object it does not work (I get a compilation error). If I assign the nested object to a local variable and then apply the function, it works. Why? Is it because of Mavel and the way it handles nested objects?
Using the nested object accessor approach (compilation error "Unable to Analyse Expression"):
ObjectA( objectB. ( (someFunction(someVariable)) == 0 ) )
Using a non nested object accessor approach (this works):
ObjectA( $objectB : objectB )
ObjectB( (someFunction(someVariable)) == 0 ) from $objectB
2). Is there any other reason why I should not use the nested object approach?
Or, said in other words, is there a difference between this:
ObjectA( $objectB : objectB )
ObjectB( someVariable == 0 ) from $objectB`
And this:
ObjectA( objectB. ( someVariable == 0 ) )`
3). Is it possible to assign a nested object with access on its variables to a local variable, e.g. because of use in some other rule (extends) which conditions for some particular reason I do not want to include in this rule?
ObjectA( $objectB : objectB. ( someVariable == 0 ) )`
I am using Drools 6.5.0 although most coding is done in KIE workbench 6.5.0. I use a local Java mirror project to get better indications on compilation errors and so.
Related
hiera data
ae::namespace_by_fqdn_pattern:
'((^dfw-oel6)|(^dfw-oel7)|(^dfw-ubuntu1604))-((client))([0-9]{2}).pp-devcos-ae.us-central1.gcp.dev.blah.com': '/test/blah/regression/client'
'((^dfw-oel6)|(^dfw-oel7)|(^dfw-ubuntu1604))-((server))([0-9]{2}).pp-devcos-ae.us-central1.gcp.dev.blah.com': '/test/blah/regression/server'
class
class ae {
$namespace = hiera('ae::namespace')
$target_host_patterns = hiera('ae::target_host_patterns')
hiera_hash('ae::namespace_by_fqdn_pattern').each |String $pattern, String $ns| {
if $facts['networking']['fqdn'].match($pattern) {
$ae::namespace = "${ns}"
}
}
<snip>
... yields
Error: Could not retrieve catalog from remote server: Error 500 on SERVER: Server Error: Illegal attempt to assign to 'ae::enforcerd_namespace'. Cannot assign to variables in other namespaces (file: /etc/puppetlabs/code/environments/ar/modules/ae/manifests/init.pp, line: 21, column: 13) on node dfw-ubuntu1604-client02.pp-devcos.us-central1.gcp.dev.blah.com
... anyone here know how to do this correctly? trying to conditionally override that $ae::namespace variable but i'm too puppet-ignorant to know how to get it working : (
the loop and the pattern matching bits work. just can't figure out how to correctly set that class variable from within the hiera_hash().each loop.
How to set a puppet class variable from within a hiera_hash each loop?
You cannot. The associated block of an each() call establishes a local scope for each iteration. Variable assignments within apply to that local scope, and therefore last only for the duration of one execution of the block. You cannot anyway assign a new value to a variable during its lifetime, so even if you could assign to a class variable from within an each() call, it would be difficult to use that capability (and your approach would not work).
There are several ways you could approach the problem without modifying the form of the data. You could leverage the filter() function, for example, but my personal recommendation would be to use the reduce() function, something like this:
$namespace = lookup('ae::target_host_patterns').reduce(lookup('ae::namespace')) |$ns, $entry| {
$facts['networking']['fqdn'].match($entry[0]) ? { true => $entry[1], default => $ns }
}
That does pretty much exactly what your original code seems to be trying to do, except that the selected namespace is returned by the reduce() call, to be assigned to a variable by code at class scope, instead of the lambda trying to assign it directly. Note also that it takes care not only of testing the patterns but of assigning the default namespace when none of the patterns match, as it needs to do because you can only assign to the namespace variable once.
so the solution i landed on was to change the hiera data to:
ae::namespace : '/test/blah/regression'
ae::namespace_patterns: ['((^dfw-oel6)|(^dfw-oel7)|(^dfw-ubuntu1604))-((client))([0-9]{2}).pp-devcos-ae.us-central1.gcp.dev.blah.com', '((^dfw-oel6)|(^dfw-oel7)|(^dfw-ubuntu1604))-((server))([0-9]{2}).pp-devcos-ae.us-central1.gcp.dev.blah.com']
ae::namespace_by_pattern:
'((^dfw-oel6)|(^dfw-oel7)|(^dfw-ubuntu1604))-((client))([0-9]{2}).pp-devcos-ae.us-central1.gcp.dev.blah.com': '/test/paypal/regression/client'
'((^dfw-oel6)|(^dfw-oel7)|(^dfw-ubuntu1604))-((server))([0-9]{2}).pp-devcos-ae.us-central1.gcp.dev.blah.com': '/test/paypal/regression/server'
then the class code to:
$pattern = hiera_hash('ae::namespace_patterns').filter |$pattern| {
$facts['networking']['fqdn'] =~ $pattern
}
if length($pattern) {
$namespace = hiera('ae::namespace_by_pattern')[$pattern[0]]
} else {
$namespace = hiera('ae::namespace')
}
definitely still open to better answers. just what my own hacking produced as workable so far through much trial and error.
I'm facing a problem while using Drools.
I try to update an attribute from a nested member. The update seems to work, but the when clause do not consider it.
I have 2 Obj object, sharing the same Cpt object.
Cpt cpt = new Cpt();
Obj obj1 = new Obj("obj1");
obj1.setComposant("R2");
obj1.counter = cpt;
Obj obj2 = new Obj("obj2");
obj2.setComposant("R2");
obj2.counter = cpt;
kSession.insert(obj2);
kSession.insert(obj1);
My rule is define as:
rule "R2"
when
m : Obj(composant == "R2" && counter.value == 0)
then
System.out.println(m.getName() + " " + m.getCounter().getValue());
m.getCounter().increment();
end
I was expecting Obj1 to match the when clause, then update the value of the counter (from 0 to 1). So the Obj2 should not match the where clause.
But in fact, it does, even if the display is as I expected :
obj1 0
obj2 1
Can someone explain me what am I doing wrong ?
All reactions of the Drools Rule Engine with respect to changes in the set of facts require to be notified by using one of the extensions for the Right Hand Side language. You need to call update(f) for the modified fact object f, or you may use the modify(f){...} statement.
However... Changing a contained object X via the reference from fact A and telling the Engine that fact A has been modified will not make it see that fact B, also referencing X, has been changed as well.
This is where you should reconsider your design. Is it really necessary to have an X shared via references from A and B? Or: what about making X a fact and updating it? The latter may mean that you have to rewrite your rules, making the relation between Obj and Cpt visible on the left hand side. But, in my experience, it is usually better to have this than some complex mechanism propagating update notifications from some joint contained object to its parents.
Edit What I mean by "making the relation visible" is shown by the rule below:
rule "R2"
when
Obj(composant == "R2", $counter: counter )
$c: Cpt( this == $counter, value == 0)
then
modify( $c ){ increment() }
end
I have a problem with parameterizations of list of object by using spock where block. It seems the ListInput value is not taking from the where clause and always coming null value. I have verified the same feature for string and other primitive types and it is working fine.
Does Spock support parameterizations objects ? If yes what is the issue here .
def "check Param Of List of Objects"()
{
expect:
def a= hasflag(ListInput);
a== flag
where:
ListInput | flag
BOList1 | true
BOList2 | false
}
Here the type of BOList1 is an java ArrayList contains the object
You haven't really provided enough information for a definitive answer but I'll try to help.
The where block isn't exactly just a block of code, it's more like a number of parameters passed to a method. It can do a lot, but sometimes you need to pass your code a little differently.
Of note:
- Void methods aren't allowed (but you can get around this using .with{} )
- An iterative parameter cannot also be a derived parameter (constructed from other parameters)
- If you're referencing class level variables (defined within the class but outside this test) they need to be given the #Shared annotation for your tests to have access.
Given more information about where your lists are coming from will help me give better advice.
Final tip; explicitly typecast your parameters to see if that gives you anymore information
def "check Param Of List of Objects"(ArrayList listInput, boolean flag) {
expect:
flag == hasflag(ListInput);
where:
listInput | flag
BOList1 | true
BOList2 | false
}
I am trying to retrieve all direct indirect method calls for all methods in an assembly using the CQL provided by nDepend.
Issue is I am not able to iterate through all methods inside a assembly to get this info.
The DepthOfIsUsedBy only allows a string type and not a collection of strings.
Is there a way t get this info for all methods inside an assembly?
What about using the method DepthOfIsUsing() instead of DepthOfIsUsedBy() :o)
from m in Assemblies.WithNameNotIn("nunit.uikit").ChildMethods()
let depth0 = m.DepthOfIsUsing("nunit.uikit")
where depth0 >= 0 orderby depth0
select new { m, depth0 }
This query has been generated through the menu below. (Btw a more sophisticated solution could be elaborated with the magic method FillIterative(), but it is not necessary here).
Taking account the comment of Prasad, what about trying this query that list all direct & indirect callers from A, for each method of B:
from m in Assemblies.WithNameIn("AsmB").ChildMethods()
where m.IsPubliclyVisible // Optimization
let indirectcallers = m.MethodsCallingMe
.FillIterative(
callers => callers.SelectMany(m1 => m1.MethodsCallingMe))
.DefinitionDomain
.Where(m1 => m1.ParentAssembly.Name == "AsmA")
.ToArray() // Avoid double enumeration
where indirectcallers.Length > 0
orderby indirectcallers.Length descending
select new { m, indirectcallers }
We are using accountability pattern for organizational structure. I using linq to nhibernate to find some departments and position but I have two problem.
var query =
Repository<Party>.Find(p => p.IsInternal == true)
.Where(p => p.Parents.Any(c => c.Parent.PartyId == id))
.Where(p =>
(
p.PartyType.PartyTypeId == (int)PartyTypeDbId.Department &&
_secretariat.Departments.Select(c => c.PartyId).Contains(p.PartyId)
)
||
(
p.PartyType.PartyTypeId == (int)PartyTypeDbId.Position &&
p.Children.Any(c =>
c.AccountabilityType.AccountabilityTypeId == (int)AccountabilityTypeDbId.TenurePersonOfPosition &&
((Person)c.Child).UserName != null)
)
);
First : I got 'Unhandled Expression Type: 1003' for this part of query : '_secretariat.Departments.Select(c => c.PartyId).Contains(p.PartyId)'
and I got Property not found 'UserName'
We have many complex queries i think we need to use stored procedure.
Sorry for bad Inglish!
One nice thing that you can do with LINQ is break your queries into multiple parts. Since you are building an expression tree that won't get executed until the results are enumerated, you don't have to do it all in one line (like SQL).
You can even make some reusable "filters" that you can apply to IQueryable. These filter functions accept an IQueryable as an argument, and return one as a result. You can build these as extension methods if you like (I like to).
As for your immediate problem, you may want to try a join on _secretariat instead of attempting a subquery. I've seen them work in scenarios where subqueries don't.
In addition to Lance's comments you might want to look at a compiled Linq query and breaking up some of the responsibilties to follow SOLID principles.
I've just also found out that there are issues with the Contains when containing Any linq methods. However, Any seems to work well within Any, hence:
_secretariat.Departments.Select(c => c.PartyId).Any(x => x == p.PartyId)