JAXB: comment démélanger une liste d'objets de types différents mais avec un parent commun?

Il y a un motif assez commun dans nos applications. Nous configurer une configuration d'un ensemble (ou une liste) des objets en Xml, ce qui implémentent une interface commune. Au démarrage, l'application lit le Xml et utilise JAXB pour créer/configurer une Liste d'objets. Je n'ai jamais compris (après lecture des différents posts à de nombreuses reprises) de la "bonne façon" de faire cela en utilisant seulement JAXB.

Par exemple, nous avons une interface Feeet plusieurs de mise en œuvre concrète des classes qui ont en commun certaines propriétés, ainsi que quelques divergences de propriétés et des comportements très différents. Le Xml que nous utilisons pour configurer la Liste des Taxes utilisée par l'application est:

<fees>
   <fee type="Commission" name="commission" rate="0.000125" />
   <fee type="FINRAPerShare" name="FINRA" rate="0.000119" />
   <fee type="SEC" name="SEC" rate="0.0000224" />
   <fee type="Route" name="ROUTES">
       <routes>
        <route>
            <name>NYSE</name>
            <rates>
                <billing code="2" rate="-.0014" normalized="A" />
                <billing code="1" rate=".0029" normalized="R" />
            </rates>
        </route>        
        </routes>
          ...
    </fee>
  </fees>

Dans le Xml ci-dessus, chaque <fee> élément correspond à un béton sous-classe d'une Taxe de l'interface. Le type attribut donne des informations sur le type d'instancier, et puis une fois qu'il est instancié, le JAXB unmarshalling applique les propriétés et le reste de Xml.

J'ai toujours recours à de faire quelque chose comme ceci:

private void addFees(TradeFeeCalculator calculator) throws Exception {
    NodeList feeElements = configDocument.getElementsByTagName("fee");
    for (int i = 0; i < feeElements.getLength(); i++) {
        Element feeElement = (Element) feeElements.item(i);
        TradeFee fee = createFee(feeElement);
        calculator.add(fee);
    }
}

private TradeFee createFee(Element feeElement) {
    try {
        String type = feeElement.getAttribute("type");
        LOG.info("createFee(): creating TradeFee for type=" + type);
        Class<?> clazz = getClassFromType(type);
        TradeFee fee = (TradeFee) JAXBConfigurator.createAndConfigure(clazz, feeElement);
        return fee;
    } catch (Exception e) {
        throw new RuntimeException("Trade Fees are misconfigured, xml which caused this=" + XmlUtils.toString(feeElement), e);
    }
}

Dans le code ci-dessus, le JAXBConfigurator est juste un simple wrapper autour de la JAXB objets pour unmarshalling:

public static Object createAndConfigure(Class<?> clazz, Node startNode) {
    try {
        JAXBContext context = JAXBContext.newInstance(clazz);
        Unmarshaller unmarshaller = context.createUnmarshaller();
        @SuppressWarnings("rawtypes")
        JAXBElement configElement = unmarshaller.unmarshal(startNode, clazz);
        return configElement.getValue();
    } catch (JAXBException e) {
        throw new RuntimeException(e);
    }
}

À la fin, le code ci-dessus, nous obtenons une Liste qui contient selon les types ont été configurés dans le fichier Xml.

Est-il un moyen d'obtenir JAXB pour faire cela automatiquement sans avoir à écrire le code pour parcourir les éléments ci-dessus?

source d'informationauteur Sam Goldberg