Idea Live Template to Log Method Args - java

I would like to be able to create a live template in Jetbrain's Idea that will log the method's arguments. Let's call it "larg". It would work like:
public void get(String one, String two) {
larg<tab>
to create
public void get(String one, String two) {
log.info("get: one = " + one + " two = " + two);
I'm fine with getting the method name in, but have not figured out how to pull in the method arguments. Any ideas?

I'm 4 years late, but the predefined template soutp pretty much does this using a groovyscript variable.
Here's the groovy script that does what you're looking for
groovyScript("'\"' + _1.collect { it + ' = [\" + ' + it + ' + \"]'}.join(', ') + '\"'", methodParameters())

Looks like it is not currently possible with a live template.
From the Jetbrain's forum:
There is no predefined live template function to do this for you automatically.
You can write a plugin that would provide such a function.

this is my groovy script
groovyScript("import com.intellij.psi.*;import com.intellij.psi.util.PsiTreeUtil; def file = PsiDocumentManager.getInstance(_editor.project).getPsiFile(_editor.document); PsiMethod method = PsiTreeUtil.findElementOfClassAtOffset(file, _editor.caretModel.offset, PsiMethod.class, false); PsiParameter[] parameters = method == null ? PsiParameter.EMPTY_ARRAY : method.parameterList.parameters; return parameters.size() == 0 ? '' : '\"' + method.name + ' : ' + parameters.collect { def prefix = it.name + ' = '; def type = it.type; return type instanceof PsiArrayType ? type.componentType instanceof PsiPrimitiveType ? prefix + '\" + java.util.Arrays.toString(' + it.name + ')' : prefix + '\" + java.util.Arrays.deepToString(' + it.name + ')' : prefix + '\" + ' + it.name }.join(' + \", ')", methodParameters())

In Android Studio in Kotlin I use this to log classname, methodname and parameters.
I use my name as tag to easily filter in logcat. I use these mainly for debugging, I don't commit these messages with my name.
Log.d("MYNAME", "$CLASS_NAME$:$METHOD_NAME$: $PARAMETERS$")
And then the parameters are defined as follows.
CLASS_NAME : kotlinClassName()
METHOD_NAME : kotlinFunctionName()
PARAMETERS : groovyScript("'' + _1.collect { it + ' = $' + it}.join(', ') ", functionParameters())
This would be the result if used in the main activity
fun aFunctionWithParameters( first: Int, second: String, third: ArrayList<String>){
Log.d("MYNAME", "MainActivity:aFunctionWithParameters: first = $first, second = $second, third = $third")
}
I based my solution on Rob's answer and edited it to my needs.

Related

Need a way to get to get the pattern in a string matched with List.stream().anyMatch()

I'm matching a list of strings against a list of keywords. The goal is to get a string only one time if it has any of the keywords in it.
Actually I'm doing it with this loop:
for (int i = 0; i < keywords.size(); i++) {
if (text.toLowerCase().contains(keywords.get(i))) {
System.out.println("keyword >>> " + keywords.get(i)
+ " text >>> " + text);
break;
}
}
I like to know if there is a way to get the keyword if I'm using the java stream API like so:
if (keywords.stream().anyMatch(text.toLowerCase()::contains)) {
System.out.println("keyword >>> " + "how to get the keyword here"
+ " text >>> " + text);
}
anyMatch returns a boolean
Using .filter() & findFirst() you can retrieve a value. Note that if you use findFirst() you get an Optional<String> and could either use ifPresent() like this:
keywords.stream()
.filter(keyword -> text.toLowerCase().contains(keyword))
.findFirst()
.ifPresent(keyWord -> System.out.println("[2] keyword >>> " + keyWord + " text >>> " + text));
Or with Optional.isPresent() & Optional.get():
Optional<String> firstKey = keywords.stream()
.filter(keyword -> text.toLowerCase().contains(keyword))
.findFirst();
if (firstKey.isPresent()) {
System.out.println("[2] keyword >>> " + firstKey.get() + " | text >>> " + text);
}
As a less fancy alternative to stream there is a nicer for syntax in Java 1.6+
for(String keyword: keywords) {
if (text.toLowerCase().contains(keyword)) {
System.out.println("keyword >>> " + keyword
+ "text >>> " + text);
break;
}
}
I find the for syntax easier to read than the stream syntax. In a previous job I did a lot of C++ lambda functions with BOOST and the code was hard to parse, and the errors hard to trace.
Another option would be to print an informational message if the keyword was not found. This is easily done by moving the isPresent test inside the print statement.
List<String> keywords =
Arrays.asList("now", "is", "the", "time");
String text = "what are your names?";
Optional<String> opt = keywords.stream()
.filter(keyword -> text
.toLowerCase().contains(keyword))
.findFirst();
System.out.println(!opt.isPresent() ? "No keyword was found!" :
"keyword >>> " + opt.get()
+ " text >>> " + text);
Prints
No keyword was found!

java: unable to cast an Integer object to String

I'm trying to concatenate multiple objects inside a String variable called 'update' from a 'data' array within the method 'addClient' below:
public int addClient(Object[] data) {
try {
if (((String)data[0]).trim().isEmpty() || ((String)data[1]).trim().isEmpty() || ((int)data[2] < 0) || ((int)data[3] <= 0)) {
return StatusBar.ERR_INVALID_INPUT_CODE;
}
// the line below is causing the exception
String update = "INSERT INTO Client VALUES(" + ((String)data[0]).trim() + "," + ((String)data[1]).trim() + "," + ((Integer)data[3]).intValue() + "," + ((Integer)data[4]).intValue() + "," + ((Boolean)data[2]).booleanValue() + "," + ((String)data[5]).trim() + ")";
if (statement.executeUpdate(update) != 1) {
return StatusBar.ERR_INTERNAL_CODE;
}
}
catch (Exception e) {
e.printStackTrace();
return StatusBar.ERR_INTERNAL_CODE;
}
return StatusBar.ERR_SUCCESS_CODE;
}
However when the code above executes; an exception gets raised showing the following message:
java.lang.ClassCastException: java.lang.Integer cannot be cast to
java.lang.String
at Model.addClient(Model.java:43)
The 'data' object array is obtained through the call of the following method:
public Object[] getFields() {
return new Object[]{jTextFieldName.getText(), jTextFieldAddress.getText(),
jComboBoxType.getSelectedIndex(),
jSpinnerPhone.getValue(), jSpinnerFax.getValue(),
jTextFieldWebsite.getText()};
}
I did many searches and tried many methods including String.valueOf and Integer.toString, but without any success ..
Why I'm getting such behavior? How can it be solved?
You have a lot of options casting to String.
You chose the "simple" option that will work only if the object is really a String, and you just need to down-cast it (from Object) to String.
Try using one of the following options:
new String (your-Integer-here);
(your-Integer-here).toString();
(your-Integer-here) + "";
Let me know if it's working now :)
The elements of your data array can be of any reference type. Therefore you can't cast them to String without checking their type first.
Luckily, you can simply call their toString method instead.
Change
((String)data[0])
to
data[0].toString()
Instead of casting to String, you can call .toString() method on object, if that is your intention.
You are casting your object
i.e
if (((String)data[0]).trim().isEmpty() || ((String)data[1]).trim().isEmpty() || ((int)data[2] < 0) || ((int)data[3] <= 0)) to
if (data[0].toString().trim().isEmpty() || (data[1].toString().trim().isEmpty() || ((int)data[2] < 0) || ((int)data[3] <= 0))
Assuming data[3] and data[2] are of type Integers.
*PS:You can also log the values, to make sure what the values are.
You can try as below and let me know how it goes.
private static void concater(){
String[] data={"abc","def","23","45","true","xyz"};
String update = "INSERT INTO Client VALUES(" + ((String)data[0]).trim() + "," + ((String)data[1]).trim() + "," + Integer.parseInt(data[2]) + "," +
Integer.parseInt(data[3]) + "," + Boolean.parseBoolean(data[4]) + "," + ((String)data[5]).trim() + ")";
System.out.println(update); //INSERT INTO Client VALUES(abc,def,23,45,true,xyz)
}

Log function call on new line in Java and C#

I have a logging function in CSharp and Java that I use in walking the stack. How do I make each log print to a new line only. Below are my Java and CSharp Functions.
public static void LogFunctionCall(String parameters){
Object trace = Thread.currentThread().getStackTrace()[3];
android.util.Log.i("##################" + trace.toString()+ "", parameters );
}
the java version is this
public static void LogFunctionCall(string parameters,
[System.Runtime.CompilerServices.CallerMemberName] string methodName = "",
[System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "",
[System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
{
var stackFrame = new StackFrame(1);
var callerMethod = stackFrame.GetMethod();
var className = callerMethod.DeclaringType;
System.Diagnostics.Trace.WriteLine("CCCCCCCCCCCCCCCC" + " " + className + " " + methodName + " " + sourceLineNumber + " " + parameters + "\n");
}
I code on a windows machine.
Please where exactly do I need to place the new line character. I tried this
public static void LogFunctionCall(String parameters){
Object trace = Thread.currentThread().getStackTrace()[3];
android.util.Log.i("##################" + trace.toString()+ "", parameters + "\n" );
}
but I still saw some of the logs being clumped up on a single line.
Instead of \n, try \r\n (carriage return and newline). Some text editors will display differently, so the newline may be in there, but whatever app you're using to read the logs might not be displaying it correctly.
You could also try
System.lineSeparator();
I've seen instances where the /n won't work but the lineSep does.
Also, because it hasn't been mentioned, Environment.NewLine will give you the new line character that is configured for the current environment.

Hibernate query language like operator not working

cmTDsquery = createQuery("from CmTxnDetailStage cstg where cstg.statusCd=:err" +
" and (cstg.id.batchName like :batchname or cstg.id.batchName like :batchname1)"+
" and cstg.prodTypeBlfd like :search1 "+
" and trunc(cstg.tranUploadDttm)=:uploadDt");
cmTDsquery.bindStringProperty("search1", CmTxnDetailStage.properties.prodTypeBlfd, search);
I declared the search parameter as
search = "MON%";
If I replace the :search1 with 'MON%' ,It works fine and query returns result.
Only above code does not work and returns NULL.
Thanks
----------------Edit 1
cmTDsquery.bindStringProperty("batchname",CmTxnDetailStage.properties.batchName,batchNamePattern);
cmTDsquery.bindStringProperty("batchname1",CmTxnDetailStage.properties.batchName,batchNamePattern1);
Sorry to mention this late , but above bindStringProperty methods works like a charm.
batchname and batchname1 contains "CR_STLM_UBROL%" and "%RMB_PINDBT%".
Do like this while setting parameter
"%"+search+"%"
I can't understand exactly the line
cmTDsquery.bindStringProperty("search1", CmTxnDetailStage.properties.prodTypeBlfd, search);
Do you set the correct value - "MON%" and not for example "MON"?
I have used HQL like query.setParameter("search1","MON%") and it worked fine with like operators.
My code is almost the same :
whereClause = whereClause + (whereClause.length() > 0 ? "AND " : "") + "ac.name LIKE :name ";
And further in my code :
if (searchCriteria.getNameSearchOperator() == SQL_STRING_SEARCH_OPERATORS.CONTAINS) {
value = "%" + value + "%";
}
if (searchCriteria.getNameSearchOperator() == SQL_STRING_SEARCH_OPERATORS.START_WITH) {
value = value + "%";
}
query.setParameter("name", value);
Try using setParameter instead of bindStringProperty.

Basic XML parsing issues. Cannot find node names via Java XmlStreamReader method. Any ideas?

Having no luck in parsing some basic XML. I'm doing this in the Apex language, but it's syntactically nearly identical to Java and in this case uses java.xml.stream.XMLStreamReader as its XML parsing engine.
The problem is: I'm having no luck getting to any of the actual XML node names. The getLocalName() method within the XmlStreamReader class always returns null for all nodes as I loop through them.
code is here
Very basic functionality at this point. If you run this, you will see that reader.getLocalName() always returns null and so do all accompanying methods (getNameSpace(), getLocation(), getPrefix()).
Any ideas why? I'm stuck with the XML arriving in the format it's in...so I have to parse it as-is. I could use various workarounds (regEx, counting nodes, etc.) but those are messy and not ideal.
I have reformed your code into one block that can be tested in the workbench's anonymous execution window. I run the code and then filter the Execution Log to show USER_DEBUG statements. The output shows node names and text as you would expect.
I think the key is to use the APEX methods hasText() and hasName().
String XML_STR = '<document>' + '<result>success</result>' +'<resultcode>000000</resultcode>' +
'<note></note>' + '<item>' +'<quantity>1</quantity>' +
'<fname>Bob</fname>' +'<lname>Tungsten</lname>' +
'<address>23232 Fleet Street</address>' +'<city>Santa Clara</city>' +
'<state>CA</state>' +'<zip>94105</zip>' +
'<country>United States</country>' +'<email>blahblahblah#blahblahblah.com</email>' +
'<phone>4155555555</phone>' +'</item>' +'</document>';
XmlStreamReader reader = new XmlStreamReader(XML_STR);
while (reader.hasNext()) {
System.debug('$$$ reader.getEventType(): ' + reader.getEventType());
if (reader.hasName()) {
System.debug('$$$ reader.getLocalName(): ' + reader.getLocalName());
// System.debug('$$$ reader.getNamespace(): ' + reader.getNamespace());
// System.debug('$$$ reader.getprefix(): ' + reader.getprefix());
}
if (reader.hasText()) {
System.debug('$$$ reader.getText(): ' + reader.getText());
}
System.debug('$$$ Go to next');
reader.next();
}
Here is another solution based on the recipe by Jon Mountjoy
http://developer.force.com/cookbook/recipe/parsing-xml-using-the-apex-dom-parser
private String walkThrough(DOM.XMLNode node) {
String result = '\n';
if (node.getNodeType() == DOM.XMLNodeType.COMMENT) {
return 'Comment (' + node.getText() + ')';
}
if (node.getNodeType() == DOM.XMLNodeType.TEXT) {
return 'Text (' + node.getText() + ')';
}
if (node.getNodeType() == DOM.XMLNodeType.ELEMENT) {
result += 'Element: ' + node.getName();
if (node.getText().trim() != '') {
result += ', text=' + node.getText().trim();
}
if (node.getAttributeCount() > 0) {
for (Integer i = 0; i< node.getAttributeCount(); i++ ) {
result += ', attribute #' + i + ':' + node.getAttributeKeyAt(i) + '=' + node.getAttributeValue(node.getAttributeKeyAt(i), node.getAttributeKeyNsAt(i));
}
}
for (Dom.XMLNode child: node.getChildElements()) {
result += walkThrough(child);
}
return result;
}
return ''; //should never reach here
}
private String parse(String toParse) {
DOM.Document doc = new DOM.Document();
try {
doc.load(toParse);
DOM.XMLNode root = doc.getRootElement();
return walkThrough(root);
} catch (System.XMLException e) { // invalid XML
return e.getMessage();
}
}
String XML_STR = '<document>' + '<result>success</result>' +'<resultcode>000000</resultcode>' +
'<note></note>' + '<item>' +'<quantity>1</quantity>' +
'<fname>Bob</fname>' +'<lname>Tungsten</lname>' +
'<address>23232 Fleet Street</address>' +'<city>Santa Clara</city>' +
'<state>CA</state>' +'<zip>94105</zip>' +
'<country>United States</country>' +'<email>blahblahblah#blahblahblah.com</email>' +
'<phone>4155555555</phone>' +'</item>' +'</document>';
System.debug(parse(XML_STR));

Categories