(reader, FiscalTicketDTO.class);
this.tickets = tktFacto.immutableReadObjects("tickets");
+ this.extra = reader.readExtra();
}
/**
@@ -131,6 +138,14 @@ public final class CashSessionDTO implements DTOInterface, Serializable
return this.tickets;
}
+ /**
+ * Get all other data.
+ * @return The root object of extra data.
+ */
+ public ExtraObject getExtra() {
+ return this.extra;
+ }
+
@Override
public void checkIntegrity() throws IntegrityExceptions {
// TODO Auto-generated method stub
diff --git a/src/main/java/org/pasteque/coreutil/datatransfer/dto/MovementDTO.java b/src/main/java/org/pasteque/coreutil/datatransfer/dto/MovementDTO.java
index 8b4695f..9999d2d 100644
--- a/src/main/java/org/pasteque/coreutil/datatransfer/dto/MovementDTO.java
+++ b/src/main/java/org/pasteque/coreutil/datatransfer/dto/MovementDTO.java
@@ -5,6 +5,7 @@ import java.util.Date;
import org.pasteque.coreutil.ParseException;
import org.pasteque.coreutil.datatransfer.integrity.IntegrityExceptions;
import org.pasteque.coreutil.datatransfer.parser.Reader;
+import org.pasteque.coreutil.extra.ExtraObject;
/**
* Change in currency amounts not introduced by the payment of a ticket.
@@ -26,6 +27,8 @@ public final class MovementDTO implements DTOInterface, Serializable
private double currencyAmount;
/** See {@link getDate()}. */
private Date date;
+ /** See {@link getExtra()}. */
+ private ExtraObject extra;
/**
* Create a movement from all fields.
@@ -33,16 +36,19 @@ public final class MovementDTO implements DTOInterface, Serializable
* @param currency See {@link getCurrency()}.
* @param currencyAmount See {@link getCurrencyAmount()}.
* @param date See {@link getDate()}.
+ * @param extra See {@link getExtra()}.
*/
public MovementDTO(
WeakAssociationDTO paymentMode,
WeakAssociationDTO currency,
double currencyAmount,
- Date date) {
+ Date date,
+ ExtraObject extra) {
this.paymentMode = paymentMode;
this.currency = currency;
this.currencyAmount = currencyAmount;
this.date = date;
+ this.extra = extra;
}
/**
@@ -60,6 +66,7 @@ public final class MovementDTO implements DTOInterface, Serializable
reader.endObject();
this.currencyAmount = reader.readDouble("currencyAmount");
this.date = reader.readDate("date");
+ this.extra = reader.readExtra();
}
/**
@@ -94,6 +101,14 @@ public final class MovementDTO implements DTOInterface, Serializable
return this.date;
}
+ /**
+ * Get all other data.
+ * @return The root object of extra data.
+ */
+ public ExtraObject getExtra() {
+ return this.extra;
+ }
+
@Override
public void checkIntegrity() throws IntegrityExceptions {
// TODO Auto-generated method stub
diff --git a/src/main/java/org/pasteque/coreutil/datatransfer/dto/PaymentDTO.java b/src/main/java/org/pasteque/coreutil/datatransfer/dto/PaymentDTO.java
index e712830..afd10e5 100644
--- a/src/main/java/org/pasteque/coreutil/datatransfer/dto/PaymentDTO.java
+++ b/src/main/java/org/pasteque/coreutil/datatransfer/dto/PaymentDTO.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import org.pasteque.coreutil.ParseException;
import org.pasteque.coreutil.datatransfer.integrity.IntegrityExceptions;
import org.pasteque.coreutil.datatransfer.parser.Reader;
+import org.pasteque.coreutil.extra.ExtraObject;
/**
*
Payment amount Data Transfer Object. A payment may refer to a single one
@@ -24,6 +25,8 @@ public final class PaymentDTO implements DTOInterface, Serializable
private double amount;
/** See {@link getCurrencyAmount()}. */
private double currencyAmount;
+ /** See {@link getExtra()}. */
+ private ExtraObject extra;
/**
* Create a payment from all fields.
@@ -31,16 +34,19 @@ public final class PaymentDTO implements DTOInterface, Serializable
* @param amount See {@link getAmount()}.
* @param currency See {@link getCurrency()}.
* @param currencyAmount See {@link getCurrencyAmount()}.
+ * @param extra See {@link getExtra()}.
*/
public PaymentDTO(
WeakAssociationDTO paymentMode,
double amount,
WeakAssociationDTO currency,
- double currencyAmount) {
+ double currencyAmount,
+ ExtraObject extra) {
this.paymentMode = paymentMode;
this.amount = amount;
this.currency = currency;
this.currencyAmount = currencyAmount;
+ this.extra = extra;
}
/**
@@ -58,6 +64,7 @@ public final class PaymentDTO implements DTOInterface, Serializable
this.currency = new WeakAssociationDTO(reader);
reader.endObject();
this.currencyAmount = reader.readDouble("currencyAmount");
+ this.extra = reader.readExtra();
}
/**
@@ -92,6 +99,14 @@ public final class PaymentDTO implements DTOInterface, Serializable
return this.currencyAmount;
}
+ /**
+ * Get all other data.
+ * @return The root object of extra data.
+ */
+ public ExtraObject getExtra() {
+ return this.extra;
+ }
+
@Override
public void checkIntegrity() throws IntegrityExceptions {
// TODO Auto-generated method stub
diff --git a/src/main/java/org/pasteque/coreutil/datatransfer/dto/TaxAmountDTO.java b/src/main/java/org/pasteque/coreutil/datatransfer/dto/TaxAmountDTO.java
index 77aaacd..37bb238 100644
--- a/src/main/java/org/pasteque/coreutil/datatransfer/dto/TaxAmountDTO.java
+++ b/src/main/java/org/pasteque/coreutil/datatransfer/dto/TaxAmountDTO.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import org.pasteque.coreutil.ParseException;
import org.pasteque.coreutil.datatransfer.integrity.IntegrityExceptions;
import org.pasteque.coreutil.datatransfer.parser.Reader;
+import org.pasteque.coreutil.extra.ExtraObject;
/**
*
Tax amount Data Transfer Object. A tax amount may refer to a single one
@@ -26,6 +27,8 @@ public final class TaxAmountDTO implements DTOInterface, Serializable
private double amount;
/** See {@link getIncludedInBase()}. */
private boolean includedInBase;
+ /** See {@link getExtra()}. */
+ private ExtraObject extra;
/**
* Create a tax from all fields.
@@ -34,18 +37,21 @@ public final class TaxAmountDTO implements DTOInterface, Serializable
* @param base See {@link getBase()}.
* @param amount See {@link getAmount()}.
* @param includedInBase See {@link getIncludedInBase()}.
+ * @param extra See {@link getExtra()}.
*/
public TaxAmountDTO(
WeakAssociationDTO tax,
double taxRate,
double base,
double amount,
- boolean includedInBase) {
+ boolean includedInBase,
+ ExtraObject extra) {
this.tax = tax;
this.taxRate = taxRate;
this.base = base;
this.amount = amount;
this.includedInBase = includedInBase;
+ this.extra = extra;
}
/**
@@ -62,6 +68,7 @@ public final class TaxAmountDTO implements DTOInterface, Serializable
this.base = reader.readDouble("base");
this.amount = reader.readDouble("amount");
this.includedInBase = reader.readBoolean("includedInBase");
+ this.extra = reader.readExtra();
}
/**
@@ -106,6 +113,14 @@ public final class TaxAmountDTO implements DTOInterface, Serializable
return this.includedInBase;
}
+ /**
+ * Get all other data.
+ * @return The root object of extra data.
+ */
+ public ExtraObject getExtra() {
+ return this.extra;
+ }
+
@Override
public void checkIntegrity() throws IntegrityExceptions {
// TODO Auto-generated method stub
diff --git a/src/main/java/org/pasteque/coreutil/datatransfer/dto/TaxDTO.java b/src/main/java/org/pasteque/coreutil/datatransfer/dto/TaxDTO.java
index 5bc26e8..d40551a 100644
--- a/src/main/java/org/pasteque/coreutil/datatransfer/dto/TaxDTO.java
+++ b/src/main/java/org/pasteque/coreutil/datatransfer/dto/TaxDTO.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import org.pasteque.coreutil.ParseException;
import org.pasteque.coreutil.datatransfer.integrity.IntegrityExceptions;
import org.pasteque.coreutil.datatransfer.parser.Reader;
+import org.pasteque.coreutil.extra.ExtraObject;
/**
* Tax Data Transfer Object.
@@ -17,20 +18,25 @@ public final class TaxDTO implements DTOInterface, Serializable
private double amount;
/** See {@link getIncludedInBase()}. */
private boolean includedInBase;
+ /** See {@link getExtra()}. */
+ private ExtraObject extra;
/**
* Create a tax from all fields.
* @param type See {@link getType()}.
* @param amount See {@link getAmount()}.
* @param includedInBase See {@link getIncludedInBase()}.
+ * @param extra See {@link getExtra()}.
*/
public TaxDTO(
String type,
double amount,
- boolean includedInBase) {
+ boolean includedInBase,
+ ExtraObject extra) {
this.type = type;
this.amount = amount;
this.includedInBase = includedInBase;
+ this.extra = extra;
}
/**
@@ -43,6 +49,7 @@ public final class TaxDTO implements DTOInterface, Serializable
this.type = reader.readString("type");
this.amount = reader.readDouble("amount");
this.includedInBase = reader.readBoolean("includedInBase");
+ this.extra = reader.readExtra();
}
/**
@@ -75,6 +82,14 @@ public final class TaxDTO implements DTOInterface, Serializable
return this.includedInBase;
}
+ /**
+ * Get all other data.
+ * @return The root object of extra data.
+ */
+ public ExtraObject getExtra() {
+ return this.extra;
+ }
+
@Override
public void checkIntegrity() throws IntegrityExceptions {
// TODO Auto-generated method stub
diff --git a/src/main/java/org/pasteque/coreutil/datatransfer/dto/TicketDTO.java b/src/main/java/org/pasteque/coreutil/datatransfer/dto/TicketDTO.java
index bf839c4..30a7958 100644
--- a/src/main/java/org/pasteque/coreutil/datatransfer/dto/TicketDTO.java
+++ b/src/main/java/org/pasteque/coreutil/datatransfer/dto/TicketDTO.java
@@ -7,6 +7,7 @@ import org.pasteque.coreutil.ParseException;
import org.pasteque.coreutil.datatransfer.integrity.IntegrityExceptions;
import org.pasteque.coreutil.datatransfer.parser.DTOFactory;
import org.pasteque.coreutil.datatransfer.parser.Reader;
+import org.pasteque.coreutil.extra.ExtraObject;
/**
*
Receipt of a finalized and paid order. Tickets are immutable unless changes
@@ -55,6 +56,8 @@ public final class TicketDTO implements DTOInterface, Serializable
private double finalPrice;
/** See {@link getFinalTaxedPrice()}. */
private double finalTaxedPrice;
+ /** See {@link getExtra()}. */
+ private ExtraObject extra;
/**
* Create an ticket from all fields.
@@ -76,6 +79,7 @@ public final class TicketDTO implements DTOInterface, Serializable
* @param discountRate See {@link getDiscountRate()}.
* @param finalPrice See {@link getFinalPrice()}.
* @param finalTaxedPrice See {@link getFinalTaxedPrice()}.
+ * @param extra See {@link getExtra()}.
*/
public TicketDTO(
WeakAssociationDTO cashRegister,
@@ -95,7 +99,8 @@ public final class TicketDTO implements DTOInterface, Serializable
WeakAssociationDTO discountProfile,
double discountRate,
double finalPrice,
- double finalTaxedPrice) {
+ double finalTaxedPrice,
+ ExtraObject extra) {
this.cashRegister = cashRegister;
this.sequence = sequence;
this.number = number;
@@ -114,6 +119,7 @@ public final class TicketDTO implements DTOInterface, Serializable
this.discountRate = discountRate;
this.finalPrice = finalPrice;
this.finalTaxedPrice = finalTaxedPrice;
+ this.extra = extra;
}
/**
@@ -146,6 +152,7 @@ public final class TicketDTO implements DTOInterface, Serializable
this.taxes = taxFacto.immutableReadObjects("taxes");
DTOFactory pmtFacto = new DTOFactory(reader, PaymentDTO.class);
this.payments = pmtFacto.immutableReadObjects("payments");
+ this.extra = reader.readExtra();
}
/**
@@ -311,6 +318,14 @@ public final class TicketDTO implements DTOInterface, Serializable
return this.finalTaxedPrice;
}
+ /**
+ * Get all other data.
+ * @return The root object of extra data.
+ */
+ public ExtraObject getExtra() {
+ return this.extra;
+ }
+
@Override
public void checkIntegrity() throws IntegrityExceptions {
// TODO Auto-generated method stub
diff --git a/src/main/java/org/pasteque/coreutil/datatransfer/dto/ZTicketDTO.java b/src/main/java/org/pasteque/coreutil/datatransfer/dto/ZTicketDTO.java
index b4e9e13..0c185a7 100644
--- a/src/main/java/org/pasteque/coreutil/datatransfer/dto/ZTicketDTO.java
+++ b/src/main/java/org/pasteque/coreutil/datatransfer/dto/ZTicketDTO.java
@@ -7,6 +7,7 @@ import org.pasteque.coreutil.ParseException;
import org.pasteque.coreutil.datatransfer.integrity.IntegrityExceptions;
import org.pasteque.coreutil.datatransfer.parser.DTOFactory;
import org.pasteque.coreutil.datatransfer.parser.Reader;
+import org.pasteque.coreutil.extra.ExtraObject;
/**
* Receipt of a finalized cash session. Once a cash session is closed,
@@ -64,6 +65,8 @@ public final class ZTicketDTO implements DTOInterface, Serializable
private ImmutableList payments;
/** See {@link getCustBalances()}. */
private ImmutableList custBalances;
+ /** See {@link getExtra()}. */
+ private ExtraObject extra;
/**
* Create an ticket from all fields.
@@ -87,6 +90,7 @@ public final class ZTicketDTO implements DTOInterface, Serializable
* @param catTaxes See {@link getCatTaxes()}.
* @param payments See {@link getPayments()}.
* @param custBalances See {@link getCustBalances()}.
+ * @param extra See {@link getExtra()}.
*/
public ZTicketDTO(
WeakAssociationDTO cashRegister,
@@ -108,7 +112,8 @@ public final class ZTicketDTO implements DTOInterface, Serializable
ZTicketCatSalesDTO[] catSales,
ZTicketCatTaxesDTO[] catTaxes,
PaymentDTO[] payments,
- ZTicketCustBalanceDTO[] custBalances) {
+ ZTicketCustBalanceDTO[] custBalances,
+ ExtraObject extra) {
this.cashRegister = cashRegister;
this.sequence = sequence;
this.continuous = continuous;
@@ -129,6 +134,7 @@ public final class ZTicketDTO implements DTOInterface, Serializable
this.catTaxes = new ImmutableList(catTaxes);
this.payments = new ImmutableList(payments);
this.custBalances = new ImmutableList(custBalances);
+ this.extra = extra;
}
/**
@@ -168,7 +174,7 @@ public final class ZTicketDTO implements DTOInterface, Serializable
this.payments = pmtFacto.immutableReadObjects("payments");
DTOFactory custBFacto = new DTOFactory(reader, ZTicketCustBalanceDTO.class);
this.custBalances = custBFacto.immutableReadObjects("custBalances");
- reader.startArray("custBalances");
+ this.extra = reader.readExtra();
}
/**
@@ -354,6 +360,14 @@ public final class ZTicketDTO implements DTOInterface, Serializable
return this.custBalances;
}
+ /**
+ * Get all other data.
+ * @return The root object of extra data.
+ */
+ public ExtraObject getExtra() {
+ return this.extra;
+ }
+
@Override
public void checkIntegrity() throws IntegrityExceptions {
// TODO Auto-generated method stub
diff --git a/src/main/java/org/pasteque/coreutil/datatransfer/dto/package-info.java b/src/main/java/org/pasteque/coreutil/datatransfer/dto/package-info.java
index 588e65f..f0daf2e 100644
--- a/src/main/java/org/pasteque/coreutil/datatransfer/dto/package-info.java
+++ b/src/main/java/org/pasteque/coreutil/datatransfer/dto/package-info.java
@@ -4,5 +4,7 @@
* All the DTO are final to ensure the immutability. Extensions should use
* encapsulation to add more data or ease-of-use, to ensure the major package
* using them cannot be alterated.
+ * This objects contains only amounts and minimal content description, all
+ * other data are stored in extra objects allow extensions.
*/
package org.pasteque.coreutil.datatransfer.dto;
diff --git a/src/main/java/org/pasteque/coreutil/datatransfer/parser/JSONReader.java b/src/main/java/org/pasteque/coreutil/datatransfer/parser/JSONReader.java
index 4c532d5..44ce918 100644
--- a/src/main/java/org/pasteque/coreutil/datatransfer/parser/JSONReader.java
+++ b/src/main/java/org/pasteque/coreutil/datatransfer/parser/JSONReader.java
@@ -15,7 +15,7 @@ import org.pasteque.coreutil.datatransfer.format.BinaryDTOFormat;
/**
* Read values from a JSON representation of data.
*/
-public class JSONReader implements Reader
+public class JSONReader extends ReaderHelper
{
/** Constant for the state of not having parsed anything yet. */
private static final String ROOT_NAME = "__ROOT__";
@@ -98,13 +98,13 @@ public class JSONReader implements Reader
}
}
- @Override
+ @Override // from Reader
public boolean hasKey(String key) throws ParseException {
this.checkCurrentObject();
return this.currentObject.has(key);
}
- @Override
+ @Override // from Reader
public List listKeys() throws ParseException {
this.checkCurrentObject();
Set keySet = this.currentObject.keySet();
@@ -116,25 +116,25 @@ public class JSONReader implements Reader
return keys;
}
- @Override
+ @Override // from Reader
public int getArraySize() throws ParseException {
this.checkCurrentArray();
return this.currentArray.length();
}
- @Override
+ @Override // from Reader
public boolean isNull(String key) throws ParseException {
this.checkCurrentObject();
return this.currentObject.isNull(key);
}
- @Override
+ @Override // from Reader
public boolean isNull(int index) throws ParseException {
this.checkCurrentArrayIndex(index);
return this.currentArray.isNull(index);
}
- @Override
+ @Override // from Reader
public boolean readBoolean(String key) throws ParseException {
this.checkCurrentObject();
try {
@@ -144,12 +144,7 @@ public class JSONReader implements Reader
}
}
- @Override
- public Boolean readBooleanOrNull(String key) throws ParseException {
- return (this.isNull(key)) ? null : Boolean.valueOf(this.readBoolean(key));
- }
-
- @Override
+ @Override // from Reader
public boolean readBoolean(int index) throws ParseException {
this.checkCurrentArrayIndex(index);
try {
@@ -159,12 +154,7 @@ public class JSONReader implements Reader
}
}
- @Override
- public Boolean readBooleanOrNull(int index) throws ParseException {
- return (this.isNull(index)) ? null : Boolean.valueOf(this.readBoolean(index));
- }
-
- @Override
+ @Override // from Reader
public String readString(String key) throws ParseException {
this.checkCurrentObject();
try {
@@ -174,17 +164,7 @@ public class JSONReader implements Reader
}
}
- @Override
- public String readStringOrNull(String key) throws ParseException {
- return (this.isNull(key)) ? null : this.readString(key);
- }
-
- @Override
- public String readStringOrEmpty(String key) throws ParseException {
- return (this.isNull(key)) ? "" : this.readString(key);
- }
-
- @Override
+ @Override // from Reader
public String readString(int index) throws ParseException {
this.checkCurrentArrayIndex(index);
try {
@@ -194,17 +174,7 @@ public class JSONReader implements Reader
}
}
- @Override
- public String readStringOrNull(int index) throws ParseException {
- return (this.isNull(index)) ? null : this.readString(index);
- }
-
- @Override
- public String readStringOrEmpty(int index) throws ParseException {
- return (this.isNull(index)) ? "" : this.readString(index);
- }
-
- @Override
+ @Override // from Reader
public int readInt(String key) throws ParseException {
this.checkCurrentObject();
try {
@@ -214,12 +184,7 @@ public class JSONReader implements Reader
}
}
- @Override
- public Integer readIntOrNull(String key) throws ParseException {
- return (this.isNull(key)) ? null : Integer.valueOf(this.readInt(key));
- }
-
- @Override
+ @Override // from Reader
public int readInt(int index) throws ParseException {
this.checkCurrentArrayIndex(index);
try {
@@ -229,13 +194,7 @@ public class JSONReader implements Reader
}
}
- @Override
- public Integer readIntOrNull(int index) throws ParseException {
- return (this.isNull(index)) ? null : Integer.valueOf(this.readInt(index));
- }
-
-
- @Override
+ @Override // from Reader
public double readDouble(String key) throws ParseException {
this.checkCurrentObject();
try {
@@ -245,12 +204,7 @@ public class JSONReader implements Reader
}
}
- @Override
- public Double readDoubleOrNull(String key) throws ParseException {
- return (this.isNull(key)) ? null : Double.valueOf(this.readDouble(key));
- }
-
- @Override
+ @Override // from Reader
public double readDouble(int index) throws ParseException {
this.checkCurrentArray();
try {
@@ -260,12 +214,7 @@ public class JSONReader implements Reader
}
}
- @Override
- public Double readDoubleOrNull(int index) throws ParseException {
- return (this.isNull(index)) ? null : Double.valueOf(this.readDouble(index));
- }
-
- @Override
+ @Override // from Reader
public Date readDate(String key) throws ParseException {
this.checkCurrentObject();
try {
@@ -281,12 +230,7 @@ public class JSONReader implements Reader
}
}
- @Override
- public Date readDateOrNull(String key) throws ParseException {
- return (this.isNull(key)) ? null : this.readDate(key);
- }
-
- @Override
+ @Override // from Reader
public Date readDate(int index) throws ParseException {
this.checkCurrentArrayIndex(index);
try {
@@ -302,12 +246,7 @@ public class JSONReader implements Reader
}
}
- @Override
- public Date readDateOrNull(int index) throws ParseException {
- return (this.isNull(index)) ? null : this.readDate(index);
- }
-
- @Override
+ @Override // from Reader
public byte[] readBinary(String key) throws ParseException {
this.checkCurrentObject();
try {
@@ -318,12 +257,7 @@ public class JSONReader implements Reader
}
}
- @Override
- public byte[] readBinaryOrNull(String key) throws ParseException {
- return (this.isNull(key)) ? null : this.readBinary(key);
- }
-
- @Override
+ @Override // from Reader
public byte[] readBinary(int index) throws ParseException {
this.checkCurrentArrayIndex(index);
try {
@@ -334,12 +268,7 @@ public class JSONReader implements Reader
}
}
- @Override
- public byte[] readBinaryOrNull(int index) throws ParseException {
- return (this.isNull(index)) ? null : this.readBinary(index);
- }
-
- @Override
+ @Override // from Reader
public void startObject() throws ParseException {
if (this.currentObject == null && this.currentArray == null
&& this.mainObject == null && this.mainArray == null) {
@@ -350,7 +279,7 @@ public class JSONReader implements Reader
}
}
- @Override
+ @Override // from Reader
public void startObject(String key) throws ParseException {
this.checkCurrentObject();
try {
@@ -361,7 +290,7 @@ public class JSONReader implements Reader
this.path.add(new Path(PathType.OBJECT, key));
}
- @Override
+ @Override // from Reader
public void startObject(int index) throws ParseException {
this.checkCurrentArrayIndex(index);
try {
@@ -373,14 +302,14 @@ public class JSONReader implements Reader
this.path.add(new Path(PathType.OBJECT, index));
}
- @Override
+ @Override // from Reader
public void endObject() throws ParseException {
this.checkCurrentObject();
this.path.remove(this.path.size() - 1);
this.runPath();
}
- @Override
+ @Override // from Reader
public void startArray() throws ParseException {
if (this.currentObject == null && this.currentArray == null
&& this.mainObject == null && this.mainArray == null) {
@@ -391,7 +320,7 @@ public class JSONReader implements Reader
}
}
- @Override
+ @Override // from Reader
public void startArray(String key) throws ParseException {
this.checkCurrentObject();
try {
@@ -403,7 +332,7 @@ public class JSONReader implements Reader
this.path.add(new Path(PathType.ARRAY, key));
}
- @Override
+ @Override // from Reader
public void startArray(int index) throws ParseException {
this.checkCurrentArrayIndex(index);
try {
@@ -414,7 +343,7 @@ public class JSONReader implements Reader
this.path.add(new Path(PathType.ARRAY, index));
}
- @Override
+ @Override // from Reader
public void endArray() throws ParseException {
this.checkCurrentArray();
this.path.remove(this.path.size() - 1);
diff --git a/src/main/java/org/pasteque/coreutil/datatransfer/parser/Reader.java b/src/main/java/org/pasteque/coreutil/datatransfer/parser/Reader.java
index de516b9..0379f51 100644
--- a/src/main/java/org/pasteque/coreutil/datatransfer/parser/Reader.java
+++ b/src/main/java/org/pasteque/coreutil/datatransfer/parser/Reader.java
@@ -3,6 +3,7 @@ package org.pasteque.coreutil.datatransfer.parser;
import java.util.Date;
import java.util.List;
import org.pasteque.coreutil.ParseException;
+import org.pasteque.coreutil.extra.ExtraObject;
/**
* Data reader.
@@ -268,6 +269,15 @@ public interface Reader
*/
public byte[] readBinaryOrNull(String key) throws ParseException;
+ /**
+ * Read the extra object.
+ * @return The root extra object. If not present, it must return an empty
+ * extra object.
+ * @throws ParseException When an error occurs while reading the extra
+ * object.
+ */
+ public ExtraObject readExtra() throws ParseException;
+
/**
* Read binary data as base64 at the given index of the current element.
* @param index The index to read in the current element.
diff --git a/src/main/java/org/pasteque/coreutil/datatransfer/parser/ReaderHelper.java b/src/main/java/org/pasteque/coreutil/datatransfer/parser/ReaderHelper.java
new file mode 100644
index 0000000..d2d2bec
--- /dev/null
+++ b/src/main/java/org/pasteque/coreutil/datatransfer/parser/ReaderHelper.java
@@ -0,0 +1,169 @@
+package org.pasteque.coreutil.datatransfer.parser;
+
+import java.util.Date;
+import java.util.List;
+import org.pasteque.coreutil.ParseException;
+import org.pasteque.coreutil.extra.ExtraObject;
+
+/**
+ * Common behaviour implementation of a data reader.
+ */
+public abstract class ReaderHelper implements Reader
+{
+ @Override // from Reader
+ public abstract boolean hasKey(String key) throws ParseException;
+
+ @Override // from Reader
+ public abstract List listKeys() throws ParseException;
+
+ @Override // from Reader
+ public abstract int getArraySize() throws ParseException;
+
+ @Override // from Reader
+ public abstract boolean isNull(String key) throws ParseException;
+
+ @Override // from Reader
+ public abstract boolean isNull(int index) throws ParseException;
+
+ @Override // from Reader
+ public abstract boolean readBoolean(String key) throws ParseException;
+
+ @Override // from Reader
+ public Boolean readBooleanOrNull(String key) throws ParseException {
+ return (this.isNull(key)) ? null : Boolean.valueOf(this.readBoolean(key));
+ }
+
+ @Override // from Reader
+ public abstract boolean readBoolean(int index) throws ParseException;
+
+ @Override // from Reader
+ public Boolean readBooleanOrNull(int index) throws ParseException {
+ return (this.isNull(index)) ? null : Boolean.valueOf(this.readBoolean(index));
+ }
+ @Override // from Reader
+ public abstract String readString(String key) throws ParseException;
+
+ @Override // from Reader
+ public String readStringOrNull(String key) throws ParseException {
+ return (this.isNull(key)) ? null : this.readString(key);
+ }
+
+ @Override // from Reader
+ public String readStringOrEmpty(String key) throws ParseException {
+ return (this.isNull(key)) ? "" : this.readString(key);
+ }
+
+ @Override // from Reader
+ public abstract String readString(int index) throws ParseException;
+
+ @Override // from Reader
+ public String readStringOrNull(int index) throws ParseException {
+ return (this.isNull(index)) ? null : this.readString(index);
+ }
+
+ @Override // from Reader
+ public String readStringOrEmpty(int index) throws ParseException {
+ return (this.isNull(index)) ? "" : this.readString(index);
+ }
+
+ @Override // from Reader
+ public abstract int readInt(String key) throws ParseException;
+
+ @Override // from Reader
+ public Integer readIntOrNull(String key) throws ParseException {
+ return (this.isNull(key)) ? null : Integer.valueOf(this.readInt(key));
+ }
+
+ @Override // from Reader
+ public abstract int readInt(int index) throws ParseException;
+
+ @Override // from Reader
+ public Integer readIntOrNull(int index) throws ParseException {
+ return (this.isNull(index)) ? null : Integer.valueOf(this.readInt(index));
+ }
+
+ @Override // from Reader
+ public abstract double readDouble(String key) throws ParseException;
+
+ @Override // from Reader
+ public Double readDoubleOrNull(String key) throws ParseException {
+ return (this.isNull(key)) ? null : Double.valueOf(this.readDouble(key));
+ }
+
+ @Override // from Reader
+ public abstract double readDouble(int index) throws ParseException;
+
+ @Override // from Reader
+ public Double readDoubleOrNull(int index) throws ParseException {
+ return (this.isNull(index)) ? null : Double.valueOf(this.readDouble(index));
+ }
+
+ @Override // from Reader
+ public abstract Date readDate(String key) throws ParseException;
+
+ @Override // from Reader
+ public Date readDateOrNull(String key) throws ParseException {
+ return (this.isNull(key)) ? null : this.readDate(key);
+ }
+
+ @Override // from Reader
+ public abstract Date readDate(int index) throws ParseException;
+
+ @Override // from Reader
+ public Date readDateOrNull(int index) throws ParseException {
+ return (this.isNull(index)) ? null : this.readDate(index);
+ }
+
+ @Override // from Reader
+ public abstract byte[] readBinary(String key) throws ParseException;
+
+ @Override // from Reader
+ public byte[] readBinaryOrNull(String key) throws ParseException {
+ return (this.isNull(key)) ? null : this.readBinary(key);
+ }
+
+ @Override // from Reader
+ public abstract byte[] readBinary(int index) throws ParseException;
+
+ @Override // from Reader
+ public byte[] readBinaryOrNull(int index) throws ParseException {
+ return (this.isNull(index)) ? null : this.readBinary(index);
+ }
+
+ @Override // from Reader
+ public ExtraObject readExtra() throws ParseException {
+ if (!this.hasKey(ExtraObject.EXTRA_ROOT_FIELD)
+ || this.isNull(ExtraObject.EXTRA_ROOT_FIELD)) {
+ return new ExtraObject();
+ } else {
+ this.startObject("extra");
+ ExtraObject o = new ExtraObject(this);
+ this.endObject();
+ return o;
+ }
+ }
+
+ @Override // from Reader
+ public abstract void startObject() throws ParseException;
+
+ @Override // from Reader
+ public abstract void startObject(String key) throws ParseException;
+
+ @Override // from Reader
+ public abstract void startObject(int index) throws ParseException;
+
+ @Override // from Reader
+ public abstract void endObject() throws ParseException;
+
+ @Override // from Reader
+ public abstract void startArray() throws ParseException;
+
+ @Override // from Reader
+ public abstract void startArray(String key) throws ParseException;
+
+ @Override // from Reader
+ public abstract void startArray(int index) throws ParseException;
+
+ @Override // from Reader
+ public abstract void endArray() throws ParseException;
+}
diff --git a/src/main/java/org/pasteque/coreutil/datatransfer/parser/Writer.java b/src/main/java/org/pasteque/coreutil/datatransfer/parser/Writer.java
index 473d02f..3d95c3e 100644
--- a/src/main/java/org/pasteque/coreutil/datatransfer/parser/Writer.java
+++ b/src/main/java/org/pasteque/coreutil/datatransfer/parser/Writer.java
@@ -1,5 +1,7 @@
package org.pasteque.coreutil.datatransfer.parser;
+import org.pasteque.coreutil.ParseException;
+
/**
* Data writer.
* A reader must always be initialized from its DTO, typically within
@@ -7,6 +9,123 @@ package org.pasteque.coreutil.datatransfer.parser;
*/
public interface Writer
{
+ /**
+ * Add an int to the current array.
+ * @param value The value to write.
+ * @throws ParseException When writing from outside an array.
+ */
+ public void writeInt(int value) throws ParseException;
+
+ /**
+ * Add an int to the current object.
+ * @param key The key of the value to write.
+ * @param value The value to write.
+ * @throws ParseException When writing from outside an object.
+ */
+ public void writeInt(String key, int value) throws ParseException;
+
+ /**
+ * Add an int to the current array.
+ * @param value The value to write.
+ * @throws ParseException When writing from outside an array.
+ */
+ public void writeDouble(double value) throws ParseException;
+
+ /**
+ * Add an int to the current object.
+ * @param key The key of the value to write.
+ * @param value The value to write.
+ * @throws ParseException When writing from outside an object.
+ */
+ public void writeDouble(String key, double value) throws ParseException;
+
+ /**
+ * Add an int to the current array.
+ * @param value The value to write.
+ * @throws ParseException When writing from outside an array.
+ */
+ public void writeBoolean(boolean value) throws ParseException;
+
+ /**
+ * Add an int to the current object.
+ * @param key The key of the value to write.
+ * @param value The value to write.
+ * @throws ParseException When writing from outside an object.
+ */
+ public void writeBoolean(String key, boolean value) throws ParseException;
+
+ /**
+ * Add an int to the current array.
+ * @param value The value to write.
+ * @throws ParseException When writing from outside an array.
+ * @throws IllegalArgumentException When the value is null.
+ * Use {@link writeNull()} instead.
+ */
+ public void writeString(String value) throws ParseException;
+
+ /**
+ * Add an int to the current object.
+ * @param key The key of the value to write.
+ * @param value The value to write.
+ * @throws ParseException When writing from outside an object.
+ * @throws IllegalArgumentException When the value is null.
+ * Use {@link writeNull()} instead.
+ */
+ public void writeString(String key, String value) throws ParseException;
+
+ /**
+ * Add a null value to the current array.
+ * @throws ParseException When writing from outside an array.
+ */
+ public void writeNull() throws ParseException;
+
+ /**
+ * Add a null value to the current object.
+ * @param key The key of the value to write.
+ * @throws ParseException When writing from outside an object.
+ */
+ public void writeNull(String key) throws ParseException;
+
+ /**
+ * Start (create) a dictionary as the root element or inside an array.
+ * @throws ParseException When the root element is already created or
+ * not currently inside an array.
+ */
+ public void startObject() throws ParseException;
+
+ /**
+ * Start (create) a dictionary as a child element.
+ * @param key The key to read in the current dictionary.
+ * @throws ParseException When writing a key from outside an object.
+ */
+ public void startObject(String key) throws ParseException;
+
+ /**
+ * Finalize the current object and return up into the tree.
+ * @throws ParseException When the current element is not an object.
+ */
+ public void endObject() throws ParseException;
+
+ /**
+ * Start (create) an array as the root element or inside an array.
+ * @throws ParseException When the root element is already created
+ * or not currently inside an array.
+ */
+ public void startArray() throws ParseException;
+
+ /**
+ * Start (create) an array as a child element.
+ * @param key The key in the parent dictionary.
+ * @throws ParseException When writing a key from outside an object.
+ */
+ public void startArray(String key) throws ParseException;
+
+ /**
+ * Finalize the current array and return up into the tree.
+ * @throws ParseException When the current element is not an array.
+ */
+ public void endArray() throws ParseException;
+
/**
* Get the encoded data.
* @return The encoded data.
diff --git a/src/main/java/org/pasteque/coreutil/extra/ExtraArray.java b/src/main/java/org/pasteque/coreutil/extra/ExtraArray.java
new file mode 100644
index 0000000..e493345
--- /dev/null
+++ b/src/main/java/org/pasteque/coreutil/extra/ExtraArray.java
@@ -0,0 +1,193 @@
+package org.pasteque.coreutil.extra;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.pasteque.coreutil.ImmutableList;
+import org.pasteque.coreutil.ParseException;
+import org.pasteque.coreutil.datatransfer.parser.Reader;
+import org.pasteque.coreutil.datatransfer.parser.Writer;
+
+/**
+ * Extra data as an array.
+ */
+public final class ExtraArray implements ExtraData
+{
+ /** See {@link getField(). */
+ private final String field;
+ /** See {@link getValue()}. */
+ private final ImmutableList value;
+ /** See {@link getType()}. */
+ private final ExtraType type;
+
+ /**
+ * Construct an array from a list of values.
+ * @param field The name of the field.
+ * @param type The type of data in the array.
+ * @param value The values in the array. Each data can have the index
+ * as field name.
+ * @throws IllegalArgumentException When the type of one value doesn't match
+ * the type of the array.
+ * @throws Error When one of the {@link ExtraType} is not handled.
+ */
+ /* package */ ExtraArray(String field, ExtraType type, List value)
+ throws IllegalArgumentException {
+ this.field = field;
+ this.type = type;
+ for (ExtraData extra : value) {
+ if (!this.type.checkExtraType(extra)) {
+ throw new IllegalArgumentException(String.format("Invalid type of data %s, expected %s", extra.getClass().toString(), type.getTypeExtraClass().toString()));
+ }
+ }
+ this.value = new ImmutableList(value);
+ }
+
+ /**
+ * Construct an array from a list of values.
+ * @param field The name of the field.
+ * @param type The type of data in the array.
+ * @param value The values in the array. Each data can have the index
+ * as field name.
+ * @throws IllegalArgumentException When the type of one value doesn't match
+ * the type of the array.
+ * @throws Error When one of the {@link ExtraType} is not handled.
+ */
+ /* package */ ExtraArray(String field, ExtraType type, ImmutableList value)
+ throws IllegalArgumentException {
+ this.field = field;
+ this.type = type;
+ for (ExtraData extra : value) {
+ if (!this.type.checkExtraType(extra)) {
+ throw new IllegalArgumentException(String.format("Invalid type of data %s, expected %s", extra.getClass().toString(), type.getTypeExtraClass().toString()));
+ }
+ }
+ this.value = value;
+ }
+
+ /**
+ * Construct an array from a reader.
+ * @param field The name of the field.
+ * @param reader The reader to read data from. It must aready be pointing
+ * to the array.
+ * @throws ParseException When an error happens while reading the data.
+ */
+ /* package */ ExtraArray(String field, Reader reader) throws ParseException {
+ ExtraType arrayType = ExtraType.fromCode(reader.readString("ta"));
+ reader.startArray("v");
+ List data = new ArrayList(reader.getArraySize());
+ for (int i = 0; i < reader.getArraySize(); i++) {
+ switch (arrayType) {
+ case STRING:
+ data.add(new ExtraString(String.valueOf(i), reader.readString(i)));
+ break;
+ case BOOLEAN:
+ data.add(new ExtraBoolean(String.valueOf(i), reader.readBoolean(i)));
+ break;
+ case INTEGER:
+ data.add(new ExtraInt(String.valueOf(i), reader.readInt(i)));
+ break;
+ case DOUBLE:
+ data.add(new ExtraDouble(String.valueOf(i), reader.readDouble(i)));
+ break;
+ case OBJECT:
+ reader.startObject(i);
+ try {
+ data.add(new ExtraObject(String.valueOf(i), reader));
+ } catch (ParseException e) {
+ reader.endObject();
+ reader.endArray();
+ throw e;
+ }
+ reader.endObject();
+ break;
+ case ARRAY:
+ reader.startObject(i);
+ try {
+ data.add(new ExtraArray(String.valueOf(i), reader));
+ } catch (ParseException e) {
+ reader.endObject();
+ reader.endArray();
+ throw e;
+ }
+ reader.endObject();
+ break;
+ case NULL:
+ data.add(new ExtraNull(String.valueOf(i)));
+ break;
+ default:
+ assert false;
+ }
+ }
+ reader.endArray();
+ this.field = field;
+ this.type = arrayType;
+ this.value = new ImmutableList(data);
+ }
+
+ /**
+ * Get the field associated to this extra data.
+ * @return the field name.
+ */
+ @Override // from ExtraData
+ public String getField() {
+ return this.field;
+ }
+
+ /**
+ * Get the type of value hold.
+ * @return The type of values.
+ */
+ public ExtraType getType() {
+ return this.type;
+ }
+
+ @Override // from ExtraData
+ public ImmutableList getValue() {
+ return this.value;
+ }
+
+ /**
+ * Write the content of this ExtraArray in the current writer object.
+ * The Writer must already be inside the object to write.
+ * @param to The writer to write to.
+ * @throws ParseException When an error occurs while writing.
+ */
+ private void innerWrite(Writer to) throws ParseException {
+ to.writeString("t", ExtraType.ARRAY.getTypeCode());
+ to.writeString("ta", this.type.getTypeCode());
+ to.startArray("v");
+ for (ExtraData v : this.value) {
+ try {
+ if (v == null || this.type == ExtraType.NULL) {
+ to.writeNull();
+ } else if (this.type == ExtraType.STRING) {
+ to.writeString((String) v.getValue());
+ } else if (this.type == ExtraType.BOOLEAN) {
+ to.writeBoolean((Boolean) v.getValue());
+ } else if (this.type == ExtraType.INTEGER) {
+ to.writeInt((Integer) v.getValue());
+ } else if (this.type == ExtraType.DOUBLE) {
+ to.writeDouble((Double) v.getValue());
+ } else if (this.type == ExtraType.OBJECT) {
+ ((ExtraObject) v).writeInArray(to);
+ } else if (this.type == ExtraType.ARRAY) {
+ to.startObject();
+ ((ExtraArray) v).innerWrite(to);
+ to.endObject();
+ } else {
+ assert false;
+ }
+ } catch (ParseException e) {
+ to.endArray();
+ throw e;
+ }
+ }
+ to.endArray();
+ }
+
+ @Override // from ExtraData
+ public void write(Writer to) throws ParseException {
+ to.startObject(this.field);
+ this.innerWrite(to);
+ to.endObject();
+ }
+}
diff --git a/src/main/java/org/pasteque/coreutil/extra/ExtraBoolean.java b/src/main/java/org/pasteque/coreutil/extra/ExtraBoolean.java
new file mode 100644
index 0000000..910aa9e
--- /dev/null
+++ b/src/main/java/org/pasteque/coreutil/extra/ExtraBoolean.java
@@ -0,0 +1,55 @@
+package org.pasteque.coreutil.extra;
+
+import org.pasteque.coreutil.ParseException;
+import org.pasteque.coreutil.datatransfer.parser.Writer;
+
+/**
+ * Extra data as a boolean.
+ */
+public final class ExtraBoolean implements ExtraData
+{
+ /** See {@link getField(). */
+ private final String field;
+ /** See {@link getBoolean()}. */
+ private final boolean value;
+
+ /**
+ * Create an extra data.
+ * @param field The field name.
+ * @param value the value.
+ */
+ /* package */ ExtraBoolean(String field, boolean value) {
+ this.field = field;
+ this.value = value;
+ }
+
+ /**
+ * Get the field associated to this extra data.
+ * @return the field name.
+ */
+ @Override // from ExtraData
+ public String getField() {
+ return this.field;
+ }
+
+ /**
+ * Get value.
+ * @return The value.
+ */
+ public boolean getBoolean() {
+ return this.value;
+ }
+
+ @Override // from ExtraData
+ public Object getValue() {
+ return Boolean.valueOf(this.value);
+ }
+
+ @Override // from ExtraData
+ public void write(Writer to) throws ParseException {
+ to.startObject(this.field);
+ to.writeString("t", ExtraType.BOOLEAN.getTypeCode());
+ to.writeBoolean("v", this.value);
+ to.endObject();
+ }
+}
diff --git a/src/main/java/org/pasteque/coreutil/extra/ExtraBuilder.java b/src/main/java/org/pasteque/coreutil/extra/ExtraBuilder.java
new file mode 100644
index 0000000..4186882
--- /dev/null
+++ b/src/main/java/org/pasteque/coreutil/extra/ExtraBuilder.java
@@ -0,0 +1,348 @@
+package org.pasteque.coreutil.extra;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Generator to create and embed {@link org.pasteque.coreutil.extra.ExtraData}
+ * in a dedicated object.
+ * Create a builder and add fields for all extra data and close the builder
+ * to get the root {@link org.pasteque.coreutil.extra.ExtraObject}
+ * to pass to major objects.
+ */
+public final class ExtraBuilder
+{
+ /** The current object being built. Null when building an array. */
+ private TempExtraObject currentObject;
+ /** The current array being built. Null when building an object. */
+ private TempExtraArray currentArray;
+ /** The current branch of the tree of objects and array being built. */
+ private List path;
+
+ /**
+ * Create an empty builder to create an {@link ExtraObject}.
+ */
+ public ExtraBuilder() {
+ this.path = new ArrayList();
+ this.currentObject = new TempExtraObject(ExtraObject.EXTRA_ROOT_FIELD);
+ this.path.add(this.currentObject);
+ }
+
+ /**
+ * Check that the builder is currently building an object.
+ * @throws IllegalStateException When not currently building an object.
+ */
+ private void checkCurrentObject() throws IllegalStateException {
+ if (this.currentObject == null) {
+ throw new IllegalStateException("ExtraBuilder is not currently building an object.");
+ }
+ }
+
+ /**
+ * Check that the builder is currently building an array.
+ * @throws IllegalStateException When not currently building an array.
+ */
+ private void checkCurrentArray() throws IllegalStateException {
+ if (this.currentArray == null) {
+ throw new IllegalStateException("ExtraBuilder is not currently building an array.");
+ }
+ }
+
+ /**
+ * End building the current object or array and move up to the path
+ * to get back to editing the parent object or array.
+ * @throws IllegalStateException When already at the root object.
+ * @throws Error When the path contains anything but ExtraObject or ExtraArray.
+ */
+ private void pathUp() throws IllegalStateException {
+ if (path.size() <= 1) {
+ throw new IllegalStateException("ExtraBuilder is already building the root object. Use close() instead.");
+ }
+ this.path.remove(this.path.size() - 1);
+ ExtraData last = this.path.get(this.path.size() - 1);
+ if (last instanceof TempExtraObject) {
+ this.currentObject = (TempExtraObject) last;
+ this.currentArray = null;
+ } else if (last instanceof TempExtraArray) {
+ this.currentObject = null;
+ this.currentArray = (TempExtraArray) last;
+ } else {
+ throw new Error(String.format("Corrupted ExtraBuilder path. Expecting TempExtraObject or TempExtraArray, found %s", last.getClass().toString()));
+ }
+ }
+
+ /**
+ * Start building a new object as a child of the current array.
+ * @throws IllegalStateException When not currently building an array.
+ */
+ public void startObject() throws IllegalStateException {
+ this.checkCurrentArray();
+ TempExtraObject newObject = new TempExtraObject(String.valueOf(this.currentArray.size()));
+ this.currentArray.addValue(newObject);
+ this.path.add(newObject);
+ this.currentObject = newObject;
+ this.currentArray = null;
+ }
+
+ /**
+ * Start building a new object as a value of the current object.
+ * @param field The name of the field of the current object that will hold
+ * the new object.
+ * @throws IllegalStateException When not currently building an object.
+ */
+ public void startObject(String field) throws IllegalStateException {
+ this.checkCurrentObject();
+ TempExtraObject newObject = new TempExtraObject(field);
+ this.currentObject.setValue(newObject);
+ this.path.add(newObject);
+ this.currentObject = newObject;
+ this.currentArray = null;
+ }
+
+ /**
+ * End building the current object and get back to editing its parent.
+ * @throws IllegalStateException When not currently building an object or
+ * when trying to end the root object.
+ */
+ public void endObject() throws IllegalStateException {
+ this.checkCurrentObject();
+ this.pathUp();
+ }
+
+ /**
+ * Start building a new array as a child of the current array.
+ * @param type The type of data the array will contain.
+ * @throws IllegalStateException When not currently building an array.
+ */
+ public void startArray(ExtraType type) throws IllegalStateException {
+ this.checkCurrentArray();
+ TempExtraArray array = new TempExtraArray(this.currentArray.size(), type);
+ this.currentArray.addValue(array);
+ this.path.add(array);
+ this.currentArray = array;
+ this.currentObject = null;
+ }
+
+ /**
+ * Start building a new array as a value of the current object.
+ * @param field The name of the field of the current object that will hold
+ * the new array.
+ * @param type The type of data the array will contain.
+ * @throws IllegalStateException When not currently building an object.
+ */
+ public void startArray(String field, ExtraType type) throws IllegalStateException {
+ this.checkCurrentObject();
+ TempExtraArray array = new TempExtraArray(field, type);
+ this.currentObject.setValue(array);
+ this.path.add(array);
+ this.currentArray = array;
+ this.currentObject = null;
+ }
+
+ /**
+ * End building the current array and get back to editing its parent.
+ * @throws IllegalStateException When not currently building an array.
+ */
+ public void endArray() throws IllegalStateException {
+ this.checkCurrentArray();
+ this.pathUp();
+ }
+
+ /**
+ * Add a null value to the current array.
+ * @throws IllegalStateException When not currently building an array.
+ */
+ public void addNull() throws IllegalStateException {
+ this.checkCurrentArray();
+ this.currentArray.addValue(new ExtraNull(this.currentArray.size()));
+ }
+
+ /**
+ * Add a null value to the current object.
+ * @param field The name of the field that holds the value.
+ * @throws IllegalStateException When not currently building an object.
+ */
+ public void addNull(String field) throws IllegalStateException {
+ this.checkCurrentObject();
+ ExtraNull value = new ExtraNull(field);
+ this.currentObject.setValue(value);
+ }
+
+ /**
+ * Add a value to the current array.
+ * @param value The value to add. It adds a null value instead when null.
+ * @throws IllegalStateException When not currently building an array.
+ * @throws IllegalArgumentException When not building an array of String.
+ */
+ public void add(String value) throws IllegalStateException {
+ this.checkCurrentArray();
+ if (value == null) {
+ this.addNull();
+ } else {
+ this.currentArray.addValue(new ExtraString(this.currentArray.size(), value));
+ }
+ }
+
+ /**
+ * Add a value to the current object.
+ * @param field The name of the field that holds the value.
+ * @param value The value to add. It adds a null value instead when null.
+ * @throws IllegalStateException When not currently building an object.
+ */
+ public void add(String field, String value) throws IllegalStateException {
+ this.checkCurrentObject();
+ if (value == null) {
+ this.addNull(field);
+ } else {
+ this.currentObject.setValue(new ExtraString(field, value));
+ }
+ }
+
+ /**
+ * Stop building extra data and get the final object.
+ * Once close is called, no other operation can be done.
+ * @return The finalized extra data to pass to a major object.
+ */
+ public ExtraObject close() {
+ TempExtraObject root = (TempExtraObject) this.path.get(0);
+ this.path.clear();
+ this.currentObject = null;
+ this.currentArray = null;
+ return (ExtraObject) root.finalizeExtra();
+ }
+
+ /**
+ * Interface to convert local temporary extra object and array
+ * to the definitive extra data.
+ */
+ private interface TempExtra {
+ /**
+ * Convert the temporary extra to the definitive one.
+ * @return An immutable extra data.
+ */
+ public ExtraData finalizeExtra();
+ }
+
+ /**
+ * A buildable extra object.
+ */
+ private class TempExtraObject implements ExtraData, TempExtra
+ {
+ private List data;
+ private String field;
+
+ public TempExtraObject(String field) {
+ this.data = new ArrayList();
+ this.field = field;
+ }
+
+ /**
+ * Set or replace a value to the current object.
+ * If the field is already set, it is replaced.
+ * @param value The value to add.
+ */
+ private void setValue(ExtraData value) {
+ for (int i = 0; i < this.data.size(); i++) {
+ ExtraData v = this.data.get(i);
+ if (value.getField().equals(v.getField())) {
+ this.data.set(i, value);
+ return;
+ }
+ }
+ this.data.add(value);
+ }
+
+ @Override // from ExtraData
+ public String getField() {
+ return this.field;
+ }
+
+ @Override // from ExtraData
+ public ExtraData getValue() {
+ return this.finalizeExtra();
+ }
+
+ /**
+ * Does nothing.
+ * @param w Not used.
+ */
+ @Override // from ExtraData
+ public void write(org.pasteque.coreutil.datatransfer.parser.Writer w) {}
+
+ @Override // from TempExtra
+ public ExtraData finalizeExtra() {
+ for (int i = 0; i < this.data.size(); i++) {
+ ExtraData v = this.data.get(i);
+ if ((v instanceof TempExtra)) {
+ this.data.set(i, ((TempExtra) v).finalizeExtra());
+ }
+ }
+ return new ExtraObject(this.field, this.data);
+ }
+ }
+
+ /**
+ * A buildable extra array.
+ */
+ private class TempExtraArray implements ExtraData, TempExtra
+ {
+ private List data;
+ private String field;
+ private ExtraType type;
+
+ public TempExtraArray(String field, ExtraType type) {
+ this.data = new ArrayList();
+ this.field = field;
+ this.type = type;
+ }
+
+ /**
+ * Get the size of the array as a string for the name of the next
+ * element to add.
+ * @return The size of the array as a string.
+ */
+ public String size() {
+ return String.valueOf(data.size());
+ }
+
+ /**
+ * Add a value to the array.
+ * @param value The value to add.
+ * @throws IllegalArgumentException When the type of one value doesn't match
+ * the type of the array.
+ */
+ private void addValue(ExtraData value) throws IllegalArgumentException {
+ if (!this.type.checkExtraType(value)) {
+ throw new IllegalArgumentException(String.format("Invalid type of data %s, expected %s", value.getClass().toString(), this.type.getTypeExtraClass().toString()));
+ }
+ this.data.add(value);
+ }
+
+ @Override // from ExtraData
+ public String getField() {
+ return this.field;
+ }
+
+ @Override // from ExtraData
+ public ExtraData getValue() {
+ return this.finalizeExtra();
+ }
+
+ /**
+ * Does nothing.
+ * @param w Not used.
+ */
+ @Override // from ExtraData
+ public void write(org.pasteque.coreutil.datatransfer.parser.Writer w) {}
+
+ @Override // from TempExtra
+ public ExtraData finalizeExtra() {
+ for (int i = 0; i < this.data.size(); i++) {
+ ExtraData v = this.data.get(i);
+ if ((v instanceof TempExtra)) {
+ this.data.set(i, ((TempExtra) v).finalizeExtra());
+ }
+ }
+ return new ExtraArray(this.field, this.type, this.data);
+ }
+ }}
diff --git a/src/main/java/org/pasteque/coreutil/extra/ExtraData.java b/src/main/java/org/pasteque/coreutil/extra/ExtraData.java
new file mode 100644
index 0000000..739a26d
--- /dev/null
+++ b/src/main/java/org/pasteque/coreutil/extra/ExtraData.java
@@ -0,0 +1,31 @@
+package org.pasteque.coreutil.extra;
+
+import org.pasteque.coreutil.ParseException;
+import org.pasteque.coreutil.datatransfer.parser.Writer;
+
+/**
+ * Data outside the minimal ones to be passed to the major version.
+ */
+public interface ExtraData
+{
+ /**
+ * Get the name of the field this data belongs to.
+ * @return The name of the field.
+ */
+ public String getField();
+
+ /**
+ * Get the value of the data as an object.
+ * @return The value.
+ */
+ public Object getValue();
+
+ /**
+ * Write the data to a writer.
+ * @param to The writer to put the data in. The data is not responsible
+ * of the state of the writer. The object holding the extra data must
+ * ensure the writer is in a correct state.
+ * @throws ParseException When the writer is in an incorrect state.
+ */
+ public void write(Writer to) throws ParseException;
+}
diff --git a/src/main/java/org/pasteque/coreutil/extra/ExtraDouble.java b/src/main/java/org/pasteque/coreutil/extra/ExtraDouble.java
new file mode 100644
index 0000000..69f943a
--- /dev/null
+++ b/src/main/java/org/pasteque/coreutil/extra/ExtraDouble.java
@@ -0,0 +1,55 @@
+package org.pasteque.coreutil.extra;
+
+import org.pasteque.coreutil.ParseException;
+import org.pasteque.coreutil.datatransfer.parser.Writer;
+
+/**
+ * Extra data as a double.
+ */
+public final class ExtraDouble implements ExtraData
+{
+ /** See {@link getField(). */
+ private final String field;
+ /** See {@link getDouble()}. */
+ private final double value;
+
+ /**
+ * Create an extra data.
+ * @param field The field name.
+ * @param value the value.
+ */
+ /* package */ ExtraDouble(String field, double value) {
+ this.field = field;
+ this.value = value;
+ }
+
+ /**
+ * Get the field associated to this extra data.
+ * @return the field name.
+ */
+ @Override // from ExtraData
+ public String getField() {
+ return this.field;
+ }
+
+ /**
+ * Get value.
+ * @return The value.
+ */
+ public double getDouble() {
+ return this.value;
+ }
+
+ @Override // from ExtraData
+ public Object getValue() {
+ return Double.valueOf(this.value);
+ }
+
+ @Override // from ExtraData
+ public void write(Writer to) throws ParseException {
+ to.startObject(this.field);
+ to.writeString("t", ExtraType.DOUBLE.getTypeCode());
+ to.writeDouble("v", this.value);
+ to.endObject();
+ }
+}
diff --git a/src/main/java/org/pasteque/coreutil/extra/ExtraInt.java b/src/main/java/org/pasteque/coreutil/extra/ExtraInt.java
new file mode 100644
index 0000000..9ef6508
--- /dev/null
+++ b/src/main/java/org/pasteque/coreutil/extra/ExtraInt.java
@@ -0,0 +1,55 @@
+package org.pasteque.coreutil.extra;
+
+import org.pasteque.coreutil.ParseException;
+import org.pasteque.coreutil.datatransfer.parser.Writer;
+
+/**
+ * Extra data as an int.
+ */
+public final class ExtraInt implements ExtraData
+{
+ /** See {@link getField(). */
+ private final String field;
+ /** See {@link getInt()}. */
+ private final int value;
+
+ /**
+ * Create an extra data.
+ * @param field The field name.
+ * @param value the value.
+ */
+ /* package */ ExtraInt(String field, int value) {
+ this.field = field;
+ this.value = value;
+ }
+
+ /**
+ * Get the field associated to this extra data.
+ * @return the field name.
+ */
+ @Override // from ExtraData
+ public String getField() {
+ return this.field;
+ }
+
+ /**
+ * Get value.
+ * @return The value.
+ */
+ public int getInt() {
+ return this.value;
+ }
+
+ @Override // from ExtraData
+ public Object getValue() {
+ return Integer.valueOf(this.value);
+ }
+
+ @Override // from ExtraData
+ public void write(Writer to) throws ParseException {
+ to.startObject(this.field);
+ to.writeString("t", ExtraType.INTEGER.getTypeCode());
+ to.writeInt("v", this.value);
+ to.endObject();
+ }
+}
diff --git a/src/main/java/org/pasteque/coreutil/extra/ExtraNull.java b/src/main/java/org/pasteque/coreutil/extra/ExtraNull.java
new file mode 100644
index 0000000..279b22e
--- /dev/null
+++ b/src/main/java/org/pasteque/coreutil/extra/ExtraNull.java
@@ -0,0 +1,44 @@
+package org.pasteque.coreutil.extra;
+
+import org.pasteque.coreutil.ParseException;
+import org.pasteque.coreutil.datatransfer.parser.Writer;
+
+/**
+ * Extra data holding a null value. Use this class instead of
+ * typed extra data with a null value.
+ */
+public final class ExtraNull implements ExtraData
+{
+ /** See {@link getField(). */
+ private final String field;
+
+ /**
+ * Create an extra data.
+ * @param field The field name.
+ */
+ /* package */ ExtraNull(String field) {
+ this.field = field;
+ }
+
+ /**
+ * Get the field associated to this extra data.
+ * @return the field name.
+ */
+ @Override // from ExtraData
+ public String getField() {
+ return this.field;
+ }
+
+ @Override // from ExtraData
+ public Object getValue() {
+ return null;
+ }
+
+ @Override // from ExtraData
+ public void write(Writer to) throws ParseException {
+ to.startObject(this.field);
+ to.writeString("t", ExtraType.NULL.getTypeCode());
+ to.writeNull("v");
+ to.endObject();
+ }
+}
diff --git a/src/main/java/org/pasteque/coreutil/extra/ExtraObject.java b/src/main/java/org/pasteque/coreutil/extra/ExtraObject.java
new file mode 100644
index 0000000..83c407a
--- /dev/null
+++ b/src/main/java/org/pasteque/coreutil/extra/ExtraObject.java
@@ -0,0 +1,200 @@
+package org.pasteque.coreutil.extra;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.pasteque.coreutil.ImmutableList;
+import org.pasteque.coreutil.ParseException;
+import org.pasteque.coreutil.datatransfer.parser.Reader;
+import org.pasteque.coreutil.datatransfer.parser.Writer;
+
+/**
+ * Collection of {@link org.pasteque.coreutil.extra.ExtraData}
+ * to extend major classes. An extra object is the root of the extra data
+ * and can contain other extra objects as well.
+ */
+public final class ExtraObject implements ExtraData
+{
+ /**
+ * The name of the field for the root element of extra data.
+ */
+ public static final String EXTRA_ROOT_FIELD = "extra";
+ /** See {@link getField(). */
+ private final String field;
+ /** See {@link getObject(). */
+ private final ImmutableList value;
+
+ /**
+ * Sort extra data by key and return an ordered list of them.
+ * @param data The maybe unsorted list of extra data.
+ * @return An immutable list of extra data containing all extra data
+ * sorted alphabetically by their key.
+ * @throws IllegalArgumentException When multiple extra data shares the
+ * same key.
+ */
+ private static ImmutableList sortExtraKeys(Iterable data)
+ throws IllegalArgumentException {
+ List keys = new ArrayList();
+ List sorted = new ArrayList();
+ for (ExtraData d : data) {
+ keys.add(d.getField());
+ }
+ Collections.sort(keys);
+ String lastKey = null;
+ for (String key : keys) {
+ if (key.equals(lastKey)) {
+ throw new IllegalArgumentException(String.format("Key %s is set multiple times in extra object.", key));
+ }
+ for (ExtraData d : data) {
+ if (d.getField().equals(key)) {
+ sorted.add(d);
+ break;
+ }
+ }
+ lastKey = key;
+ }
+ return new ImmutableList(sorted);
+ }
+
+ /**
+ * Create an empty extra data as the root element.
+ */
+ public ExtraObject() {
+ this(EXTRA_ROOT_FIELD, new ImmutableList());
+ }
+
+ /**
+ * Create an extra data as the root element.
+ * @param value the value.
+ * @throws IllegalArgumentException When multiple extra data shares the
+ * same key.
+ */
+ /* package */ ExtraObject(List data) {
+ this(EXTRA_ROOT_FIELD, data);
+ }
+
+ /**
+ * Create an extra data.
+ * @param value the value.
+ * @throws IllegalArgumentException When multiple extra data shares the
+ * same key.
+ */
+ /* package */ ExtraObject(String field, List data) {
+ this.field = field;
+ this.value = sortExtraKeys(data);
+ }
+
+ /**
+ * Create an extra data.
+ * @param value the value.
+ * @throws IllegalArgumentException When multiple extra data shares the
+ * same key.
+ */
+ /* package */ ExtraObject(String field, ImmutableList data) {
+ this.field = field;
+ this.value = sortExtraKeys(data);
+ }
+
+ /**
+ * Instantiate from raw data from a reader.
+ * @param key The key to assign to this extra object.
+ * @param reader The reader that must be currently pointing to this object.
+ * @throws IllegalArgumentException When multiple extra data shares the
+ * same key.
+ * @throws ParseException When an error occurs while parsing the object.
+ * See {@link org.pasteque.coreutil.datatransfer.parser.Reader} for details.
+ */
+ /* package */ ExtraObject(String key, Reader reader)
+ throws ParseException, IllegalArgumentException {
+ List keys = reader.listKeys();
+ List data = new ArrayList(keys.size());
+ for (String extraKey : keys) {
+ reader.startObject(extraKey);
+ String typeCode = reader.readString("t");
+ ExtraType type = ExtraType.fromCode(typeCode);
+ switch (type) {
+ case STRING:
+ data.add(new ExtraString(extraKey, reader.readString("v")));
+ break;
+ case BOOLEAN:
+ data.add(new ExtraBoolean(extraKey, reader.readBoolean("v")));
+ break;
+ case INTEGER:
+ data.add(new ExtraInt(extraKey, reader.readInt("v")));
+ break;
+ case DOUBLE:
+ data.add(new ExtraDouble(extraKey, reader.readDouble("v")));
+ break;
+ case OBJECT:
+ data.add(new ExtraObject(extraKey, reader));
+ break;
+ case ARRAY:
+ data.add(new ExtraArray(extraKey, reader));
+ case NULL:
+ data.add(new ExtraNull(extraKey));
+ break;
+ default:
+ assert false;
+ }
+ reader.endObject();
+ }
+ this.field = key;
+ this.value = sortExtraKeys(data);
+ }
+
+ /**
+ * Instantiate from raw data from a reader.
+ * @param r The reader that must be currently pointing to this object.
+ * @throws ParseException When an error occurs while parsing the object.
+ * See {@link org.pasteque.coreutil.datatransfer.parser.Reader} for details.
+ */
+ public ExtraObject(Reader r) throws ParseException {
+ this(EXTRA_ROOT_FIELD, r);
+ }
+
+ @Override // from ExtraData
+ public String getField() {
+ return this.field;
+ }
+
+ @Override // from ExtraData
+ public Object getValue() {
+ return this.value;
+ }
+
+ /**
+ * Write this object in an {@link ExtraArray} without providing a field
+ * @param to The write to write this object to.
+ * @throws ParseException When an error occurs while writing a field.
+ */
+ /* package */ void writeInArray(Writer to) throws ParseException {
+ to.startObject();
+ for (ExtraData d : this.value) {
+ try {
+ d.write(to);
+ } catch (ParseException e) {
+ to.endObject();
+ throw e;
+ }
+ }
+ to.endObject();
+ }
+
+ @Override // from ExtraData
+ public void write(Writer to) throws ParseException {
+ to.startObject(this.field);
+ to.writeString("t", ExtraType.OBJECT.getTypeCode());
+ to.startObject("v");
+ for (ExtraData d : this.value) {
+ try {
+ d.write(to);
+ } catch (ParseException e) {
+ to.endObject();
+ to.endObject();
+ throw e;
+ }
+ }
+ to.endObject();
+ to.endObject();
+ }
+}
diff --git a/src/main/java/org/pasteque/coreutil/extra/ExtraString.java b/src/main/java/org/pasteque/coreutil/extra/ExtraString.java
new file mode 100644
index 0000000..dc9a5b9
--- /dev/null
+++ b/src/main/java/org/pasteque/coreutil/extra/ExtraString.java
@@ -0,0 +1,61 @@
+package org.pasteque.coreutil.extra;
+
+import org.pasteque.coreutil.ParseException;
+import org.pasteque.coreutil.datatransfer.parser.Writer;
+
+/**
+ * Extra data as a {@link java.lang.String}. This can also holds the reference
+ * of an associated object.
+ */
+public final class ExtraString implements ExtraData
+{
+ /** See {@link getField(). */
+ private final String field;
+ /** See {@link getString()}. */
+ private final String value;
+
+ /**
+ * Create an extra data.
+ * @param field The field name.
+ * @param value the value.
+ * @throws InvalidArgumentException When value is null.
+ * @see org.pasteque.coreutil.extra.ExtraNull
+ */
+ /* package */ ExtraString(String field, String value) {
+ if (value == null) {
+ throw new IllegalArgumentException("ExtraData cannot have a null value. Use ExtraNull instead.");
+ }
+ this.field = field;
+ this.value = value;
+ }
+
+ /**
+ * Get the field associated to this extra data.
+ * @return the field name.
+ */
+ @Override // from ExtraData
+ public String getField() {
+ return this.field;
+ }
+
+ /**
+ * Get value.
+ * @return The value.
+ */
+ public String getString() {
+ return this.value;
+ }
+
+ @Override // from ExtraData
+ public Object getValue() {
+ return this.value;
+ }
+
+ @Override // from ExtraData
+ public void write(Writer to) throws ParseException {
+ to.startObject(this.field);
+ to.writeString("t", ExtraType.STRING.getTypeCode());
+ to.writeString("v", this.value);
+ to.endObject();
+ }
+}
diff --git a/src/main/java/org/pasteque/coreutil/extra/ExtraType.java b/src/main/java/org/pasteque/coreutil/extra/ExtraType.java
new file mode 100644
index 0000000..c983ed2
--- /dev/null
+++ b/src/main/java/org/pasteque/coreutil/extra/ExtraType.java
@@ -0,0 +1,116 @@
+package org.pasteque.coreutil.extra;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Enumeration of available data types}.
+ */
+public enum ExtraType
+{
+ /** Type of {@link java.lang.String}, matching {@link ExtraString} data. */
+ STRING("s", String.class, ExtraString.class),
+ /** Type of boolean data. */
+ BOOLEAN("b", Boolean.class, ExtraBoolean.class),
+ /** Type of integer data. */
+ INTEGER("i", Integer.class, ExtraInt.class),
+ /** Type of float/double data. */
+ DOUBLE("d", Double.class, ExtraDouble.class),
+ /** Type of object data. */
+ OBJECT("o", Map.class, ExtraObject.class),
+ /** Type of array data. */
+ ARRAY("a", List.class, ExtraArray.class),
+ /** Type of null data. */
+ NULL("n", null, ExtraNull.class);
+
+ /** See {@link getTypeCode()}. */
+ private final String typeCode;
+ /** See {@link getTypeClass()}. */
+ private final Class> type;
+ /** See {@link getTypeExtraClass()}. */
+ private final Class extends ExtraData> extraType;
+
+ /**
+ * Get a type from its type code.
+ * @param code The code value.
+ * @return The according enumeration value.
+ * @throws IllegalArgumentException When code is not found
+ * within the enumerated values
+ */
+ public static final ExtraType fromCode(String code) throws IllegalArgumentException {
+ for (ExtraType v : ExtraType.values()) {
+ if (v.getTypeCode().equals(code)) {
+ return v;
+ }
+ }
+ throw new IllegalArgumentException(code);
+ }
+
+ /**
+ * Get the type of an extra data.
+ * @param data The extra data to check.
+ * @return The type of that extra data.
+ */
+ public static final ExtraType fromExtra(ExtraData data) {
+ for (ExtraType v : ExtraType.values()) {
+ if (v.checkExtraType(data)) {
+ return v;
+ }
+ }
+ throw new Error(String.format("Unknown ExtraData type %s", data.getClass().toString()));
+ }
+
+ /**
+ * Internal constructor.
+ * @param typeCode The code to identify the type.
+ * @param type The expected java class.
+ * @param extraType The expected {@link ExtraData} implementation class.
+ */
+ private ExtraType(String typeCode, Class> type, Class extends ExtraData> extraType) {
+ this.typeCode = typeCode;
+ this.type = type;
+ this.extraType = extraType;
+ }
+
+ /**
+ * Get the associated constant.
+ * @return The code for DTO.
+ */
+ public String getTypeCode() {
+ return this.typeCode;
+ }
+
+ /**
+ * Get the expected java class of this type.
+ * @return A java class, like String.class.
+ */
+ public Class> getTypeClass() {
+ return this.type;
+ }
+
+ /**
+ * Get the expected {@link ExtraData} implementation class.
+ * @return An {@link ExtraData} implementation, like {@link ExtraString}.
+ */
+ public Class extends ExtraData> getTypeExtraClass() {
+ return this.extraType;
+ }
+
+ /**
+ * Check if an object is the same java type as this type expects.
+ * @param o The object to check.
+ * @return True if the object is acceptable for this type.
+ */
+ public boolean checkRawType(Object o) {
+ return this.type.isInstance(o);
+ }
+
+ /**
+ * Check if an extra object is the same type as this type expects.
+ * @param o The extra object.
+ * @return True if the object is the same extra type or an {@link ExtraNull}.
+ */
+ public boolean checkExtraType(ExtraData o) {
+ return (this.extraType.isInstance(o)) || (o instanceof ExtraNull);
+ }
+}
diff --git a/src/main/java/org/pasteque/coreutil/extra/package-info.java b/src/main/java/org/pasteque/coreutil/extra/package-info.java
new file mode 100644
index 0000000..9312c4b
--- /dev/null
+++ b/src/main/java/org/pasteque/coreutil/extra/package-info.java
@@ -0,0 +1,12 @@
+/**
+ * Non-mandatory data to pass to the major version. Use an
+ * {@link org.pasteque.coreutil.extra.ExtraBuilder} to
+ * remove the semantic from model classes to pass them to major data
+ * that don't care about their meaning.
+ * An {@link org.pasteque.coreutil.extra.ExtraObject} is composed of
+ * types of {@link org.pasteque.coreutil.extra.ExtraData} for typed
+ * values. All values of {@link org.pasteque.coreutil.extra.ExtraData}
+ * implementations are non-null. When the value is null, use an explicit
+ * {@link org.pasteque.coreutil.extra.ExtraNull}.
+ */
+package org.pasteque.coreutil.extra;
diff --git a/src/main/java/org/pasteque/coreutil/transition/LineTransition.java b/src/main/java/org/pasteque/coreutil/transition/LineTransition.java
index 649a36a..e6e19c5 100644
--- a/src/main/java/org/pasteque/coreutil/transition/LineTransition.java
+++ b/src/main/java/org/pasteque/coreutil/transition/LineTransition.java
@@ -1,6 +1,7 @@
package org.pasteque.coreutil.transition;
import org.pasteque.coreutil.ImmutableList;
+import org.pasteque.coreutil.extra.ExtraObject;
import org.pasteque.coreutil.price.Discount;
import org.pasteque.coreutil.price.Price;
import org.pasteque.coreutil.price.Quantity;
@@ -63,4 +64,12 @@ public interface LineTransition {
* @return The full discount applied to the base price.
*/
public Discount getFinalDiscount();
+
+ /**
+ * Get all other data.
+ * Implementations should use an {@link org.pasteque.coreutil.extra.ExtraBuilder}
+ * to remove the semantic of all non-mandatory fields.
+ * @return The root object of extra data.
+ */
+ public ExtraObject getExtra();
}
diff --git a/src/main/java/org/pasteque/coreutil/transition/OrderTransition.java b/src/main/java/org/pasteque/coreutil/transition/OrderTransition.java
index 135f964..573692b 100644
--- a/src/main/java/org/pasteque/coreutil/transition/OrderTransition.java
+++ b/src/main/java/org/pasteque/coreutil/transition/OrderTransition.java
@@ -1,6 +1,8 @@
package org.pasteque.coreutil.transition;
import org.pasteque.coreutil.ImmutableList;
+import org.pasteque.coreutil.extra.ExtraObject;
+import org.pasteque.coreutil.price.Discount;
import org.pasteque.coreutil.price.FinalTaxAmount;
import org.pasteque.coreutil.price.Price2;
@@ -32,4 +34,18 @@ public interface OrderTransition
* @return The content of the order.
*/
public ImmutableList getLines();
+
+ /**
+ * Get the discount applied to the whole order.
+ * @return The discount applied to the whole order.
+ */
+ public Discount getDiscount();
+
+ /**
+ * Get all other data.
+ * Implementations should use an {@link org.pasteque.coreutil.extra.ExtraBuilder}
+ * to remove the semantic of all non-mandatory fields.
+ * @return The root object of extra data.
+ */
+ public ExtraObject getExtra();
}
diff --git a/src/main/java/org/pasteque/major/domain/MajorCashSession.java b/src/main/java/org/pasteque/major/domain/MajorCashSession.java
index 0ada81c..4b88ead 100644
--- a/src/main/java/org/pasteque/major/domain/MajorCashSession.java
+++ b/src/main/java/org/pasteque/major/domain/MajorCashSession.java
@@ -3,10 +3,10 @@ package org.pasteque.major.domain;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
-
import org.pasteque.coreutil.datatransfer.dto.CashSessionDTO;
import org.pasteque.coreutil.datatransfer.dto.FiscalTicketDTO;
import org.pasteque.coreutil.datatransfer.dto.MovementDTO;
+import org.pasteque.coreutil.extra.ExtraObject;
/**
* Ongoing cash session, managing movements and payments.
@@ -32,6 +32,8 @@ public final class MajorCashSession
private List tickets;
/** See {@link isClosed()}. */
private boolean closed;
+ /** See {@link getExtra()}. */
+ private ExtraObject extra;
/**
* Create a cash session from all fields.
@@ -41,6 +43,7 @@ public final class MajorCashSession
* @param openDate See {@link getOpenDate()}.
* @param movements The list of movements registered during this session.
* @param tickets The list of tickets already registered during this session.
+ * @param extra See {@link getExtra()}.
*/
public MajorCashSession(
MajorCashRegister cashRegister,
@@ -48,7 +51,8 @@ public final class MajorCashSession
boolean continuous,
Date openDate,
List movements,
- List tickets) {
+ List tickets,
+ ExtraObject extra) {
this.cashRegister = cashRegister;
this.sequence = sequence;
this.continuous = continuous;
@@ -56,6 +60,7 @@ public final class MajorCashSession
this.movements = movements;
this.tickets = tickets;
this.closed = false;
+ this.extra = extra;
}
/**
@@ -239,4 +244,12 @@ public final class MajorCashSession
public Date getOpenDate() {
return openDate;
}
+
+ /**
+ * Get all other data.
+ * @return The root object of extra data.
+ */
+ public final ExtraObject getExtra() {
+ return this.extra;
+ }
}
diff --git a/src/main/java/org/pasteque/major/domain/MajorLine.java b/src/main/java/org/pasteque/major/domain/MajorLine.java
index 683fd70..3868029 100644
--- a/src/main/java/org/pasteque/major/domain/MajorLine.java
+++ b/src/main/java/org/pasteque/major/domain/MajorLine.java
@@ -1,6 +1,7 @@
package org.pasteque.major.domain;
import org.pasteque.coreutil.ImmutableList;
+import org.pasteque.coreutil.extra.ExtraObject;
import org.pasteque.coreutil.price.Discount;
import org.pasteque.coreutil.price.Price;
import org.pasteque.coreutil.price.Quantity;
@@ -15,7 +16,6 @@ import org.pasteque.coreutil.transition.LineTransition;
* @see org.pasteque.major.domain.MajorOrder
* @see org.pasteque.major.domain.MajorTicket
*/
-// TODO add extradata to pass to MajorTicket
public final class MajorLine implements LineTransition
{
/** See {@link getProductReference()}. */
@@ -34,6 +34,8 @@ public final class MajorLine implements LineTransition
private final Price totalPrice;
/** See {@link getFinalDiscount()}. */
private final Discount finalDiscount;
+ /** See {@link getExtra()}. */
+ private final ExtraObject extra;
/**
* Create a major line from outside this package.
@@ -61,6 +63,7 @@ public final class MajorLine implements LineTransition
* @param totalTaxes See {@link getTotalTaxes()}.
* @param totalPrice See {@link getTotalPrice()}.
* @param finalDiscount See {@link getFinalDiscount()}.
+ * @param extra See {@link getExtra()}.
*/
/* package */ MajorLine(
String productReference,
@@ -70,7 +73,8 @@ public final class MajorLine implements LineTransition
Price price,
ImmutableList totalTaxes,
Price totalPrice,
- Discount finalDiscount) {
+ Discount finalDiscount,
+ ExtraObject extra) {
this.productReference = productReference;
this.productLabel = productLabel;
this.unitPrice = unitPrice;
@@ -79,6 +83,7 @@ public final class MajorLine implements LineTransition
this.totalTaxes = totalTaxes;
this.totalPrice = totalPrice;
this.finalDiscount = finalDiscount;
+ this.extra = extra;
}
/**
@@ -94,6 +99,7 @@ public final class MajorLine implements LineTransition
this.totalTaxes = source.getTotalTaxes();
this.totalPrice = source.getTotalPrice();
this.finalDiscount = source.getFinalDiscount();
+ this.extra = source.getExtra();
}
@Override // from LineTransition
@@ -135,4 +141,9 @@ public final class MajorLine implements LineTransition
public Discount getFinalDiscount() {
return this.finalDiscount;
}
+
+ @Override // from LineTransition
+ public ExtraObject getExtra() {
+ return this.extra;
+ }
}
diff --git a/src/main/java/org/pasteque/major/domain/MajorOrder.java b/src/main/java/org/pasteque/major/domain/MajorOrder.java
index 56cdfa3..7f5030d 100644
--- a/src/main/java/org/pasteque/major/domain/MajorOrder.java
+++ b/src/main/java/org/pasteque/major/domain/MajorOrder.java
@@ -1,6 +1,8 @@
package org.pasteque.major.domain;
import org.pasteque.coreutil.ImmutableList;
+import org.pasteque.coreutil.extra.ExtraObject;
+import org.pasteque.coreutil.price.Discount;
import org.pasteque.coreutil.price.FinalTaxAmount;
import org.pasteque.coreutil.price.Price2;
import org.pasteque.coreutil.transition.LineTransition;
@@ -13,13 +15,14 @@ import org.pasteque.coreutil.transition.OrderTransition;
* for ease of use, but instances are not expected to be generated from
* themselves.
*/
-// TODO add extradata to pass to MajorTicket
public final class MajorOrder implements OrderTransition
{
private final Price2 finalPrice;
private final ImmutableList taxAmounts;
private final Price2 finalTaxedPrice;
private final ImmutableList lines;
+ private final Discount discount;
+ private final ExtraObject extra;
/**
* Create a major order from all data.
@@ -27,16 +30,22 @@ public final class MajorOrder implements OrderTransition
* @param taxAmounts See {@link getTaxAmounts()}.
* @param finalTaxedPrice See {@link getFinalTaxedPrice()}.
* @param lines See {@link getLines()}.
+ * @param discount See {@link getDiscount()}.
+ * @param extra See {@link getExtra()}.
*/
public MajorOrder(
Price2 finalPrice,
ImmutableList taxAmounts,
Price2 finalTaxedPrice,
- ImmutableList lines) {
+ ImmutableList lines,
+ Discount discount,
+ ExtraObject extra) {
this.finalPrice = finalPrice;
this.taxAmounts = taxAmounts;
this.finalTaxedPrice = finalTaxedPrice;
this.lines = lines;
+ this.discount = discount;
+ this.extra = extra;
}
/**
@@ -60,10 +69,13 @@ public final class MajorOrder implements OrderTransition
trans.getPrice(),
trans.getTotalTaxes(),
trans.getTotalPrice(),
- trans.getFinalDiscount());
+ trans.getFinalDiscount(),
+ trans.getExtra());
}
this.lines = MajorLine.fromTransition(order.getLines());
+ this.discount = order.getDiscount();
+ this.extra = order.getExtra();
}
/**
@@ -110,4 +122,20 @@ public final class MajorOrder implements OrderTransition
public ImmutableList getMajorLines() {
return this.lines;
}
+
+ /**
+ * Get the discount applied to the whole order.
+ * @return The discount applied to the whole order.
+ */
+ public Discount getDiscount() {
+ return this.discount;
+ }
+
+ /**
+ * Get all other data.
+ * @return The root object of extra data.
+ */
+ public ExtraObject getExtra() {
+ return this.extra;
+ }
}
diff --git a/src/main/java/org/pasteque/major/domain/MajorTicket.java b/src/main/java/org/pasteque/major/domain/MajorTicket.java
index 5b4d6c3..3f9c188 100644
--- a/src/main/java/org/pasteque/major/domain/MajorTicket.java
+++ b/src/main/java/org/pasteque/major/domain/MajorTicket.java
@@ -3,6 +3,7 @@ package org.pasteque.major.domain;
import java.util.Date;
import java.util.List;
import org.pasteque.coreutil.constants.FiscalTicketType;
+import org.pasteque.coreutil.extra.ExtraObject;
import org.pasteque.coreutil.price.Price2;
import org.pasteque.coreutil.price.TaxAmount;
import org.pasteque.coreutil.ImmutableList;
@@ -38,7 +39,8 @@ public final class MajorTicket
private Price2 finalTaxedPrice;
/** See {@link getFinalPrice(). */
private Price2 finalPrice;
- // TODO: add extra data
+ /** See {@link getExtra(). */
+ private ExtraObject extra;
/**
* Create by linking an order and payments. It will create the associated
@@ -115,7 +117,7 @@ public final class MajorTicket
* @return The payment date, when the ticket was created..
*/
public Date getDate() {
- return date;
+ return this.date;
}
/**
@@ -123,7 +125,7 @@ public final class MajorTicket
* @return The content of the ticket.
*/
public ImmutableList getLines() {
- return lines;
+ return this.lines;
}
/**
@@ -131,7 +133,7 @@ public final class MajorTicket
* @return The list of payments used to pay the ticket.
*/
public ImmutableList getPayments() {
- return payments;
+ return this.payments;
}
/**
@@ -139,7 +141,7 @@ public final class MajorTicket
* @return The list of tax amounts.
*/
public ImmutableList getTaxAmounts() {
- return taxAmounts;
+ return this.taxAmounts;
}
/**
@@ -147,7 +149,7 @@ public final class MajorTicket
* @return The total price.
*/
public Price2 getFinalTaxedPrice() {
- return finalTaxedPrice;
+ return this.finalTaxedPrice;
}
/**
@@ -155,6 +157,14 @@ public final class MajorTicket
* @return The total price without taxes.
*/
public Price2 getFinalPrice() {
- return finalPrice;
+ return this.finalPrice;
}
-}
\ No newline at end of file
+
+ /**
+ * Get the non mandatory extra data.
+ * @return The root object containing all the extra data.
+ */
+ public ExtraObject getExtra() {
+ return this.extra;
+ }
+}
diff --git a/src/main/java/org/pasteque/major/domain/Movement.java b/src/main/java/org/pasteque/major/domain/Movement.java
index cb3699a..dde1e55 100644
--- a/src/main/java/org/pasteque/major/domain/Movement.java
+++ b/src/main/java/org/pasteque/major/domain/Movement.java
@@ -1,6 +1,7 @@
package org.pasteque.major.domain;
import java.util.Date;
+import org.pasteque.coreutil.extra.ExtraObject;
import org.pasteque.coreutil.datatransfer.dto.MovementDTO;
import org.pasteque.coreutil.datatransfer.dto.WeakAssociationDTO;
import org.pasteque.coreutil.price.Price2;
@@ -25,6 +26,8 @@ public class Movement
private final Price2 currencyAmount;
/** See {@link getDate()}. */
private Date date;
+ /** See {@link getExtra()}. */
+ private final ExtraObject extra;
/**
* Create a payment from all fields.
@@ -34,6 +37,7 @@ public class Movement
* @param currencyLabel See {@link getCurrencyLabel()}.
* @param currencyAmount See {@link getCurrencyAmount()}.
* @param date See {@link getDate()}.
+ * @param extra See {@link getExtra()}.
*/
public Movement(
String paymentModeReference,
@@ -41,13 +45,15 @@ public class Movement
String currencyReference,
String currencyLabel,
Price2 currencyAmount,
- Date date) {
+ Date date,
+ ExtraObject extra) {
this.paymentModeReference = paymentModeReference;
this.paymentModeLabel = paymentModeLabel;
this.currencyReference = currencyReference;
this.currencyLabel = currencyLabel;
this.currencyAmount = currencyAmount;
this.date = date;
+ this.extra = extra;
}
/**
@@ -61,6 +67,7 @@ public class Movement
this.currencyLabel = dto.getCurrency().getLabel();
this.currencyAmount = new Price2(dto.getCurrencyAmount());
this.date = new Date(dto.getDate().getTime());
+ this.extra = dto.getExtra();
}
/**
@@ -116,6 +123,14 @@ public class Movement
return this.date;
}
+ /**
+ * Get all other data.
+ * @return The root object of extra data.
+ */
+ public final ExtraObject getExtra() {
+ return this.extra;
+ }
+
/**
* Get a DTO from this object.
* @return The content of this object as a DTO.
@@ -129,6 +144,7 @@ public class Movement
this.currencyReference,
this.currencyLabel),
this.currencyAmount.toDouble(),
- this.date);
+ this.date,
+ this.extra);
}
}
diff --git a/src/main/java/org/pasteque/major/domain/Payment.java b/src/main/java/org/pasteque/major/domain/Payment.java
index 69f66f9..2e185ea 100644
--- a/src/main/java/org/pasteque/major/domain/Payment.java
+++ b/src/main/java/org/pasteque/major/domain/Payment.java
@@ -1,6 +1,7 @@
package org.pasteque.major.domain;
import org.pasteque.coreutil.datatransfer.dto.WeakAssociationDTO;
+import org.pasteque.coreutil.extra.ExtraObject;
import org.pasteque.coreutil.price.Price2;
import org.pasteque.coreutil.datatransfer.dto.PaymentDTO;
@@ -24,6 +25,8 @@ public final class Payment
private final String currencyLabel;
/** See {@link getCurrencyAmount()}. */
private final Price2 currencyAmount;
+ /** See {@link getExtra()}. */
+ private final ExtraObject extra;
/**
* Create a payment from all fields.
@@ -33,6 +36,7 @@ public final class Payment
* @param currencyReference See {@link getCurrencyReference()}.
* @param currencyLabel See {@link getCurrencyLabel()}.
* @param currencyAmount See {@link getCurrencyAmount()}.
+ * @param extra See {@link getExtra()}.
*/
public Payment(
String paymentModeReference,
@@ -40,13 +44,15 @@ public final class Payment
String currencyReference,
String currencyLabel,
Price2 amount,
- Price2 currencyAmount) {
+ Price2 currencyAmount,
+ ExtraObject extra) {
this.paymentModeReference = paymentModeReference;
this.paymentModeLabel = paymentModeLabel;
this.currencyReference = currencyReference;
this.currencyLabel = currencyLabel;
this.amount = amount;
this.currencyAmount = currencyAmount;
+ this.extra = extra;
}
/**
@@ -60,6 +66,7 @@ public final class Payment
this.currencyReference = dto.getCurrency().getReference();
this.currencyLabel = dto.getCurrency().getLabel();
this.currencyAmount = new Price2(dto.getCurrencyAmount());
+ this.extra = dto.getExtra();
}
/**
@@ -116,6 +123,14 @@ public final class Payment
return currencyAmount;
}
+ /**
+ * Get all other data.
+ * @return The root object of extra data.
+ */
+ public ExtraObject getExtra() {
+ return this.extra;
+ }
+
/**
* Get a DTO from this object.
* @return The content of this object as a DTO.
@@ -129,6 +144,7 @@ public final class Payment
new WeakAssociationDTO(
this.currencyReference,
this.currencyLabel),
- this.currencyAmount.toDouble());
+ this.currencyAmount.toDouble(),
+ this.extra);
}
}
diff --git a/src/main/java/org/pasteque/major/domain/package-info.java b/src/main/java/org/pasteque/major/domain/package-info.java
index 052eb36..60cf814 100644
--- a/src/main/java/org/pasteque/major/domain/package-info.java
+++ b/src/main/java/org/pasteque/major/domain/package-info.java
@@ -5,5 +5,4 @@
* but not modified. All properties and methods are then final but the class
* may be extended to include more data.
*/
-// TODO: add a way to propagate extra data to the DTO
package org.pasteque.major.domain;