Template to show method name and parameter values in Eclipse - eclipse

Is there any way to have a template (Java -> Editor -> Templates) in Eclipse that generate something like this
debug("methodName arg1=" + arg1 + " arg2=" + arg2 + " arg3=" + arg3);
When used in a method. For instance:
public void setImage(long rowId, long contactId, String thinggy) {
// invoking the template here, produces this:
debug("setImage rowId=" + rowId + " contactId=" + contactId + " thinggy=" + thinggy);
}
I couldn't find a way to do that with the standard template UI, maybe there exists a plugin to do this kinds of things?

This is a start:
debug("${enclosing_method_arguments}: ", ${enclosing_method_arguments});
which produces the following:
debug("arg1, arg2, arg3: ", arg1, arg2, arg3);
I haven't found a way to separate out each argument. I found this page that ran into the same problem.
For other Eclipse template stuff, look at this question.

I guess it's probably a bit too late to answer this question but maybe my answer will help someone :
System.out.println(String.format("%tH:% %s", java.util.Calendar.getInstance(), "${enclosing_package}.${enclosing_type}.${enclosing_method}(${enclosing_method_arguments})"));
String[] lArgsNames = new String("${enclosing_method_arguments}").split(", ");
Object[] lArgsValues = new Object[] {${enclosing_method_arguments}};
for (int i = 0; i < lArgsValues.length; i++) {
System.out.println("\t" + (lArgsValues[i] != null ? ("(" + lArgsValues[i].getClass().getSimpleName() + ") \"" + lArgsNames[i] + "\" = \"" + lArgsValues[i] + "\"") : "\"" + lArgsNames[i] + "\" is null"));
}
For this method :
public void foo(boolean arg){
// ...
}
the output would be:
18:43:43:076 > any.package.AnyClass.foo(arg)
(Boolean) "arg" = "true"
This code seems to be able to handle any object, primitive type and null value. And yes it's a little bit complicated for the purpose!

I've made small plugin that adds nicely formatted variable:
https://github.com/dernasherbrezon/eclipse-log-param
Eclipse doesnt provide any information about parameter type, so there is no Arrays.toString(...)

or template=
if (aLog.isDebugEnabled()) {
aLog.debug(String.format("${enclosing_method}:${enclosing_method_arguments}".replaceAll(", ", "=%s, ")+"=%s", ${enclosing_method_arguments}));
}
gives
public static void hesteFras(boolean connect, Object ged, String frans, int cykel) {
if (aLog.isDebugEnabled()) {
aLog.debug(String.format("hesteFras: connect, ged, frans, cykel".replaceAll(", ", "=%s, ") + "=%s",
connect, ged, frans, cykel));
}
which for
hesteFras(false, null, "sur", 89);
gives a log statement:
hesteFras: connect=false, ged=null, frans=sur, cykel=89

The eclipse-log-param plugin is useful to avoid having to type the logging line manually. However, it would be even nicer to have the line added automatically for all new methods.
Is this even possible? It looks like in Windows->Preferences->Code Style->Code Templates->Code there are ways to configure automatically added code like auto-generated methods ("Method body" template, which has an "Auto-generated method stub" comment). But there's no way to configure new methods which are not generated.
Furthermore, the variable formatted_method_parameters is not available when editing the template for "Method body".

Related

how to enum in a if with mybatis annotation

I have a problem to write the syntax using an enum in a if in MyBatis annotation.
#Delete("<script>DELETE FROM tb_a WHERE "
+ "<if test='context.name().equals(ALBUM)'>"
+ " album_id = #{id}"
+ "</if>"
+ "<if test='context.name().equals(VIDEOLIBRARY)'>"
+ " videolibrary_id = #{id}"
+ "</if>"
+ "</script>")
boolean delete(#Param("id") int id, #Param("context") EContext context);
Enum
public enum EContext {
ALBUM,
VIDEOLIBRARY,
IMAGE,
VIDEO,
}
the correct syntax as fare I know is like this <if test="context.name().equals('ALBUM')">
But I don't know how to write it with annotation.
I get this error message
Thanks for your help
Edited to show more about the code
name() method returns a java.lang.String and in OGNL, a string literal should be enclosed in single or double quotes.
So, the if element should be written as..
+ "<if test=\"context.name().equals('ALBUM')\">"
or
+ "<if test='context.name().equals(\"ALBUM\")'>"

ServiceStack Ormlite Deserialize Array for In Clause

I am storing some query criteria in the db via a ToJson() on the object that contains all the criteria. A simplified example would be:
{"FirstName" :[ {Operator: "=", Value: "John"}, { Operator: "in", Value:" ["Smith", "Jones"]"}], "SomeId": [Operator: "in", Value: "[1,2,3]" }]}
The lists are either string, int, decimal or date. These all map to the same class/table so it is easy via reflection to get FirstName or SomeId's type.
I'm trying to create a where clause based on this information:
if (critKey.Operator == "in")
{
wb.Values.Add(keySave + i, (object)ConvertList<Members>(key,
(string)critKey.Value));
wb.WhereClause = wb.WhereClause + " And {0} {1} (#{2})".Fmt(critKey.Column,
critKey.Operator, keySave + i);
}
else
{
wb.Values.Add(keySave + i, (object)critKey.Value);
wb.WhereClause = wb.WhereClause + " And {0} {1} #{2}".Fmt(critKey.Column, critKey.Operator, keySave + i);
}
It generates something like this (example from my tests, yes I know the storenumber part is stupid):
Email = #Email0 And StoreNumber = #StoreNumber0 And StoreNumber in (#StoreNumber1)
I'm running into an issue with the lists. Is there a nice way to do this with any of the ormlite tools instead of doing this all by hand? The where clause generates fine except when dealing with lists. I'm trying to make it generic but having a hard time on that part.
Second question maybe related but I can't seem to find how to use parameters with in. Coming from NPoco you can do (colum in #0, somearray)` but I cant' seem to find out how to do this without using Sql.In.
I ended up having to write my own parser as it seems ormlite doesn't support have the same support for query params for lists like NPoco. Basically I'd prefer to be able to do this:
Where("SomeId in #Ids") and pass in a parameter but ended up with this code:
listObject = ConvertListObject<Members>(key, (string)critKey.Value);
wb.WhereClause = wb.WhereClause + " And {0} {1} ({2})"
.Fmt(critKey.Column, critKey.Operator,listObject.EscapedList(ColumnType<Members>(key)));
public static string EscapedList(this List<object> val, Type t)
{
var escapedList = "";
if (t == typeof(int) || t == typeof(float) || t == typeof(decimal))
{
escapedList = String.Join(",", val.Select(x=>x.ToString()));
} else
{
escapedList = String.Join(",", val.Select(x=>"'" + x.ToString() + "'"));
}
return escapedList;
}
I'd like to see other answers especially if I'm missing something in ormlite.
When dealing with lists you can use the following example
var storeNumbers = new [] { "store1", "store2", "store3" };
var ev = Db.From<MyClass>
.Where(p => storeNumbers.Contains(p => p.StoreNumber));
var result = Db.Select(ev);

Custom procedure fails to collect properties of a class parameter; why?

OK, first of all, I'm a rookie with Caché, so the code will probably be poor, but...
I need to be able to query the Caché database in Java in order to rebuild source files out of the Studio.
I can dump methods etc without trouble, however there is one thing which escapes me... For some reason, I cannot dump the properties of parameter EXTENTQUERYSPEC from class Samples.Person (namespace: SAMPLES).
The class reads like this in Studio:
Class Sample.Person Extends (%Persistent, %Populate, %XML.Adaptor)
{
Parameter EXTENTQUERYSPEC = "Name,SSN,Home.City,Home.State";
// etc etc
}
Here is the code of the procedure:
CREATE PROCEDURE CacheQc.getParamDesc(
IN className VARCHAR(50),
IN methodName VARCHAR(50),
OUT description VARCHAR(8192),
OUT type VARCHAR(50),
OUT defaultValue VARCHAR(1024)
) RETURNS NUMBER LANGUAGE COS {
set ref = className _ "||" _ methodName
set row = ##class(%Dictionary.ParameterDefinition).%OpenId(ref)
if (row = "") {
quit 1
}
set description = row.Description
set type = row.Type
set defaultValue = row.Default
quit 0
}
And the Java code:
private void getParamDetail(final String className, final String paramName)
throws SQLException
{
final String call
= "{ ? = call CacheQc.getParamDesc(?, ?, ?, ?, ?) }";
try (
final CallableStatement statement = connection.prepareCall(call);
) {
statement.registerOutParameter(1, Types.INTEGER);
statement.setString(2, className);
statement.setString(3, paramName);
statement.registerOutParameter(4, Types.VARCHAR);
statement.registerOutParameter(5, Types.VARCHAR);
statement.registerOutParameter(6, Types.VARCHAR);
statement.executeUpdate();
final int ret = statement.getInt(1);
// HERE
if (ret != 0)
throw new SQLException("failed to read parameter");
System.out.println(" description: " + statement.getString(4));
System.out.println(" type : " + statement.getString(5));
System.out.println(" default : " + statement.getString(6));
}
}
Now, for the aforementioned class/parameter pair the condition marked // HERE is always triggered and therefore the exception thrown... If I comment the whole line then I see that all three of OUT parameters are null, even defaultValue!
I'd have expected the latter to have the value mentioned in Studio...
So, why does this happen? Is my procedure broken somewhat?
In first you should check that you send right value for className and paramName, full name and in right case and. Why you choose storage procedures, when you can use select? And you can call your procedure in System Management Portal to see about probable errors.
select description, type,_Default "Default" from %Dictionary.ParameterDefinition where id='Sample.Person||EXTENTQUERYSPEC'
Your example, works well for me.
package javaapplication3;
import com.intersys.jdbc.CacheDataSource;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Types;
public class JavaApplication3 {
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws SQLException {
CacheDataSource ds = new CacheDataSource();
ds.setURL("jdbc:Cache://127.0.0.1:56775/Samples");
ds.setUser("_system");
ds.setPassword("SYS");
Connection dbconnection = ds.getConnection();
String call = "{ ? = call CacheQc.getParamDesc(?, ?, ?, ?, ?)}";
CallableStatement statement = dbconnection.prepareCall(call);
statement.registerOutParameter(1, Types.INTEGER);
statement.setString(2, "Sample.Person");
statement.setString(3, "EXTENTQUERYSPEC");
statement.registerOutParameter(4, Types.VARCHAR);
statement.registerOutParameter(5, Types.VARCHAR);
statement.registerOutParameter(6, Types.VARCHAR);
statement.executeUpdate();
int ret = statement.getInt(1);
System.out.println("ret = " + ret);
System.out.println(" description: " + statement.getString(4));
System.out.println(" type : " + statement.getString(5));
System.out.println(" default : " + statement.getString(6));
}
}
end result
ret = 0
description: null
type : null
default : Name,SSN,Home.City,Home.State
UPD:
try to change code of your procedure and add some debug like here
Class CacheQc.procgetParamDesc Extends %Library.RegisteredObject [ ClassType = "", DdlAllowed, Owner = {UnknownUser}, Not ProcedureBlock ]
{
ClassMethod getParamDesc(className As %Library.String(MAXLEN=50), methodName As %Library.String(MAXLEN=50), Output description As %Library.String(MAXLEN=8192), Output type As %Library.String(MAXLEN=50), Output defaultValue As %Library.String(MAXLEN=1024)) As %Library.Numeric(SCALE=0) [ SqlName = getParamDesc, SqlProc ]
{
set ref = className _ "||" _ methodName
set row = ##class(%Dictionary.ParameterDefinition).%OpenId(ref)
set ^debug($i(^debug))=$lb(ref,row,$system.Status.GetErrorText($g(%objlasterror)))
if (row = "") {
quit 1
}
set description = row.Description
set type = row.Type
set defaultValue = row.Default
quit 0
}
}
and after some test from java, check zw ^debug
SAMPLES>zw ^debug
^debug=4
^debug(3)=$lb("Sample.Person||EXTENTQUERYSPEC","31#%Dictionary.ParameterDefinition","ERROR #00: (no error description)")
Well, uh, I found the problem... Talk about stupid.
It happens that I had the Samples.Person class open in Studio and had made a "modification" to it; and deleted it just afterwards. Therefore the file was "as new"...
But the procedure doesn't seem to agree with this statement.
I closed the Studio where that file was, selected not to modify the "changes", reran the procedure again, and it worked...
Strangely enough, the SQL query worked even with my "fake modification". I guess it's a matter of some cache problem...

Entity Framework - Table-Valued Functions - Parameter Already Exists

I am using table-valued functions with Entity Framework 5. I just received this error:
A parameter named 'EffectiveDate' already exists in the parameter collection. Parameter names must be unique in the parameter collection. Parameter name: parameter
It is being caused by me joining the calls to table-valued functions taking the same parameter.
Is this a bug/limitation with EF? Is there a workaround? Right now I am auto-generating the code (.edmx file).
It would be really nice if Microsoft would make parameter names unique, at least on a per-context basis.
I've created an issue for this here.
In the meantime, I was able to get this to work by tweaking a few functions in the .Context.tt file, so that it adds a GUID to each parameter name at runtime:
private void WriteFunctionImport(TypeMapper typeMapper, CodeStringGenerator codeStringGenerator, EdmFunction edmFunction, string modelNamespace, bool includeMergeOption) {
if (typeMapper.IsComposable(edmFunction))
{
#>
[EdmFunction("<#=edmFunction.NamespaceName#>", "<#=edmFunction.Name#>")]
<#=codeStringGenerator.ComposableFunctionMethod(edmFunction, modelNamespace)#>
{ var guid = Guid.NewGuid().ToString("N"); <#+
codeStringGenerator.WriteFunctionParameters(edmFunction, " + guid", WriteFunctionParameter);
#>
<#=codeStringGenerator.ComposableCreateQuery(edmFunction, modelNamespace)#>
} <#+
}
else
{
#>
<#=codeStringGenerator.FunctionMethod(edmFunction, modelNamespace, includeMergeOption)#>
{ <#+
codeStringGenerator.WriteFunctionParameters(edmFunction, "", WriteFunctionParameter);
#>
<#=codeStringGenerator.ExecuteFunction(edmFunction, modelNamespace, includeMergeOption)#>
} <#+
if (typeMapper.GenerateMergeOptionFunction(edmFunction, includeMergeOption))
{
WriteFunctionImport(typeMapper, codeStringGenerator, edmFunction, modelNamespace, includeMergeOption: true);
}
} }
...
public void WriteFunctionParameters(EdmFunction edmFunction, string nameSuffix, Action<string, string, string, string> writeParameter)
{
var parameters = FunctionImportParameter.Create(edmFunction.Parameters, _code, _ef);
foreach (var parameter in parameters.Where(p => p.NeedsLocalVariable))
{
var isNotNull = parameter.IsNullableOfT ? parameter.FunctionParameterName + ".HasValue" : parameter.FunctionParameterName + " != null";
var notNullInit = "new ObjectParameter(\"" + parameter.EsqlParameterName + "\"" + nameSuffix + ", " + parameter.FunctionParameterName + ")";
var nullInit = "new ObjectParameter(\"" + parameter.EsqlParameterName + "\"" + nameSuffix + ", typeof(" + parameter.RawClrTypeName + "))";
writeParameter(parameter.LocalVariableName, isNotNull, notNullInit, nullInit);
}
}
...
public string ComposableCreateQuery(EdmFunction edmFunction, string modelNamespace)
{
var parameters = _typeMapper.GetParameters(edmFunction);
return string.Format(
CultureInfo.InvariantCulture,
"return ((IObjectContextAdapter)this).ObjectContext.CreateQuery<{0}>(\"[{1}].[{2}]({3})\"{4});",
_typeMapper.GetTypeName(_typeMapper.GetReturnType(edmFunction), modelNamespace),
edmFunction.NamespaceName,
edmFunction.Name,
string.Join(", ", parameters.Select(p => "#" + p.EsqlParameterName + "\" + guid + \"").ToArray()),
_code.StringBefore(", ", string.Join(", ", parameters.Select(p => p.ExecuteParameterName).ToArray())));
}
Not a bug. Maybe a limitation or an omission. Apparently this use case has never been taken into account. EF could use auto-created parameter names, but, yeah, it just doesn't.
You'll have to resort to calling one of the functions with .AsEnumerable(). For some reason, this must be the first function in the join (as I have experienced). If you call the second function with .AsEnumerable() it is still translated to SQL and the name collision still occurs.

AspectJ - Retrieve list of annotated parameters

From the following previous question (AspectJ - Presence of annotation in join point expression not recognized),
My goal:
In an aspect, i'd like to be able to extract/retrieve all annotated parameters from matching functions, no matter how many there are. (and then apply some treatment on but it's not the scope of this question)
So for the moment, this is what i did (not working):
#Before("execution (* org.xx.xx.xx..*.*(#org.xx.xx.xx.xx.xx.Standardized (*),..))")
public void standardize(JoinPoint jp) throws Throwable {
Object[] myArgs = jp.getArgs();
getLogger().info("Here: arg length=" + myArgs.length);
// Roll on join point arguments
for (Object myParam : myArgs) {
getLogger().info(
"In argument with " + myParam.getClass().getAnnotations().length
+ " declaread annotations");
getLogger().info("Class name is " + myParam.getClass().getName());
// Get only the one matching the expected #Standardized annotation
if (myParam.getClass().getAnnotation(Standardized.class) != null) {
getLogger().info("Found parameter annotated with #Standardized");
standardizeData(myParam.getClass().getAnnotation(Standardized.class), myParam);
}
}
}
This is the code matched by the advice:
public boolean insertLog(#Standardized(type = StandardizedData.CLIPON) CliponStat theStat) {
// ...
}
And the traces generated by a junit test:
INFO: ICI: arg lenght=1
INFO: In argument with 0 declaread annotations
Looks like it doesn't detect the annotation
So my question is: how to detect parameters which have specific annotation(s) ?
Does somebody have an idea how to do it?
Thanks in advance for your help.
Regards.
Edit: i found this thread Pointcut matching methods with annotated parameters, discussing of the same thing, and applied the given solution but it doesn't work..
I hope I understand you right.
myParam.getClass().getAnnotations() gives you the annotations on a class. Something like:
#Standardized(type = StandardizedData.CLIPON)
public class Main{...}
Maybe this pointcut/advice helps you:
#Before("execution (* org.xx.xx.xx..*.*(#org.xx.xx.xx.xx.xx.Standardized (*),..))")
public void standardize(JoinPoint jp) throws Throwable {
Object[] args = jp.getArgs();
MethodSignature ms = (MethodSignature) jp.getSignature();
Method m = ms.getMethod();
Annotation[][] parameterAnnotations = m.getParameterAnnotations();
for (int i = 0; i < parameterAnnotations.length; i++) {
Annotation[] annotations = parameterAnnotations[i];
System.out.println("I am checking parameter: " + args[i]);
for (Annotation annotation : annotations) {
System.out.println(annotation);
if (annotation.annotationType() == Standardized.class) {
System.out.println("we have a Standardized Parameter with type = "
+ ((Standardized) annotation).type());
}
}
}
}
This gives me the following output:
I am checking parameter: main.CliponStat#331f2ee1
#annotation.Standardized(type=CLIPON)
we have a Standardized Parameter with type = CLIPON