How to correctly implement properties in complex objects - java

I have the following models:
class IdNamePair
{
protected int id;
protected String name;
public IdNamePair()
{
id = 0;
name = "";
}
}
class Voyage extends IdNamePair
{
//Several string and int variables
}
class Employee extends IdNamePair
{
//Several string and int variables
}
class Vessel extends IdNamePair
{
//Some string and int variables
}
class Details
{
//Several string and int variables
}
class Summary
{
protected Vessel vessel;
protected Employee chief;
protected Employee operator;
protected List<Details> details
}
class Update
{
protected LocalDateTime created;
protected LocalDateTime modified;
List<Summary> summaries;
//Some string and int variable.
}
I fail to understand how to create a complex Object with several Lists, Maps and instances of other classes. I can replace existing types of fields with corresponding property types (String to StringProperty, double to DoubleProperty, etc.) but how do I handle complex types (List<Summary>, HashMap<String, Vessel>, List<Details>)?
The other question is if I want to support properties, should I convert existing objects or do I need to create new ones. I can replace
class IdNamePair
{
protected int id;
protected String name;
}
with
class IdNamePair
{
protected IntegerProperty id;
protected StringProperty name;
}
or I can provide a new type
class IdNamePairEx
{
protected IntegerProperty id;
protected StringProperty name;
public IdNamePairEx(IdNamePair idNamePair);
///to simple object
public IdNamePair toIdNamePair();
///from simple object
public void fromIdNamePair(IdNamePair idNamePair);
}
and use it when dealing with GUI code. This approach would provide backward compatibility with existing code (JSON serialization, JDBC) but would effectively double the amount of my model classes. What is a preferred way?
Update:
I have a program that communicates to PostgreSQL and executes various CRUD operations. Corresponding classes exist for each table in the database.
I need to develop a new module that would make use of existing classes and I would like to implement GUI updates via bindings and properties.
Do I need to replace each type of variable with it's corresponding property type (String -> StringProperty) or is it better to create similar classes that operate via properties and provide conversion methods (class Vessel -> class VesselWithPropertiesInteadOfRawTypes)?

Related

Java Gson ClassCastException

I am building a Java Servlets 3.0 REST API and using Gson to serialize some data to json.
I get this error, though:
java.lang.ClassCastException: za.co.a.models.tables.sybase.Family cannot be cast to java.util.Map
at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.write(MapTypeAdapterFactory.java:145)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:97)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:61)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:127)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:245)
at com.google.gson.Gson.toJson(Gson.java:704)
at com.google.gson.Gson.toJson(Gson.java:683)
at com.google.gson.Gson.toJson(Gson.java:638)
at com.google.gson.Gson.toJson(Gson.java:618)
at za.co.a.helpers.JsonHelper.toJson(JsonHelper.java:33)
at za.co.a.models.tables.sybase.ActiveProcesses.saveProcess(ActiveProcesses.java:57)
My code is as follows:
#Table(name = "E_FAMILY")
public class Family extends IGenericModel <Family>
{
#Id
public BigDecimal EMPLOYEE_ID;
#Id
public BigDecimal FAMILY_ID;
#Id
public BigDecimal COMPANY_ID;
public String FIRSTNAME;
public String SECONDNAME;
public String SURNAME;
public String RELATION;
public int RELATION_ID;
public String MED_DEPENDENT_YN;
public String TAX_DEPENDENT_YN;
public String GENDER;
public Date BIRTHDATE;
public String TEL_HOME;
public String TEL_WORK;
public String TEL_CELL;
public String E_MAIL;
...
}
The calling code:
public String toJson(Object obj)
{
return gson.toJson(obj);
}
Family, in this case is field in a larger class, however, I'm not having any problems with any other fields or any other classes that are similar. This is the first time, in the year I've been developing this, that this error comes up. Is there a limit to the size or complexity of class Gson can serialize? Or what can I check to see what's causing the error? Or is there a way change this specific mapping, (though I don't understand why Google is trying to map this class to Map)?
Thanks
Sethmo
Edit Including class hierachy
IGenericModel and IGenericReadOnlyModel only contain functions. IModel has 2 members, but I've added it as part of an ExclusionStrategy so that those members don't get serialized.
public class IGenericModel<T> extends IGenericReadOnlyModel
{
}
public class IGenericReadOnlyModel<T> extends IModel
{
}
public class IModel
{
protected String dbEngine;
protected IDatabase db;
}
Edit rest of the code
Ok, the class that holds Family is quite large and mostly full of Strings, Dates and Booleans and ints. Where Family comes in is here, the two objects are passed from the front-end and represent the old and new values (users can edit, add and delete family members in the UI, then submit those lists).
public abstract class IWebProcess extends IModel
{
protected Object _OldValue;
protected Object _NewValue;
}
Once submitted (as JSON from the UI), it's serialized:
Type familyType = new TypeToken<LinkedList<Family>>(){}.getType();
LinkedList<Family> oldFamily = gson.fromJson(oldFamilyJson, familyType);
LinkedList<Family> newFamily = gson.fromJson(newFamilyJson, familyType);
Then, the concrete class is then initialized:
IWebProcess family = WebProcess_FamilyRequisition(oldFamily,newFamily,...,...,...)
then, in the constructor of WebProcess_FamilyRequisition, I call super(oldFamily, newFamily) and then in the constructor of IWebProcess:
this._OldValue = oldFamily
this._NewValue = newFamily
I do all this casting because I save the new values to the DB first, before serializing the entire WebProcess to the DB. I've made _OldValue and _NewValue Objects because this is a base class for 8 other classes that work the same and they serialize just fine.

Object to string delimited format

I have set of objects of different types.
Ex : Employee emp, adress adr
These two classes have list of properties
public class Employee{
private Stringname;
private int age;
}
public class Adress {
private String HouseNo;
private string Street;
private string pin;
}
Each attribute is assigned with some 2 character value
Name (NA), age (AG), HouseNo(HN),Street(ST), pin(PN)
I need to construct a string with these data and delimit with a %
Output:
NA%Vidhya%AG%30%HN%80%ST%1st cross%PN%100100
Each class knows it own data best so I would let each class be responsible for generating the string. As I understand it the two char codes for each field are unique for each class and member and only used when generating the string so only the class would need them.
interface AttributeDescription {
String generateDescription();
}
public class Employee implements AttributeDescription {
//members...
public String generateDescription() {
return String.format(“NA%%%s%%AG%%%d”, name, age)
}
Then simply call this method for all objects implementing the interface.
AttributeDescription object = ...
String attr = object.generateDescription();
I don't think it can be generalized more than this given the requirements.
Update
It might be better to have a builder class for building the string to get a more unified behavior between classes. Here is an example
public class AttributeBuilder {
private builder = new StringBuilder();
public String getAttribute() {
return builder.toString();
}
public void add(String code, String value) {
if (value == null) {
return;
}
builder.append(code);
builder.append(‘%’);
builder.append(value);
builder.append(‘%’);
}
}
And then you would also have to implement add(...) methods for other data types in a similar fashion. The builder could then be used like
public String generateDescription() {
AttributeBuilder builder = new AttributeBuilder();
builder.add(“NA”, name);
builder.add(“AG”, age);
return builder.getAttribute();
}

Decide which Enum return based on object properties

I'm wondering if there is some design pattern to help me with this problem.
Let's say I have a class Person which has three attributes: name, nickname and speaksEnglish and an Enum PersonType with TypeOne, TypeTwo and TypeThree.
Let's say if a Person has nickname and speaksEnglish it's a TypeOne. If it has nickame but doesn't speaksEnglish, it's a TypeTwo. If it does not have nickame, so it's TypeThree.
My first thought would have a method with some if-else and returning the related Enum. In the future I can have more attributes in Person and other types of PersonType to decide.
So, my first thought was create a method with a bunch of if (...) { return <PersonType> } or switch-case, but I was wondering if there is some design pattern I can use instead of ifs and switch-case.
I will recomend you to use just simple inheritance with immutable objects.
So, at first you have to create abstract class:
public abstract class AbstractPerson {
private final String name;
private final Optional<String> nickname;
private final boolean speaksEnglish;
private final PersonType personType;
protected AbstractPerson(final String name, final Optional<String> nickname, final boolean speaksEnglish, final PersonType personType) {
this.name = name;
this.nickname = nickname;
this.speaksEnglish = speaksEnglish;
this.personType = personType;
}
public String getName() {
return name;
}
public Optional<String> getNickname() {
return nickname;
}
public boolean getSpeaksEnglish() {
return speaksEnglish;
}
public PersonType getPersonType() {
return personType;
}
}
With PersonType enum:
public enum PersonType {
TypeOne, TypeTwo, TypeThree;
}
Now, we have three options with corresponding constructors in child classes:
public final class EnglishSpeakingPerson extends AbstractPerson {
public EnglishSpeakingPerson(final String name, final String nickname) {
super(name, Optional.of(nickname), true, PersonType.TypeOne);
}
}
public final class Person extends AbstractPerson {
public Person(final String name, final String nickname) {
super(name, Optional.of(nickname), false, PersonType.TypeTwo);
}
public Person(final String name) {
super(name, Optional.empty(), false, PersonType.TypeThree);
}
}
In this case, our concrete classes are immutable and its type is defined in moment of creation. You don't need to create if-else ladders - if you want to create new type, just create new class/constructor.
I don't think Type can really be an attribute of a Person. I am not against #ByeBye's answer but with that implementation you will still end up changing Person class when there are new types introduced.
X type of person is ultimately a person itself. Say a Manager or Developer are both employees of a company, so it makes a lot of sense to have them as specialized classes that derive from an Employee. Similarly in your case, having person type as an attribute and then doing all if-else stuff clearly violates SOLID.
I would instead have specific implementations of Person class and mark itself as an abstract one.
public abstract class Person {
public Person(string name) {
Name = name;
}
public abstract string Name { get; set; }
public abstract string NickName { get; set; }
public abstract bool SpeaksEnglish { get; set; }
}
public class TypeOnePerson : Person {
public TypeOnePerson(string name, string nickName) : base(name) {
NickName = nickName; // Validate empty/ null
}
SpeaksEnglish = true;
}
public class TypeTwoPerson : Person {
public TypeOnePerson(string name, string nickName) : base(name) {
NickName = nickName; // Validate empty/ null
}
SpeaksEnglish = false;
}
I also think that this question is language-agnostic, it is a pure design question. So please bear with me as the code above is in C#. That doesn't matter, however.
As far as OO principles are considered why to create object with combinations of optional attributes? If its question of one or two then Optional approach will remain maintainable, but type will be based on many combinations (in future code will be full of Boolean Algebra) and question also says "...In the future I can have more attributes in Person and other types of PersonType to decide.".
I would suggest approach of using Decorator pattern, which allows us to create customized objects with complete code reuse. Person will be Component and Optional attributes (they are types e.g NickName with validation as behavior) will be concrete decorators.
Any addition to Person and adding new Concrete Decorator type remain two separate concerns. Decorator Pattern is a best candidate for this kind of requirement. Its Intent from GOF book (by Erich gamma) pattern Catalog says - "Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality". [though for very small number of expected extensions earlier answers make more sense.]

How to pass different objects (having same parent) to a constructor and how to identify type of that object in constructor

I have a scenario where I'm sending different objects to a constructor and I have to identify the class of that object and set values accordingly.
Class ABC {
private long id;
private SomeClass obj;
private String xyzName;
private Date date;
private EnumType status;
// And Getters and Setters
}
Class A extends ABC {
private String someOtherId;
private String type;
private String model;
private String manufacturer;
//and some props and Getters and Setters
}
Class B extends ABC {
private String someOtherId;
private String equipName;
private String model;
private String serialNo;
//and some props and Getters and Setters
}
Class C extends ABC {
private String someOtherId;
private String materialName;
private String desc;
private String serialNo;
//and some props and Getters and Setters
}
Note: These are the entity classes
And In Controller, I'm doing ops like adding, editing, updating(mostly changing statuses) and etc.And every time I do I have to enter or log kind of msg into
History Class. something like
From AController
historyService.enterLogToHistory(new
History(Aobject, EnumType.somestatus));
From BController,
historyService.enterLogToHistory(new History(Bobject,
EnumType.somestatus));
From CController,
historyService.enterLogToHistory(new
History(Cobject,EnumType.somestatus));
Class History() {
private long id;
private Date date;
private String Status;
private String Activity; // or msg
// some other #Transient properties
History(Object obj) {
//set above values like by getting values form this obj(using getters)
}
History(Object obj, EnumType status) {
this(obj);
// set some other #Transient properties by getting values form this obj
// and set value for msg;
}
}
So, Now my problem is how to identify that object whether it is A obj,
B, obj or C obj because if know the type of object only I can the getters of that obj and I can set values in History constructor.
So, please anyone help me out in this
To get rid of instanceof mess, consider using oveloaded constructors:
class History {
History(A a) {
// initialize by `A` instance
}
History(B b) {
// initialize by `B` instance
}
//...
}
This will work if you know classes of all instances on compile time.
Another option is to switch to static factory methods:
public class History {
// private constructor to hide instance creation
private History(ABC abc) {
this.id = abc.getId();
this.date = new Date(abc.getDate().getTime());
// ... another common properties
}
public History setStatus(Status s) {
this.status = s;
return this;
}
// public static factory methods to create instances specified by input
public static History of(A a) {
History h = new History(a);
h.type = a.getType();
// ... properties specific for `A`
return h;
}
public static History of(A a, Status status) {
return of(a).setStatus(status);
}
public static History of(B b) {
History h = new History(b);
h.model = b.getModel();
// ... properties specific for `B`
return h;
}
// ...
}
Then, to create History instances, caller invokes:
History aHistory = History.of(a);
History bHistory = History.of(b, Status.ACTIVE);
The main advantage of such approach is that more stable API is introduced, while it remains flexible for internal refactoring. Imagine, you decide to implement various behavior for History of different types, e.g. VehicleHistory and VesselHistory. So you create those classes extending History, override some methods in them and refactor a few of() methods in History class (so that not new History(), but new VehicleHistory() is called). As far as you never call constructor externally, for outer code things remain unchanged -- it receives History object as before from the same History.of() method as before.

how to choose what type of object to instantiate based on form field?

i have a struts2 form that takes in a Maintenance object. there are different types of Maintenance - for the sake of brevity let's say there is RemovePart and InstallPart. this form includes fields for both, but the user only sees one - that is based on the user's choice in the first dropdown.
what is the correct (best?) way to determine which Maintenance class to instantiate once my Action receives the data? the best i've come up with so far is below, though i can't help thinking there is a better way to do it.
EDIT 6/24 14:18 GMT: the RemovedPart and InstalledPart classes have fields that don't correspond to each other.
public class Maintenance {
private String maintenanceType;
private String removedSerialNumber;
private String removedPartName;
private String removedPartDescription;
private String removedPartPosition;
private String installedSerialNumber;
private String installedPartName;
private String installedPartSource;
// getters and setters
}
public class RemovedPart {
private String serialNumber;
private String partName;
private String partDescription;
private String partPosition;
public static createRemovedPart(Maintenance maintenance) {
return new RemovedPart(maintenance.getRemovedSerialNumber(),
maintenance.getRemovedPartName(), maintenance.getRemovedPartDescription(),
maintenance.getRemovedPartPosition());
}
private RemovedPart() {
this.serialNumber = serialNumber;
this.PartName = partName;
this.partDescription = partDescription;
this.partPosition = partPosition;
}
// getters and setters
}
public class InstalledPart {
//similar to RemovedPart
}
public class MaintAction extends ActionSupport {
Maintenance maintenance;
public String execute() {
if (maintenance.getMaintenanceType().equals("remove")) {
RemovedPart removed = RemovedPart.createRemovedPart(maintenance);
} else {
// you get the idea
}
// more logic
return SUCCESS;
}
We can't know how much complex or big is your design, but from what has been shown, IF the Maintenance class is declaring duplicate fields (eg. serialnumber for both removed and installed) WITHOUT using both of them at the same time, and hence they're declared only to be filled by the chosen type of maintenance from the page... then you don't need 3 objects, nor duplicate fields:
declare a single Maintenance class, with single fields
post it to different actions, one for removal, one for installation.
The type alone will help you to determine which kind of Maintenance you are handling from a method run by both types. However, it would be better to turn it to an Enum:
public enum MaintenanceType {
INSTALLATION(1), REMOVAL(2);
private int type;
private MaintenanceType(int t) {
type = t;
}
public int getType() {
return type;
}
}
public class Maintenance {
private MaintenanceType type;
private String serialNumber;
private String partName;
// getters and setters
public boolean isInstallation(){
return type == MaintenanceType.INSTALLATION;
};
public boolean isRemoval(){
return type == MaintenanceType.REMOVAL;
};
}
If I understand your Problem correctly you want to have several kinds of Maintenance?
In this case you should think about inheritance
public abstract class Maintenance{
//code
}
public class Removal extends Maintenance{
//has everything Maintenance hase plus extras you can add here
}
public class Installation extends Maintenance{
//same as Removal
}
you could then define a Maintenance like this:
Mainenance m = new Removal();
you could also use interfaces,
public Interface Maintenance{
private String serialNumber;
...
public String getSerialNumber();
...
}
your classes could then implement the Interface and you could use them similar to the inherited version.

Categories