How do I do nested foralls in Drools? - nested

Question
Considering these classes:
class BookCase { ArrayList<Book> books }
class Book { ArrayList<Page> pages }
class Page { String color }
And considering this natural language rule:
When all pages in a bookcase are black, do A
The trivial approach would be to nest forall clauses, but in Drools can't do that, because forall clauses only allow Patterns (not Conditional Elements, what a forall clause is) inside!
How do I express this in Drools then?

This is close, but not quite the right thing:
rule "all black pages"
when
BookCase( $books: books )
$book: Book( $pages: pages ) from $books
not Page( color != "black" ) from $pages
then
System.out.println( "doing A" );
end
The problem is that this will fire once for each book where all pages are black. To assess all pages in all books one could assemble a list of all pages and make sure they are all black:
rule "all black pages, take 2"
when
BookCase( $books: books )
$pages: ArrayList() from accumulate( Book( $ps: pages ) from $books,
init( ArrayList list = new ArrayList(); ),
action( list.addAll( $ps ); ),
result( list ) )
not Page( color != "black" ) from $pages
then
System.out.println( "doing A" );
end

You can actually nest multiple foralls if you don't use forall(p1 p2 p3...), but the equivalent not(p1 and not(and p2 p3...)). Then, to keep individual books and pages from firing the rule, chuck an exists in between there.
rule 'all pages in bookcase are black'
when
(and
$bookCase: BookCase()
(not (exists (and
$book: Book() from $bookCase.books
not( (and
not( (exists (and
$page: Page() from $book.pages
not( (and
// slightly different constraint than I used in question
eval($page.color == $book.color)
) )
) ) )
) )
) ) )
)
then
...
end
Unlike using accumulate to create a flat list of all pages, this will maintain the context of $page, that is, when a page is put in a constraint with its parent book as in the example above, in this solution Drools still 'knows' what the parent book is.

While I was writing the question, I think I found the answer myself:
BookCase($caseContents : books)
$bookWithOnlyBlackPages : ArrayList<Page>() from $caseContents
forall ( $page : Page(this memberOf $bookWithOnlyBlackPages)
Page(this == $page,
color == "black") )
forall ( $bookInCase : ArrayList<Page>(this memberOf $caseContents)
ArrayList<Page>(this == $bookInCase,
this == $bookWithOnlyBlackPages) )

Related

Wordpress Woocommerce Variable Products

When setting up a variable type product in woocommerce based on product attributes, for the respective product, the front-end store provides a dropdown box where the user can pick the product attribute (ie lets say shirt size S, M or L).
At the moment that dropdown box is propagated by the attribute names, can someone please let me know where is the function located where I can make this dropdown be propagated by the names PLUS the particular attribute description?
So for instance, if the size attribute has name 'S' and description 'Small', I want the dropdown to say 'S [Small]', rather than just 'S', which is how it would be presented at the moment.
there's a filter available for this... but currently, version 2.5.2, you can only check for its name. Which for me, not so flexible. But at least we have this...
try pasting this code to your functions.php
add_filter('woocommerce_variation_option_name','rei_variation_option_name',10,1) ;
function rei_variation_option_name($name){
if ($name == 'S') {
$name = 'Small';
}
if ($name == 'M') {
$name = 'Medium';
}
if ($name == 'L') {
$name = 'Large';
}
return $name;
}
Please take note that this is just for displaying it. Database has not been change.
The solution I used, is this:
wc-template-functions.php, function wc_dropdown_variation_attribute_options
Modify:
$html .= '<option value="' . esc_attr( $term->slug ) . '" ' . selected( sanitize_title( $args['selected'] ), $term->slug, false ) . '>' . esc_html( apply_filters( 'woocommerce_variation_option_name', $term->name ) ) . '</option>';
to
$html .= '<option value="' . esc_attr( $term->slug ) . '" ' . selected( sanitize_title( $args['selected'] ), $term->slug, false ) . '>' . esc_html( apply_filters( 'woocommerce_variation_option_name', $term) ) . '</option>';
Then in functions.php, implement the following:
add_filter('woocommerce_variation_option_name','variation_option_name_description',10,1) ;
function variation_option_name_description($term){
return $term->name.' ['.$term->description.']';
}
Thanks to Reigel for steering me in the right direction.

Render article with given template in a velocity template

I have defined:
A structure
Two or mote templates associated to the structure (full content, short block abstract, ...)
A web content in the given structure
in a different template I have the functions to gather the reference to my article; I wish to render an article with a given template.
...
#set( $templateId = 27121)
#set ($DDMTemplateLocalService = $serviceLocator.findService("com.liferay.portlet.dynamicdatamapping.service.DDMTemplateLocalService"))
#set( $ddmTemplate = $DDMTemplateLocalService.getTemplate($templateId))
#if( ( $articleId != $reserved-article-id.data ) )
#set( $webContent = $journalContentUtil.getContent( $groupId, $articleId, $ddmTemplate.getPrimaryKey(), "view", "$locale", $xmlRequest ) )
#if ( $webContent )
<div>${webContent}</div>
#else
<div>Cannot use $templateName</div>
#end
#end
... the variable $webContent is always empty .
The reply comes from liferay forum https://www.liferay.com/community/forums/-/message_boards/view_message/45238697
"Method getContent of JournalContentUtil gets ddmTemplateKey as a third parameter, not ddmTemplateId. These are two different properties of DDMTemplate. If you use $ddmTemplate.getTemplateKey() instead of $ddmTemplate.getPrimaryKey(), it should work (of course if there are no other bugs)."
thanks to Krzysztof Gołębiowski
When you are outside of a Velocity tag, you need to use ${webContent}. The same goes for Freemarker.

Joomla - additional search ordering option

Looking at adding an additional search ordering option but not sure how to go about doing it as I have little to no Joomla experience.
Currently the default search ordering options are
Newest First
Oldest First
Most Popular
Alphabetical
Section/Category
I think I have located the code that generates these options in \components\com_search\views\search\view.html.php
$orders = array();
$orders[] = JHTML::_('select.option', 'newest', JText::_( 'Newest first' ) );
$orders[] = JHTML::_('select.option', 'oldest', JText::_( 'Oldest first' ) );
$orders[] = JHTML::_('select.option', 'popular', JText::_( 'Most popular' ) );
$orders[] = JHTML::_('select.option', 'alpha', JText::_( 'Alphabetical' ) );
$orders[] = JHTML::_('select.option', 'category', JText::_( 'Section/Category' ) );
Do I add the additional option here or is this a core file that I shouldn't edit? If so, how can I go about adding an additional search ordering option?
Thank you
Technically you can edit any core file. However you would have to be prepared to readd this edit in every time you update Joomla!
However any default.php file should be copied into and done as a template override. If you're planning on adding to the search functionality - a view.html.php file CAN'T be done as a template override. The best way to do it in this case would be to add a plugin to give this functionality.
For how to add a plugin giving this extra functionality see the documentation pages:
http://docs.joomla.org/Creating_a_search_plugin
http://docs.joomla.org/Creating_a_Smart_Search_plug-in

Drupal 7 - Ubercart - Attributes in Views Fields

I have products that have attributes for 'color' & 'strength'. I'm trying to get those options listed under those attributes as fields for views, so that I can use them as filters. So for example sort by color & strength.
I've looked all around on google and can only find modules for Drupal 6. Anyone know of anything for 7?
Like said in the previous post I had 2 attributes 'color' & 'strength' which I needed to match for exact product matches but ubercart didn't have anything for that, so I wrote them into URL for get statements as variables 1 & 2, so for example a URL which had both attributes selected would look like:
www.website.com/node/68?1=96&2=7
Sometimes one variable would be set but not the other, so I had to make up for that also by using a % wildcard. Here's the code for that part
// Since PHP's serialize function sometimes serializes in the incorrect order,
// here we manually build the comparison key
// Additionally append the image links urls with provided strength/color data
if( isset( $_REQUEST['1'] ) ) {
$_1 = $_REQUEST['1'];
if( $_1 !== '%' ) $url[] = "1=$_1";
} else $_1 = '%';
if( isset( $_REQUEST['2'] ) ) {
$_2 = $_REQUEST['2'];
if( $_2 !== '%' ) $url[] = "2=$_2";
} else $_2 = '%';
$combination = "a:2:{i:1;s:";
$combination .= $_1 == '%' ? '%:"%";' : strlen($_1) . ':"' . $_1 . '";';
$combination .= "i:2;s:";
$combination .= $_2 == '%' ? '%:"%";' : strlen($_2) . ':"' . $_2 . '";';
$combination .= '}';
// if some products don't have a second attribute at all
$combination2 = "a:1:{i:1;s:";
$combination2 .= $_1 == '%' ? '%:"%"' : strlen($_1) . ':"' . $_1 . '";';
$combination2 .= ';}';
Underneath that I had to do some extra queries like if a taxonomy was set and check if some dynamic properties were set, thats why the WHERE is stored in a variable. Frankly they'll just confuse anyone so I left them out. But for your sake the next part you just need to query it.
$where = "WHERE (pa.combination LIKE :pattern1 OR pa.combination LIKE :pattern2) AND s.stock IS NOT NULL";
$comparison = array( ':pattern1' => $combination,
':pattern2' => $combination2 );
$filtered = db_query(
"
SELECT pa.nid, pa.model, pa.combination, n.title, p.sell_price, f.uri
FROM {uc_product_adjustments} pa
LEFT JOIN {node} n ON pa.nid = n.nid
LEFT JOIN {uc_products} p ON pa.nid = p.nid
LEFT JOIN {field_data_uc_product_image} i ON i.entity_type = 'node' AND i.entity_id = n.nid
LEFT JOIN {file_managed} f ON f.fid = i.uc_product_image_fid
LEFT JOIN {uc_product_stock} s ON pa.model = s.sku AND s.stock <> '0'
$where
",
$comparison
);
Lastly loop over the results and store them in a normal array
foreach( $filtered as $i => $record ) {
if( is_int( array_search( $record->nid, $nids ) ) ) continue;
else {
$nids[] = $record->nid;
$result[] = $record;
}
}
This code checks for any products that match any of the attribute values that are currently in stock
You may have a look at these sandbox projects : UC Views Attributes Work and UC attribute views.
I'm looking for a similar feature, as it seems not possible to get UC attributes into a view. I cannot test myself right now as I have a deadline this weekend for a project, but I'd be happy to have your feedback.

Complex queries in linq to nhibernate

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)

Resources