msbuild task conditional operators in parameter value - msbuild

Is there any way how to use conditional variables as parameters when calling MSBuild tasks?
for example, if we have text being string argument in MySampleTask msbuild task:
<MySampleTask text="if a not empty ? a : b" />
How to pass text string variable if we may have 2 local string variables a and b? How to achieve behavior in above code?

I'm not aware of such operator, but what you want is equivalent to
<MySampleTask text="$(a)" Condition="'$(a)' != ''" />
<MySampleTask text="$(b)" Condition="'$(a)' == ''" />
Or, same principle but applied to a property first; probably the most 'standard' way:
<PropertyGroup>
<a Condition="'$(a)' == ''">$(b)</a>
</PropertyGroup>
<MySampleTask text="$(a)" />

Related

Mapbox: Error setting property: icon-image [2] Branch labels must be numbers or strings

I'm trying to use the match() Expression from Mapbox's Android SDK 9.0.0 with a list of ids. But I'm getting the following error at runtime:
"Error setting property: icon-image [2] Branch labels must be numbers or strings."
I am coding in Kotlin.
To isolate the essence of the problem, I'm trying to pass match() an array of a single String element using the arrayOf() operator:
match(get(KEY_ID), literal(arrayOf("134")), appearanceIfSelected, appearanceIfNotSelected)
The code above didn't work though and gave the error above. The following code that used arrayListOf() also failed:
match(get(KEY_ID), literal(arrayListOf(pois!!.first().id)), appearanceIfSelected, appearanceIfNotSelected)
listOf() also failed:
match(get(KEY_ID), literal(listOf(pois!!.first().id)), appearanceIfSelected, appearanceIfNotSelected)
Wrapping in array() failed too:
match(get(KEY_ID), array(literal(listOf("134"))), appearanceIfSelected, appearanceIfNotSelected)
I have been wrapping in literal() because the following won't even compile:
match(get(KEY_ID), arrayOf("134"), appearanceIfSelected, appearanceIfNotSelected)
As a workaround, I replaced match() with any() and passed a variable number of arguments using the Kotlin spread operator "*"
val eqPOIIdExpressions = arrayOf(eq(get(KEY_ID), "134"))
// The * operator below converts the Array<Expression> into varargs for any
// see https://proandroiddev.com/kotlins-vararg-and-spread-operator-4200c07d65e1
switchCase(
any(*eqPOIIdExpressions), appearanceIfSelected,
appearanceIfNotSelected
)
Once I got that working, I went ahead and added all the array elements:
val eqPOIIdExpressions = pois!!.map {
eq(get(KEY_ID), it.id)
}.toTypedArray()

modifiers within false conditions

Sorry of this has been asked before, but I can't find it.
Why does the following fail with
Uncaught --> Smarty Compiler: Syntax error in template
"/home/ezms/public_html_subs/dev4/design/backend/templates/index.tpl"
on line 31 "{""|foo }" unknown modifier "foo"
{if false} {""|foo} {/if}
I have certain code conditionally included I.e.
{if $x_enabled} {
function foo() {
return "hello";
}
}
I would expect that if the smarty IF condition did not evaluate to true that the modifier would not be executed. Where am I going wrong?
Smarty is a compiler and uses a lexer to convert its code syntax into PHP. Then Smarty has PHP execute the code.
When compiling, it will fault on the unrecognized modifier. If the modifier was recognized, the lexer would convert that to a real function (based on what the plugin does) -- for example, foo(""). Being a modifier plugin, you are free to make the plugin do much more work deemed necessary, even if the result of any action on the argument is not used.
Then...
The compiled PHP code would be something like:
if(false){$smarty_user_functions->foo("");}
If the compile is successful, Smarty then has PHP execute that code, where PHP employs its own optimizing algorithms converting the human-readable script to token/opcode/bytecode. If when PHP runs this code, it will decide what to do on a false condition.
You should add your foo modifier function in smarty plugin directory (https://www.smarty.net/docs/en/plugins.modifiers.tpl)
file would have a name modifier.foo.php
and contain code:
function smarty_modifier_foo()
{
return 'hello';
}
then, your code {if false} {""|foo} {/if} in template will works.

Is it possible to modify the original collection in foreach inside loop?

I want to mimick this:
for (int i = 0; i < items.getTotal(); i++) {
// ....
items = // new items get assigned.
}
Is it possible with foreach component?
I think you will better of using a collection-splitter and a collection-aggregator which will modify the original payload.
<collection-splitter />
<set-payload value="do something" />
<collection-aggregator />
Alternatively, if you must use foreach, you could use a flowVar to keep track of the items and the set the payload to the flowVar after the foreach:
<set-variable variableName="items" value="#[[]]" />
<foreach>
<set-payload value="do something" />
<expression-component>flowVars.items.add(payload)</expression-component>
</foreach>
<set-payload value="#[flowVars.items]" />
A workaround:
Outside the foreach:
Set a session variable X to the content of the linkedlist thru which
you want to loop.
All my MS JDBC 4.1 stored procedure calls return 1-n hashmaps with key=resultSetx and value of a linkedlist. Each occurrence in the linkedlist is another hashmap containing a 1 row's worth of resultset pairs (key=value) - so we run into this a lot.
At the foreach top level:
Set the payload collection reference to the payload which contains
the linkedlist. Reminder: (The default counter flowVar starts
at 1. Linkedlist offsets begin at 0.)
Inside the foreach:
Set another variable (ctr-1) equal to counter - 1; if you don't it
can make some ugly and difficult MEL with those counter -1
references).
Point your list inserts at the session variable X linkedlist.
After completion of foreach:
- Don't forget to remove the redundant list it wastes space.
Cheers-MPC:-)

2 tasks inside a msbuild loop

I'm trying to achieve something like this:
<ItemGroup>
<Projects Include="projectpath1"/>
<Projects Include="projectpath2"/>
...
<ItemGroup/>
// foreach project {
<GetCss Project=%Project.Identity CssOutputs=#CssFiles/>
<MergeCss CssInputs=#CssFiles CssOutputFile="test.css"/>
// } execute GetCss then MergeCss foreach project
GetCss and MergeCss are custom inline tasks.
I don't want:
// foreach project {
<GetCss Project=%Project.Identity CssOutputs=#CssFiles/>
// }
// foreach project {
<MergeCss CssInputs=#CssFiles CssOutputFile="test.css"/>
// }
Thanks in advance for your help.
Based on your code, it looks like you'd want to perform target batching so that you could call both of the inline tasks for each of your Projects items. Here's an example of a batched target named GetAndMergeCss, with the assumption that your GetCss inline task takes a string for an input and the CssFiles listed for CssOuputs are MSBuild items to be consumed by your MergeCss inline task:
<ItemGroup>
<Projects Include="projectpath1"/>
<Projects Include="projectpath2"/>
</ItemGroup>
<Target Name="GetAndMergeCss" Outputs="%(Projects.Identity)">
<PropertyGroup>
<ThisProjectIdentity>%(Projects.Identity)</ThisProjectIdentity>
</PropertyGroup>
<Message Text="Preparing to get and merge css for project: $(ThisProjectIdentity)" />
<GetCss Project="$(ThisProjectIdentity)" CssOutputs="#(CssFiles)"/>
<!--Or this works too...<GetCss Project="%(Projects.Identity)" CssOutputs="#(CssFiles)"/>-->
<MergeCss CssInputs="#(CssFiles)" CssOutputFile="test.css"/>
</Target>

Velocity: Is a any way to check if variable is defined

I want to include one template nested into others cont1, cont2, cont3.
And nested template should be hide one specific control for cont1 only.
Before inclusion into cont1 I would like to assign value to some flag variable $hideMyControl.
And inside nested template I would like to check if $hideMyControl is assigned value.
How to perform such check?
#if($hideMyControl)
// your code
#end
If $hideMyControl is defined, your code will execute
You can do this using
#if($!{$articleLeader})
// Perform your operation or the template part you want to show.
#end
For more info, see the 'formal reference' section of the Apache Velocity Reference Manual.
#if($!{hideMyControl} != "")
## do something if $hideMyControl is defined
#end
This works for me in AWS API Gateway Body Mapping Templates. Please refer to Quiet Reference Notation in Velocity User Guide for more information.
I was using
#if ($hideMyControl)
//do something
#end
since a few months ago,
however today its not working anymore.
I came here to find help, and noticed a new way of writing it :
#if($!{$hideMyControl})
// do something
#end
this code works!
According to the docs for Strict Reference Mode it is possible to several constructions to check if variable is defined.
#if ($foo)#end ## False
#if ( ! $foo)#end ## True
#if ($foo && $foo.bar)#end ## False and $foo.bar will not be evaluated
#if ($foo && $foo == "bar")#end ## False and $foo == "bar" wil not be evaluated
#if ($foo1 || $foo2)#end ## False $foo1 and $foo2 are not defined
So this code works in my case.
#if( !$value )
// Perform your operation or the template part you want to show.
#end
To check if $hideMyControl is in Velocity context and IS NOT boolean 'true' value (or 'false' as well):
#if ($hideMyControl && $hideMyControl != true)
##do stuff
#end
Sure, if you really use your $hideMyControl variable as boolean type, you don't need second part of condition.