JAXB element name based on object property

I have to create object model for following XMLs:

XML sample 1:

<InvoiceAdd>
  <TxnDate>2009-01-21</TxnDate>
  <RefNumber>1</RefNumber>
  <InvoiceLineAdd>
  </InvoiceLineAdd>
</InvoiceAdd>

XML Sample 2:

<SalesOrderAdd>
  <TxnDate>2009-01-21</TxnDate>
  <RefNumber>1</RefNumber>
  <SalesOrderLineAdd>
  </SalesOrderLineAdd>
</SalesOrderAdd>

The XML output will be based on a single string parameter or enum. String txnType = "Invoice"; (or "SalesOrder");

I would use single class TransactionAdd:

@XmlRootElement
public class TransactionAdd {  
  public String txnDate;
  public String refNumber;

  private String txnType;
  ...

  public List<LineAdd> lines;
}

instead of using subclasses or anything else. The code which creates the TransactionAdd instance is the same for both types of transaction it only differs on the type.

This XML is used by a rather known product called QuickBooks and is consumed by QuickBooks web service - so I can't change the XML, but I want to make it easy to be able to set element name based on property (txnType).

I would consider something like a method to determine target element name:

@XmlRootElement
public class TransactionAdd {  
  public String txnDate;
  public String refNumber;

  private String txnType;
  ...

  public List<LineAdd> lines;

  public String getElementName() {
     return txnType + "Add";
  }
}

Different transactions will be created using following code:

t = new TransactionAdd();
t.txnDate = "2010-12-15";
t.refNumber = "123";
t.txnType = "Invoice";

The goal is to serialize t object with the top-level element name based on txnType. E.g.:

<InvoiceAdd>
   <TxnDate>2009-01-21</TxnDate>
   <RefNumber>1</RefNumber>
</InvoiceAdd>

In case of t.txnType = "SalesOrder" the result should be

<SalesOrderAdd>
   <TxnDate>2009-01-21</TxnDate>
   <RefNumber>1</RefNumber>
</SalesOrderAdd>

At the moment I see only one workaround with subclasses InvoiceAdd and SalesOrderAdd and using @XmlElementRef annotation to have a name based on class name. But it will need to instantiate different classes based on transaction type and also will need to have two other different classes InvoiceLineAdd and SalesOrderLineAdd which looks rather ugly.

Please suggest me any solution to handle this. I would consider something simple.

8
задан Vladimir 15 December 2010 в 12:27
поделиться