Ограниченный поток задач имеет следующую структуру:
Действие StartView — это фрагмент страницы, где мы вводим количество пассажиров, а действие DynamicView предоставляет фрагмент страницы для ввода информации о пассажире. На данный момент у нас есть только одно действие для информации о пассажирах, и я добавлю дополнительные действия, если количество пассажиров больше одного.
InputNumberSpinbox во фрагменте страницы StartView передает свое значение свойству passengerNumber некоторого базового компонента PageFlowScope, а действие для кнопки « Отправить» — это метод того же компонента:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
public class MainTrain { //Extra added train stops private List<ActivityId> dynamicStops = new ArrayList<ActivityId>(); //Value of inputNumberSpinbox private int passengersNumber = 1 ; public String buttonPress(){ //The number of extra added train stops is greater than needed if (passengersNumber <= dynamicStops.size()) clearExtraStops(); else //The number of extra added train stops is less than needed if (passengersNumber- 1 > dynamicStops.size()) addDynamicStops(); return null ; } |
Таким образом, нажимая на кнопку « Отправить» , мы либо добавляем некоторые остановки поезда, либо очищаем дополнительные остановки в зависимости от значения inputNumberSpinbox . Мы сохраняем все добавленные динамические остановки в списке dynamicStops . Давайте посмотрим на метод clearExtraStops () :
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
private void clearExtraStops() { for ( int i = dynamicStops.size(); i >= passengersNumber; i--) { //Get ActivityId to be removed ActivityId removeActivityId = dynamicStops.get(i- 1 ); //Get current train model and remove train stop TrainModel trainModel = TrainUtils.findCurrentTrainModel(); trainModel.getTrainStops().remove(removeActivityId); //Remove activity from task flow definition getTaskFlowDefinition().getActivities().remove(removeActivityId); dynamicStops.remove(i- 1 ); } } |
Метод удаляет две вещи: остановка поезда из модели поезда и действие из определения потока задач. Метод addDynamicStops () будет гораздо интереснее:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
private void addDynamicStops() { for ( int i = dynamicStops.size(); i < passengersNumber - 1 ; i++) { //Creating new ActivityId ActivityId activityId = new ActivityId(getTaskFlowId(), new StringBuilder( "DynamicView" ).append(i).toString()); //The main trick of the post. //We consider DynamicView activity as a base for new train stop and new activity //Get base activity (DynamicView) and its train stop Activity baseActivity = getBaseDynamicActivity(); TrainStopContainer stopContainer = (TrainStopContainer)baseActivity.getMetadataObject(); TrainStop baseTrainStop = stopContainer.getTrainStop(); //Create new Activity based on DynamicView but with new ActivityId ActivityImpl activityImpl = new ActivityImpl(baseActivity, activityId); //Add created activity to the task flow definition getTaskFlowDefinition().getActivities().put(activityId, activityImpl); //Create new train stop based on the DynamicView's train stop TrainStopModel trainStopModel = new TrainStopModel( new TrainStopImpl(baseTrainStop, i+ 2 ), activityId); //Add created train stop to the train stop model TrainModel trainModel = TrainUtils.findCurrentTrainModel(); trainModel.getTrainStops().put(activityId, trainStopModel); //Add created activity to our list dynamicStops.add(activityId); } } private Activity getBaseDynamicActivity() { ActivityId baseActivityId = new ActivityId(getTaskFlowId(), "DynamicView" ); MetadataService metadataService = MetadataService.getInstance(); return metadataService.getActivity(baseActivityId); } private TaskFlowDefinition getTaskFlowDefinition() { MetadataService metadataService = MetadataService.getInstance(); return metadataService.getTaskFlowDefinition(getTaskFlowId()); } private TaskFlowId getTaskFlowId() { ControllerContext controllerContext = ControllerContext.getInstance(); ViewPortContext currentViewPortCtx = controllerContext.getCurrentViewPort(); TaskFlowContext taskFlowCtx = currentViewPortCtx.getTaskFlowContext(); return taskFlowCtx.getTaskFlowId(); } |
Итак, основной трюк этого поста заключается в создании новых действий и остановок поездов на основе существующих для DynamicView . Чтобы реализовать идею, я создал два класса: ActivityImpl и TrainStopImpl . Классы — это не что иное, как прокси-классы, реализующие интерфейсы Activity и TrainStop соответственно. Они делегируют реализацию интерфейса базовым экземплярам, за исключением некоторых конкретных методов, таких как getters for Id и DisplayName:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
public class TrainStopImpl implements TrainStop { //Base instance private TrainStop baseTrainStop; private int mpassNo; private static final String PASSANGER_FORM = "Passenger's data: " ; public TrainStopImpl(TrainStop trainStop, int passNo) { baseTrainStop = trainStop; mpassNo = passNo; } //Specific implementation public String getDisplayName() { return new StringBuilder(PASSANGER_FORM).append(mpassNo).toString(); } public String getOutcome() { return baseTrainStop.getOutcome(); } public String getSequential() { return baseTrainStop.getSequential(); } ... |
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
|
public class ActivityImpl implements Activity { private Activity baseActivity; private ActivityId mid; public ActivityImpl(Activity activity, ActivityId id) { baseActivity = activity; mid = id; } //Specific implementation public ActivityId getId() { return mid; } public String getType() { return baseActivity.getType(); } public Object getMetadataObject() { return baseActivity.getMetadataObject(); } ... |
И еще одна картинка для этого поста, просто чтобы показать, что он работает:
Вот и все! Вы можете скачать пример приложения для JDeveloper 11.1.1.2.0.
Справка: динамический поезд ADF. Добавление остановки поезда программно от нашего партнера JCG Евгения Федоренко в блоге ADF Practice .