Solucionado (ver solução)
Solucionado
(ver solução)
7
respostas

Problema com Serialização em Polimorfismo

Olá pessoal, estou tendo problemas com o segundo exercício de polimorfismo, quando eu gero o xml ele nao esta gerando o xml dos atributos da classe pai isto é ele so esta colocando o nome da classe filha e não coloca os atributos herdados;

expected:<...produtos>
    <livro[ codigo="1589">
      <nome>O Pássaro Raro</nome>
      <preco>100.0</preco>
      <descrição>dez histórias sobre a existência</descrição>
    </livro>
    <musica codigo="1590">
      <nome>Meu Passeio</nome>
      <preco>100.0</preco>
      <descrição>música livre</descrição>
    </musica]>
  </produtos>
</co...>

" but was:<...produtos>
    <livro[/>
    <musica/]>
  </produtos>

</co...>

junit.framework.AssertionFailedError: expected:<...produtos>
    <livro[ codigo="1589">
      <nome>O Pássaro Raro</nome>
      <preco>100.0</preco>
      <descrição>dez histórias sobre a existência</descrição>
    </livro>
    <musica codigo="1590">
      <nome>Meu Passeio</nome>
      <preco>100.0</preco>
      <descrição>música livre</descrição>
    </musica]>
  </produtos>
</co...>

 but was:<...produtos>

 <livro[/>
    <musica/]>
  </produtos>
public class Produto {

    private String nome;
    private double preco;
    private String descricao;
    private int codigo;

    public Produto(String nome, double preco, String descricao, int codigo) {
        this.nome = nome;
        this.preco = preco;
        this.descricao = descricao;
        this.codigo = codigo;
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 43 * hash + Objects.hashCode(this.nome);
        hash = 43 * hash + (int) (Double.doubleToLongBits(this.preco) ^ (Double.doubleToLongBits(this.preco) >>> 32));
        hash = 43 * hash + Objects.hashCode(this.descricao);
        hash = 43 * hash + this.codigo;
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Produto other = (Produto) obj;
        if (!Objects.equals(this.nome, other.nome)) {
            return false;
        }
        if (Double.doubleToLongBits(this.preco) != Double.doubleToLongBits(other.preco)) {
            return false;
        }
        if (!Objects.equals(this.descricao, other.descricao)) {
            return false;
        }
        if (this.codigo != other.codigo) {
            return false;
        }
        return true;
    }



public class Livro extends Produto {

    public Livro(String nome, double preco, String descricao, int codigo) {
        super(nome, preco, descricao, codigo);
    }

}


public class Musica extends Produto {

    public Musica(String nome, double preco, String descricao, int codigo) {
        super(nome, preco, descricao, codigo);
    }

}


public class CompraTest {
 @Test
    public void deveSerializarLivroEMusica() {
        String resultadoEsperado = "<compra>\n"
                + "  <id>15</id>\n"
                + "  <produtos>\n"
                + "    <livro codigo=\"1589\">\n"
                + "      <nome>O Pássaro Raro</nome>\n"
                + "      <preco>100.0</preco>\n"
                + "      <descrição>dez histórias sobre a existência</descrição>\n"
                + "    </livro>\n"
                + "    <musica codigo=\"1590\">\n"
                + "      <nome>Meu Passeio</nome>\n"
                + "      <preco>100.0</preco>\n"
                + "      <descrição>música livre</descrição>\n"
                + "    </musica>\n"
                + "  </produtos>\n"
                + "</compra>";

        XStream xstream = this.xstreamParaCompraEProduto();
        Compra compra = this.compraComLivroEMusica();

        String resultadoObtido = xstream.toXML(compra);

        Assert.assertEquals(resultadoEsperado, resultadoObtido);

    }


    private Compra compraComLivroEMusica() {
        Produto passaro = new Livro("O Pássaro Raro", 100.0, "dez histórias sobre a existência", 1589);
        Produto passeio = new Musica("Meu Passeio", 100.0, "música livre", 1590);

        List<Produto> produtos = new ArrayList<>();
        produtos.add(passaro);
        produtos.add(passeio);

        return new Compra(15, produtos);
    }

 public XStream xstreamParaCompraEProduto() {
        XStream xstream = new XStream();

        xstream.alias("compra", Compra.class);
        xstream.alias("produto", Produto.class);
        xstream.alias("musica", Musica.class);
        xstream.alias("livro", Livro.class);

        xstream.useAttributeFor(Produto.class, "codigo");
        xstream.aliasField("descrição", Produto.class, "descricao");
        return xstream;
    }


}
7 respostas

Oi Weslen, tudo bem? Acho que faltou adicionar essa instrução:

xstream.addImplicitCollection(Compra.class, "produtos");

Pode testar com ela? Logo depois de criar o XStream, você faz:

XStream xstream = this.xstreamParaCompraEProduto();
xstream.addImplicitCollection(Compra.class, "produtos");

Ola Rodrigo, obrigado pela ajuda, porem mesmo colocando esta instrução a saída permanece a mesma isto é ainda não são presentados os atributos na saída.

Weslen pode compartilhar todo o conteúdo do teste, da configuração etc? Poderemos conferir se o código tem algo a mais ou a menos do que precisa.

Ola gilherme, obrigado pela ajuda, segue todo o codigo do teste e as classes que este depende....

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.caelum.xstream;

import com.thoughtworks.xstream.XStream;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import org.junit.Assert;
import org.junit.Test;

/**
 *
 * @author Weslen
 */
public class CompraTest {

    @Test
    public void deveSerializarCadaUmDosProdutosDeUmaCompra() {
        Compra compra = compraComGeladeiraEFerro();
        String resultadoEsperado = "<compra>\n"
                + "  <id>15</id>\n"
                + "  <produtos>\n"
                + "    <produto codigo=\"1587\">\n"
                + "      <nome>geladeira</nome>\n"
                + "      <preco>1000.0</preco>\n"
                + "      <descrição>geladeira duas portas</descrição>\n"
                + "    </produto>\n"
                + "    <produto codigo=\"1588\">\n"
                + "      <nome>ferro de passar</nome>\n"
                + "      <preco>100.0</preco>\n"
                + "      <descrição>ferro com vaporizador</descrição>\n"
                + "    </produto>\n"
                + "  </produtos>\n"
                + "</compra>";

        XStream xstream = xstreamParaCompraEProduto();

        String resultadoObtido = xstream.toXML(compra);

        Assert.assertEquals(resultadoEsperado, resultadoObtido);

    }

    @Test
    public void deveGerarUmaCompraComOsProdutosAdequados() {
        Compra compraEsperada = compraComGeladeiraEFerro();
        String xmlDeOrigem = "<compra>\n"
                + "  <id>15</id>\n"
                + "  <produtos>\n"
                + "    <produto codigo=\"1587\">\n"
                + "      <nome>geladeira</nome>\n"
                + "      <preco>1000.0</preco>\n"
                + "      <descrição>geladeira duas portas</descrição>\n"
                + "    </produto>\n"
                + "    <produto codigo=\"1588\">\n"
                + "      <nome>ferro de passar</nome>\n"
                + "      <preco>100.0</preco>\n"
                + "      <descrição>ferro com vaporizador</descrição>\n"
                + "    </produto>\n"
                + "  </produtos>\n"
                + "</compra>";
        XStream xstream = xstreamParaCompraEProduto();

        Compra compraResultado = (Compra) xstream.fromXML(xmlDeOrigem);

        Assert.assertEquals(compraEsperada, compraResultado);

    }

    @Test
    public void deveSerializarDuasGeladeirasIguais() {
        String resultadoEsperado = "<compra>\n"
                + "  <id>15</id>\n"
                + "  <produtos>\n"
                + "    <produto codigo=\"1587\">\n"
                + "      <nome>geladeira</nome>\n"
                + "      <preco>1000.0</preco>\n"
                + "      <descrição>geladeira duas portas</descrição>\n"
                + "    </produto>\n"
                + "    <produto codigo=\"1587\">\n"
                + "      <nome>geladeira</nome>\n"
                + "      <preco>1000.0</preco>\n"
                + "      <descrição>geladeira duas portas</descrição>\n"
                + "    </produto>\n"
                + "  </produtos>\n"
                + "</compra>";
        XStream xstream = this.xstreamParaCompraEProduto();

        xstream.setMode(XStream.NO_REFERENCES);

        String resultadoObtido = xstream.toXML(this.compraDuasGeladeirasIguais());

        Assert.assertEquals(resultadoEsperado, resultadoObtido);

    }

    @Test
    public void deveSerializarColecaoImplicita() {
        String resultadoEsperado = "<compra>\n"
                + "  <id>15</id>\n"
                + "  <produto codigo=\"1587\">\n"
                + "    <nome>geladeira</nome>\n"
                + "    <preco>1000.0</preco>\n"
                + "    <descrição>geladeira duas portas</descrição>\n"
                + "  </produto>\n"
                + "  <produto codigo=\"1588\">\n"
                + "    <nome>ferro de passar</nome>\n"
                + "    <preco>100.0</preco>\n"
                + "    <descrição>ferro com vaporizador</descrição>\n"
                + "  </produto>\n"
                + "</compra>";

        Compra compra = this.compraComGeladeiraEFerro();
        XStream xstream = this.xstreamParaCompraEProduto();

        xstream.addImplicitCollection(Compra.class, "produtos");

        String resultadoObtido = xstream.toXML(compra);

        Assert.assertEquals(resultadoEsperado, resultadoObtido);

    }

    @Test
    public void deveSerializarLivroEMusica() {
        String resultadoEsperado = "<compra>\n"
                + "  <id>15</id>\n"
                + "  <produtos  class=\"linked-list\">\n"
                + "    <livro codigo=\"1589\">\n"
                + "      <nome>O Pássaro Raro</nome>\n"
                + "      <preco>100.0</preco>\n"
                + "      <descrição>dez histórias sobre a existência</descrição>\n"
                + "    </livro>\n"
                + "    <musica codigo=\"1590\">\n"
                + "      <nome>Meu Passeio</nome>\n"
                + "      <preco>100.0</preco>\n"
                + "      <descrição>música livre</descrição>\n"
                + "    </musica>\n"
                + "  </produtos>\n"
                + "</compra>";

        XStream xstream = this.xstreamParaCompraEProduto();

        Compra compra = this.compraComLivroEMusica();

        String resultadoObtido = xstream.toXML(compra);

        Assert.assertEquals(resultadoEsperado, resultadoObtido);

    }

    @Test
    public void deveUsarUmConversorDiferente() {
        String xmlEsperado = "<compra estilo=\"novo\">\n"
                + "  <id>15</id>\n"
                + "  <fornecedor>guilherme.silveira@caelum.com.br</fornecedor>\n"
                + "  <endereco>\n"
                + "    <linha1>Rua Vergueiro 3185</linha1>\n"
                + "    <linha2>8 andar - Sao Paulo - SP</linha2>\n"
                + "  </endereco>\n"
                + "  <produtos>\n"
                + "    <produto codigo=\"1587\">\n"
                + "      <nome>geladeira</nome>\n"
                + "      <preco>1000.0</preco>\n"
                + "      <descrição>geladeira duas portas</descrição>\n"
                + "    </produto>\n"
                + "    <produto codigo=\"1587\">\n"
                + "      <nome>geladeira</nome>\n"
                + "      <preco>1000.0</preco>\n"
                + "      <descrição>geladeira duas portas</descrição>\n"
                + "    </produto>\n"
                + "  </produtos>\n"
                + "</compra>";

        Compra compra = compraDuasGeladeirasIguais();

        XStream xstream = xstreamParaCompraEProduto();
        xstream.setMode(XStream.NO_REFERENCES);
        xstream.registerConverter(new CompraDiferenteConverter());
        String xmlGerado = xstream.toXML(compra);

        Assert.assertEquals(xmlEsperado, xmlGerado);
    }

    @Test
    public void deserializaComConversor() {
        String xmlGerado = "<compra estilo=\"novo\">\n"
                + "  <id>15</id>\n"
                + "  <fornecedor>guilherme.silveira@caelum.com.br</fornecedor>\n"
                + "  <endereco>\n"
                + "    <linha1>Rua Vergueiro 3185</linha1>\n"
                + "    <linha2>8 andar - Sao Paulo - SP</linha2>\n"
                + "  </endereco>\n"
                + "  <produtos>\n"
                + "    <produto codigo=\"1587\">\n"
                + "      <nome>geladeira</nome>\n"
                + "      <preco>1000.0</preco>\n"
                + "      <descrição>geladeira duas portas</descrição>\n"
                + "    </produto>\n"
                + "    <produto codigo=\"1587\">\n"
                + "      <nome>geladeira</nome>\n"
                + "      <preco>1000.0</preco>\n"
                + "      <descrição>geladeira duas portas</descrição>\n"
                + "    </produto>\n"
                + "  </produtos>\n"
                + "</compra>";
        Compra compra = this.compraDuasGeladeirasIguais();
        XStream xstream = xstreamParaCompraEProduto();
        xstream.setMode(XStream.NO_REFERENCES);
        xstream.registerConverter(new CompraDiferenteConverter());
        Compra deserializada = (Compra) xstream.fromXML(xmlGerado);

        Assert.assertEquals(compra, deserializada);

    }

    private Compra compraComLivroEMusica() {
        Produto passaro = new Livro("O Pássaro Raro", 100.0, "dez histórias sobre a existência", 1589);
        Produto passeio = new Musica("Meu Passeio", 100.0, "música livre", 1590);

        List<Produto> produtos = new LinkedList<>();
        produtos.add(passaro);
        produtos.add(passeio);

        return new Compra(15, produtos);
    }

    public Compra compraComGeladeiraEFerro() {
        List<Produto> listaDeProdutos = new ArrayList<>();
        Produto geladeira = geladeira();
        Produto ferro = ferro();
        listaDeProdutos.add(geladeira);
        listaDeProdutos.add(ferro);
        Compra compraEsperada = new Compra(15, listaDeProdutos);
        return compraEsperada;
    }

    public Compra compraDuasGeladeirasIguais() {
        Produto geladeira = geladeira();

        List<Produto> produtos = new ArrayList<Produto>();
        produtos.add(geladeira);
        produtos.add(geladeira);

        Compra compra = new Compra(15, produtos);
        return compra;

    }

    public XStream xstreamParaCompraEProduto() {
        XStream xstream = new XStream();

        xstream.alias("compra", Compra.class);
        xstream.alias("produto", Produto.class);
        xstream.alias("musica", Musica.class);
        xstream.alias("livro", Livro.class);

        xstream.useAttributeFor(Produto.class, "codigo");
        xstream.aliasField("descrição", Produto.class, "descricao");
        return xstream;
    }

    public Produto ferro() {
        Produto ferro = new Produto("ferro de passar", 100.0, "ferro com vaporizador", 1588);
        return ferro;
    }

    public Produto geladeira() {
        Produto geladeira = new Produto("geladeira", 1000.0, "geladeira duas portas", 1587);
        return geladeira;
    }

}






public class Categoria {

    private Categoria pai;
    private String nome;

    public Categoria(Categoria pai, String nome) {
        this.pai = pai;
        this.nome = nome;
    }

    public void setPai(Categoria pai) {
        this.pai = pai;
    }

}




public class Compra {

    private int id;
    private List<Produto> produtos = new ArrayList<>();

    public Compra(int id, List<Produto> produtos) {
        this.id = id;
        this.produtos = produtos;
    }

    @Override
    public int hashCode() {
        int hash = 5;
        hash = 67 * hash + this.id;
        hash = 67 * hash + Objects.hashCode(this.produtos);
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Compra other = (Compra) obj;
        if (this.id != other.id) {
            return false;
        }
        if (!Objects.equals(this.produtos, other.produtos)) {
            return false;
        }
        return true;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public List<Produto> getProdutos() {
        return produtos;
    }

    public void setProdutos(List<Produto> produtos) {
        this.produtos = produtos;
    }

}



public class CompraDiferenteConverter implements Converter {

    public CompraDiferenteConverter() {
    }

    @Override
    public boolean canConvert(Class type) {
        return type.isAssignableFrom(Compra.class);
    }

    @Override
    public void marshal(Object object, HierarchicalStreamWriter writer,
            MarshallingContext context) {
        writer.addAttribute("estilo", "novo");

        Compra compra = (Compra) object;
        writer.startNode("id");
        context.convertAnother(compra.getId());
        writer.endNode();
        writer.startNode("fornecedor");
        writer.setValue("guilherme.silveira@caelum.com.br");
        writer.endNode();
        writer.startNode("endereco");
        writer.startNode("linha1");
        writer.setValue("Rua Vergueiro 3185");
        writer.endNode();
        writer.startNode("linha2");
        writer.setValue("8 andar - Sao Paulo - SP");
        writer.endNode();
        writer.endNode();
        writer.startNode("produtos");
        context.convertAnother(compra.getProdutos());
        writer.endNode();
    }

    @Override
    public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
        reader.moveDown();
        String nomeId = reader.getNodeName();
        String valorId = reader.getValue();
        reader.moveUp();

        reader.moveDown();
        String nodeFornecedor = reader.getNodeName();
        String valorFornecedor = reader.getValue();
        reader.moveUp();

        reader.moveDown();

        reader.moveDown();
        String nodeLinha1 = reader.getNodeName();
        String valorLinha1 = reader.getValue();
        reader.moveUp();

        reader.moveDown();
        String nodeLinha2 = reader.getNodeName();
        String valorLinha2 = reader.getValue();
        reader.moveUp();
        reader.moveUp();

        reader.moveDown();
        List<Produto> produtos = new ArrayList<>();
        int id = Integer.parseInt(valorId);
        Compra compra = new Compra(id, produtos);

        List<Produto> produtosLidos = (List<Produto>) context.convertAnother(compra, List.class);

        produtos.addAll(produtosLidos);
        reader.moveUp();

        return compra;

    }

}


public class Livro extends Produto {

    public Livro(String nome, double preco, String descricao, int codigo) {
        super(nome, preco, descricao, codigo);
    }

}


public class Musica extends Produto {

    public Musica(String nome, double preco, String descricao, int codigo) {
        super(nome, preco, descricao, codigo);
    }

}


public class PrecoConverter implements SingleValueConverter {

    @Override
    public boolean canConvert(Class type) {
        return type.isAssignableFrom(Double.class);
    }

    @Override
    public Object fromString(String valor) {
        try {
            return this.getFormatter().parse(valor);
        } catch (ParseException ex) {
            throw new ConversionException("Impossivel comverter: " + valor, ex);
        }
    }

    @Override
    public String toString(Object valor) {
        return this.getFormatter().format(valor);
    }

    public NumberFormat getFormatter() {
        Locale brasil = new Locale("pt", "br");
        NumberFormat formatador = NumberFormat.getCurrencyInstance(brasil);
        return formatador;

    }

}


public class Produto {

    private String nome;
    private double preco;
    private String descricao;
    private int codigo;

    public Produto(String nome, double preco, String descricao, int codigo) {
        this.nome = nome;
        this.preco = preco;
        this.descricao = descricao;
        this.codigo = codigo;
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 43 * hash + Objects.hashCode(this.nome);
        hash = 43 * hash + (int) (Double.doubleToLongBits(this.preco) ^ (Double.doubleToLongBits(this.preco) >>> 32));
        hash = 43 * hash + Objects.hashCode(this.descricao);
        hash = 43 * hash + this.codigo;
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Produto other = (Produto) obj;
        if (!Objects.equals(this.nome, other.nome)) {
            return false;
        }
        if (Double.doubleToLongBits(this.preco) != Double.doubleToLongBits(other.preco)) {
            return false;
        }
        if (!Objects.equals(this.descricao, other.descricao)) {
            return false;
        }
        if (this.codigo != other.codigo) {
            return false;
        }
        return true;
    }

}

Weslen, os demais testes estão passando? É só nesse que não serializa?

solução!

Bom dia Weslen,

Rodei o código exato que nos passou e o resultado foi a diferença de um espaço em branco a mais no seu "produtos" no deveSerializarLivroEMusica:

Expected

<compra>
  <id>15</id>
  <produtos  class="linked-list">
    <livro codigo="1589">
      <nome>O Pássaro Raro</nome>
      <preco>100.0</preco>
      <descrição>dez histórias sobre a existência</descrição>
    </livro>
    <musica codigo="1590">
      <nome>Meu Passeio</nome>
      <preco>100.0</preco>
      <descrição>música livre</descrição>
    </musica>
  </produtos>
</compra>


Actual

<compra>
  <id>15</id>
  <produtos class="linked-list">
    <livro codigo="1589">
      <nome>O Pássaro Raro</nome>
      <preco>100.0</preco>
      <descrição>dez histórias sobre a existência</descrição>
    </livro>
    <musica codigo="1590">
      <nome>Meu Passeio</nome>
      <preco>100.0</preco>
      <descrição>música livre</descrição>
    </musica>
  </produtos>
</compra>

Os outros testes todos passam. Usei o XStream 1.4.7 que estava a mão aqui, qual versão você está usando?

Att

aaa que droga como nao vi isso haha realmente era só o espaço embranco, obrigado pela ajuda Guilherme e Rodrigo ^^