String comparision in Apache free marker - string

I have a list which contains below values. The list Gets data from restAPI.
I know how to compare record but list has many values so i dont know how to search in array or in list. for eg list has below values. I need to check whether particular record exist in list or not.
var items= [
{
"organizationCode": "FP1",
"organizationName": "FTE Process Org"
},
{
"organizationCode": "T11",
"organizationName": "FTE Discrete Org"
},
{
"organizationCode": "PD2",
"organizationName": "Product development Org"
},
{
"organizationCode": "PD1",
"organizationName": "Product1 development Org"
},
{
"organizationCode": "MD1",
"organizationName": "Main development Org"
}
]
I have to search value based on organizationName.
I tried
items.organizationName?contains(<input>)
But not working
I could not get any material so seeking help.

The problem is that items.organizationName is an error already, since items is purely a list, so it has no named sub-variables directly. (You may saw that pattern when items is coming from XML, where you can get the list of sub-elements like that. But same doesn't work with plain lists.) So, what you need is this expression:
items?map(it -> it.organizationName)?seq_contains(input)
Slightly related, but sometimes you want to retrieve the list of matching items (so you also will have the organizationCode), in which case you should write items?filter(it -> it.organizationName == input).
Note that ?map and ?filter was added in FreeMarker 2.3.29.
See also:
https://freemarker.apache.org/docs/ref_builtins_sequence.html#ref_builtin_filter
https://freemarker.apache.org/docs/ref_builtins_sequence.html#ref_builtin_map

Related

How to remove the warning "this might be empty" from result view in bixby

I am showing few information to the user on card and structure has min(Optional) and I don't want to change that. There is possibility that it might be blank. But how to put it in condition in result-view. I tried like if(this.name) but then yellow line appears on condition and template both.
Using an if statement is the correct way.
For example, here is how a capsule I have written will handle an optional gameTitle property when displaying my Character structure.
if(exists(character.gameTitle)) {
cell-card {
slot2 {
content {
order (PrimarySecondary)
primary ("#{value(character.gameTitle)}")
}
}
}
}

Buildfire: Private Portal plugin

I am having a very specific issue with a gateway plugin I am trying to finish.
I am trying to navigate to a different plugin using
'buildfire.pluginInstance.get($scope.deepLinnk,function (err, plugin) {
if (err) {
$scope.status = 'error!';
}
else {
console.log(plugin);
$scope.navigateSignIn(plugin);}
});
$scope.navigateSignIn = function (plugin) {
buildfire.navigation.navigateTo({
pluginId: plugin.token,
instanceId: plugin.instanceId,
title: plugin.title,
folderName: plugin.pluginTypeId
});
};
The navigateTo object is the only way I can get buildfire.navigate.navigateTo to work for buildfire made plugins.
However, when I try to navigate to plugins that I have created, the debugger shows and an alert saying "cannot load config file" then the entire platform crashes and makes me sign in again.
How can I navigate to plugins that I have created?
How are you getting the pluginId, instanceId and folderName? You cant simply save them or hard code them in. You need to initiate a dynamic data lookup see https://github.com/BuildFire/sdk/wiki/How-to-use-the-Datastore-Dynamic-Data
also you can look at an example such as the folder plugin https://github.com/BuildFire/folderPlugin/blob/d84551feb06cfc304c325480ca96d87795a66929/widget/widget.controller.js#L163
Basically every time a plugin is updated the plugin identifiers like folderName or title may change. So you need to keep your reference data fresh using dynamic data.
Here is a simple example that may draw a better picture. If you are referencing a plugin titled "Holiday Sales" so you save to your datastore collection {title: "Holiday Sales"} and hence forth refer to it by that title. This may work for a short period of time. However, if the app owner changes the title to "Summer Sale" now your copy is out-of-date. In traditional databases you would have 2 tables one with the source of truth and the other would have a foreign key referencing the first table. This way you join and always display the latest data.
Dynamic data is sort of an assisted lookup for you. You simply give it a key and what that key references. Then at run time when you make the call it will make the lookup you need server side and return to you the latest data you are looking for.
sample:
buildfire.datastore.save("MyData",{
_buildfire: { /// key identifier
myPluginsToNavTo: {
data:["123123-123123","asdasda-asdasd"] /// plugin instances
,dataType: "pluginInstance"
}
}
});
======
buildfire.datastore.getWithDynamicData("MyData",function(err,data){
// data would be:
/*
_buildfire: { /// key identifier
myPluginsToNavTo: {
data:["55f71347d06b61b4010351dc","asdasda-asdasd"]
,dataType: "pluginInstance"
,result: [ /// <=============new property added dynamically
{
"id": "55f71347d06b61b4010351dc",
"data": {
"pluginTypeId": 3212,
"token": "6372b101-addf-45da-bb0a-9208a09e7b6b",
"title": "YouTube Plugin",
"iconUrl": "http://s3-us-west-2.amazonaws.com/pluginserver/plugins/6372b101-addf-45da-bb0a-9208a09e7b6b/resources/image.png",
}
,{
"id": "asdasda-asdasd",
"data": {
"pluginTypeId": 123123,
"token": "1223123123-addf-45da-bb0a-9208a09e7b6b",
"title": "Plugin 2",
"iconUrl": "...",
}
}
}
]
}
}
*/
});
hope this helps

How to link/join multiple Lucene docs by AND operation

I am beginner to lucene. Now I am blocked because of a search issue. We are developing an API to use lucene as search engine for our application and have to make lot of queries with different conditions as joined.
We store many entities into lucene as individual documents.
Each entity comes as number of records and stored into lucene as individual docs. Added below a sample structure of data,
Serial no. 1 --> 16 are docs into lucene.
1) "id": "1","sendr_name": "**sender1**", "recip_name": "**recipient1**", "subject": "**subject1**"
2) "id": "1","attachment": "**attachment1**"
3) "id": "1","domain": "**domain1**", "ip": "ip1"
5) "id": "1","mid": "**mid1**"
6) "id": "1","type": "type1"
7) "id": "2","sendr_name": "sender1", "recip_name": "recipient1", "subject": "subject1"
8) "id": "2","attachment": "attachment2"
9) "id": "2","domain": "domain1", "ip": "ip2"
10) "id": "2","mid": "mid2"
11) "id": "2","type": "type2"
12) "id": "3","sendr_name": "sender1", "recip_name": "recipient3", "subject": "subject3"
13) "id": "3","attachment": "attachment3"
14) "id": "3","domain": "domain1", "ip": "ip3"
15) "id": "3","mid": "mid3"
16) "id": "3","type": "type3"
Note : serial no. 1-16 are documents for different entities and field "id" get generated internally , so id value cannot use as query value by user.
My need is to extract specific entity or entities on specific condition.
+sendr_name:sender1 + recip_name:recipient1 +subject:subject1 +attachment:attachment1 +domain:domain1 +mid:mid1
This is to get an entity info(1-6 docs for an entity).
But above query fails to return result because attachment, mid and domain in different docs.
Is there any way that we can span AND condition to multiple docs? or is there anyway that we can join query on a field like doc1.id = doc2.id?
I request you all to provide your suggestions or help to solve this issue.
First of all, with plain Lucene, its not recommended to store heterogeneous documents in same index as that can have multitude of other problems in long run and other infrastructure problems.
Go through this SO Answer. You better use other top level techs like SOLR or ElasticSearch for that matter which are better capable to handle scenario that you describe.
You have not shown any code so its not clear if you are using Java or .NET or Lucene API version.
I am using Lucene 6.0 with Java and I think, its achievable with - BooleanQuery as top level container.
public static BooleanQuery.Builder buildQuery(final SearchBean searchBean) {
BooleanQuery.Builder finalQuery = new BooleanQuery.Builder();
finalQuery.add(buildDoc1Query(searchBean).build(), Occur.SHOULD);
finalQuery.add(buildDoc2Query(searchBean).build(), Occur.SHOULD);
....
....
return finalQuery;
}
i.e. first you build queries for each entity type depending on what all needed to be searched. SearchBean is a POJO that has all the searchable fields for all doc types combined.
private static BooleanQuery.Builder buildDoc1Query(SearchBean searchBean ) {
BooleanQuery.Builder doc1MatchQuery = new BooleanQuery.Builder();
if (StringUtils.isNotEmpty(searchBean.getSender_name())) {
doc2MatchQuery.add(new BoostQuery(new TermQuery(new Term(AppConstants.SENDER_NAME, searchBean.getSender_name())), MatchingBooster.SENDER_NAME), BooleanClause.Occur.MUST);
}
if (StringUtils.isNotEmpty(searchBean.getRecip_name())) {
doc2MatchQuery.add(new BoostQuery(new TermQuery(new Term(AppConstants.RECIP_NAME, searchBean.getRecip_name()())), MatchingBooster.RECIP_NAME), BooleanClause.Occur.MUST);
}
....
....
return doc2MatchQuery;
}
StringUtils is coming from Apache Commons library.
AppConstants contains indexed field names.
What is important here is - BooleanClause.Occur.MUST in child queries and Occur.SHOULD in master and that way you group child queries into one master query.
So you will get something like - (+sendr_name:sender1 + recip_name:recipient1 +subject:subject1) (+attachment:attachment1) ....so on.
Above will give you doc1 & doc2.
You can remove boosting part in above sample code ( BoostQuery) and can directly use TermQuery.
Hope it helps and let me know if I misunderstood your requirement.

in a civicrm webform, create multiple 'groups' fields

In CiviCRM webform, you can 'enable tag and groups'. Configuring those allows you to create option elements in the webform.
This creates one 'widget', one dropdown or set of checkboxes. I have two field instances where I want the user to select a group - say for example
which mailing lists do you want to receive (a,b,c)
what food are you interested in (d,e,f)
a,b,c,d,e and f are all groups. I can not change that.
How could I do that ?
A technical suggestion below, but first, I'd suggest that your real solution is to not use groups for the second question. Groups are set up nicely to handle mailing lists, but if it's to track interests, you'd be better off setting those up as custom fields. It'll solve this immediate issue, and it'll make it easier to deal with tandem searches and so forth (on list b and likes food d).
Now if you must have them as groups, you can create a fake field and move checkboxes into it using jQuery. Create the fake field with one option that you don't care about, but label it "What food are you interested in", or equivalent. Then, edit the Groups field that CiviCRM generated: label it more specifically as "which mailing lists...", and choose Static Options so it doesn't start offering up just any group for someone to choose.
Now, add the following javascript:
// first remove the dummy checkboxes in your fake field
$('#yourdummyfield .form-item').each( function() { $(this).remove(); });
// now move things into the dummy field
$('#yourdummyfield').append( $('#groupsfield .form-item-d');
$('#yourdummyfield').append( $('#groupsfield .form-item-e');
$('#yourdummyfield').append( $('#groupsfield .form-item-f');
From the form processing perspective, they'll all be evaluated as the "groups" field. However, they'll look separate. For better or worse, this will have to be adjusted as you add new groups fields.
After using Andrew Hunts suggestion for a while, I finally solved this on the server side, in a custom module, using webform logic as described here
http://www.webomelette.com/drupal-webform-submission-presave-hook
Basicly, on presave, I look for 2 custom fields containing group ids (mailing and food in the example). Then I add these to the CiviCRM groups field.
I'll add the code below, which has some more logic:
to make it flexible, I use one hidden field to contain the fieldkey
of the civicrm groups selector to add the other fields in. that
field is called 'the_groups_element' (but its not the groups element, it contains the key of the groups element)
there is only one foods group allowed, so before it adds you to a food group, it removes all other food groups from the groups selector.
You could probably make it even more generic, but since I had different logic for the different groups, this was suitable for me.
function getFoodGroups() {
// return foodgroups
}
function getMailGroups() {
// return mailgroups
}
function MYMODULE_webform_submission_presave($node, &$submission) {
$groupselm = '';
$groups_cid = false;
$foods_cid = false;
$mailings_cid = false;
// http://www.webomelette.com/drupal-webform-submission-presave-hook
foreach($node->webform['components'] as $cid=>$comp) {
if ($comp['form_key']=='the_groups_element') {
$groupselm = $comp['value'];
break;
}
}
if ($groupselm) {
foreach($node->webform['components'] as $cid=>$comp) {
if ($comp['form_key']==$groupselm) $groups_cid = $comp['cid'];
if ($comp['form_key']=='the_foods') $foods_cid = $comp['cid'];
if ($comp['form_key']=='the_mailings') $mailings_cid = $comp['cid'];
}
$group_gids = $submission->data[$groups_cid];
if (!$group_gids) $group_gids=array();
if ($foods_cid!==false && $submission->data[$foods_cid]) {
// remove all current foods
foreach ($group_gids as $gidx=>$group_gid) {
foreach (getFoodGroups() as $foodgroup) {
if ($group_gid==$foodgroup['gid']) {
if ($debug) drupal_set_message('removing foodgroup '.$foodgroup['gid']);
unset($group_gids[$gidx]);
}
}
}
// validate and add submitted regions
$foodsgids = $submission->data[$foods_cid];
if (!is_array($foodsgids)) $foodsgids = array($foodsgids);
foreach ($foodsgids as $foodsgid) {
foreach (getFoodGroups() as $foodgroup) {
if ($foodsgid==$foodgroup['gid']) {
$group_gids[]=$foodsgid;
break; // only one food allowed
}
}
}
}
if ($mailings_cid!==false && $submission->data[$mailings_cid]) {
// just add submitted mailings, dont remove any
$mailinggids = $submission->data[$mailings_cid];
if (!is_array($mailinggids)) $mailinggids = array($mailinggids);
foreach ($mailinggids as $mailinggid) {
foreach (getMailGroups() as $mailing) {
if ($mailinggid==$mailing['gid']) {
if ($debug) drupal_set_message('adding mailing '.$mailing['gid']);
$group_gids[]=$mailinggid;
}
}
}
}
$submission->data[$groups_cid] = array_unique($group_gids);
}

CouchDB Views - emit Keys as JSON & filter based on any attribute

Consider following Employee document structure
{
"_id":...,
"rev":...,
"type":"Employee",
"fName":...,
"lName":...,
"designation":...,
"department":...,
"reportingTo":...,
"isActive":..,
more attributes
more attributes
}
And following map function in a View named "Employee"
function(doc) {
if (doc.type=="Employee") {
emit({
"EID":doc._id,
"FirstName":doc.fName,
"LastName":doc.lName,
"Designation":doc.designation,
"Department":doc.department,
"ReportingTo":doc.reportingTo,
"Active":doc.isActive
},
null
);
}
};
I want to query this view based on any combination & order of emitted attributes ( a query may include few random attributes may be like duck typing ). Is it possible? If so kindly let me know some samples or links.
Thanks
I've ran into the same problem a few times; you can, but you'll have to index each by itself (not all in one hash like you've done). But you could through the whole thing in the value for emit. It can be fairly inefficient, but gets the job done. (See this link: View Snippets)
I.e.:
function(doc) {
if (doc.type=="Employee") {
emit(["EID",doc.values.EID], doc.values);
emit(["FirstName", doc.fName], doc.values);
emit(["LastName", doc.lName], doc.values);
emit(["Designation", doc.designation], doc.values);
emit(["Department", doc.department], doc.values);
emit(["ReportingTo", doc.reportingTo], doc.values);
emit(["Active", doc.isActive], doc.values);
}
}
This puts all "EID" things in the same part of the tree, etc., I'm not sure if that is good or bad for you.
If you start needing a lot of functionality with [field name:]value searches, its probably worth it to move towards a Lucene-CouchDB setup. Several exist, but are a little immature.

Resources