Xtend/Xpand find and replace (rule) - java

Is it possible set a rule that will allow an Xpand method to output a specified string of text depending on the input. For example:
«FOR a:e.attributes»
Type = «a.eClass.name»
Value = «a.name.toFirstUpper»
«ENDFOR»
The above code may output:
Type = StringAttribute
Value = String1
Type = IntegerAttribute
Value = 123
How would I make this output:
Type = String
Value = String1
Type = int
Value = 123
I know this can be done with if statements but I would like to be able it to be more or less automatic. It would be a waste to have to specify such rules every time I need to output these details in the same file. Could someone show me what kind of code I could use to achieve this? Thank you.

I suggest that you create a reusable Xtend helper
toSimpleName(String inp):
switch (inp) {
case "StringAttribute" : "String"
case "IntegerAttribute" : "int"
// ...more cases here...
default : inp
}
;
and then call it from your Xpand template like this:
«FOR a:e.attributes»
Type = «a.eClass.name.toSimpleName()»
Value = «a.name.toFirstUpper»
«ENDFOR»

Related

Jackson's ObjectMapper().writeValueAsString() ignores variables that begin with "is_"

If a have an anonymous class like:
val a = object {
val is_something = "some value"
val something = "other value"
}
and call
println(ObjectMapper().writeValueAsString(a))
the result would be
"{"something":"other value"}"
And it's like this for all variables that begin with "is_". Why?
Correction, it doesn't ignore it. It takes off the "is" and moves the variable to the end of the string. So here the result would be
"{"something":"other value","_something":"some value"}"
Still, why does it do that?
Jackson apparently scans the class that you pass in for getters and setters
and then use those methods for serialization and deserialization.
"Get", "Set", "is" are eliminated and what remains in those methods will be used as Json field.
Hence your "is_something" is changed into "_something" and so on.
The issue was solved by adding #JsonProperty on top of "is_something" and capitalizing it.
So the object would look like
val a = object {
#JsonProperty
val Is_something = "some value"
val something = "other value"
}
Still have no idea what caused the problem

Kotlin accessing variable from other class not by name directly but by string variable

I'm trying to access a variable from another class. The usual way would be:
in Class A
var something = ClassB().element
in Class B
val element = "hi"
Is it also possible to address element not by its name directly, but when I have the name stored in a string? So I have a string that holds
var name = "element"
and want to do something like
var something = ClassB().name //(this doesn't work)
The reason I'm asking is because I have a class in which I do some pitch processing and another class in which I store all of my pitch data in float arrays (the Hz values of different musical notes for different tunings of different instruments)
In the class I do my pitchprocessing in I want to select the right float array depending on a user selection (made with a spinner), which I "translate" with a map (so for example the spinner says "Standard Tuning" and the according array would be called "guitarStandard", in my map "Standard Tuning" would be the key and "guitarStandard" the according value). To not hardcode the different cases in which I need different arrays with if statements, I simply want the name of the array stored in a string by getting the correct value of my map and adress it that way.
I feel like that should be either super simpel or I'm thinking about it the completely wrong way, can someone help out? Thanks
I would advise that you don't store a list of strings, and instead store a list of lambdas that return property values:
class Foo {
val prop1 = arrayOf(1.0, 2.0, 3.0)
val prop2 = arrayOf(4.0, 5.0, 6.0)
}
fun main() {
val props: List<(Foo) -> Array<Double>> = listOf({it.prop1}, {it.prop2})
val foo = Foo()
for (prop in props) {
println(prop(foo).toList())
}
}
But, if you wanted to search up property names from a string, you should look into reflection.
I'd suggest to refactor your ClassB by extracting those properties to separate enum class:
enum class Tunes(vararg f: Float) {
TUNE1(1.0f, 2.0f, 3.0f), TUNE2(4.0f, 5.0f, 6.0f);
val frequencies: FloatArray = f
}
That will make your mapping more straightforward and won't involve reflection:
import Tunes.*
val mapping = mapOf("Standard Tuning" to TUNE1, "Alternate Tuning" to TUNE2)
val result = mapping[userInput]?.frequencies

Google Protocol Buffers checking if a field has been set

I am iterating over the fields of GPB message and have to find out the list of fields which have been set in the message
public void printFields(Person person){
Builder builder = person.toBuilder();
Descriptor descriptor = Person.getDescriptor();
List<FieldDescriptor> fields = descriptor.getFields();
for(FieldDescriptor fd : fields){
Object value = builder.get(fd); //this gives the value
// how to check if this field is set or not
}
}
Checking value for null doesnot help as there can be primitive types in the message as well.
I have read about hasXXX() methods on the message class which tells whether XXX has default value or explicit value, but how to invoke these using builder/descriptor/fieldDescriptor.
If you are using Java 8, you can find the defined fields using the streaming api:
List<Descriptors.FieldDescriptor> definedPersonFields = Person.getDescriptor()
.getFields()
.stream()
.filter(Person::hasField)
.collect(Collectors.toList())
It is late, but may be useful for other people..
The below code will print modified attribute name and its value. you can change it identify populated attributes in proto
Map<Descriptors.FieldDescriptor, Object> modifiedFields = proto.getAllFields();
for(Descriptors.FieldDescriptor fieldDescriptor : modifiedFields.keySet())
{
int protNum = fieldDescriptor.toProto().getNumber();
Descriptors.FieldDescriptor.Type fieldType = fieldDescriptor.getType();
Object value = modifiedFields.get(fieldDescriptor);
System.out.println(fieldDescriptor.getFullName());
System.out.println(value);
}
Why do you need to use descriptor/fieldDescriptor? They are even not available if you define "option optimize_for = LITE_RUNTIME".
Anyway, you can do it already on a Person.Builder or just Person, e.g.:
Builder builder = person.toBuilder();
if (builder.hasXXX()){
XXX xxx = builder.getXXX();
}

Groovy/Grails Contains with Lowercase

I want to check a list contains a specific string .
before checking all entries in list as well as sting should be in. lowercase
I tried like this
def venueName = params.name
def venueNameLists = Venue.executeQuery("select name from Venue")
if(venueNameLists.toLowerCase().contains(venueName.toLowerCase())){
error = true;
log.debug("save :: duplicate name")
flash.message = "Venue name already exist";
render(view: "create", model: [venueInstance: new Venue(params)])
return
}
gives error
No signature of method: java.util.ArrayList.toLowerCase() is applicable for argument types: () values: []. Stacktrace follows:
groovy.lang.MissingMethodException: No signature of method: java.util.ArrayList.toLowerCase() is applicable for argument types: () values: []
I agree with aiolos: use constraints or try to find instance by name ignore case. But to fix this your way try *. (spread operator):
venueNameLists*.toLowerCase().contains(venueName.toLowerCase())
If you would like to check a duplicate entry before saving an element, use constraints on your domain class. Here you could use unique constraint or implement your own if you need it case insensitive.
If you need to check it manually, try this:
def venueWithNameFromParams = Venue.findByNameIlike(params.name) // ignore case
if(venueWithNameFromParams){
// venueName is in venueNameList
}
If you were looking how to check if multiple strings contains a word, while ignoring case-sensitive, use (?i) on a regex of words.
For example, the following will be positive condition:
word = "YES"
word.matches(/(?i)yes|ok|true/)

Android - Getting identifier for view using string variable

I have a string variable which is the same as the identifier for a view.
I would like to use the R.id.xxx, but obviously I can't just replace the xxx with my string as the xxx is actually an int. What can I do to get around this?
Thanks!
Nonsense. The framework obviously discourages that approach but it is possible: just use Java reflection, e.g.,
java.lang.reflect.Field f = R.id.class.getField(name);
int id = f == null ? -1 : (Integer)f.get(null);
// now just use findViewById(id);
String s=getString(R.string.xxx);

Categories

Resources