tikxml icon indicating copy to clipboard operation
tikxml copied to clipboard

Type Converter for a different type of a List for example RealmList<MyObject>

Open FabianTerhorst opened this issue 9 years ago • 28 comments

It's not possible right now, because RealmList<MyObject>.class doesn't work. The addTypeAdapter should support adding a typeadapter for a Java.lang.refl.Type.

FabianTerhorst avatar Jun 02 '16 13:06 FabianTerhorst

This is also needed for the support of a Map for example.

FabianTerhorst avatar Jun 02 '16 17:06 FabianTerhorst

With moshi for example you can use something like this Type realmIntegerList = Types.newParameterizedType(RealmInteger.class, RealmList.class);

FabianTerhorst avatar Jun 02 '16 17:06 FabianTerhorst

And for maps moshi use Type[] keyAndValue = Types.mapKeyAndValueTypes(type, rawType);

FabianTerhorst avatar Jun 02 '16 17:06 FabianTerhorst

Agreed!

Fabian Terhorst [email protected] schrieb am Do., 2. Juni 2016, 20:16:

And for maps moshi use Type[] keyAndValue = Types.mapKeyAndValueTypes(type, rawType);

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/Tickaroo/tikxml/issues/28#issuecomment-223359206, or mute the thread https://github.com/notifications/unsubscribe/AAjnrmc_4n92kTuULUtbzphV8qpO1wYqks5qHw_QgaJpZM4IslHC .

sockeqwe avatar Jun 03 '16 07:06 sockeqwe

Hi, currently trying to use TikXml for RealmList's. Any known workarounds?

meierjan avatar Sep 26 '16 12:09 meierjan

It's on my TO DO list, but has low priority ... I'm working right now on other things towards an 1.0 release, but will try to fix this before releasing 1.0 ...

A "workaround" (which for me is a much cleaner approach anyway) is to have XML annotated models and realm models in 2 separated classes.

sockeqwe avatar Sep 26 '16 12:09 sockeqwe

I don't think having 2 different entities for the same thing in the data layer is always a cleaner approach (especially if there already is a mapping between data and domain layer) but thanks for the hint.

Too bad this is a actually really nice library (I have always missed an annotation based xml-parsing library since ig-json-parser). What a pitty

btw the TypeConverter api of LoganSquare is not as nice as moshi's but having the JsonParser in parse(JsonParser parser) (equivalent to read(String string)) can be pretty powerful.

meierjan avatar Sep 26 '16 12:09 meierjan

Ok, so latest 0.5.5-SNAPSHOT adds pretty the same API as Moshi has (Also a class Types to create such generic parameterized types). You can now register TypeAdapter and TypeConerter by hand via Type instead of Class<T>.

So things likeType[] keyAndValue = Types.mapKeyAndValueTypes(type, rawType); or RealmList should work now, but you have to write manually a TypeAdapter and register that one.

I don't think having 2 different entities for the same thing in the data layer is always a cleaner approach (especially if there already is a mapping between data and domain layer) but thanks for the hint.

Let's talk about that again in one year after a small API change in one of your xml feeds crashes your app because of a missing Realm migration. But I agree, there is no always or recommendation that works for all kind of situations.

sockeqwe avatar Sep 26 '16 13:09 sockeqwe

Great feature. 👍 . Awesome work.

FabianTerhorst avatar Sep 26 '16 13:09 FabianTerhorst

Wow, that's the low priority speed? Really awesome work!

meierjan avatar Sep 26 '16 13:09 meierjan

One question, how can i prevent the annotation processor to generate a wrong ChildElementBinder that is using new ArrayList<Object>?

FabianTerhorst avatar Sep 26 '16 14:09 FabianTerhorst

So that the annotation processor is using the getTypeAdapter(type) and not getTypeAdapter(class)

FabianTerhorst avatar Sep 26 '16 14:09 FabianTerhorst

if (value.getObjects() == null) { value.setObjects(new ArrayList<Object>()); }

is the problem

FabianTerhorst avatar Sep 26 '16 14:09 FabianTerhorst

https://github.com/Tickaroo/tikxml/blob/cadd68075d27d9e96f9f3d7a79b6c05b72889426/processor/src/main/java/com/tickaroo/tikxml/processor/field/PolymorphicElementField.kt#L85 there is the problem.

FabianTerhorst avatar Sep 26 '16 14:09 FabianTerhorst

apt { arguments { " "//this can´t accept stuff like io.realm.RealmList } }

FabianTerhorst avatar Sep 26 '16 14:09 FabianTerhorst

Indeed, list are a special edge case. I'm rewriting the code generator right now and will consider that ...

sockeqwe avatar Sep 26 '16 14:09 sockeqwe

ok thanks.

FabianTerhorst avatar Sep 26 '16 14:09 FabianTerhorst

@FabianTerhorst could you manage to parse them? I failed.... (even in 0.8.1-SNAPSHOT)

meierjan avatar Nov 09 '16 15:11 meierjan

its not implemented properly for lists. this will be fixed with a future snapshot release

sockeqwe avatar Nov 09 '16 15:11 sockeqwe

Any ETA? (rly just looking forward to test this)

meierjan avatar Jan 25 '17 11:01 meierjan

No ETA :( I'm working on this parser while gradle is building ... But I don't think that this will be implemented until the end of February.

If you want to submit a pull request for this, I can give you some advises how and where to implement this.

Jan Meier [email protected] schrieb am Mi., 25. Jan. 2017, 12:36:

Any ETA?

— You are receiving this because you modified the open/close state.

Reply to this email directly, view it on GitHub https://github.com/Tickaroo/tikxml/issues/28#issuecomment-275086125, or mute the thread https://github.com/notifications/unsubscribe-auth/AAjnrlMHRPyTxsbuXdgG3z9k6QpC9hTwks5rVzOegaJpZM4IslHC .

sockeqwe avatar Jan 25 '17 11:01 sockeqwe

Yeah, please. A short introduction would be great.

meierjan avatar Jan 25 '17 11:01 meierjan

Hello, i'm trying to use tikxml in conjunction with RealmList, but i'm not sure how to set up the type adapter. Can anyone give me a hand? Thank you :)

AleSpero avatar Dec 05 '17 15:12 AleSpero

I'm not on my laptop right now and I'm not sure if it works, but this could work:

class RealmTypeAdapter extends TypeAdapter<RealmList<Foo>>{

  @Override
  public RealmList<Foo> fromXml(XmlReader reader, TikXmlConfig config) {
      // you need to parse some peace a little bit manually
      // i.e. each element in the xml stream like <foo bar="123" /> 
      RealmList<Foo> fooList= new RealmList<>();
      while(reader.hasElements()) {
          reader.beginElement();
          String elementName = reader.nextElementName();
          TypeAapter<Foo> fooParser = config. getTypeAdapter(Foo.class);
          Foo foo = fooParser. fromXml(reader, config);
          fooList.add(foo);

       // not sure if this one is needed:
      reader.endElement();
      }
   }

  @Override
  public void toXml(XmlWriter writer, TikXmlConfig config, RealmList<Foo> value, String overridingXmlElementTagName)
      throws IOException {
      // TODO implement if needed
   }
   
}

Then when instantiating your TikXml instance do something like this:


TikXml tikXml = new TikXml.Builder()
         .addTypeAdapter(Types. newParameterizedType(RealmList.class, Foo.class))
         .build();

Maybe you also need a compileTimeChecks = false in your annotation like this: (not sure if required, try it out):

@Xml
class SomeData {
    @Element(compileTimeChecks = false)
     RealmList<Foo> fooList;
}

sockeqwe avatar Dec 05 '17 16:12 sockeqwe

Thank you for the fast response, really appreciated. I'll look into it.

Another question: what if i have N objects which extend RealmObject (the objects are nothing special, they contain just a bunch of strings). Do i need to implement a typeadapter for all of them? or just for realmobject?

Right now if i have something like that:

    @Xml
    class SomeData {
        @Element
        Foo foo;
        //foo extends RealmObject
    }

It just work flawlessly. i feel like i can write a generic typeadapter for RealmLists without creating other typeadapters.

Here's what i got so far:

    public class RealmListTypeAdapter implements TypeAdapter<RealmList<? extends RealmObject>> {

    @Override
    public RealmList<? extends RealmObject> fromXml(XmlReader reader, TikXmlConfig config) throws IOException {

        RealmList<? extends RealmObject> list = new RealmList<RealmObject>();

        while(reader.hasElement()){

            reader.beginElement();
            reader.nextElementName();
            //and now?

        }

        return null;
    }

Thank you. :)

AleSpero avatar Dec 05 '17 17:12 AleSpero

public class RealmListTypeAdapter implements TypeAdapter<RealmList<? extends RealmObject>> {

    @Override
    public RealmList<? extends RealmObject> fromXml(XmlReader reader, TikXmlConfig config) throws IOException {

        RealmList<? extends RealmObject> list = new RealmList<RealmObject>();

        while(reader.hasElement()){

            reader.beginElement();
             String elementName =  reader.nextElementName();
            //and now?
            if (elementName.equals(foo)){
               TypeAapter<Foo> fooParser = config. getTypeAdapter(Foo.class);
               RealmObject foo = fooParser. fromXml(reader, config);
               list.add(foo);
            } else {
               TypeAapter<Bar> barParser = config. getTypeAdapter(Bar.class);
               RealmObject bar = fooParser. fromXml(reader, config);
               list.add(bar);
           }
        }

        return list;
    }

You basically have to make a mapping from "String" (ElementName) to the java class you would like to parse. You can use Map<String, Class>, then use the returned Class to get the corresponding TypeAdapter.

Perhaps there will be an easier way to do this in the future (like an abstract class your type adapter has to extend) or a better API i.e. an additional Annotation but I can't make any promise at this time ...

sockeqwe avatar Dec 05 '17 17:12 sockeqwe

Hello, I use the solution you write for RealmList but I have an error : error: <identifier> expected value.previsions = config.getTypeAdapter(RealmList<Foo>.class).fromXml(reader, config);

Can you help me to resolve this error ?

komuros avatar Nov 12 '18 13:11 komuros

Hello, how and where is RealmList declared?

CppGeekMajor avatar Apr 20 '23 09:04 CppGeekMajor