I have a Velocity template file which has the data from XML. I want to convert the string into integer type.
How can I do that?
Aha! Been there.
#set($intString = "9")
#set($Integer = 0)
$Integer.parseInt($intString)
Doing this uses the java underlying velocity. The $Integer variable is nothing more that a java Integer object which you can then use to access .parseInt
Edit: The above code is for demonstration. Of course there are ways to optimize it.
If you have some control over the velocity context, here's an alternative that alleviates the need to set a variable in the Velocity template.
Context velocityContext = new Context();
velocityContext.put(Integer.class.getSimpleName(), Integer.class);
This allows you to call the static methods of java.lang.Integer in your template using $Integer.parseInt($value) and doesn't rely upon the #set having been called prior to performing the type conversion in the template.
The problem with parseInt is that it throws an exception in case the string is not parseable.
In case you have the NumberTool loaded into your context a better solution than parseInt is the following:
#set($intString = "009")
#set($Integer=$numberTool.toNumber($intString).intValue())
#if($Integer)
## ok
#else
## nok
#end
Sometimes the NumberTool is also loaded as $number.
However, a little drawback is, that the NumberTool simply parses the first number it finds and ignores the rest, so "123a" => 123.
Nice and easy:
#set( $stringToCast = "0" )
$number.toNumber($stringToCast)
$number is the default key name for the NumberTool, but it can be override by specifying a different name in the configuration (for example $numberTool). You have to check what name for NumberTool is used in your Velocity environment.
toNumber method returns:
the object as a Number or null if no conversion is possible
If you want to have explicite an int variable, not a Number object, you can use the intValue method on the result. So the above code will looks like this:
#set( $stringToCast = "0" )
$number.toNumber($stringToCast).intValue()
Of course, you can assign the result to another variable (for example $intVal).
So the full code can look like this:
#set( $stringToCast = "0" )
#set( $intVal = $number.toNumber($stringToCast).intValue() )
Related
I read the byte buddy and javassist doc and I would like do not know if is possible to convert a string like:
get foos where name == toto
to
data.getFoos().stream()
.filter( f -> f.name.equals( "toto" ) )
.collect( Collectors.toSet() )
A regex could capture the expression as:
final Pattern query = Pattern.compile("get (\\w+) where (\\w+) ([=!]+) (\\w+)");
final Scanner scanner = new Scanner(System.in);
final Matcher matcher = query.matcher(input);
matcher.group(1) // foos -> Foo and foos -> getFoos()
matcher.group(2) // field to use as filter
matcher.group(3) // symbol == / !=
matcher.group(4) // thing to match
convert get foos to getFoos()
check from Foo class if name field exists
if fields name is not an instance of Number.class translate == to .equals
make the expression
loop and print results
I read some examples without able to found a such thing. So I come here to get your light. thanks
Both Byte Buddy and Javassist generate byte code, not Java code. Javassist does however have functionality to translate String-contained source code to byte code from your inputs. However, the source code level is at Java 4 level such that you cannot use lambdas.
I do however wonder if this is the correct approach for your problem. Rather, I would suggest you to programmatically resolve a stream from the arguments. You could amplify this by creating a custom aPI to transform your arguments into the stream in question.
I am using Windows Workflow Foundation in .NET 4.0. Below is some syntax/semantic confusion I have.
I have 2 equivalent way to declare an Assign activity to assign a value to a workflow variable (varIsFreeShipping).
(1) Using XAML in the designer.
(2) Using code.
But in approach 2, the it seems I am creating a new OutArgument< Boolean > and assign value to it, not to the original Variable< Boolean> varIsFreeShipping. And OutArgument and Variable are totally different types.
So how could the value assigned to this new Argument finally reach the original Variable?
This pattern seems common in WF 4.0. Could anybody shed some light on this?
Thanks!
As a matter of fact, the second (2) method can be written just as:
Then = new Assign<bool>
{
To = varIsFreeShipping,
Value = true
}
This all works because OutArgument<T> can be initialized through a Variable<T> using an implicit operator.
In your first (1) assign, using the editor, that's what's happening behind the scene; the variable is being implicitly converted from Variable to OutArgument.
WF4 uses alot of implicit operators mainly on Activity<T> from/to Variable<T>, OutArgument<T> from/to Variable<T>, etc. If you look at it, they all represent a piece of data (already evaluated or not), that is located somewhere. It's exactly the same as in C#, for example:
public int SomeMethod(int a)
{
var b = a;
return a;
}
You can assign an argument to a variable, but you can also return that same variable as an out argument. That's what you're doing with that Assign<T> activity (using the variable varIsFreeShipping as the activity's out argument).
This answers your question?
Velocity just print the tag name if no value was found in VelocityContext, ie, $name in my template file, but there is no value for "name" in VelocityContext, so just "$name" was printed. I want Velocity to print a default value if there is no value for the variable, I just tried to extends AbstractCotnext and override internalGet() method, but the return value of internalGet() will be cast to Node object, I don't know how to create a new Node object in my internalGet() method, and also I think this way is very complex.
is there a simple way to set a default value (default value is just a string) ?
thanks.
Not easily for all variables as far as I see, I only managed to do it for some variables specifically as follows:
Template:
#if ( !$somevar )
#set ( $somevar = "mycontent" )
#end
Var is: $somevar
Result:
Var is: mycontent
Create a velocimacro in your template:
#macro(defaultValue $parm)
#if (!$!parm || $!parm == "")
i-like-will
#else
$parm
#end
#end
And call it like this in the same template:
#defaultValue($name)
Check Apache Velocity - Velocity User Guide for more info on velocimacros (and velocity in general).
A little late to the party, but you could also perform a check when defining a variable. I had to compress this to one line to remove excess space in the output, but here is an example from one of my projects:
#set ( $qlDefault = "qlinks" )
#set ( $qlClass = "#if($sharedCtaImage.getChild('path').value != '/')$qlDefault#else$qlDefault full#end" )
Default class is defined, then I check if another, specific value is filled in to determine if I keep the default class or append an additional class. This could also work for swapping out classes as well.
Google around for Velocity ReferenceInsertionEventHandler for a way to do it broadly.
Consider the DisplayTool's alt() method for individual cases (part of the VelocityTools project)
For an empty default value, $!name will do. Otherwise,
#{if}($name)${name}#{else}${default_value}#{end}
See http://velocity.apache.org/engine/2.0/user-guide.html#quiet-reference-notation
There are a couple things you can do short of hacking Velocity internals. Have a look at this question.
I am rewriting bytecode using Javassist. I need to modify type of some local variables to object. How can I access local variables and change their types using Javassist?
Thanks.
This question is quite old but since I did something similar I'll post my solution:
Since I did not found any solution to change the type of a field in a class in Javassist, I just deleted the old method and added a new one with the same name but my desired type:
CtClass point = ClassPool.getDefault().get("Point");
CtField toBeDeleted = point .getField("fieldName");
point .removeField(toBeDeleted);
CtField newField = CtField.make("public int fieldName = 0;", point);
point.addField(newField );
So with this example I took the field fieldName in class point that was of type let's say Object and know has been changed in a field of type 'int' and initialized to 0
I want the following code to set the 'name' field of the myClass instance to be equal to 'super_awesome_name':
super_awesome_name = myClass();
where the myClass constructor is as follows:
function obj = myClass()
obj.name = ???;
end
Is there some way to do this in Matlab? Right now I can accomplish something very similar with assignin, but it makes the syntax very unnatural:
myClass(super_awesome_name);
where the myClass constructor is as follows:
function obj = myClass(var_name)
obj.name = assignin('caller',var_name, obj);
end
As far as I know, there is no convenient way of doing so. You can see this yourself since MATLAB will have to perform some when constructing an object like that.
First construct the object
Store that object in super_awesome_name
But step 1 needs information from step 2 (i.e. the name of the variable). So you will have to work around that.
You solution may work, but it leaves a lot of room for error. Just consider the case when super_awesome_name is undefined before the construction: this will throw an exception due to an unitialized variable.
IMHO it is easier to make a constructor that accepts a string containing the name (or possibly a variable, as you can get the variable name of an argument by using inputname). Using inputname, however is just a bit clearer than using assignin.
Why do you need such functionality? I'm thinking of a situation where you might do something like:
x = myObjectThatHasAName(); % x.name contains 'x'
y = myObjectThatHasAName(); % y.name contains 'y'
x = y; % x.name contains 'y' !
So that might be the behavior you are looking for, but it may become very confusing if you pass the variables along a lot. It looks to me like you are mixing debugging information into your actual computations.
If you need the functionality to determine the actual variable name in another method or function, just use inputname. Then you won't need to keep track of the variable name yourself with all confusing consequences. That would be what I'd propose to do in most cases. You can see an example in the MATLAB documentation.
On the other hand, I think the clearest way to store the variable name inside the object, could be something like:
classdef myObjectThatHasAName
properties
name = '';
end
methods
function obj = myObjectThatHasAName()
end
function obj = storeName(obj,name)
if nargin < 2
name = inputname(1);
end
if ~isempty(name) % && isempty(obj.name)
obj.name = inputname(1);
end
end
end
end
I haven't tested this (lack of MATLAB on my current computer), but the following code should do it:
x = myObjectThatHasAName();
x = x.storeName();
% or x = storeName(x);
% or x = storeName(x,'x');
If you don't mind the overhead, you could always incorporate the storeName into each other method (and forget about calling storeMethod outside of the methods). This keeps track of the variable name where the object resided before the last assignment. A possible method might look like this:
function obj = otherMethod(obj,arguments)
obj = obj.storeName(inputname(1));
% actual code for the method
end
That way the name is set when you first call any method on the object (this almost does what you want, but I guess it will do what you need in most cases). You can of course adjust the code to just remember the first assignment (just comment out the code in storeName).