2010-08-27 8 views
0

Comme le titre l'indique, j'ai deux objets différents qui implémentent la même interface et je veux les ajouter à la même collection.Comment Jibx peut-il ajouter deux objets différents implémentant la même interface dans une collection?

Mon XML ressemble à:

<root> 
    <item-list> 
    <item> 
     <type1> 
      <id>1</id> 
     </type1> 
    </item> 
    <item> 
     <type2> 
      <id>2</id> 
      <other>1</other> 
     </type2> 
    </item> 
    </item-list>  
</root> 

La balise sous item peut être soit type1 ou type2 à tout moment. Ils ont des valeurs similaires mais, comme vous le voyez, type2 a un autre champ.

Mon interface est:

public interface Item { 

    public String getID(); 
} 

Mes trois classes:

public class MyObj { 
    private ArrayList<Item> items = new ArrayList<Item>(); 

    public List<Item> getItems() { 
    return items; 
    } 
} 
public class Type1 implements Item{ 
    private String id; 

    @Override 
    public String getID() { 
     return id; 
    } 
} 

public class Type2 implements Item { 
    private String id; 
    private String other; 

    @Override 
    public String getID() { 
     return id; 
    } 

    public String getOther() { 
     return other; 
    } 
} 

Mes regards contraignants comme ceci:

<binding direction="input" > 

<mapping name="item-list" class="jibx.woe.MyObj" > 

    <collection field="items" > 
     <structure name="item" choice="true" ordered="false"> 

      <structure name="type1" map-as="type1"/> 

      <structure name="type2" map-as="type2"/> 

     </structure> 

    </collection> 

</mapping> 
<mapping class="jibx.woe.Type1" abstract="true" type-name="type1"> 
    <value name="id" field="id"/> 
</mapping> 

<mapping class="jibx.woe.Type2" abstract="true" type-name="type2"> 
    <value name="id" field="id"/> 
    <value name="other" field="other"/> 
</mapping> 

Et quand je le lance, je obtenir la cette erreur:

*** Error during code generation for file 'C:\Projects\IdeaProjects\jibx-woe\src \main\config\woe-binding.xml' - 
this may be due to an error in your binding or classpath, or to an error in the JiBX code *** 

Internal error: Expected jibx.woe.Type1 on stack, found java.lang.Object full stack: 
    0: java.lang.Object 
    1: java.lang.Object 
    2: org.jibx.runtime.impl.UnmarshallingContext 

Je pensais que j'ajouter un type d'élément à la collection, maintenant ma section de collection ressemble:

<collection field="items" item-type="jibx.woe.Item"> 
     <structure name="item" choice="true" ordered="false" > 

      <structure name="type1" map-as="type1"/> 

      <structure name="type2" map-as="type2"/> 

     </structure> 

    </collection> 

Et l'erreur dit maintenant:

Internal error: Expected jibx.woe.Type1 on stack, found jibx.woe.Item 
    full stack: 
    0: jibx.woe.Item 
    1: jibx.woe.Item 
    2: org.jibx.runtime.impl.UnmarshallingContext 

Alors maintenant, je ajouter la méthode suivante à MyObj:

public void addItem(Object type) { 
     items.add((Item)type); 
    } 

et ils ont changé l'étiquette collection à:

<collection add-method="addItem"> 

Et vous obtiendrez le même même erreur que ma première tentative:

Internal error: Expected jibx.woe.Type1 on stack, found java.lang.Object 
full stack: 
    0: java.lang.Object 
    1: java.lang.Object 
    2: org.jibx.runtime.impl.UnmarshallingContext 

Et maintenant, je suis d'idées. Comment puis-je faire en sorte que cela fonctionne?

EDIT

Sur la base de la recommandation Archie ci-dessous, j'ai changé la liaison à:

<mapping name="root" class="jibx.woe.MyObj"> 

<structure name="item-list" > 

    <collection field="items"> 
     <structure name="item" /> > 

    </collection> 
</structure> 
</mapping> 

<mapping name="type1" class="jibx.woe.Type1" > 
    <value name="id" field="id"/> 
</mapping> 

<mapping name="type2" class="jibx.woe.Type2" > 
    <value name="id" field="id"/> 
    <value name="other" field="other"/> 
</mapping> 


</binding> 

Et maintenant, les travaux de liaison sans erreurs de pile (hourra!), Mais maintenant, quand je obtenir un article de ma liste à la:

List<Item> items = woe.getItems(); 
    Type1 item = (Type1) items.get(0); 

je reçois:

java.lang.ClassCastException: java.lang.Object cannot be cast to jibx.woe.Type1 

Sur ma deuxième ligne ci-dessus. Si j'imprime l'objet: System.out.println (éléments.get (0));

Il dit: [email protected]

Il est donc un objet ordinaire, pas un élément ou un Type1 (ou type2) du tout!

J'ai essayé la méthode "extends" proposée par Archie, mais cela n'a rien changé - j'ai obtenu le même résultat.

+0

pas vraiment sûr, mais essayez de remplacer Liste avec Liste et ArrayList . – mhshams

+0

Mohammad: Je n'y ai pas pensé, mais ça n'a pas marché non plus. – MikeHoss

Répondre

1

Créer un mappage abstrait pour Item. Créez ensuite deux mappages concrets pour Type1 et Type2, chacun étendant le mappage d'élément. Dans votre collection d'objets, faites de chaque élément un objet (débarrassez-vous des trucs de choix). Remarquez que dans JiBX, le mot-clé 'extends' n'a rien à voir avec les classes Java, cela signifie 'peut être substitué'. Limitation: vous devrez attribuer deux noms de balises XML de Type1 et Type2 différents (par exemple, "type1" et "type2") afin que JiBX puisse les distinguer lors de la résolution d'unmarshalling. C'est le problème avec ce que vous faites actuellement. Par exemple, quand JiBX voit un tag, comment va-t-il savoir quelle classe Java instancier?

+0

Voir ma sortie ci-dessus. Nous sommes si proches maintenant. . . J'ai également peu ou pas de contrôle sur le XML que j'analyse, donc j'ai besoin de comprendre comment le faire avec la structure ci-dessus. Mais je suis d'accord - le style que je reçois ne facilite pas cela. – MikeHoss