vendredi 3 mai 2019

Get all the local variables in a method java [duplicate]

This question already has an answer here:

How to get all the fields declared inside the method of a class. Something similar to class.getDeclaredFields() ?

public static void main(String[] args) {

        Class<String> clazz = String.class;

        Stream.of(clazz.getDeclaredFields()).forEach(field ->{
            System.out.println(field.getName()+" -> "+field.getType());
        });

}

The Above code returns all the fields declared in the class, can we do it at methods level to return all the local variables in the method.





Kotlin unable to access delegated method via reflection: "java.lang.NoSuchMethodException"

I'm trying to understand how reflection with works with delegation and I've come up with a toy example.


class Foo(val m: MutableList<Any>) : MutableList<Any> by m{
}



fun fooAdd(f: Foo) {
    val a = f::class.java.getMethod("add").invoke(f, 20);
    println(a)
}

fun main(args: Array<String>) {
    fooAdd(Foo(mutableListOf()))
}

This gives me an error:

Exception in thread "main" java.lang.NoSuchMethodException: Foo.add()

I'm not sure I understand why it's happening, seeing as add() is delegated to Foo from MutableList if I understand correctly.

How do I fix this error? Also, is there a library one ought to use for such a use-case?





Dynamically set properties of a Dynamic object

I have a dynamic object which basically holds an AvroRecord. AvroRecord class details here.

I can assign values to the properties statically but I was wondering if this could be done dynamically. I have looked at the forum question here ,here and also here. But none of these work for me.

This is the static code that works.

    var serializer = AvroSerializer.CreateGeneric(Schema);
    var rootSchema = serializer.WriterSchema as RecordSchema;
    dynamic counterpartRow = new AvroRecord(rootSchema);
    counterpartRow.CounterpartID = Row.CounterpartID
    counterpartRow.CounterpartFirstDepositDate = Row.CounterpartFirstDepositDate

The Row is an object of the InputBuffer class of SSIS and it holds all the columns coming from the upstream data source.

The schema variable used above is an avro schema, which is something like this.

 Schema = @"{
                                ""type"":""record"",
                                ""name"":""Microsoft.Hadoop.Avro.Specifications.Counterparts"",
                                ""fields"":
                                    [
                                       { ""name"":""CounterpartID"", ""type"":""int"" },
                                       { ""name"":""CounterpartFirstDepositDate"",  ""type"":[""string"",""null""] },
                                       { ""name"":""CounterpartFirstTradeDate"",""type"":[""string"",""null""] },
                                       { ""name"":""ClientSegmentReportingID"",""type"":""int"" },
                                       { ""name"":""ClientSegmentReportingName"", ""type"":[""string"",""null""] },
                                       { ""name"":""ContractID"", ""type"":""int""},
                                       { ""name"":""ContractFirstDepositDate"", ""type"":[""string"",""null""]},
                                       { ""name"":""ContractFirstTradeDate"",""type"":[""string"",""null""] },
                                       { ""name"":""ContractClosingOffice"",""type"":[""string"",""null""] },
                                       { ""name"":""LeadCreationDate"", ""type"":[""string"",""null""] },
                                       { ""name"":""ContractCountryOfResidence"", ""type"":[""string"",""null""]}
                                    ]
                            }";

I have tried something like the earlier forum links suggested like

counterpartRow.GetType().GetField("CounterpartID").SetValue(Row, Row.CounterpartID, null);

and also the other method (which apparently should work for for dynamic type), but even that does not.

foreach (string propertyName in GetPropertyKeysForDynamic(counterpartRow.Schema.Fields()))
        {
            string propertyValue = counterpartRow[propertyName];


        }

and the function defined like this.

 public List<string> GetPropertyKeysForDynamic(dynamic dynamicToGetPropertiesFor)
    {
        var jObject = (JObject)JToken.FromObject(dynamicToGetPropertiesFor);
        Dictionary<string, object> values = jObject.ToObject<Dictionary<string, object>>();
        List<string> toReturn = new List<string>();
        foreach (string key in values.Keys)
        {
            toReturn.Add(key);
        }
        return toReturn;
    }

The dictionary above returns blank.

the Row mentioned above is an object of InputBuffer class (auto generated class in SSIS).

which is something like this.

public class Input0Buffer: ScriptBuffer

{
    public Input0Buffer(PipelineBuffer Buffer, int[] BufferColumnIndexes, OutputNameMap OutputMap)
        : base(Buffer, BufferColumnIndexes, OutputMap)
    {
    }

    public Int32 CounterpartID
    {
        get
        {
            return Buffer.GetInt32(BufferColumnIndexes[0]);
        }
    }
------more properties


If you see my original static code, I am trying to dynamically generate the assignment. I have already dynamically generated the schema (instead of the static definition I have given above). So, the only piece left to generate dynamically is the assignment of the assignment. An idea could be that I generate the string but how do I then execute that string? That is only if there is no way to achieve this.





jeudi 2 mai 2019

Accessing Task properties via reflection only works if the properties are explicitly accessed in my code

I'm trying to access a property of a Task in an MS Project via System.Type.GetProperty("Finish"), but it looks like the property (and others like it e.g. Number1) is not accessible via reflection unless my code specifically uses that property. Is this a compiler setting that I can change? I'm writing a synchronization engine so it is impossible to tell ahead of time what field of a Task the client system may request.

So with the example below info will be null.

System.Type ty = typeof(Task);
System.Reflection.PropertyInfo info = ty.GetProperty("Finish");

but with the code below info is returned as a valid PropertyInfo object.

Task tk = activeProject.ProjectSummaryTask;
object done = tk.Finish;
System.Type ty = typeof(Task);
System.Reflection.PropertyInfo info = ty.GetProperty("Finish");

I basically expected GetProperty() to work for all the properties listed in the API for Task (which are quite a few).

Here is a link to the API for the Finish property: https://docs.microsoft.com/en-us/dotnet/api/microsoft.office.interop.msproject.task.finish?view=office-project-server





How do I use C# reflection to get a list of values of an object's fields that match a particular type?

I've defined a boolean property, personProperty for a class, Person, in which I want the getter, get{} to call a private method, personMethod(int arg) on each integer field value that's defined in Person (in this case _age, _phoneNumber). It should ignore all other types like readingList.

This is so that if I were to add another integer field to Person (or modify or delete any Person field names), I would not have to update the definition of personProperty which, by design choice, depends on all integer fields of the Person class (i.e., it is never the case that the developer will introduce an int field that he doesn't want personMethod to run against).

public Person
{
   private int _age;
   public int _phoneNumber;
   // protected int _futureInt;
   Dictionary<string> _readingList = new Dictionary<string>();

   public bool personProperty
   {
       get
       {
           // ...
           bool personPropertyReturnValue; 
           List<bool> resultList = new List<bool>();
           foreach(int personFieldValue in LISTOFPERSONINTS)
           {
               bool result = personMethod(personFieldValue);
               resultList.Add(result);
           }
           // Do stuff with `resultList` that'll initialize personPropertyReturnValue;
           return personPropertyReturnValue;
       }
   }

    private bool personMethod(int arg)
    {
       bool returnValue = true;
       // Do stuff to initialize `returnValue`
       return returnValue;
    }
}

I need to know what I should substitute for LISTOFPERSONINTS so that it returns an iterable over the values stored in _age, _phoneNumber (and all other future int, like _futureInt defined in Person).





Dynamic reflect object initialization of list items doesn't change original object

I'm trying to dynamically initialize the objects of a list with java reflect but after doing this the original objects are still keeping the original values and the link between the original objects and corresponding list item is broken.

Here is the piece of code for better understanding of my problem:

public class TimeModule {
    int value;

    public TimeModule() {
        this.value = 1;
    }

    public void setValue(int value) {
        this.value = value;
    }

    public int getValue() {
        return this.value;
    }

    public String print() {
        return "value: " + this.value;
    }
}


public class TimeModuleExtended1 extends TimeModule {

    double foo;

    public TimeModuleExtended1() {
        super();
        this.foo = 1.0;
    }

    public void setFoo(double foo) {
        this.foo = foo;
    }

    public double getFoo() {
        return this.foo;
    }

    @Override
    public String print() {
        return "value: " + this.value + ", foo:" + this.foo; 
    }
}


public class TimeModuleExtended2 extends TimeModule {

    double bar;

    public TimeModuleExtended2() {
        super();
        this.bar = 1.0;
    }

    public void setBar(double bar) {
        this.bar = bar;
    }

    public double getBar() {
        return this.bar;
    }

    @Override
    public String print() {
        return "value: " + this.value + ", bar:" + this.bar; 
    }
}

And here is the main code: import java.util.ArrayList; import java.util.List;

public class Test {

    public static void main(String[] args) {
        TimeModuleExtended1 t1 = new TimeModuleExtended1();
        t1.setValue(2);
        t1.setFoo(2.0);
        System.out.println("Initial Values:");
        System.out.println(t1.print());

        TimeModuleExtended2 t2 = new TimeModuleExtended2();
        t2.setValue(3);
        t2.setBar(3.0);
        System.out.println(t2.print());

        List<TimeModule> modules = new ArrayList<>();
        modules.add(t1);
        modules.add(t2);

        // reinitialize Time Base modules
        for (int i = 0; i < modules.size(); i++) {
            TimeModule m = modules.get(i);
            try {
                modules.set(i, (TimeModule) m.getClass().getConstructors()[0].newInstance());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        System.out.println("\nList Values: ");
        for (int i = 0; i < modules.size(); i++) {
            System.out.println(modules.get(i).print());
        }

        System.out.println("\nObject Values: ");
        System.out.println(t1.print());
        System.out.println(t2.print());        
    }
}

The output looks like this:

Initial Values:
value: 2, foo:2.0
value: 3, bar:3.0

List Values: 
value: 1, foo:1.0
value: 1, bar:1.0

Object Values: 
value: 2, foo:2.0
value: 3, bar:3.0

As you can see the List Values are not equal to Object Values; how to make them have similar values?





Why getAnnotation(Parsed.class).field() returning String[]?(It should return String, as it is taking input as String)

I have following code.

import com.univocity.parsers.annotations.Parsed;
import org.apache.commons.lang3.reflect.FieldUtils;
import java.lang.reflect.Field;

public class MyClass {
    public static void main(String args[]) {
        try{
            for (Field field : FieldUtils.getAllFieldsList(SpendsInputBean.class)) {
                String[] headerName = field.getAnnotation(Parsed.class).field();
//              ^
//              |____________(Shouldn't this be String)


                .
                .
                .
            }
        }catch(Exception ex){
            System.out.println(ex);
        }
    }
}

class X {
    @Parsed(field = "Abc")
    private String abc;
}

My question is Parsed(field = "Abc"), here field is taking String as input. But when I am getAnnotation(Parsed.class).field() it is returning String[] instead of String. Why this strange behaviour?

Shouldn't getAnnotation(Parsed.class).field() return String?