In a recent meeting of the AMIS ADF SIG we organized a speed date with six different DVT components (note: DVT == Data Visualization Tags, the library of rich data presentation component part of ADF). One of these components, the one that I represented during this speed date, is the Gantt Chart. This chart comes in three flavors, as I described in this article: https://technology.amis.nl/2013/02/16/adf-dvt-speed-date-meeting-the-gantt-charts/. These are the Resource Utilization Gantt Chart, the Project Gantt Chart (the archetypical Gantt Chart) and the Resource Scheduler (the most generic and flexible of the three).
In this earlier article introducing the Gantt Chart, I introduced the Resource Scheduler using the example of a Presentation Schedule that visualizes the agenda for a conference. The Resource in this case are the Rooms that holds the sessions and the chart contains bars plotted against a Room and the Time axis to represent all of the presentations:
In the article you are reading right now, I will explain how to create a Resource Schedule Gantt Chart such as the one shown here. Even more interesting, I will then explain how to add drag & drop capabilities to this chart to turn it into an interactive scheduler tool that can be used to create the schedule by moving the presentations around through the time and room dimensions.
I should note that I received valuable support from Katia and Chadwick from the ADF DVT team at Oracle while putting together this example.
Model
Even though I could easily have used a few database tables for this example – something like ROOMS, PRESENTATION and SESSION – I did not. Instead, I created a POJO model and hard-coded the data, to keep things simple and runnable even without a database. The sample would not change dramatically if we were to use the database instead of this POJO model.
The Java Classes used here are PresentationScheduler – the business service class – Resource and Allocation. The Rooms are represented here by instances of the Resource class and a Presentation is planned by creating an Allocation object. When the Presentation is rescheduled, the Allocation will be updated.
The Resource and Allocation classes are just Java beans with properties and accessor methods. Note that the Resource has a collection of all Allocations, exposed through the getAllocations() method. The PresentationScheduler has a collection of Resources that are exposed through the getResources() method. In the constructor for this class, the collection of Resources (with child allocations) is created:
The PresentationScheduler class is exposed as a Data Control:
With this in place, we can go to the ViewController project to create the page with the Gantt Chart.
ViewController
Creating the Resource Schedule Gantt Chart for this Data Control is extremely simple. Create a JSF page. Then we drag the resources collection to the page and drop it as a Gantt | Scheduling.
The editor will appear for the Scheduling Gantt.
Select the identifier property on the resources as the Resource Id. Select the allocations collection as the Tasks Accessor (this term is appropriate in the most common use case for the Gantt Charts even though in our case it is not the most apt term). From the Allocations, select the id, type, startDate and endDate properties respectively as the Task Id, Task Type, Start Time and End Time properties for the Gantt Chart.
Click on OK. When the page appears, go edit the source for the page. Specifically: set the startTime and endTime for the schedulingGantt to 2013-01-31 10:00 and 2013-01-31 23:00 respectively. Also set the labelPlacement attribute (that governs the position of the labels that go with the bars (in this case the presentations). Finally set the scale for the two time axes to days and hours respectively, as is shown in the next figure:
At this point, you can run the page and see the schedule. It is still read only – but definitely a good start:
Now we create a Java Class in the ViewController project, called GanttManager. Add a private property ganttChart of type UISchedulingGantt to the class and generate the accessor methods for this property. Then add these teo methods getTooltipKeys() and getTooltipLabels() that will return a list of properties on the Allocations to be shown on the hover over popup and a list of the prompts to be used to identify the values returned from the tooltip keys:
Next define a managed bean based on this class:
The dvt:schedulingGantt can now be extended with additional attributes to help schedule the tooltips:
set the attributes tooltipKeyLabels and tooltipKeys to the corresponding properties on the ganttManagerBean. Also set the binding attribute to the ganttChart property on the ganttManagerBean.
Rerun the application and check if the tooltips show up when you hover over the bars:
Now we are done with the niceties. Time to get going in anger.
Enabling Drag and Drop for manipulating the Presentation Schedule
Add the following method to the GanttManagerBean class. It is a DataChange Listener that will be configured on the DVT component to be called whenever a Data Change event is recognized on the Gantt Chart. An example of a Data Change Event is the dropping of a bar in the Gantt Chart.
From the DataChangeEvent we can retrieve the ResourceId values for the source resource (the room from which the session is moved) and the target resource (the room into which the presentation is allocated). We can also get the taskId – which in our case corresponds to the identifier of the Allocation. We can also extract the start time at which the bar was dropped.
Using the helper methods findResourceById we can retrieve the Resource POJOs for the source and target Resource involved in this drag and drop operation. From the sourceResource’s allocations collection, we can get hold of the Allocation POJO whose bar was being dragged and dropped.
Next we can remove this allocation POJO from the allocations collection in the source Resource POJO. Next we can create a new Allocation POJO based on the old one. The new one is instantiated with the new start time and derived end time – and the same taskId (== the presentation title). This new Allocation POJO is then added to the allocations collection of the target Resource.
At this point the model has all the latest and greatest data. However, the View tier is not yet aware of that fact. The call to the utility method refreshIterator() will change that fact – it will as the name suggests refresh the iterator, bringing in the updated data from the model into the data bindings. Finally the Gantt Chart is added as a Partial Target to the RequestContext to ensure the Gantt Chart is refreshed in the browser.
The utility method findResourceById will use the Resource Id that we learned from the DataChangeEvent and find the associated Resource POJO in the iterator used in the Page’s Binding Container. The first few lines in this method use the EL Expression #{bindings.resource} – the reference to the Gantt Data Binding – to get hold of the JUCtrlHierBinding that is the Gantt Data Binding. From this object, the codes retrieves the RowIterator. Next, we will iterate through the RowIterator, retrieving the Rows one by one until we find a row that has for its identifier attribute a value that is equal to the resource id passed in to this method. When we find that row, in two steps – via DCDataRow and its DataProvider, we get to the underlying Resource POJO that we are looking for:
The other helper method uses the executeQuery() method on the Gantt Model’s iterator binding to bring the latest model data into the data bindings:
At this point we can configure the Data Change Listener on the Gantt Chart in the jspx page:
The DataChangeListener attribute is set to refer to the handleDataChanged method in the ganttManagerBean. This automatically enables operations such as stretching and contracting the bars in the Gantt Chart as well as dragging and dropping the bars at different times in different rooms. Only this latter event is recognized by the listener method and actually processed.
Run the page and you will be able to drag the bars around, drop them and see the Gantt Chart refreshed with the new Room and Time slot for the dropped bar:
Here the presentation APEX Adventures is dragged from the Innovation room to the Class room. Its start time is also made a little earlier.
The next figure demonstrates the result – APEX Adventures is now rescheduled. Next, the RAD Race is dragged to have it start a little earlier, yet in the same room:
Finally, the presentations Boring Basics Parts 1 is rescheduled from the Meeting room to the Class room:
This next picture shows the situation after all the rescheduling is done:
Notice how the Resource Classroom is now allowing three presentations to take place concurrently. Apart from the logic of this, the DVT component can at least deal with it and present the visualization in a proper way. You should realize that at this point it is not just the ADF DVT client side representation that has been updated; the underlying model is also updated (and potentially persisted).
Note: the Gantt Chart can also serve as a drop target for data dragged from other components and dropped on the Scheduler. A drop listener can then interpret the drop event and update the Gantt Chart’s model accordingly. Likewise, the Gantt Chart can be a drop source – allowing bars getting dragged to other components.
Resources
Download the JDeveloper 11gR1 11.1.1.6 application with the sources for the application introduced in this article: PresentationSchedulerGantt.zip.
Earlier blog article introducing the ADF DVT Gantt Charts: https://technology.amis.nl/2013/02/16/adf-dvt-speed-date-meeting-the-gantt-charts/.
Oracle Documentation on the ADF DVT Gantt Chart and its drag and drop capabilities: http://docs.oracle.com/cd/E14571_01/web.1111/b31973/dv_gantt.htm#BHADGJIG.
can we do this with Database tables ?