Is possible to access $loader variable I see in the debug window? - java

As you can see in this screenshot while I'm in debug mode i can see a $loader variable that has the "() -> com.belandsoft.orariGTT.Model.RestRequestResponse, kotlin.Boolean>" content. It's possible to access these value at runtime in any way? The reflection can be helpfull in any way?
Sample code:
val mCollection: kotlin.collections.HashMap<Int, () -> Unit> = HashMap()
fun <T> myAddFunction(loader: () -> T) {
val elementCode = loader?.hashCode()
if (elementCode != null) {
mCollection[elementCode] = loader
}
}
fun myPrintFunction(): String {
val stringBuilder = StringBuilder()
var index = 0
for (i in mCollection.iterator()) {
stringBuilder.append("$index:[${i.value}] ")
index++
}
stringBuilder.toString()
}
This sadly produces a string like:
"053523:[()->kotlin.Unit], 453455:[()->kotlin.Unit]"
but I want to have:
"053523:[()->com.belandsoft.orariGTTView.MainFragment$startPtArrivalSearch$2$18839], 453455:[()->com.belandsoft.orariGTTView.MainFragment$startPtArrivalSearch$2$18845]"
Thanks.

Related

Screen is not responding as I set a result to another edit text when using RxJava

I'm implement an TextInputEditText with RxBinding.
Problem: When I do some math operation on first TextInputEditText and set the result to another TextInputEditText, The screen is not responding. When I start to type another digit, its not displayed in the edit text. I know why this happened, but don't know how to fix. For more detail, please check the code below.
Code:
class NumberSystemFragment : Fragment() {
override fun onCreateView() { ... }
override fun onViewCreated() {
binding?.run {
// It still ok if just observe a single edit text
etBinary.observeInput().subscribe {
val dec = it.fold(0L) { acc, el ->
(acc * 2) + el.digitToInt(radix = 2)
}
val oct = dec.toString(8)
val hex = dec.toString(16)
etDecimal.setText(dec.toString())
etOctal.setText(oct)
etHexadecimal.setText(hex)
}
// But, when I add more EditText, the screen will not responding.
// I know why this can happen, because when I set the result from operation above,
// and display it to another EditTexts, then the other EditText will begin to observe its input too.
// Then the racing condition or whatever it is, will occur.
etDecimal.observeInput().subscribe {
val bin = it.toLong().toString(2)
val oct = it.toLong().toString(8)
val hex = it.toLong().toString(16)
etBinary.setText(bin)
etOctal.setText(oct)
etHexadecimal.setText(hex)
}
}
}
private fun <T : EditText> T.observeInput() =
RxTextView.textChanges(this)
.skipInitialValue()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.map(CharSequence::toString)
.publish()
.refCount()
}
Sorry, I'm new with RxJava, RxBinding, etc.
Two issues.
You have created a feedback loop by setting text on the other editors, which then trigger updates on the current editor.
If your code crashes, it will stop listening to values.
First of all, make these extension method changes:
private fun <T: EditText> T.observeInput() =
RxTextView.textChanges(this)
.skipInitialValue()
.map(CharSequence::toString) // <------------------ order matters
.distinctUntilChanged() // <----------------------- order matters
.observeOn(AndroidSchedulers.mainThread())
.publish()
.refCount()
private fun TextInputEditText.setText(text: CharSequence, onlyIfChanged: Boolean) {
if (onlyIfChanged) {
if (Objects.equals(this.text.toString(), text.toString())) {
return;
}
}
this.setText(text);
}
Then, update your onNext handlers:
// etBinary
// store calculation data
try {
Log.d("XYZ-etBinary", t);
val decResult = t.fold(0L) { acc, element ->
(acc * 2) + element.digitToInt(2)
}
val octResult = decResult.toString(8)
val hexResult = decResult.toString(16).uppercase()
// and display the results to another edit text which corresponds with their radix representation
etDecimal.setText(decResult.toString(), true)
etOctal.setText(octResult, true)
etHexadecimal.setText(hexResult, true)
} catch (e: Throwable) {
Log.e("XYZ-etBinary", e.message.toString())
}
// etDecimal
// store calculation data
try {
Log.d("XYZ-etDecimal", t);
val binResult = t.toLong().toString(2)
val octResult = t.toLong().toString(8)
val hexResult = t.toLong().toString(16).uppercase()
// and display the results to another edit text which corresponds with their radix representation
etBinary.setText(binResult, true)
etOctal.setText(octResult, true)
etHexadecimal.setText(hexResult, true)
} catch (e: Throwable) {
Log.e("XYZ-etDecimal", e.message.toString())
}
Also posted it as a Pull Request on your repo: https://github.com/dansampl/EditTextWithRxJavaSampleApp/pull/1/files

How to get value of KProperty1

I have an object
I try to get access to field "english"
val englishSentence = dbField::class.declaredMemberProperties.filter { it.name == "english" }[0]
But when I
model.addAttribute("sentence", englishSentence)
I get val com.cyrillihotin.grammartrainer.entity.Sentence.english: kotlin.String
while I expect bla
You can use the call function on a KProperty to get its value from the object.
val dbField = Sentence(1, "bla-eng", "bla-rus")
val value = dbField::class.declaredMemberProperties.find { it.name == "english" }!!.call(dbField)
println(value)
Output: bla-eng
Remember that data type of value is Any here. You need to cast it manually to the desired data type.
If you want to list all the properties with their values, you can do this:
dbField::class.declaredMemberProperties.forEach {
println("${it.name} -> ${it.call(dbField)}")
}
Output:
english -> bla-eng
id -> 1
russian -> bla-rus
Do you mean this?
data class Sentence(val id:Int, val english:String, val russian:String)
val dbField = Sentence(1, "blaEng", "blaRus")
val englishProp = dbField::class.declaredMemberProperties.first { it.name == "english" }as KProperty1<Sentence, String>
println(englishProp.get(dbField))
It prints blaEng

Scala udf UnsupportedOperationException

I have a dataframe a2 written in scala :
val a3 = a2.select(printme.apply(col(“PlayerReference”)))
the column PlayerReference contains a string.
that calls an udf function :
val printme = udf({
st: String =>
val x = new JustPrint(st)
x.printMe();
})
this udf function calls a java class :
public class JustPrint {
private String ss = null;
public JustPrint(String ss) {
this.ss = ss;
}
public void printMe() {
System.out.println("Value : " + this.ss);
}
}
but i have this error for the udf :
java.lang.UnsupportedOperationException: Schema for type Unit is not supported
The goal of this exercise is to validate the chain of calls.
What should I do to solve this problem ?
The reason you're getting this error is that your UDF doesn't return anything, which, in terms of spark is called Unit.
What you should do depends on what you actually want, but, assuming you just want to track values coming through your UDF you should either change printMe so it returns String, or the UDF.
Like this:
public String printMe() {
System.out.println("Value : " + this.ss);
return this.ss;
}
or like this:
val printme = udf({
st: String =>
val x = new JustPrint(st)
x.printMe();
x
})

How to convert java 8 map, filter and streams to scala?

I am very new to scala trying to understand by changing the equivalent java to scala so that I get better understanding.
How to convert java 8 map, filter and streams to scala ?
I have the following java 8 code which I am trying to convert to Scala :
public Set<String> getValidUsages(String itemId, long sNo, Date timeOfAccess) {
Set<String> itemSet = Sets.newHashSet();
TestWindows testWindows = items.get(itemId).getTestWindows();
final boolean isTV = existsEligibleTestWindow(testWindows.getTV(), timeOfAccess);
if (isTV) {
itemSet.add(TV);
} else {
final boolean isCableUseable = existsEligibleTestWindow(testWindows.getCableUse(), timeOfAccess);
final boolean isWifi = existsEligibleTestWindow(testWindows.getWifi(), timeOfAccess);
if (isCableUseable || isWifi) {
itemSet.add(MOVIE);
}
}
if (testWindows.getUsageIds() != null) {
itemSet.addAll(testWindows.getUsageIds()
.entrySet()
.stream()
.filter(entry -> existsEligibleTestWindow(entry.getValue(), timeOfAccess))
.map(Map.Entry::getKey)
.collect(Collectors.toSet()));
}
return itemSet;
}
private boolean existsEligibleTestWindow(List<TestWindow> windows, Date timeOfAccess) {
if (windows != null) {
return windows.stream()
.filter(w -> withinDateRange(timeOfAccess, w))
.findAny()
.isPresent();
}
return false;
}
private boolean withinDateRange(Date toCheck, TestWindow window) {
return toCheck.after(window.getStartTime()) && toCheck.before(window.getEndTime());
}
I tried :
def withinDateRange(toCheck: Date, window: TestWindow): Boolean = {
toCheck.after( window.getStartTime ) && toCheck.before( window.getEndTime )
}
def getValidUsages(itemId: String, sNo: Long, timeOfAccess: Date): Set[String] = {
var itemSet = Sets.newHashSet()
val testWindows = items.value(itemId).getTestWindows
val isTV = existsEligibleTestWindow(testWindows.get(0).getTV, timeOfAccess)
if (isTV) {
itemSet += TV
} else {
val isCableUseable = existsEligibleTestWindow(testWindows.get(0).getCableUse, timeOfAccess)
val isWifi = existsEligibleTestWindow(testWindows.get(0).getWifi, timeOfAccess)
if (isCableUseable || isWifi) {
itemSet += MOVIE
}
}
if (testWindows.get(0).getUsageIds != null) {
itemSet.addAll(testWindows.get(0).getUsageIds.entrySet().stream()
.filter((x) => existsEligibleTestWindow(x._2, timeOfAccess)).map(x => Map.Entry._1 )
.collect(Collectors.toSet()))
}
itemSet
}
def existsEligibleConsumptionWindow(windows: List[ConsumptionWindow], timeOfAccess: Date): Boolean = {
if (windows != null) {
return windows.exists((x) => withinDateRange(timeOfAccess, x))
}
false
}
But getting error while doing filter and stream. Can some one point to direct direction ? Any references ? I am getting error on getValidUsages :
compile error “cannot resolve reference project with such signature
This is somewhat difficult to answer since I am unfamiliar with some of the types you use. But if I guess there are types like the following:
trait Window {
def getStartTime: LocalDate
def getEndTime: LocalDate
}
trait TestWindows extends Window {
def getTV: List[Window]
def getCableUse: List[Window]
def getWifi: List[Window]
def getUsageIds: Map[String, List[Window]]
}
then you could just do this:
def withinDateRange(toCheck: LocalDate)(window: Window): Boolean =
window.getStartTime.isBefore(toCheck) && window.getEndTime.isAfter(toCheck)
// Nothing should ever be null in Scala. If it's possible you don't have any ConsumptionWindows you should either
// model it as an empty list or an Option[List[ConsumptionWindow]]
def existsEligibleTestWindow(windows: List[Window],
timeOfAccess: LocalDate): Boolean =
windows.exists(withinDateRange(timeOfAccess))
def getValidUsages(testWindows: TestWindows, timeOfAccess: LocalDate): Set[String] = {
val isTV = existsEligibleTestWindow(testWindows.getTV, timeOfAccess)
val isCableUse = existsEligibleTestWindow(testWindows.getCableUse, timeOfAccess)
val isWifi = existsEligibleTestWindow(testWindows.getWifi, timeOfAccess)
val tvOrMovie: Option[String] = if (isTV) Some("TV")
else if (isCableUse || isWifi) Some("MOVIE")
else None
val byUsageId = testWindows.getUsageIds.collect { case (key, windows) if existsEligibleTestWindow(windows, timeOfAccess) => key }.toSet
tvOrMovie.toSet ++ byUsageId
}
In your original code there was presumably some items value, but in the above I just assume you do TestWindows testWindows = items.get(itemId).getTestWindows() outside the getValidUsages function.
My example doesn't use java structures at all and just uses the scala core collections. The other main difference is that I use immutable data structures which is, I think, a little easier to follow and generally safer.
Some items of note:
1) The Option.toSet operation result in an empty set when called upon a None.
2) There is an example of function currying used for the withinDateRange method.
3) I obviously have no idea what your original types do and had to guess at the relevant parts.
The problem seems to be that you are using Java types in Scala while depending on scala's map & filter operations. This has its own troubles but if you convert the list/collections to a Scala's collections first (warning, Scala types are immutable by default), then you should be able to just use the map/filter operations without having to call java's stream() method.
def getValidUsages(itemId: String, sNo: long, timeOfAcess: Date): Set[String] = {
var itemSet: Set[String] = Sets.newHashSet()
val testWindows: TestWindows = items.get(itemId).getTestWindows()
val isTV: Boolean = existsEligibleTestWindow(testWindows.getTV(), timeOfAccess)
isTV match {
case true => itemSet.add(TV)
case false => {
val isCableUseable: Boolean = existsEligibleTestWindow(testWindows.getCableUse(), timeOfAcess)
val isWifi: Boolean = existsEligibleTestWindow(testWindows.getWifi(), timeOfAccess)
if(isCableUseable || isWifi) {
itemSet.add(MOVIE)
}
}
}
if(testWindows.getUsageIds() != null) {
itemSet.addAll(testWindows.getUsageIds()
.stream.
.filter(entry => existsEligibleTestWindow(entry._2, timeOfAccess))
.map(filteredData => Map.Entry._1)
.collect Collectors.toSet())
}
itemSet
}
def existsEligibleTestWindow(windows: List[TestWindow], timeOfAcess: Date): Boolean = {
windows match {
case null => false
case _ => windows.stream.filter(data => withinDateRange(timeOfAcess), data).findAny().isPresent
}
}
Good luck :)

Why does my fork/join deadlock?

Consider the following snipped of code, which calculates the size of all paths given.
def pathSizes = []
paths.each { rootPath ->
pathSizes.addAll(
withPool { pool ->
runForkJoin(rootPath) { path ->
def headSizes = [:]
println path
def lines = ["ls", "-al", path].execute().text.readLines()
(0..<3).each { lines.remove(0) }
lines.each { line ->
def fields = line.split(/\s+/)
if (fields[0] =~ /^d/)
forkOffChild("$path/${fields.last()}")
else {
def userName = fields[2]
def fileSize = fields[4] as long
if (headSizes[userName] == null)
headSizes[userName] = fileSize
else
headSizes[userName] += fileSize
}
}
quietlyJoin()
System.gc()
def shallowSizes =
headSizes.collectEntries { userName, fileSize ->
def childResult =
childrenResults.sum {
it.shallowSizes[userName] ? it.shallowSizes[userName] : 0
} ?: 0
return [userName, fileSize + childResult]
}
def deepSizes =
childrenResults.sum { it.deepSizes ?: [] } +
shallowSizes.collect { userName, fileSize ->
[userName: userName, path: path, fileSize: fileSize]
}
return [shallowSizes: shallowSizes, deepSizes: deepSizes]
}.deepSizes
})
}
Why does this snippet of code deadlock? There are no interactions between threads except possibly with the system call and other parts of the Java framework. If the system calls are the problem, then how can I fix it, without removing the system calls (they are slow, hence the need to parallelize)?

Categories

Resources