View Javadoc

1   /**
2    * Copyright 2010 The Kuali Foundation Licensed under the
3    * Educational Community License, Version 2.0 (the "License"); you may
4    * not use this file except in compliance with the License. You may
5    * obtain a copy of the License at
6    * <p/>
7    * http://www.osedu.org/licenses/ECL-2.0
8    * <p/>
9    * Unless required by applicable law or agreed to in writing,
10   * software distributed under the License is distributed on an "AS IS"
11   * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
12   * or implied. See the License for the specific language governing
13   * permissions and limitations under the License.
14   * <p/>
15   */
16  package org.kuali.student.common.ui.client.configurable.mvc.multiplicity;
17  
18  import java.util.ArrayList;
19  import java.util.HashMap;
20  import java.util.List;
21  import java.util.Map;
22  import java.util.Set;
23  import java.util.Map.Entry;
24  
25  import org.kuali.student.common.ui.client.configurable.mvc.FieldDescriptor;
26  import org.kuali.student.common.ui.client.configurable.mvc.binding.ModelWidgetBinding;
27  import org.kuali.student.common.ui.client.configurable.mvc.sections.BaseSection;
28  import org.kuali.student.common.ui.client.configurable.mvc.sections.GroupSection;
29  import org.kuali.student.common.ui.client.configurable.mvc.sections.MultiplicitySection;
30  import org.kuali.student.common.ui.client.configurable.mvc.sections.Section;
31  import org.kuali.student.common.ui.client.configurable.mvc.sections.SwapSection;
32  import org.kuali.student.common.ui.client.configurable.mvc.sections.VerticalSection;
33  import org.kuali.student.common.ui.client.mvc.Callback;
34  import org.kuali.student.common.ui.client.mvc.DataModel;
35  import org.kuali.student.common.ui.client.widgets.KSButton;
36  import org.kuali.student.common.ui.client.widgets.KSButtonAbstract.ButtonStyle;
37  import org.kuali.student.common.ui.client.widgets.ListOfStringWidget;
38  import org.kuali.student.common.ui.client.widgets.list.KSRadioButtonList;
39  import org.kuali.student.common.ui.client.widgets.list.KSSelectItemWidgetAbstract;
40  import org.kuali.student.common.ui.client.widgets.list.ListItems;
41  import org.kuali.student.common.ui.client.widgets.list.SelectionChangeEvent;
42  import org.kuali.student.common.ui.client.widgets.list.SelectionChangeHandler;
43  import org.kuali.student.common.ui.client.widgets.list.impl.KSRadioButtonListImpl;
44  import org.kuali.student.common.ui.client.widgets.list.impl.SimpleListItems;
45  import org.kuali.student.common.ui.client.widgets.search.KSPicker;
46  import org.kuali.student.core.assembly.data.Data;
47  import org.kuali.student.core.assembly.data.MetadataInterrogator;
48  import org.kuali.student.core.assembly.data.QueryPath;
49  
50  import com.google.gwt.core.client.GWT;
51  import com.google.gwt.event.dom.client.BlurHandler;
52  import com.google.gwt.event.dom.client.ClickEvent;
53  import com.google.gwt.event.dom.client.ClickHandler;
54  import com.google.gwt.event.dom.client.FocusHandler;
55  import com.google.gwt.event.shared.HandlerRegistration;
56  import com.google.gwt.user.client.ui.Composite;
57  import com.google.gwt.user.client.ui.FlowPanel;
58  import com.google.gwt.user.client.ui.Widget;
59  
60  
61  public class MultiplicityGroup extends Composite {
62  
63      private MultiplicityConfiguration config;
64  
65      private List<MultiplicityGroupItem> items = new ArrayList<MultiplicityGroupItem>();
66      private List<MultiplicityGroupItem> removed = new ArrayList<MultiplicityGroupItem>();
67  
68      private FlowPanel mainPanel = new FlowPanel();
69      private FlowPanel itemsPanel = new FlowPanel();
70      private boolean loaded = false;
71      private int itemCount = 0;
72      private String parentPath;
73      private boolean isDirty = false;
74  
75      private Map<SwapCompositeCondition, List<SwapCompositeConditionFieldConfig>> swappableFieldsDefinition;
76      private List<String> deletionParentKeys;
77  
78      public MultiplicityGroup() {
79      }
80      
81      public MultiplicityGroup(MultiplicityConfiguration config, 
82              Map<SwapCompositeCondition, List<SwapCompositeConditionFieldConfig>> swappableFieldsDefinition,
83              List<String> deletionParentKeys) {
84          this.config = config;
85          initWidget(mainPanel);
86          this.swappableFieldsDefinition = swappableFieldsDefinition;
87          this.deletionParentKeys = deletionParentKeys;
88      }
89  
90  
91      /**  
92       * Creates an instance of a MultiplicityGroup based on the options in the MultiplicityConfiguration
93       *
94       * A MultiplicityGroup uses GroupSection to display data in a variable grid.  May be multiple rows and multiple fields per row based on
95       * the defs in the MultiplicityConfiguration.
96       *
97       * May contain one or more MultiplicityItemSections based on user action, dictionary defs or data found in the model.
98       *
99       * @param config
100      */
101     public MultiplicityGroup(MultiplicityConfiguration config){
102         this.config = config;
103         initWidget(mainPanel);
104     }
105 
106     protected Callback<MultiplicityGroupItem> removeCallback = new Callback<MultiplicityGroupItem>(){
107 
108         public void exec(MultiplicityGroupItem itemToRemove) {
109             itemToRemove.setDeleted(true);
110             removed.add(itemToRemove);
111             itemsPanel.remove(itemToRemove);
112         }
113     };
114 
115     public void onLoad() {
116         if (!loaded) {
117             mainPanel.add(itemsPanel);
118 
119             if(config.isUpdateable()){
120                 Widget addWidget = generateAddWidget();
121                 mainPanel.add(addWidget);
122             }
123 
124             loaded = true;
125         }
126 
127         if (!loaded || itemCount == 0){
128         	Integer minOccurs = MetadataInterrogator.getLargestMinOccurs(config.getMetaData());
129         	if (minOccurs != null) {
130 	            for (int i=0; i < minOccurs; i++){
131 	            	createItem();
132 	            }
133         	}
134 
135         }
136     }
137 
138     private Widget generateAddWidget() {
139     	KSButton addWidget;
140     	if(config.getStyleType() == MultiplicityConfiguration.StyleType.TOP_LEVEL_GROUP){
141     		addWidget = new KSButton(config.getAddItemLabel(), ButtonStyle.FORM_LARGE);
142     	}
143     	else{
144     		addWidget = new KSButton(config.getAddItemLabel(), ButtonStyle.FORM_SMALL);
145     	}
146         addWidget.addClickHandler(new ClickHandler(){
147             public void onClick(ClickEvent event) {
148                 createItem();
149             }
150         });
151         return addWidget;
152     }
153 
154     /**
155      * This adds an empty item to the multiplicity group 
156      *
157      * @return
158      */
159 	public MultiplicityGroupItem createItem(){
160     
161 		itemCount++;
162 
163 		MultiplicityGroupItem item = new MultiplicityGroupItem(config.getItemLabel() + " " + itemCount, config.getStyleType(), config.isUpdateable());
164 		
165         Widget itemWidget = createWidget();
166         
167 	    if (item != null){
168 		    item.setItemKey(new Integer(itemCount -1));
169 		    item.setItemWidget(itemWidget);
170 		    item.setRemoveCallback(removeCallback);
171 	    } else if (itemWidget instanceof MultiplicityGroupItem){
172 	    	item = (MultiplicityGroupItem)itemWidget;
173 	    	item.setItemKey(new Integer(itemCount -1));
174 	    }
175 	    items.add(item);
176 	    item.redraw();
177 	    itemsPanel.add(item);
178 
179         return item;
180 	}
181 	
182 	public FlowPanel getItemsPanel() {
183 	    return itemsPanel;
184 	}
185 
186     private Widget createWidget() {
187 
188 		GroupSection section = new GroupSection();
189         final SwappableFieldsHelper helper = new SwappableFieldsHelper();
190         // helperFieldKeys maps the paths with asterisks into absolute paths
191         final Map<String, String> helperFieldKeys = new HashMap<String, String>();
192         SwapSection swapSection = null;
193 
194 		//TODO might want fields and nested multiplicities at the same time. Remove if/else
195 
196 		if (config.getNestedConfig() != null) {
197             MultiplicitySection ms = new MultiplicitySection(config.getNestedConfig().copy());
198 			String p = config.getNestedConfig().getParentFd().getFieldKey().replace('*', Character.forDigit(itemCount-1, 10));
199     		ms.setParentPath(p);
200             section.addSection(ms);
201 		}
202 		else {
203 			for (Integer row  : config.getFields().keySet()) {
204 				List<MultiplicityFieldConfiguration> fieldConfigs = config.getFields().get(row);
205 				for (MultiplicityFieldConfiguration fieldConfig : fieldConfigs) {
206                     //TODO  Should copy widgets/bindings too?
207                     FieldDescriptor newfd = null;
208                     Widget fieldWidget = null;
209                     if (fieldConfig.getFieldWidgetInitializer() != null) {
210                         fieldWidget = fieldConfig.getFieldWidgetInitializer().getNewWidget();
211                         ModelWidgetBinding mwb = fieldConfig.getFieldWidgetInitializer()
212                             .getModelWidgetBindingInstance();
213                         newfd = new FieldDescriptor(
214                                 translatePath(fieldConfig.getFieldPath()), 
215                                 fieldConfig.getMessageKeyInfo(), 
216                                 fieldConfig.getMetadata(),
217                                 fieldWidget);
218                         newfd.setWidgetBinding(mwb);
219                     } else {
220                         newfd = new FieldDescriptor(
221                                 translatePath(fieldConfig.getFieldPath()), 
222                                 fieldConfig.getMessageKeyInfo(), 
223                                 fieldConfig.getMetadata());
224                         fieldWidget = newfd.getFieldWidget();
225                     }
226                     newfd.getFieldElement().setRequired(fieldConfig.isRequired());
227                     section.addField(newfd);
228                     helperFieldKeys.put(fieldConfig.getFieldPath(), newfd.getFieldKey());
229 
230                     // add handlers to all select field that can be selected and triggers
231                     // selection change event to notify the swap section to switch section.
232                     if (fieldWidget instanceof KSSelectItemWidgetAbstract) {
233                         ((KSSelectItemWidgetAbstract)fieldWidget).addSelectionChangeHandler(new SelectionChangeHandler() {
234                             @Override
235                             public void onSelectionChange(SelectionChangeEvent event) {
236                                 helper.updateFieldDisplay();
237                             }
238                         });
239                     } else if (fieldWidget instanceof KSPicker) {
240                         Widget inputWidget = ((KSPicker)fieldWidget).getInputWidget();
241                         if (inputWidget instanceof KSSelectItemWidgetAbstract) {
242                             ((KSSelectItemWidgetAbstract)inputWidget).addSelectionChangeHandler(new SelectionChangeHandler() {
243                                 @Override
244                                 public void onSelectionChange(SelectionChangeEvent event) {
245                                     helper.updateFieldDisplay();
246                                 }
247                             });
248                         }
249                     }
250 				}
251 				section.nextLine();
252 			}
253             if (swappableFieldsDefinition != null) {
254                 ConditionChoices conditionChoices = new ConditionChoices(
255                         new ArrayList<SwapCompositeCondition>(
256                                 swappableFieldsDefinition.keySet()));
257                 List<String> newDeletionParentKeys = null;
258                 swapSection = new SwapSection(conditionChoices);
259                 if (deletionParentKeys != null) {
260                     for (String deletionParentKey : deletionParentKeys) {
261                         newDeletionParentKeys = (newDeletionParentKeys == null)?
262                                 new ArrayList<String>() : newDeletionParentKeys;
263                         newDeletionParentKeys.add(translatePath(deletionParentKey));
264                     }
265                 }
266                 swapSection.setDeletionParentKey(newDeletionParentKeys);
267                 helper.setConditionChoices(conditionChoices);
268                 // go through swappableFieldsDefinition and create and add the fields
269                 // into conditionSection
270                 for (Entry<SwapCompositeCondition, List<SwapCompositeConditionFieldConfig>> entry : swappableFieldsDefinition.entrySet()) {
271                     SwapCompositeCondition condition = entry.getKey();
272                     List<SwapCompositeConditionFieldConfig> fieldConfigs = entry.getValue();
273                     Section conditionSection = new VerticalSection();
274                     if (fieldConfigs != null) {
275                         for (SwapCompositeConditionFieldConfig conditionFieldConfig : fieldConfigs) {
276                             if (conditionFieldConfig.useMultiplicity()) {
277                                 MultiplicityConfiguration newSubMultiplicityConfig = 
278                                     configSwappableMultiplicitySection(
279                                             conditionFieldConfig.getMultiplicityConfiguration());
280                                 MultiplicitySection subMultiplicitySection = 
281                                     new MultiplicitySection(newSubMultiplicityConfig);
282                                 conditionSection.addSection(subMultiplicitySection);
283                             } else {
284                                 MultiplicityFieldConfiguration fieldConfig = 
285                                     conditionFieldConfig.getMultiplicityFieldConfiguration();
286                                 FieldDescriptor concreteFieldDescriptor = new FieldDescriptor(
287                                         translatePath(fieldConfig.getFieldPath()),
288                                         fieldConfig.getMessageKeyInfo(),
289                                         fieldConfig.getMetadata());
290                                 concreteFieldDescriptor.getFieldElement().setRequired(fieldConfig.isRequired());
291                                 if (fieldConfig.getFieldWidgetInitializer() != null) {
292                                     Widget fieldWidget = fieldConfig.getFieldWidgetInitializer().getNewWidget();
293                                     ModelWidgetBinding mwb = fieldConfig.getFieldWidgetInitializer()
294                                         .getModelWidgetBindingInstance();
295                                     concreteFieldDescriptor.setFieldWidget(fieldWidget);
296                                     if(fieldWidget instanceof ListOfStringWidget){
297                                     	((ListOfStringWidget)fieldWidget).setFd(concreteFieldDescriptor);
298                                     }
299                                     
300                                     concreteFieldDescriptor.setWidgetBinding(mwb);
301                                 }
302                                 conditionSection.addField(concreteFieldDescriptor);
303                                 helperFieldKeys.put(fieldConfig.getFieldPath(), translatePath(fieldConfig.getFieldPath()));
304                             }
305                         }
306                     }
307                     swapSection.addSection(conditionSection, condition.getConditionId());
308                 }
309                 section.addWidget(conditionChoices);
310                 section.addSection(swapSection);
311                 helper.setSwapSection(swapSection);
312             }
313             
314             helper.setParentSection(section);
315             helper.setSwappableFieldsDefinition(swappableFieldsDefinition);
316             helper.setHelperFieldKeys(helperFieldKeys);
317         }
318 		return section;
319 	}
320 
321     public MultiplicityConfiguration configSwappableMultiplicitySection(MultiplicityConfiguration origConfig) {
322         MultiplicityConfiguration newSubMultiplicityConfig =
323             origConfig.copy();
324 
325         FieldDescriptor parentFd = origConfig.getParentFd();
326         FieldDescriptor subMultParentConfig = 
327             new FieldDescriptor(
328                     translatePath(parentFd.getFieldKey()),
329                     parentFd.getMessageKey(),
330                     parentFd.getMetadata());
331         subMultParentConfig.getFieldElement().setRequired(parentFd.getFieldElement().isRequired());
332         newSubMultiplicityConfig.setParent(subMultParentConfig);
333         Map<Integer, List<MultiplicityFieldConfiguration>> fieldConfigsMap = newSubMultiplicityConfig.getFields();
334         Map<Integer, List<MultiplicityFieldConfiguration>> newFieldsMap = new HashMap<Integer, List<MultiplicityFieldConfiguration>>();
335         int lineCounter = 0;
336         if (fieldConfigsMap != null) {
337             for (List<MultiplicityFieldConfiguration> fieldConfigsInLine : fieldConfigsMap.values()) {
338                 List<MultiplicityFieldConfiguration> newFieldConfigs = new ArrayList<MultiplicityFieldConfiguration>();
339                 for (MultiplicityFieldConfiguration fieldConfig : fieldConfigsInLine) {
340                     String configParentKey = (parentFd.getFieldKey() == null)? "" : parentFd.getFieldKey();
341                     String configFieldKey = (fieldConfig.getFieldPath() == null)? "" : fieldConfig.getFieldPath();
342                     String trimmedFieldKey = null;
343                     MultiplicityFieldConfiguration newFieldConfig = null;
344                     trimmedFieldKey = configFieldKey.substring(configParentKey.length());
345                     
346                     QueryPath fieldPath = QueryPath.concat(subMultParentConfig.getFieldKey(), 
347                             trimmedFieldKey);;
348                     newFieldConfig = new MultiplicityFieldConfiguration(
349                             fieldPath.toString(), fieldConfig.getMessageKeyInfo(), fieldConfig.getMetadata(),
350                             fieldConfig.getFieldWidgetInitializer());
351                     newFieldConfig.setRequired(fieldConfig.isRequired());
352                     newFieldConfigs.add(newFieldConfig);
353                     
354                 }
355                 newFieldsMap.put(Integer.valueOf(lineCounter), newFieldConfigs);
356                 lineCounter++;
357             }
358         }
359         newSubMultiplicityConfig.setFields(newFieldsMap);
360         
361         return newSubMultiplicityConfig;
362     }
363 
364     public String translatePath(String path) {
365         String fieldPath;
366         if (parentPath != null) {
367             QueryPath parent = QueryPath.concat(parentPath);
368             int i = parent.size();
369 
370             QueryPath subPath = QueryPath.concat(path);
371             String itemPath =  subPath.subPath(i, subPath.size()).toString();
372 
373             QueryPath qp = QueryPath.concat(parentPath, itemPath);
374             fieldPath = qp.toString();
375         }
376         else {
377             fieldPath = path;
378         }
379 
380         fieldPath = fieldPath.replace('*', Character.forDigit(itemCount-1, 10));
381         return fieldPath;
382     }
383 
384 
385     public void clear(){
386         itemsPanel.clear();
387         items.clear();
388         removed.clear();
389         itemCount = 0;
390     }
391 
392     public void redraw(){
393         for (MultiplicityGroupItem item:items){
394             item.redraw();
395         }
396     }
397 
398     public void incrementItemKey(){
399 		itemCount++;
400 	}
401 
402     /**
403 	 * This returns the index key for the model for the item currently being added by addItem
404 	 * This is useful, if you need to refer to the index in the createItem method
405 	 * @return
406 	 */
407 	public int getAddItemKey(){
408 		return itemCount-1;
409 	}
410 
411 
412     public List<MultiplicityGroupItem> getItems() {
413         return items;
414     }
415 
416     public List<MultiplicityGroupItem> getRemovedItems() {
417         return removed;
418     }
419 
420 	public int getItemCount() {
421 		return itemCount;
422 	}
423 	
424 	public void setItemCount(int itemCount) {
425 		this.itemCount = itemCount;
426 	}
427 
428 	public String getParentPath() {
429 		return parentPath;
430 	}
431 
432     /**
433      * Allows the parentpath for this instance to be set, e.g. course/formats/0/activities
434      * 
435      * @param parentPath
436      */
437     public void setParentPath(String parentPath) {
438 		this.parentPath = parentPath;
439 	}
440 
441 	public MultiplicityConfiguration getConfig() {
442 		return config;
443 	}
444 
445 	public void setConfig(MultiplicityConfiguration config) {
446 		this.config = config;
447 	}   
448 	
449     public void resetDirtyFlags() {
450     	isDirty = false;
451 		for (MultiplicityGroupItem item:items){
452 			item.resetDirtyFlags();
453 			Widget itemWidget = item.getItemWidget();
454 			if (itemWidget instanceof BaseSection){
455 				((BaseSection)itemWidget).resetDirtyFlags();
456 			}
457 		}
458     }
459 	
460 	public boolean isDirty(){
461 		for (MultiplicityGroupItem item:items){
462 			if (item.isDirty()){
463 				isDirty = true;
464 				break;
465 			} else {
466 				Widget itemWidget = item.getItemWidget();
467 				if (itemWidget instanceof BaseSection && ((BaseSection)itemWidget).isDirty()){
468 					isDirty = true;
469 					break;
470 				}
471 			}
472 		}
473 		return isDirty;
474 	}
475 	
476 	public void setIsDirty(boolean dirty){
477 		isDirty = dirty;
478 	}
479 	
480     public class ConditionChoices extends KSRadioButtonList{
481         private KSRadioButtonListImpl selectItemWidget = GWT.create(KSRadioButtonListImpl.class);
482         public ConditionChoices(List<SwapCompositeCondition> conditions){
483             SimpleListItems choices = new SimpleListItems();
484             if (conditions != null) {
485                 for (SwapCompositeCondition condition : conditions) {
486                     choices.addItem(condition.getConditionId(), condition.getConditionId());
487                 }
488             }
489             selectItemWidget.setListItems(choices);
490         }
491 
492         /**
493          * @see org.kuali.student.common.ui.client.widgets.list.KSSelectItemWidgetAbstract#deSelectItem(java.lang.String)
494          */
495         public void deSelectItem(String id) {
496             selectItemWidget.deSelectItem(id);  
497         }
498 
499         /**
500          * @see org.kuali.student.common.ui.client.widgets.list.KSSelectItemWidgetAbstract#getSelectedItems()
501          */
502         public List<String> getSelectedItems() {
503             return selectItemWidget.getSelectedItems();
504         }
505 
506         /**
507          * @see org.kuali.student.common.ui.client.widgets.list.KSSelectItemWidgetAbstract#selectItem(java.lang.String)
508          */
509         public void selectItem(String id) {
510             selectItemWidget.selectItem(id);
511         }
512 
513         public void setListItems(ListItems listItems) {
514             selectItemWidget.setListItems(listItems);      
515         }
516 
517         /**
518          * Use to set number of columns to use when displaying list
519          * 
520          */
521         public void setColumnSize(int cols){
522             selectItemWidget.setColumnSize(cols);
523         }
524             
525         public void setMultipleSelect(boolean isMultipleSelect) {}
526 
527         /**
528          * This overridden method is not used
529          * 
530          * @see org.kuali.student.common.ui.client.widgets.list.KSSelectItemWidgetAbstract#onLoad()
531          */
532         @Override
533         public void onLoad() {}
534        
535         public HandlerRegistration addSelectionChangeHandler(SelectionChangeHandler handler) {
536             return selectItemWidget.addSelectionChangeHandler(handler);
537         }
538 
539         public ListItems getListItems() {
540             return selectItemWidget.getListItems();
541         }
542 
543         public String getName() {
544             return selectItemWidget.getName();
545         }
546 
547         public void setName(String name) {
548             selectItemWidget.setName(name);
549         }
550 
551         @Override
552         public void setEnabled(boolean b) {
553             selectItemWidget.setEnabled(b);
554         }
555 
556         @Override
557         public boolean isEnabled() {
558             return selectItemWidget.isEnabled();
559         }
560 
561         @Override
562         public boolean isMultipleSelect() {
563             return selectItemWidget.isMultipleSelect();
564         }
565 
566         @Override
567         public void redraw() {
568             selectItemWidget.redraw();
569         }
570 
571         @Override
572         public void clear() {
573             selectItemWidget.clear();
574         }
575 
576         @Override
577         public HandlerRegistration addBlurHandler(BlurHandler handler) {
578             return selectItemWidget.addBlurHandler(handler);
579         }
580 
581         @Override
582         public HandlerRegistration addFocusHandler(FocusHandler handler) {
583             return selectItemWidget.addFocusHandler(handler);
584         }
585 
586         public void addWidgetReadyCallback(Callback<Widget> callback) {
587             selectItemWidget.addWidgetReadyCallback(callback);
588         }
589 
590         public boolean isInitialized() {
591             return selectItemWidget.isInitialized();
592         }
593 
594         public void setInitialized(boolean initialized) {
595             selectItemWidget.setInitialized(initialized);
596         }
597         
598         /**
599          * By default if the list items used by the checkbox has multiple attributes, the checkbox
600          * generated will display all attributes as columns. Set this property to true if this
601          * behavior is not desired.
602          * 
603          * @param ignoreMultiple
604          */
605         public void setIgnoreMultipleAttributes(boolean ignoreMultiple){
606             selectItemWidget.setIgnoreMultipleAttributes(ignoreMultiple);
607         }
608     }
609 
610     public class SwappableFieldsHelper {
611         
612         private GroupSection parentSection;
613         private Map<SwapCompositeCondition, List<SwapCompositeConditionFieldConfig>> swappableFieldsDefinition = 
614             new HashMap<SwapCompositeCondition, List<SwapCompositeConditionFieldConfig>>();
615         private Map<String, String> helperFieldKeys;
616         private ConditionChoices conditionChoices;
617         private SwapSection swapSection;
618         public void updateFieldDisplay() {
619             Set<Entry<SwapCompositeCondition, List<SwapCompositeConditionFieldConfig>>> entries =
620                 (swappableFieldsDefinition == null)? null : swappableFieldsDefinition.entrySet();
621             if (parentSection == null) {
622                 throw new RuntimeException("parentSection cannot be null");
623             }
624             if (entries != null) {
625                 for (Entry<SwapCompositeCondition, List<SwapCompositeConditionFieldConfig>> entry : entries) {
626                     SwapCompositeCondition condition = entry.getKey();
627                     if (condition.evaluate(parentSection, helperFieldKeys)) {
628                         // clear values in the widgets
629                         List<Section> deletedSections = swapSection.getDeletedSections();
630                         List<FieldDescriptor> fields = null;
631                         if (deletedSections != null) {
632                             for (Section deletedSection : deletedSections) {
633                                 fields = (fields == null)? new ArrayList() : fields;
634                                 fields.addAll(deletedSection.getFields());
635                             }
636                         }
637                         if (fields != null) {
638                             for (FieldDescriptor field : fields) {
639                                 Widget fieldWidget = field.getFieldWidget();
640                                 DataModel dataModel = new DataModel();
641                                 dataModel.setRoot(new Data());
642                                 ((ModelWidgetBinding)field.getModelWidgetBinding())
643                                 .setWidgetValue(fieldWidget, 
644                                         dataModel, field.getFieldKey());
645                             }
646                         }
647                         // trigger SectionChangeEvent to notify the selection widget
648                         // that the selected condition has changed.
649                         SelectionChangeEvent selectionChangeEvent =
650                             new SelectionChangeEvent(conditionChoices);
651                         selectionChangeEvent.setUserInitiated(true);
652                         conditionChoices.selectItem(condition.getConditionId());
653                         conditionChoices.fireEvent(selectionChangeEvent);
654                     }
655                 }
656             }
657         }
658         public GroupSection getParentSection() {
659             return parentSection;
660         }
661         public void setParentSection(GroupSection parentSection) {
662             this.parentSection = parentSection;
663         }
664         public Map<SwapCompositeCondition, List<SwapCompositeConditionFieldConfig>> getSwappableFieldsDefinition() {
665             return swappableFieldsDefinition;
666         }
667         public void setSwappableFieldsDefinition(Map<SwapCompositeCondition, List<SwapCompositeConditionFieldConfig>> swappableFieldsDefinition) {
668             this.swappableFieldsDefinition = swappableFieldsDefinition;
669         }
670         public Map<String, String> getHelperFieldKeys() {
671             return helperFieldKeys;
672         }
673         public void setHelperFieldKeys(Map<String, String> helperFieldKeys) {
674             this.helperFieldKeys = helperFieldKeys;
675         }
676         public ConditionChoices getConditionChoices() {
677             return conditionChoices;
678         }
679         public void setConditionChoices(ConditionChoices conditionChoices) {
680             this.conditionChoices = conditionChoices;
681         }
682         public SwapSection getSwapSection() {
683             return swapSection;
684         }
685         public void setSwapSection(SwapSection swapSection) {
686             this.swapSection = swapSection;
687         }
688     }
689 
690 }