The example sources like other examples is prepared for download at
http://www.fishbolt.org/dowloads/eclipse/example.plugins.zip
Data Model plug-in
The separated eclipse plug-in creation is described in the section. The plug-in will contain the data model declaration. It is a good practice to separate data model from user interface.
Plug-in creation
Let's add a dependency after the plug-in creation:
image at
http://fishbolt.org/eclipse/org.fishbolt.model.hibernate.annotations/doc/img/example1.gif
image at
http://fishbolt.org/eclipse/org.fishbolt.model.hibernate.annotations/doc/img/example2.gif
And let's add the following line to MANIFEST.MF
file (to use single class loader for work with hibernate libraries):
Eclipse-RegisterBuddy: org.fishbolt.model.hibernate.annotations
Data object classes and its managers creation
"Department" data object:
/**
* Data object presenting department
*/
@DisplayLabel("Department")
@ImageResource("department.gif")
@Entity
@Tuplizer(impl = CompanyModelTuplizer.class)
@AccessType("org.fishbolt.model.hibernate.FieldAccessor")
public class Department extends HDataObject {
@Id
@GeneratedValue
@DisplayLabel("Identity")
public final static FieldDeclaration id =new FieldDeclaration(Department.class);
@ObjectPresentationField
@Column(unique=true, nullable=false)
@DisplayLabel("Name")
@Width(250)
public final static FieldDeclaration name =new FieldDeclaration(Department.class);
@DisplayLabel("Employees")
@Relation(inverse="department")
@OneToMany(targetEntity=Employee.class)
@JoinColumn(name="department")
public final static FieldDeclaration> employees =new FieldDeclaration>(Department.class);
public Department(DepartmentManager manager) {
super(manager);
}
public Department() {
super();
}
}
"Department" data object manager:
/**
* Manager class for {@link Department} data object.
*/
public class DepartmentManager extends HDataObjectManager{
/**
* Constructor inherited from the super class
*/
public DepartmentManager(IDataModel dataModel,ObjectDescriptor<?,?> objectDescriptor) {
super(dataModel, objectDescriptor);
}
/**
* Searches for a department by its name
* @param name - the name of the department to search for
* @return department or null
*/
public Department findDepartment(String name){
String hql = "from Department where name=?";
QueryUniqueResultCommand cmd =
new QueryUniqueResultCommand(hql);
cmd.setParameters(new Parameter(name));
return this.getModel().processCommand(cmd);
}
}
"Employee" data object:
/**
* Data object presenting employee
*/
@DisplayLabel("Employee")
@ImageResource("employee.gif")
@Entity
@Tuplizer(impl = CompanyModelTuplizer.class)
@AccessType("org.fishbolt.model.hibernate.FieldAccessor")
public class Employee extends HDataObject {
@Id
@GeneratedValue
@DisplayLabel("Identity")
public final static FieldDeclaration id =new FieldDeclaration(Employee.class);
@Transient
@ObjectPresentationField
@DisplayLabel("Name")
@Width(250)
public final static FieldDeclaration name =new FieldDeclaration(Employee.class);
@Column(nullable=false)
@DisplayLabel("First Name")
public final static FieldDeclaration firstName =new FieldDeclaration(Employee.class);
@Column(nullable=false)
@DisplayLabel("Last Name")
public final static FieldDeclaration lastName =new FieldDeclaration(Employee.class);
@DisplayLabel("Phone Number")
public final static FieldDeclaration phoneNumber =new FieldDeclaration(Employee.class);
@SimpleDateFormatPresentation("dd/MM/yyyy")
@DisplayLabel("Birthday")
public final static FieldDeclaration birthday =new FieldDeclaration(Employee.class);
@DisplayLabel("Salary")
@Column(nullable=false)
@DecimalFormatPresentation("#,##0.00")
@PresentationDecorator(prefix="$ ")
public final static FieldDeclaration salary =new FieldDeclaration(Employee.class);
@DisplayLabel("Health")
@NumberFormatPresentation(NumberFormatInstance.percent)
public final static FieldDeclaration health =new FieldDeclaration(Employee.class);
@DisplayLabel("Department")
@Relation(inverse="employees")
@ManyToOne(optional=false)
@JoinColumn(name="department")
public final static FieldDeclaration department =new FieldDeclaration(Employee.class);
public Employee(EmployeeManager manager) {
super(manager);
}
public Employee() {
super();
}
}
"Employee" data object manager:
/**
* Manager class for {@link Employee} data object.
*/
public class EmployeeManager extends HDataObjectManager{
/**
* Constructor inherited from the super class
*/
public EmployeeManager(IDataModel dataModel,ObjectDescriptor<?,?> objectDescriptor) {
super(dataModel, objectDescriptor);
}
/**
* Searches for an employee among all employees of a company
* @param firstName - employee's first name
* @param lastName - employee's last name
* @return List of employees
*/
public List findEmployee(String firstName,String lastName){
String hql = "from Employee where firstName=? and lastName = ?";
QueryListCommand cmd = new QueryListCommand(hql);
cmd.setParameters(
new Parameter(firstName),
new Parameter(lastName));
return this.getModel().processCommand(cmd);
}
/**
* Searches for an employee in a department
* @param firstName - employee's first name
* @param lastName - employee's last name
* @param department
* @return List of employees
*/
public List findEmployee(String firstName,String lastName, Department department){
String hql = "from Employee where firstName=? and lastName=? and department=?";
QueryListCommand cmd = new QueryListCommand(hql);
cmd.setParameters(
new Parameter(firstName),
new Parameter(lastName),
new Parameter(department));
return this.getModel().processCommand(cmd);
}
}
Data model class declaration
/**
* Company model class
*/
public class CompanyModel extends DataModel {
public final static ObjectDescriptor employee =
new EObjectDescriptor(CompanyModel.class);
public final static ObjectDescriptor department =
new EObjectDescriptor(CompanyModel.class);
public static ModelDescriptor getDescriptor(){
return CompanyModel.department.getModelDescriptor();
}
private static CompanyModel instance;
public static CompanyModel getInstance(){
return (instance == null) ?
instance = new CompanyModel(getDescriptor()) : instance;
}
private CompanyModel(ModelDescriptor modelDescriptor) {
super(modelDescriptor);
}
}
Configuring hibernate
Let's crate the Tuplizer-class (mentioned at co-named annotation in data objects)
public class CompanyModelTuplizer extends DataObjectTuplizer {
/**
* Constructor inherited from the super class
*/
public CompanyModelTuplizer(EntityMetamodel entityMetamodel,PersistentClass mappedEntity) {
super(entityMetamodel, mappedEntity);
}
@Override
protected ModelDescriptor getModelDescriptor() {
return CompanyModel.getDescriptor();
}
}
hibernate.cfg.xml creation
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
org.hibernate.dialect.PostgreSQLDialect
org.postgresql.Driver
jdbc:postgresql://localhost/company
postgres
********
Calculated fields
The "Employee" data object contains name filed. The filed is calculated and doesn't mapped to the database as a result.The algorithm of the filed value evaluation implemented bellow:
public class EmployeeFullNameCalculation implements IFieldCalculation {
public FieldPath[] getInfluencingPaths(FieldDescriptor dependent) {
return new FieldPath[]{
new FieldPath(true, CompanyModel.employee,Employee.firstName),
new FieldPath(true, CompanyModel.employee,Employee.lastName)
};
}
public String evaluateValue(IDataField toEvaluate) {
Employee employee = (Employee)toEvaluate.getDataObject();
return ModelUtil.getValue(employee,Employee.firstName)+
" " + ModelUtil.getValue(employee,Employee.lastName);
}
}
Let's bind in code the algorithm and data field
public class CompanyCalculationProviderFactory extends FieldCalculationProviderFactorySafe{
/**
* Binds calculated fields with calculation classes
*/
@Override
protected void bindCalculations() {
// binding Employee.name with EmployeeFullNameCalculation
bindCalculation(CompanyModel.employee,Employee.name,new EmployeeFullNameCalculation());
}
}
Changes in the plug-in manifest
Let's register factory providers - declare extension of the ModelAdapterFactory point:
image at
http://eclipse.org/eclipse/org.fishbolt.model.hibernate.annotations/doc/img/example3.gif"/>
Hence the plugin.xml looks in the following way:
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.2"?>
Let's export packages:
image at
http://eclipse.org/eclipse/org.fishbolt.model.hibernate.annotations/doc/img/example4.gif"/>
And add the driver library:
image at
http://eclipse.org/eclipse/org.fishbolt.model.hibernate.annotations/doc/img/example5.gif"/>
image at
http://eclipse.org/eclipse/org.fishbolt.model.hibernate.annotations/doc/img/example6.gif"/>
The resulting plug-in
image at
http://eclipse.org/eclipse/org.fishbolt.model.hibernate.annotations/doc/img/example7.gif"/>
Database tables creation
Let's create the "company" database (Postgres - server). And let's create tables:
CREATE TABLE department
(
id integer NOT NULL,
name character varying(255) NOT NULL,
CONSTRAINT department_pkey PRIMARY KEY (id),
CONSTRAINT department_name_key UNIQUE (name)
)
CREATE TABLE employee
(
id integer NOT NULL,
firstname character varying(255) NOT NULL,
lastname character varying(255) NOT NULL,
phonenumber character varying(255),
birthday date,
health double precision,
parttime boolean,
salary numeric(19,2),
department integer NOT NULL,
CONSTRAINT employee_pkey PRIMARY KEY (id),
CONSTRAINT fk4afd4acec0414ee2 FOREIGN KEY (department)
REFERENCES department (id)
)
UI plug-in
Let's create UI plug-in and add the dependencies
image at
http://eclipse.org/eclipse/org.fishbolt.model.hibernate.annotations/doc/img/example8.gif"/>
As it shownat the picture, the created data model plug-in (example.org.fishbolt.model.hibernate.annotations) is among the dependencies.
Data object wizards
Let's create wizard clasess. The "Employe" data object wizard listing is bellow:
/**
* Wizard for adding new employees
*/
public class NewEmployeeWizard extends ObjectNewWizard {
public NewEmployeeWizard() {
// indicating the descriptor of a data object
// whose instances will be created by the wizard
super(CompanyModel.employee);
}
@Override
protected IDataModel getDataModel(IWorkbench workbench,IStructuredSelection selection) {
// providing a reference to the data model
// to which new Employee instances will be added
return CompanyModel.getInstance();
}
@SuppressWarnings("unchecked")
@Override
public void init(IWorkbench workbench,IStructuredSelection selection){
super.init(workbench, selection);
String name = LabelProvider.getDisplayLabel(CompanyModel.employee);
// adding pages for step-by-step creation of Employee instances
this.addPage(
new ObjectSimpleWizardPage(name,name,null,
Employee.firstName,
Employee.lastName,
Employee.department,
Employee.phoneNumber));
this.addPage(
new ObjectSimpleWizardPage(name,name,null,
Employee.birthday,
Employee.salary,
Employee.health));
}
}
Let's register corresponding extension
image at
http://eclipse.org/eclipse/org.fishbolt.model.hibernate.annotations/doc/img/example9.gif"/>
The first page of the "Employee" wizard:
image at
http://eclipse.org/eclipse/org.fishbolt.model.hibernate.annotations/doc/img/example10.gif"/>
Let's add UI action which opens wizard to create new "Employee" data object
public class OpenNewEmployeeWizardAction extends OpenNewWizardAction {
@SuppressWarnings("unchecked")
public OpenNewEmployeeWizardAction(ViewerController controller) {
super(controller, "New Employee...","Creates a new employee");
}
@Override
public INewWizard getNewWizard() {
return new NewEmployeeWizard();
}
@Override
public void updateEnable() {
this.setEnabled(getActionObject() instanceof Department);
}
}
See continue
Data object editor,
Change data field value dialog,
Department-employee tree,
Employees table,
Employee search panel,
Application UI
at the
http://fishbolt.org/eclipse/org.fishbolt.model.hibernate.annotations/doc/plugin.article.en.html#dataObjectEditor