displaying different messages depending on parameters

I’m new to android development. I have 10 different buttons and I want to display a toast for each one of them. The message is something like:

“This is the button: ” + numButton

Where numButton is a prop passed to the function. This is the function code:

public void displayMensaje(View v) {
        Toast.makeText(ActividadUno.this, "Test", Toast.LENGTH_SHORT).show();
    }

And this is the xml:

<Button
        android:id="@+id/button11"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="30dp"
        android:layout_marginLeft="30dp"
        android:layout_marginTop="400dp"
        android:text="churro"
        android:onClick="displayMensaje"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

Solution:

You can cast the View in Button and get the text of button.

Something like this:

public void displayMensaje(View v) {
    Button button = (Button) v;
    String title = button.getText();
    String message = "Test " + title;
    Toast.makeText(ActividadUno.this, message, Toast.LENGTH_SHORT).show();
}  

Edit:
According to my understanding from your comment below, you have multiple buttons in your activity, and you want to display different values on clicking different buttons.

You can have a Map with keys as button titles and values as nutrition values.

Below is a general example of how you can achieve this:

public class MyActivity extends Activity {
    // Your Message Format
    private static final String MSG_FORMAT = "Item Name: %s\n"
            + "Fat: %s\n"
            + "Protein: %s\n"
            + "Calories: %s";

    // A Map to hold info of all items
    // Key = button title
    // Value = Array containing item info
    private Map<String, String[]> info = new HashMap();

    // Assuming you have 3 buttons in your activity
    private Button btnMilk;
    private Button btnEggs;
    private Button btnChicken;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.my_activity);

        btnMilk = (Button) findViewById(R.id.btn_milk);
        btnEggs = (Button) findViewById(R.id.btn_eggs);
        btnChicken = (Button) findViewById(R.id.btn_chicken);

        // 0 = Fat, 1 = Protein, 2 = Calories
        String[] milkInfo = new String[]{"12", "20", "125"};
        String[] eggsInfo = new String[]{"10", "50", "205"};
        String[] chickenInfo = new String[]{"50", "5", "500"};

        // load your Map with the data
        info.put(btnMilk.getText(), milkInfo);
        info.put(btnEggs.getText(), eggsInfo);
        info.put(btnChicken.getText(), chickenInfo);

    }

    public void displayMessage(View v) {
        Button button = (Button) v;

        String title = button.getText();

        // Get item info from your Map
        String[] itemInfo = info.get(title);

        // Create message using the format and values from the array
        String message = String.format(MSG_FORMAT, title, itemInfo[0], itemInfo[1], itemInfo[2]);

        Toast.makeText(MyActivity.this, message, Toast.LENGTH_SHORT).show();
    }
}

Hope this helps

Advertisements

Regex for partial path

I have paths like these (single lines):

/
/abc
/def/
/ghi/jkl
/mno/pqr/
/stu/vwx/yz
/abc/def/ghi/jkl

I just need patterns that match up to the third “/”. In other words, paths containing just “/” and up to the first 2 directories. However, some of my directories end with a “/” and some don’t. So the result I want is:

/
/abc
/def/
/ghi/jkl
/mno/pqr/
/stu/vwx/
/abc/def/

So far, I’ve tried (\/|.*\/) but this doesn’t get the path ending without a “/”.

Solution:

^((\/([^/]+){0,2}\/?)

To break it down

  • ^ is the start of the string

  • {0,2} means repeat the previous between 0 and 2 times.

  • Then it ends with an optional slash by using a ?

  • String end is $ so it doesn’t match longer strings.

  • () Around the whole thing to capture it.

But I’ll point out that the is almost always the wrong answer for directory matching. Some directories have special meaning, like /../.. which actually goes up two directories, not down. Better to use the systems directory API instead for more robust results.

How to append values from XML to TestNG emailable HTML report using xslt

I just have some dynamic XML file which has values like below:

 <testCaseId>CSPDDataObject [testCaseId=US_KINDLE_22, description=RISK with AUTH-fulfillment phase]</testCaseId>
 <message>Some logger details</message>
 <exception>java.lang.AssertionError: expected [true] but found [false]</exception>

The complete XML structure:

 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <FailedDetails>
    <FailedMessage>
        <testCaseId>US_KINDLE_TC1</testCaseId>
        <message> some logger</message>
        <exception>java.lang.AssertionError: expected [true] but found [false]
        </exception>
     </FailedMessage>
     <FailedMessage>
        <testCaseId>US_KINDLE_TC2</testCaseId>
        <message> some logger</message>
        <exception>java.lang.AssertionError: expected [true] but found [false]
        </exception>
    </FailedMessage>
       ......(n) (It repeats 'n' times)
  </FailedDetails>

I just want to append this values into existing testNG emailable report in the below tags:

 <h3> </h3><table> <tr> <td> need to append the above one with respective tag value</td></tr></table>

Screenshot:

enter image description here
This is the sample snapshot for existing html view. I just want to add the xml values next to this tags.

Sample Emailable report:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>TestNG Report</title><style type="text/css">table {margin-bottom:10px;border-collapse:collapse;empty-cells:show}th,td {border:1px solid #009;padding:.25em .5em}th {vertical-align:bottom}td {vertical-align:top}table a {font-weight:bold}.stripe td {background-color: #E6EBF9}.num {text-align:right}.passedodd td {background-color: #3F3}.passedeven td {background-color: #0A0}.skippedodd td {background-color: #DDD}.skippedeven td {background-color: #CCC}.failedodd td,.attn {background-color: #F33}.failedeven td,.stripe .attn {background-color: #D00}.stacktrace {white-space:pre;font-family:monospace}.totop {font-size:85%;text-align:center;border-bottom:2px solid #000}</style></head><body><table><tr><th>Test</th><th># Passed</th><th># Skipped</th><th># Failed</th><th>Time (ms)</th><th>Included Groups</th><th>Excluded Groups</th></tr><tr><th colspan="7">TransferMoney-Suite</th></tr><tr><td><a href="#t0">KindleReaderTest</a></td><td class="num">41</td><td class="num">0</td><td class="num attn">17</td><td class="num">10,316,154</td><td></td><td></td></tr><tr class="stripe"><td><a href="#t1">Suite setup and teardown</a></td><td class="num">0</td><td class="num">0</td><td class="num">0</td><td class="num">2,521</td><td></td><td></td></tr><tr><th>Total</th><th class="num">41</th><th class="num">0</th><th class="num attn">17</th><th class="num">10,318,675</th><th colspan="2"></th></tr></table><table><thead><tr><th>Class</th><th>Method</th><th>Start</th><th>Time (ms)</th></tr></thead><tbody><tr><th colspan="4">TransferMoney-Suite</th></tr></tbody><tbody id="t0"><tr><th colspan="4">KindleReaderTest — failed</th></tr><tr class="failedeven"><td rowspan="17">com.amazon.e2e.device.os22</td><td><a href="#m0">KindleReaderTest</a></td><td rowspan="17">1540236982369</td><td rowspan="17">116625</td></tr><tr class="failedeven"><td><a href="#m1">KindleReaderTest</a></td></tr><tr class="failedeven"><td><a href="#m2">KindleReaderTest</a></td></tr><tr class="failedeven"><td><a href="#m3">KindleReaderTest</a></td></tr><tr class="failedeven"><td><a href="#m4">KindleReaderTest</a></td></tr><tr class="failedeven"><td><a href="#m5">KindleReaderTest</a></td></tr><tr class="failedeven"><td><a href="#m6">KindleReaderTest</a></td></tr><tr class="failedeven"><td><a href="#m7">KindleReaderTest</a></td></tr><tr class="failedeven"><td><a href="#m8">KindleReaderTest</a></td></tr><tr class="failedeven"><td><a href="#m9">KindleReaderTest</a></td></tr><tr class="failedeven"><td><a href="#m10">KindleReaderTest</a></td></tr><tr class="failedeven"><td><a href="#m11">KindleReaderTest</a></td></tr><tr class="failedeven"><td><a href="#m12">KindleReaderTest</a></td></tr><tr class="failedeven"><td><a href="#m13">KindleReaderTest</a></td></tr><tr class="failedeven"><td><a href="#m14">KindleReaderTest</a></td></tr><tr class="failedeven"><td><a href="#m15">KindleReaderTest</a></td></tr><tr class="failedeven"><td><a href="#m16">KindleReaderTest</a></td></tr><tr><th colspan="4">KindleReaderTest — passed</th></tr><tr class="passedeven"><td rowspan="41">com.amazon.e2e.device.os22</td><td><a href="#m17">KindleReaderTest</a></td><td rowspan="41">1540241421467</td><td rowspan="41">218092</td></tr><tr class="passedeven"><td><a href="#m18">KindleReaderTest</a></td></tr><tr class="passedeven"><td><a href="#m19">KindleReaderTest</a></td></tr><tr class="passedeven"><td><a href="#m20">KindleReaderTest</a></td></tr><tr class="passedeven"><td><a href="#m21">KindleReaderTest</a></td></tr><tr class="passedeven"><td><a href="#m22">KindleReaderTest</a></td></tr><tr class="passedeven"><td><a href="#m23">KindleReaderTest</a></td></tr><tr class="passedeven"><td><a href="#m24">KindleReaderTest</a></td></tr><tr class="passedeven"><td><a href="#m25">KindleReaderTest</a></td></tr><tr class="passedeven"><td><a href="#m26">KindleReaderTest</a></td></tr><tr class="passedeven"><td><a href="#m27">KindleReaderTest</a></td></tr><tr class="passedeven"><td><a href="#m28">KindleReaderTest</a></td></tr><tr class="passedeven"><td><a href="#m29">KindleReaderTest</a></td></tr><tr class="passedeven"><td><a href="#m30">KindleReaderTest</a></td></tr><tr class="passedeven"><td><a href="#m31">KindleReaderTest</a></td></tr><tr class="passedeven"><td><a href="#m32">KindleReaderTest</a></td></tr><tr class="passedeven"><td><a href="#m33">KindleReaderTest</a></td></tr><tr class="passedeven"><td><a href="#m34">KindleReaderTest</a></td></tr><tr class="passedeven"><td><a href="#m35">KindleReaderTest</a></td></tr><tr class="passedeven"><td><a href="#m36">KindleReaderTest</a></td></tr><tr class="passedeven"><td><a href="#m37">KindleReaderTest</a></td></tr><tr class="passedeven"><td><a href="#m38">KindleReaderTest</a></td></tr><tr class="passedeven"><td><a href="#m39">KindleReaderTest</a></td></tr><tr class="passedeven"><td><a href="#m40">KindleReaderTest</a></td></tr><tr class="passedeven"><td><a href="#m41">KindleReaderTest</a></td></tr><tr class="passedeven"><td><a href="#m42">KindleReaderTest</a></td></tr><tr class="passedeven"><td><a href="#m43">KindleReaderTest</a></td></tr><tr class="passedeven"><td><a href="#m44">KindleReaderTest</a></td></tr><tr class="passedeven"><td><a href="#m45">KindleReaderTest</a></td></tr><tr class="passedeven"><td><a href="#m46">KindleReaderTest</a></td></tr><tr class="passedeven"><td><a href="#m47">KindleReaderTest</a></td></tr><tr class="passedeven"><td><a href="#m48">KindleReaderTest</a></td></tr><tr class="passedeven"><td><a href="#m49">KindleReaderTest</a></td></tr><tr class="passedeven"><td><a href="#m50">KindleReaderTest</a></td></tr><tr class="passedeven"><td><a href="#m51">KindleReaderTest</a></td></tr><tr class="passedeven"><td><a href="#m52">KindleReaderTest</a></td></tr><tr class="passedeven"><td><a href="#m53">KindleReaderTest</a></td></tr><tr class="passedeven"><td><a href="#m54">KindleReaderTest</a></td></tr><tr class="passedeven"><td><a href="#m55">KindleReaderTest</a></td></tr><tr class="passedeven"><td><a href="#m56">KindleReaderTest</a></td></tr><tr class="passedeven"><td><a href="#m57">KindleReaderTest</a></td></tr></tbody><tbody id="t1"></tbody></table><h2>KindleReaderTest</h2><h3 id="m0">com.amazon.e2e.device.os22#KindleReaderTest</h3><table class="result"><tr class="param"><th>Parameter #1</th></tr><tr class="param stripe"><td>CSPDDataObject [testCaseId=US_KINDLE_22, description=RISK with AUTH-fulfillment phase]</td></tr><tr><th>Messages</th></tr><tr><td>
{ SOME LOGGER MESSAGE GOES HERE }
</td></tr><tr><th>Exception</th></tr><tr><td>
java.lang.AssertionError: expected [true] but found [false]
</td></tr></table><p class="totop"><a href="#summary">back to summary</a></p> <h2>Suite setup and teardown</h2></body></html>

Any leads…

Solution:

This xslt will read the html file and append the xml nodes after table[@class=’result’]. While parinsg the html, the doctype will cause an error. So before runing the xlst remove the first line in the html.

XLS file

<?xml version="1.0"?>
<xsl:stylesheet version="2.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns="http://www.w3.org/1999/xhtml"
                xpath-default-namespace="http://www.w3.org/1999/xhtml">
    <xsl:output method="html" indent="yes" omit-xml-declaration="yes"
                doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"
                doctype-system="http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd" />
    <xsl:param name="failedxml.outputDir" />
    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:variable name="doc" select="document($failedxml.outputDir)" />
    <xsl:template match="body/table[@class='result']">
        <xsl:copy-of select="."/>
        <xsl:for-each select="$doc/node()/child::element()">
            <table class="result">
                <tr class="param">
                    <th>Parameter #1</th>
                </tr>
                <tr class="param stripe">
                    <td> <xsl:value-of select ="child::element()[1]"/></td>
                </tr>
                <tr>
                    <th>Messages</th>
                </tr>
                <tr>
                    <td>
                        
</td> </tr> <tr> <th>Exception</th> </tr> <tr> <td>
</td> </tr> </table> </xsl:for-each> </xsl:template> </xsl:stylesheet>

I ran using gradle like,

configurations{ xslt }
dependencies {
    xslt    'net.sf.saxon:saxon:8.7'
}
task generateReport << {
    File reportDir=new File("${projectDir}/HTML_Reports")
    if(reportDir.exists()){
        reportDir.deleteDir()
    }
    reportDir.mkdir()

   File emailreport=new File("${projectDir}/emailable-report.html")
   // Write some script to remove DOCTYPE from html file before running xslt.

    ant.xslt(in: "${testReportDir.absolutePath}/emailable-report.html",
             style: "${projectDir.absolutePath}/merge_html.xsl",
             out: "${reportDir.absolutePath}/index.html",
             classpath: configurations.xslt.asPath) {
            param(name: 'failedxml.outputDir', expression:  "${projectDir.absolutePath}/failedtest.xml")
        }

Flattening a collection within collection to get a single List<>

I’m quite new to using Java and was trying to flatten collections within collections using map to try and get a single List. However I don’t seem to be able to get this working. In order to reproduce this I’ve created quite a simple example of what I’m trying to do. Here is what I have so far:

ClassA

import java.util.List;

public class ClassA {
    private List<ClassB> listOfClassB;

    public ClassA(List<ClassB> listOfClassB) {
        this.listOfClassB = listOfClassB;
    }

    public List<ClassB> getListOfClassB() {
        return this.listOfClassB;
    }
}

ClassB

    public class ClassB {
    private String item;

    public ClassB(String item) {
        this.item = item;
    }

    public String getItem() {
        return item;
    }
}

Main

public class Main {
    public static void main(String[] args) {
        ClassB firstClass = new ClassB("A");
        ClassB secondClass = new ClassB("B");
        ClassB thirdClass = new ClassB("C");
        ClassB fourthClass = new ClassB("D");
        ArrayList<ClassB> firstClassList = new ArrayList<>();
        ArrayList<ClassB> secondClassList = new ArrayList<>();

        firstClassList.add(firstClass);
        firstClassList.add(secondClass);
        secondClassList.add(thirdClass);
        secondClassList.add(fourthClass);

        ArrayList<ClassA> classes = new ArrayList<>();
        classes.add(new ClassA(firstClassList));
        classes.add(new ClassA(secondClassList));

        List<List<String>> collect = classes.stream().map(c -> c.getListOfClassB().stream().map(ClassB::getItem).collect(Collectors.toList())).collect(Collectors.toList());
    }
}

As you can see on the bottom I am able to get List<List<String>> but what I’m looking to get is a List<String> of the items within ClassB. I’ve tried using a flatmap for this but I couldn’t get it working and was looking for some guidance.

Thanks in advance.

Solution:

Here is the flatmap example which works fine:

classes.stream().flatMap(aclass -> aclass.getListOfClassB().stream())
    .forEach(b -> System.out.println("Class B Item Name : "+b.getItem()));

It gives the following output:

Class B Item Name : A
Class B Item Name : B
Class B Item Name : C
Class B Item Name : D

and to get the exact answer:

List<String> collect2 = classes.stream().flatMap(aclass -> aclass.getListOfClassB().stream())
    .map(b -> b.getItem())
    .collect(Collectors.toList());

it gives me a list as follows:

collect2 : [A, B, C, D]

short and char auto unboxing in java

   HashSet charSet = new HashSet();
   for (char i = 0; i < 100; i++) {
      charSet.add(i);
      charSet.remove(i - 1);
    }
    System.out.println(charSet.size());

    HashSet intSet = new HashSet();
    for (int i = 0; i < 100; i++) {
        intSet.add(i);
        intSet.remove(i - 1);
    }
    System.out.println(intSet.size());

Output is 100 and 1 respectively.

I just realized that short and char do no get auto unboxed in Java. Why didn’t the designers think it was important to do that?

Solution:

This is actually nothing to do with boxing or unboxing.

When you apply an arithmetic operation to a char, it is converted to an int, as per JLS §5.6.2:

  1. Widening primitive conversion (§5.1.2) is applied to convert either or both operands as specified by the following rules:
    • If either operand is of type double, the other is converted to double.
    • Otherwise, if either operand is of type float, the other is converted
      to float.
    • Otherwise, if either operand is of type long, the other is converted
      to long.
    • Otherwise, both operands are converted to type int.

Thus, i - 1 is not a char, but an int. And because there are no Integers in your charSet (only Characters), there is nothing to be removed. If you were to cast i - 1 to a char, you would get the result you are expecting.

Eclipse – Sonar S2629 possible false positive with new String

I’m using latest Eclipse and Sonar plugin

In answer for logging there’s the following line:

log.debug("Request body: {}", new String(body, "UTF-8"));

Which should create String only if in DEBUG level:

/**
 * Log a message at the DEBUG level according to the specified format
 * and argument.
 * <p/>
 * <p>This form avoids superfluous object creation when the logger
 * is disabled for the DEBUG level. </p>
 *
 * @param format the format string
 * @param arg    the argument
 */
public void debug(String format, Object arg);

But Sonar is marking it as squid:S2629:

“Preconditions” and logging arguments should not require evaluation (squid:S2629)

And give examples with concatenation

logger.log(Level.DEBUG, “Something went wrong: ” + message); // Noncompliant; string concatenation performed even when log level too high to show DEBUG messages

Is it a false positive sonar warning or am I missing something?

This isn’t a duplicate of this question which is generally asking about the rule concept, which is concatenation, but not formatting with creating object as new String

Also link of an answer says creating new Date() isn’t creating an issue with built in format:

public static void main(String[] args) {
    LOGGER.info("The program started at {}", new Date());
}

}

Logging this way, you avoid performance overhead for strings concatenation when nothing should be actually logged.

Solution:

In non-DEBUG mode the line

log.debug("Request body: {}", new String(body, "UTF-8"));

instead of

log.debug(MessageFormatter.format("Request body: {}", new String(body, "UTF-8")));

avoids the creation of the string that is created via MessageFormatter.format(String messagePattern, Object arg), but not the creation of the other string that is created by new String(body, "UTF-8").

This means it is not a false positive, because the arguments are calculated first before the logging method is called.

As long as SLF4J does not support lambda expression to lazy evaluate arguments (see comment by ZhekaKozlov), the following utility method can be used as a workaround:

private static Object lazyToString(final Supplier<String> stringSupplier) {
    return new Object() {
        @Override
        public String toString() {
            return stringSupplier.get();
        }
    };
}

This can be used to limit the converting of the byte array into a string to the DEBUG mode only:

log.debug("Request body: {}", lazyToString(() -> new String(body, StandardCharsets.UTF_8)));

Java 11 and E(fx)clipse JavaFX plugin on Eclipse 4.9: An error has occurred – see the log file

I can’t get my Eclipse 2018-09 (4.9) running with Java 11 and E(fx)clipse JavaFX plugin.

I run the typical Help -> Install new software procedure for E(fx)clipse, but after restart, Eclipse fully crashes: I can’t even open Eclipse anymore for a new workspace!

When I try to run Eclipse, I get a dialog:

“An error has occurred. See the log file C:\workspace\.metadata\.log”

I’ve put a copy of that log file on my Github.

Well, I could run a hello world JavaFX application using this manual library setup, but I’d really like to get E(fx)clipse running in order to get the Eclipse menu options and functionality. So how to solve that? Thanks.

Solution:

In Eclipse e(fx)clipse the support for Java 11 has just been implemented and is just available since version 3.4.1, but according to your log you have version 3.3.0.201809010600.

See Eclipse bug 539739