Simple XML on Android - class MyArrayList<E> extends ArrayList<E>? - java

I am new to the simple xml library. I really like it but I have got a problem.
Here are my classes (some code has been removed to make it more concise):
#Root
#ElementList
public class MyArrayList<E> extends ArrayList<E>{
public void ToXml() throws Exception{
Serializer serializer = new Persister();
File file = new File("somewhere in my file system");
serializer.write(this, file);
}
}
¬
#Root
public abstract class MediaEntry implements Serializable {
private static final long serialVersionUID = 1L;
#Element
public String Title;
#Element
public String Description;
#Element
public String Url;
#Element
public String LocalPath;
public MediaEntry(String title, String description,
String url, String localPath) {
Title= title;
Description= description;
Url= url;
LocalPath= localPath;
}
}
¬
public class VideoEntry extends MediaEntry {
private static final long serialVersionUID = 1L;
public VideoEntry(String title, String description,
String url, String localPath) {
super(title, description, url, localPath);
}
}
When I instantiate MyArrayList add some VideoEntries and call ToXml, I only get an empty root ie.
<MyArrayList />
How to I solve this? Is it something to do with the fact that MyArrayList is generic?

The List has to be a member of an element (and no seperate class) to get the desired behaviour, you can set the ElementList inline, so there is no parent element.
#Root
public class MyArrayList<E> {
#ElementList(inline=true)
ArrayList<E> list = new ArrayList<E>();
public boolean add(E entry) {
return list.add(entry);
}
public void ToXml() throws Exception {
Serializer serializer = new Persister();
File file = new File("somewhere in my file system");
serializer.write(this, file);
}
}
Just thought of another solution which may even be better (you have access to all the List functions - but I'm not sure if there are any side-effects, so i leave my original solution)
#Root
public class MyArrayList<E> extends ArrayList<E> {
#ElementList(inline=true)
MyArrayList<E> list = this;
public void ToXml() throws Exception {
Serializer serializer = new Persister();
File file = new File("somewhere in my file system");
serializer.write(this, file);
}
}
To deserialize you have to declare for SimpleXML, whicht element is used for which constructor-parameter:
#Root
public abstract class MediaEntry implements Serializable {
private static final long serialVersionUID = 1L;
#Element
public String Title;
#Element
public String Description;
#Element
public String Url;
#Element
public String LocalPath;
public MediaEntry(#Element(name = "Title") String title,
#Element(name = "Description") String description,
#Element(name = "Url") String url,
#Element(name = "LocalPath") String localPath) {
Title = title;
Description = description;
Url = url;
LocalPath = localPath;
}
}
Btw, if you are just start programming Java, you might consider reading the Java code conventions - it is not a good practice to start method- and variablenames with a capital letter (so you can prevent getting used to bad habits ;-))

Related

Yaml deserilization to POJO using Jackson

How to deserialize Yaml to POJO when a key is dynamic? I have a Yaml file with this structure:
paths
/user:
get:
summary: Example summary
description: Some description
/account
post:
summary: Another summary
description: Another description
And I need to deserialize it to a Java Object:
public class PathsWrapper {
private List<Path> paths;
}
public class Path {
private String url;
private List<Method> methods;
}
public class Method {
private String method;
private String summary;
private String description;
}
You can use a map like so:
public class PathsWrapper {
private List<Path> paths;
}
public class Path {
private Map<String,List<Method>> url;
}
public class Method {
private Map<String, MethodDescription> method;
}
public class MethodDescription {
private String summary;
private String description;
}

Why in my code do I have this inheritance problem? Create an object passing a specialized type instead of declared abstract super type

Working on a Java application I am finding the following problem related to inheritance.
I have the following situation:
1) I defined an abstract class named TrendFromExcelAbstract. This class contains some basic fields common to other classes which extend it and represent different tabs of an Excel file (but this is not important now):
public abstract class TrendFromExcelAbstract {
private Long id;
private String date;
private String time;
private String excelDocumentName;
private String excelDocumentSheet;
public TrendFromExcelAbstract() {
super();
}
public TrendFromExcelAbstract(Long id, String date, String time, String excelDocumentName,
String excelDocumentSheet) {
super();
this.id = id;
this.date = date;
this.time = time;
this.excelDocumentName = excelDocumentName;
this.excelDocumentSheet = excelDocumentSheet;
}
................................................................
................................................................
GETTER AND SETTER METHODS
................................................................
................................................................
}
Then I have a class named CompVibrAndTempDTO extending the previous abstract class:
public class CompVibrAndTempDTO extends TrendFromExcelAbstract {
// Temperature reading point
private String tempReadingPointA;
private String tempReadingPointB;
private String tempReadingPointC;
private String tempReadingPointD;
private String tempReadingPointE;
private String tempReadingPointF;
private String tempReadingPointG;
private String tempReadingPointH;
private String tempReadingPointI;
private String tempReadingPointJ;
private String tempReadingPointK;
private String tempReadingPointL;
private String tempReadingPointM;
private String tempReadingPointN;
private String tempReadingPointO;
private String tempReadingPointP;
// Vibration reading point
private String vibrReadingPointA;
private String vibrReadingPointB;
private String vibrReadingPointC;
private String vibrReadingPointD;
private String vibrReadingPointE;
private String vibrReadingPointF;
private String vibrReadingPointG;
private String vibrReadingPointH;
private String vibrReadingPointI;
private String vibrReadingPointJ;
private String vibrReadingPointK;
private String vibrReadingPointL;
public CompVibrAndTempDTO() {
super();
}
public CompVibrAndTempDTO(Long id, String date, String time, String excelDocumentName, String excelDocumentSheet,
String tempReadingPointA, String tempReadingPointB, String tempReadingPointC, String tempReadingPointD,
String tempReadingPointE, String tempReadingPointF, String tempReadingPointG, String tempReadingPointH,
String tempReadingPointI, String tempReadingPointJ, String tempReadingPointK, String tempReadingPointL,
String tempReadingPointM, String tempReadingPointN, String tempReadingPointO, String tempReadingPointP,
String vibrReadingPointA, String vibrReadingPointB, String vibrReadingPointC, String vibrReadingPointD,
String vibrReadingPointE, String vibrReadingPointF, String vibrReadingPointG, String vibrReadingPointH,
String vibrReadingPointI, String vibrReadingPointJ, String vibrReadingPointK, String vibrReadingPointL) {
........................................................................................................................
........................................................................................................................
........................................................................................................................
}
........................................................................................................................
........................................................................................................................
GETTER AND SETTER METHODS
........................................................................................................................
........................................................................................................................
}
Then I have another DTO class named ExcelTabGeneralInfoDTO like this:
public class ExcelTabGeneralInfoDTO {
private String excelDocumentName;
private String excelSheetName;
private List<TrendFromExcelAbstract> trendOfTabList;
public ExcelTabGeneralInfoDTO() {
super();
}
public ExcelTabGeneralInfoDTO(String excelDocumentName, String excelSheetName,
List<TrendFromExcelAbstract> trendOfTabList) {
super();
this.excelDocumentName = excelDocumentName;
this.excelSheetName = excelSheetName;
this.trendOfTabList = trendOfTabList;
}
..................................................................
..................................................................
GETTER AND SETTER METHODS
..................................................................
..................................................................
}
As you can see this class contains this list field:
private List<TrendFromExcelAbstract> trendOfTabList;
The idea is that this field represents a list of any objects that derive from TrendFromExcelAbstract
The problem is that in another class I am trying to do something like this:
public List<ExcelTabGeneralInfoDTO> getCompVibrAndTempTab() {
List<CompVibrAndTempDTO> tabTrendList = excelRepo.findCompVibrAndTempTab();
String excelDocumentName;
String excelSheetName;
if(tabTrendList.size() >=0 ) {
excelDocumentName = tabTrendList.get(0).getExcelDocumentName();
excelSheetName = tabTrendList.get(0).getExcelDocumentSheet();
}
ExcelTabGeneralInfoDTO result = new ExcelTabGeneralInfoDTO(excelDocumentName, excelSheetName, tabTrendList);
return result;
}
So basically at this line:
ExcelTabGeneralInfoDTO result = new ExcelTabGeneralInfoDTO(excelDocumentName, excelSheetName, tabTrendList);
I am trying to create a new ExcelTabGeneralInfoDTO, passing to it the tabTrendList list having type List.
I get the following error message:
Description Resource Path Location Type
The constructor ExcelTabGeneralInfoDTO(String, String, List<CompVibrAndTempDTO>) is undefined ExcelServiceImpl.java /energy-prg-be/src/main/java/com/springboot/excelapi/services line 425 Java Problem
Description Resource Path Location Type
Type mismatch: cannot convert from List<ExcelTabGeneralInfoDTO> to List<CompVibrAndTempDTO> ExcelResource.java /energy-prg-be/src/main/java/com/springboot/excelapi/resources line 167 Java Problem
My idea is that I can use the more general type (ExcelTabGeneralInfoDTO) and then pass the child type (CompVibrAndTempDTO). But it seems that my assumption is false. What is wrong? What am I missing? Why can't I do something like this? How can I fix it?
ExcelTabGeneralInfoDTO does not have a defined constructor for List<CompVibrAndTempDTO>, only for List<TrendFromExcelAbstract>. Try declaring tabTrendList as a List<TrendFromExcelAbstract> and see if it works.

How to subclass a Java builder class?

I have two builders - PayloadA and PayloadB. To make example simpler, I have removed lot of other fields.
PayloadA.Builder constructor takes processName, genericRecord as an input parameter and then extract few things from genericRecord. And on that I am doing validation.
PayloadB.Builder constructor also takes processName, genericRecord as an input parameter and then it extract few different things from genericRecord as compared to above. And on those different fields I am doing validation.
As you can see, common thing between those two Payload?.Builder is processName, genericRecord, extracting oldTimestamp value and then isValid method.
Below is my PayloadA class:
public final class PayloadA {
private final String clientId;
private final String deviceId;
private final String processName;
private final GenericRecord genericRecord;
private final Long oldTimestamp;
private PayloadA(Builder builder) {
this.clientId = builder.clientId;
this.deviceId = builder.deviceId;
this.processName = builder.processName;
this.genericRecord = builder.genericRecord;
this.oldTimestamp = builder.oldTimestamp;
}
public static class Builder {
private final String processName;
private final GenericRecord genericRecord;
private final String clientId;
private final String deviceId;
private final Long oldTimestamp;
public Builder(PayloadA payload) {
this.processName = payload.processName;
this.genericRecord = payload.genericRecord;
this.clientId = payload.clientId;
this.deviceId = payload.deviceId;
this.oldTimestamp = payload.oldTimestamp;
}
public Builder(String processName, GenericRecord genericRecord) {
this.processName = processName;
this.genericRecord = genericRecord;
this.clientId = (String) DataUtils.parse(genericRecord, "clientId");
this.deviceId = (String) DataUtils.parse(genericRecord, "deviceId");
this.oldTimestamp = (Long) DataUtils.parse(genericRecord, "oldTimestamp");
}
// calling this method to validate
public boolean isValid() {
return isValidClientIdDeviceId();
}
private boolean isValidClientIdDeviceId() {
// validate here
}
public PayloadA build() {
return new PayloadA(this);
}
}
// getter here
}
Below is my PayloadB class:
public final class PayloadB {
private final GenericRecord genericRecord;
private final String processName;
private final String type;
private final String datumId;
private final Long oldTimestamp;
private PayloadB(Builder builder) {
this.processName = builder.processName;
this.genericRecord = builder.genericRecord;
this.type = builder.type;
this.datumId = builder.datumId;
this.oldTimestamp = builder.oldTimestamp;
}
public static class Builder {
private final GenericRecord genericRecord;
private final String processName;
private final String type;
private final String datumId;
private final Long oldTimestamp;
public Builder(PayloadB payload) {
this.processName = payload.processName;
this.genericRecord = payload.genericRecord;
this.type = payload.type;
this.datumId = payload.datumId;
this.oldTimestamp = payload.oldTimestamp;
}
public Builder(String processName, GenericRecord genericRecord) {
this.processName = processName;
this.genericRecord = genericRecord;
this.type = (String) DataUtils.parse(genericRecord, "type");
this.datumId = (String) DataUtils.parse(genericRecord, "datumId");
this.oldTimestamp = (Long) DataUtils.parse(genericRecord, "oldTimestamp");
}
// calling this method to validate
public boolean isValid() {
return isValidType() && isValidDatumId();
}
private boolean isValidType() {
// validate here
}
private boolean isValidDatumId() {
// validate here
}
public PayloadB build() {
return new PayloadB(this);
}
}
// getter here
}
Now is there any way I can use concept of abstract class here? I can create an abstract class Payload but what should be the stuff inside my abstract class:
public final class PayloadA extends Payload { ... }
public final class PayloadB extends Payload { ... }
And then once I build both my builder, I will pass it to some other method and there I want to access all the fields using getters. So let's say I have build PayloadA so I will send to execute method as shown below and then in that method, I want to extract all the fields of PayloadA. Similarly if I send PayloadB to execute method, then I want to extract all the fields of PayloadB class using getters. How can I do this?
private void execute(Payload payload) {
// How can I access fields of PayloadA or PayloadB
// depending on what was passe
}
Create a super class for the payloads only if the mentioned fields are not common by a coincidence. You can move common fields and methods (but not the builders) in there. You could even create a super class for the builders but it will probably clutter the code too much.
If you really have a use for the payload super class then you can implement your execute method with the Visitor Pattern:
First, you have to create a visitor where you can access your concrete classes:
public class PayloadVisitor {
public void visit(PayloadA payloadA) {
// use payload A here
}
public void visit(PayloadB payloadB) {
// use payload B here
}
}
Then you have to add a method to your super class accepting the visitor:
public abstract class Payload {
// common fields and methods
public abstract void accept(PayloadVisitor visitor);
}
Override the method accept in the subclasses:
public final class PayloadA extends Payload {
// ...
#Override
public void accept(PayloadVisitor visitor) {
visitor.visit(this);
}
}
public final class PayloadB extends Payload {
// ...
#Override
public void accept(PayloadVisitor visitor) {
visitor.visit(this);
}
}
Your method execute just redirects the call to the according visit method:
private void execute(Payload payload) {
payload.accept(new PayloadVisitor());
}
The visitor pattern can be overwhelming. You can also keep it simple and use instanceof to determine the concrete class.
I think the question here is if PayloadA and PayloadB are sharing something meaning full together for the design. If the logic is somehow the same except one parameter then you can have one class.
Maybe you can have the abstract class, and for the implementation for a specific field you can return your concrete value for a specific implementation.
For example Abstract class has abstract setter/getter for a field and when you implement that method to PayloadA and PayloadB you can return the field you want.
I think the problem is the design here not how to do it. See what your classes really are and then you have many options

JSON to java object returing LinkedHashMap

I have below json string :-
{"name":"Test","sortlist":[],"filterlist":[{"fieldname":"regions_id","operator":"equals","value":{"id":1,"code":"HIGH","description":"HIGH Region","comment":"High Region","active":true}}]}
and Java class as below :-
#JsonSerialize
#JsonDeserialize
public class ItemFilter implements Serializable {
private String name;
private List<FieldFilter> filterlist = new ArrayList<FieldFilter>();
}
public class FieldFilter implements Serializable {
private static final long serialVersionUID = 1L;
private String fieldname;
private String operator;
private Object value;
}
and my convert method as below :-
public static ItemFilter convertItemFilter(String item) {
ObjectMapper mapper = new ObjectMapper();
try {
ItemFilter itemFilter = mapper.readValue(item, new TypeReference<ItemFilter>(){});
return itemFilter;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
ItemFilter domain is getting converted correctly but in private Object value; field i am getting LinkedHashMap i want to get an simple object and later i will type cast it.
Can someone please guide me how to escape LinkedHashMap and get an simple Java Object in variable?
i cant use hard coding Object type because its a generic pojo which can have any object type. hard coding will make this pojo very bigger and frontend also need to change for it. So that why i have used Object as data type.
The following class structure should return the JSON to "YourObject"
public class YourObject{
private String name;
private List<String> sortList;
private List<Filter> filterList;
public static class Filter{
private String fieldname;
private String operator;
private Value value;
}
public static class Value{
private Integer id;
private String code;
private String description;
private String comment;
private Boolean active;
}
}
Then use the following to read it into the object:
YourObject itemFilter = mapper.readValue(item, YourObject.class);

Which Java ORM framework support polymorphism of document in MongoDB?

I'm trying to use MongoDB to store a series of documents. These document share some standard attributes while it has several variation. We implement the POJO with an inheritance. The base class is Document, while it has several sub-classes such as Invoice and Orders, which has several additional fields when compared with Document class.
class Document {
DocTypeEnum type;
String title;
}
class Invoice extends Document{
Date dueDate;
}
class Order extends Document{
List<LineItems> items;
}
Is there an ORM framework support query the collection and return a list of mixed objects (invoice, order, basic document, etc) according to its type field?
List<Document> results = DocCollection.find(...);
Thanks a lot!
Morhia supports polymorphism even without requiring a type enum or anything. It stores the actual instance classname along with the rest of the data. Have a look at the #Polymorphic annotation.
You can use just any ORM that supports the desired database dialect.
The hibernate framework has Object/grid Mapper (OGM) subproject that does just this.
BuguMongo?
http://code.google.com/p/bugumongo
Another option is to use Jongo which delegates polymorphic handling to Jackson. I've wrote a blog post with some examples and you can find the full code base on GitHub.
In your specific scenario, your solution with Jackson will look like this:
public enum DocTypeEnum {
INVOICE(Constants.INVOICE), ORDER(Constants.ORDER);
DocTypeEnum(String docTypeString) {
}
public static class Constants {
public static final String INVOICE = "INVOICE";
public static final String ORDER = "ORDER";
}
}
#JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY,
property = Document.TYPE)
#JsonSubTypes({
#JsonSubTypes.Type(value = Invoice.class, name = DocTypeEnum.Constants.INVOICE),
#JsonSubTypes.Type(value = Order.class, name = DocTypeEnum.Constants.ORDER)
})
public class Document {
public static final String TYPE = "type";
public static final String TITLE = "title";
private final DocTypeEnum type;
private final String title;
public Document(DocTypeEnum type, String title) {
this.type = type;
this.title = title;
}
#JsonProperty(TYPE)
public DocTypeEnum getType() {
return type;
}
#JsonProperty(TITLE)
public String getTitle() {
return title;
}
}
#JsonIgnoreProperties(ignoreUnknown = true)
public class Invoice extends Document {
public static final String DUE_DATE = "due_date";
private final Date dueDate;
public Invoice(String title, Date dueDate) {
super(DocTypeEnum.INVOICE, title);
this.dueDate = dueDate;
}
#JsonProperty(DUE_DATE)
public Date getDueDate() {
return dueDate;
}
}
#JsonIgnoreProperties(ignoreUnknown = true)
public class Order extends Document {
public static final String ITEMS = "items";
private final List<LineItems> items;
public Order(String title, List<LineItems> items) {
super(DocTypeEnum.ORDER, title);
this.items = items;
}
#JsonProperty(ITEMS)
public List<LineItems> getItems() {
return items;
}
}

Categories