ObjectModel is the core functionality of BabyFish, it the reason why I created this framework.
ObjectModel is used to support "Smart Data Structcure", it can be splitted to two parts
ObjectModel4Java has many functionalities, this document only introduces two of them: 1, Consistency of bidirectional association; 2, Unstable objects.
(Please see demo-guide to know all functionalities).
1.3.1. Consistency of bidirectional association
Java developers often declare the data classes without any logic except getters and setters
(Bluntly, they're C-structures), the data structure described by these simple classes
does not have enough conveniences and intelligent.
For a simple example, there is a bidirectional association between
two objects, when one side of that association is modified by the developer,
the other side won't be changed, so the data structure become inconsistent,
we can navigate to object B from object A, but cannot navigate to object A from object B.
ObjectModel4Java adds the intelligent into data structure,
but it does not increase the code complexity, after all,
the classes without any logic except getters and setters is so easy to be developed that
they are accepted by every one. ObjectModel4Java only requires the developers to add a little
annotations to those simple classes, after the compilation-time bytecode instrument,
they will become powerful data classes.
Let's see an example, declare the bidirectional association between department and employees.
-
One department has many employees.
@Model //Uses ObjectModel4Java, requires compilation-time bytecode instrument.
public class Department {
//One side of bidirectional association,
//this field is the mirroring of "Employee.department".
@Association(opposite = "department")
private List<Employee> employees; //List has order.
The getters and setters are omitted
}
-
Each employee belongs to a department, and it also know its position in the list of its department.
@Model //Uses ObjectModel4Java, requires compilation-time bytecode instrument.
public class Employee {
//Other side of bidirectional association,
//this field is the mirroring of "Department.employees".
@Association(opposite = "employees")
private Department department; //Employee belongs to a department, if not, it's null
// This field is attached to "Employee.department", it's the index of current object in list of
// parent department object. If this object does not belong to any department object, it's -1.
@IndexOf("department")
private int index;
The getters and setters are omitted
}
Now, there are 6 objects, their variable names are department1, department2, employee1, employe2, employee3 and employee4, this is the data stucure:
Department object | Employee object |
---|
Variable name | employees | Variable name | department | index |
department1 | [ employee1, employee2 ] | employee1 | department1 | 0 |
employee2 | department1 | 1 |
department2 | [ employee3, employee4 ] | employee3 | department2 | 0 |
employee4 | department2 | 1 |
Then the developer modifies the "employees" collection of "department1", like this
department1.getEmployees().add(0, employee3);
This code inserts the "employee3" into the head of "department1.employees",
In order to preserve the consistency of data strucure, ObjectModel4Java will do these works:
- Remove "employee3" from the collection "department2.employees" automatically.
- Assign the "employee3.department" to be "department1" automatically.
- Increase "employee1.index" automatically, from 0 to 1.
- Increase "employee2.index" automatically, from 1 to 2.
- Decrease "employee4.index" automatically, from 1 to 0.
Finally, the data structure become:
Department Object | Employee Object |
---|
Variable name | employees | Variable name | department | index |
department1 | [ employee3, employee1, employee2 ] | employee1 | department1 | 1 |
employee2 | department1 | 2 |
employee3 | department1 | 0 |
department2 | [ employee4 ] | employee4 | department2 | 0 |
1.3.2. Unstable Objects.
In previous demo, the collection field uses "java.util.List", of course, "java.util.Set" and "java.util.Map"
can be used too. In this demo, we use "java.util.Set" to decribe the bidirectional many-to-many
association between companies and investors.
-
A company can be jointly funded by multiple investors.
@Model //Uses ObjectModel4Java, requires compilation-time bytecode instrument.
public class Company {
@Scalar //Scalar, not association.
private String shortName;
@Association(opposite = "companies")
// The annotation "@ComparatorRule" means this set collection uses the field "Investor.name"
// to calculate the hashCode of investor and check whether two investors are equal.
@ComparatorRule(properties = @ComparatorProperty("name"))
private Set<Investor> investors;
The getters and setters are omitted
}
-
An investor can invest in multiple companies.
@Model //Uses ObjectModel4Java, requires compilation-time bytecode instrument.
public class Investor {
@Scalar //Scalar, not association.
private String name;
@Association(opposite = "investors")
private Set<Company> companies;
The getters and setters are omitted
}
Now there are 3 object; one of them is an "Company" object whose variable name is "apple",
the other two are "Investor" objects whose variable name are "steve" and "sulley".
The data structure is:
Company object | Investor object |
---|
Variable name | shortName | investors | Variable name | name | companies |
---|
apple | Apple | [ steve, sculley ] | steve | Steve | [ apple ] |
sculley | Sculley | [ apple ] |
Now, the develop execute this code:
sculley.setName("Steve");
After execute this code, The value of "sculley.name" will be same with the value of "steve.name", both of them are "Steve";
But the collection field investors" of "Company"
uses the annotation@ComparatorRule
to let this collection cannot contains tow Investor objects with the same name.
This is a paradoxical situation.
Fortunately, the field investors" of "Company"
supports "Unstable Collection Elements"; that will cause the following effects.
-
In order to preserve the unique contraint of the set field,
the object "steve" will be crowded out from the collection
investors of object "apple"
automatically because of
"Unstable Collection Elements".
-
the object "steve" is longer the investor of "apple",
in order to preserve the consistency of bidirectional assocation.
the objet "apple" will be removed from the collection
companies of object "steve" auotmatically.
Finally, the data structure become:
Company object | Investor object |
---|
Variable name | shortName | investors | Variable name | name | companies |
---|
apple | Apple | [ sculley ] | steve | Steve | [] |
| sculley | Steve | [ apple ] |