How to shorten a conditional expression with Android Databinding - android-layout

I just want to make the following snippet shorter and more readable.
<LinearLayout android:visibility="#{ viewModel.prediction.intent == PredictionIntentType.MEETING_FOLLOWUP || (viewModel.prediction.intent == PredictionIntentType.FOLLOWUP && !viewModel.isMeetingViewGroupShown) || (viewModel.prediction.intent == PredictionIntentType.MEETING && viewModel.isMeetingViewGroupShown) ? View.VISIBLE : View.GONE }" />
When I do it multiline (see below) it won't compile
<LinearLayout
android:visibility="#{ viewModel.prediction.intent == PredictionIntentType.MEETING_FOLLOWUP
|| (viewModel.prediction.intent == PredictionIntentType.FOLLOWUP && !viewModel.isMeetingViewGroupShown)
|| (viewModel.prediction.intent == PredictionIntentType.MEETING && viewModel.isMeetingViewGroupShown)
? View.VISIBLE : View.GONE }" />
Ultimately, I just want it to look something like:
<LinearLayout android:visibility="#{ viewModel.someViewVisibility }" />
I'm using Java and viewModel.prediction is of type LiveData<Prediction> and viewmodel.isMeetingViewGroupShown is of type LiveData<Boolean> if that helps.

You should have all your logic in code files not in xml. So what you need is a boolean in your code file that looks something like this.
val visible = prediction.intent == PredictionIntentType.MEETING_FOLLOWUP
|| (prediction.intent == PredictionIntentType.FOLLOWUP && !isMeetingViewGroupShown)
|| (prediction.intent == PredictionIntentType.MEETING && isMeetingViewGroupShown
In your code file also add this method.
#BindingAdapter("visible")
fun bindVisible(linearLayout: LinearLayout, visible: Boolean) {
if(visible){
linearLayout.setVisibility(View.VISIBLE);
}else{
linearLayout.setVisibility(View.GONE);
}
}
In your xml add this to your linear layout
app:visible="#{viewModel.visible}

Ultimately, I just want it to look something like:
<LinearLayout android:visibility="#{ viewModel.someViewVisibility }" />
So do exactly that:
ViewModel:
val someViewVisibility: Int
#Bindable get() {
return if (prediction.intent == PredictionIntentType.MEETING_FOLLOWUP || (prediction.intent == PredictionIntentType.FOLLOWUP && !isMeetingViewGroupShown) || (prediction.intent == PredictionIntentType.MEETING && isMeetingViewGroupShown)) View.VISIBLE else View.GONE
}
With the property defined in your viewmodel, your simplified logic will work. Plus, now you can write a unit test for someViewVisibility and prove it works. :)
Hope that helps!

Related

Combining nested conditional logical operators

I was wondering if any can help point me to resource to teach me more about logical operators, and answer a question for me. I would like (for the sake of satisfying my curiosity) to combine these nested conditional checks with logical operators into one statement.
if(obj1 != null && obj2 != null) {
if(obj1 != undefined && obj2 != undefined) {
//do something here
}
}
I have tried
if((obj1 != null || obj1 != undefined) && (obj2 != null || obj2 != undefined)) {
//do something here
}
But I don't think that works, since if obj1 or obj2 is equal to null or undefined than the or statement will evaluate to true. So the above code in the conditional would be executed if obj1 was null or undefined AND obj2 was null or undefined, which is definitely not what I want.
So how could I combine the nested conditional into one line?
Thanks!
:)
You might be overthinking. Code like
if (a) {
if (b) {
// stuff
}
}
executes stuff only if a and b are both true, so it is simply equivalent to
if (a && b) {
// stuff
}
Thus all you have to do is take your existing conditions and connect them with &&. You can write
if((obj1 != null && obj2 != null) && (obj1 != undefined && obj2 != undefined)) {
//do something here
}

How do I open files in the most recently active Atom editor window instead of the Atom window I first opened?

Using Atom editor on Linux, I can't seem to find any option for opening files (using my file manager) in the most recent Atom window that was active. Instead, it always opens in the very first Atom window that was created.
How do I fix this?
There is an option for this:
-a, --add Open path as a new project in last used window. [boolean]
…but anyway, it does not work as expected. However, I`ve found a workaround.
This code is located somewhere around line 862 of src/main-process/atom-application.js:
if (existingWindow == null) {
if (currentWindow = window != null ? window : this.lastFocusedWindow) {
if (addToLastWindow || currentWindow.devMode === devMode && (stats.every(function(stat) {
return typeof stat.isFile === "function" ? stat.isFile() : void 0;
}) || stats.some(function(stat) {
return (typeof stat.isDirectory === "function" ? stat.isDirectory() : void 0) && !currentWindow.hasProjectPath();
}))) {
existingWindow = currentWindow;
}
}
}
Comment out the first line and its former closing bracket:
// if (existingWindow == null) {
if (currentWindow = window != null ? window : this.lastFocusedWindow) {
if (addToLastWindow || currentWindow.devMode === devMode && (stats.every(function(stat) {
return typeof stat.isFile === "function" ? stat.isFile() : void 0;
}) || stats.some(function(stat) {
return (typeof stat.isDirectory === "function" ? stat.isDirectory() : void 0) && !currentWindow.hasProjectPath();
}))) {
existingWindow = currentWindow;
}
}
// }
…aaaand voilà!
It`s a hackable text editor, after all ^_^

MD5 using Groovy in SoapUI

I created a test case which contains parameters that consist of key and value.
I need to take all those parameters in an alphabetic order, and then create a MD5 hash value which i will pass to one of the parameters of this test.
Any suggestions? i looked in google and cannot find anything helpful.
Thanks ahead!
You can retrieve the SoapUI's test case properties using a Groovy Script test step as given below.
def map = context.testCase.properties.keySet().inject([:]){map, key -> map[key] = context.testCase.getPropertyValue(key); map }
map.each { key, value -> log.info "Property name : ${key} and value : ${value}" }
Since you have the properties in map / key=value format, you should able to achieve what you are looking for.
Regarding md5 generation Refer here
import java.security.MessageDigest
def generateMD5_A(String s){
MessageDigest.getInstance("MD5").digest(s.bytes).encodeHex().toString()
}
I have done the following:
import java.security.MessageDigest
def testStep = testRunner.testCase.testSteps["3D Secure Call"]
def str = new StringBuilder();
for (prop in testStep.getPropertyList()){
if(prop.getName() != "K" && prop.getName() != "RawRequest" && prop.getName() != "Domain" && prop.getName() != "Password" && prop.getName() != "ResponseAsXml" && prop.getName() != "Request" && prop.getName() != "RawRequest" && prop.getName() != "Response" && prop.getName() != "Username" && prop.getName() != "Endpoint"){
str.append(prop.getName() + "=" + testStep.getPropertyValue(prop.getName()) + "&" )
}
}
str.append("K=1473942615907cuwmviz")
return (MessageDigest.getInstance("MD5").digest(str.bytes).encodeHex().toString())
I get the string exactly how i wish: M=10000330&PKey=8c124262b3d66f9e47185fd34eec13bbef2acd03170bcf8c284985193bc9a6&a4=50000&a5=EUR&XID=12345678912345678912&K=1473942615907cuwmviz
but now i need to apply the MD5, and i am getting an error. any suggestions?
No such property: bytes for class: java.lang.StringBuilder

Swift How can I check a variable for multiple string conditions

Currently I'm checking if a key in a dictionary contains a certain string values:
if dict["eventCode"] == "OFF" || dict["eventCode"] == "DHD" || dict["eventCode"] == "SBY"
{
// do something
}
else if dict["eventCode"] == "DHT" || dict["eventCode"] == "SLV" || dict["eventCode"] == "CLV"
{
// do something else
}
the list of possible values are about 10, the if statement is working but lengthy and prone to type errors.
What is the best way to refractor this kind of "if statement" ?
switch on String?
guard let val = dict["eventCode"] as? String else { return }
switch val {
case "OFF", "DHD", "SBY":
print("something")
case "DHT", "SLV", "CLV":
print("something else")
default:
print("default")
}
let check1 = ["OFF", "DHD", "SBY"]
let check2 = ["DHT", "SLV", "CLV"]
if check1.contains(dict["eventCode"] ?? "") {
print("found in 1")
} else if check2.contains(dict["eventCode"] ?? "") {
print("found in 2")
}
But in my opinion this looks ugly..
I usually use a switch statement:
switch dict["eventCode"] {
case let ec? where ec == "OFF" || ec == "DHD" || ec == "SBY":
// do something
case let ec? where ec == "DHT" || ec == "SLV" || ec == "CLV":
// do something else
default:
break
}
While it isn't necessarily less code than a series of if-else branches, I find the logic cleaner and easier to read.
EDIT:
#Eendje's answer is also very good, and could be combined with the switch:
let check1 = ["OFF", "DHD", "SBY"]
let check2 = ["DHT", "SLV", "CLV"]
switch dict["eventCode"] {
case let ec? where check1.contains(ec):
// do something
case let ec? where check2.contains(ec):
// do something else
default:
break
}

Test only if variable is not null in if statement

I have the following method where I want to test the event.status property only if status has been passed in:
def findEvent(String desc, String status = null, Collection events) {
return events.find {
it.description == desc && \\If status is not null: it.status == status
}
throw new Exception("Review Event Record Not Found: ${desc}")
}
I thought it could be done like this, but it doesn't seem to work:
def findEvent(String desc, String status = null, Collection events) {
return events.find {
it.description == desc && (status != null ?: {it.status == status})
}
throw new Exception("Review Event Record Not Found: ${desc}")
}
Is there any way this could be done? Or do I have to go back to something like this:
if (status != null) {
return events.find {
it.description == desc && it.status == status
}
} else if (status == null) {
return events.find {
it.description == desc
}
}
Is there some kind of best practice?
I don't believe the expression is sensical as it is.
Elvis means "if truthy, use the value, else use this other thing."
Your "other thing" is a closure, and the value is status != null, neither of which would seem to be what you want. If status is null, Elvis says true. If it's not, you get an extra layer of closure.
Why can't you just use:
(it.description == desc) && ((status == null) || (it.status == status))
Even if that didn't work, all you need is the closure to return the appropriate value, right? There's no need to create two separate find calls, just use an intermediate variable.

Resources