Coverage Report - org.kuali.student.common.ui.client.configurable.mvc.sections.BaseSection
 
Classes in this File Line Coverage Branch Coverage Complexity
BaseSection
0%
0/225
0%
0/128
2.565
BaseSection$1
0%
0/16
0%
0/8
2.565
BaseSection$1$1
0%
0/9
0%
0/4
2.565
BaseSection$1$2
0%
0/5
N/A
2.565
 
 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  
  *
 7  
  * http://www.osedu.org/licenses/ECL-2.0
 8  
  *
 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  
  */
 15  
 
 16  
 package org.kuali.student.common.ui.client.configurable.mvc.sections;
 17  
 
 18  
 import java.util.ArrayList;
 19  
 import java.util.HashSet;
 20  
 import java.util.List;
 21  
 
 22  
 import org.kuali.student.common.assembly.data.Data;
 23  
 import org.kuali.student.common.assembly.data.QueryPath;
 24  
 import org.kuali.student.common.assembly.data.Data.Key;
 25  
 import org.kuali.student.common.ui.client.application.Application;
 26  
 import org.kuali.student.common.ui.client.configurable.mvc.CanProcessValidationResults;
 27  
 import org.kuali.student.common.ui.client.configurable.mvc.FieldDescriptor;
 28  
 import org.kuali.student.common.ui.client.configurable.mvc.LayoutController;
 29  
 import org.kuali.student.common.ui.client.configurable.mvc.ValidationEventBinding;
 30  
 import org.kuali.student.common.ui.client.configurable.mvc.ValidationEventBindingImpl;
 31  
 import org.kuali.student.common.ui.client.configurable.mvc.binding.ModelWidgetBinding;
 32  
 import org.kuali.student.common.ui.client.configurable.mvc.binding.ModelWidgetBindingSupport;
 33  
 import org.kuali.student.common.ui.client.configurable.mvc.multiplicity.MultiplicityComposite;
 34  
 import org.kuali.student.common.ui.client.configurable.mvc.multiplicity.MultiplicityGroup;
 35  
 import org.kuali.student.common.ui.client.configurable.mvc.multiplicity.MultiplicityGroupItem;
 36  
 import org.kuali.student.common.ui.client.configurable.mvc.multiplicity.MultiplicityItem;
 37  
 import org.kuali.student.common.ui.client.event.ContentDirtyEvent;
 38  
 import org.kuali.student.common.ui.client.event.ValidateRequestEvent;
 39  
 import org.kuali.student.common.ui.client.mvc.Callback;
 40  
 import org.kuali.student.common.ui.client.mvc.Controller;
 41  
 import org.kuali.student.common.ui.client.mvc.DataModel;
 42  
 import org.kuali.student.common.ui.client.mvc.HasCrossConstraints;
 43  
 import org.kuali.student.common.ui.client.mvc.ModelRequestCallback;
 44  
 import org.kuali.student.common.ui.client.mvc.View;
 45  
 import org.kuali.student.common.ui.client.widgets.field.layout.element.AbbrPanel;
 46  
 import org.kuali.student.common.ui.client.widgets.field.layout.element.FieldElement;
 47  
 import org.kuali.student.common.ui.client.widgets.field.layout.element.SpanPanel;
 48  
 import org.kuali.student.common.ui.client.widgets.field.layout.layouts.FieldLayout;
 49  
 import org.kuali.student.common.validation.dto.ValidationResultInfo;
 50  
 import org.kuali.student.common.validation.dto.ValidationResultInfo.ErrorLevel;
 51  
 
 52  
 import com.google.gwt.core.client.GWT;
 53  
 import com.google.gwt.user.client.ui.Widget;
 54  
 
 55  
 /**
 56  
  * The base section is the base implementation of the section interface.
 57  
  * @author Kuali Student
 58  
  *
 59  
  */
 60  0
 public abstract class BaseSection extends SpanPanel implements Section{
 61  
 
 62  
         protected FieldLayout layout;
 63  
 
 64  0
         protected ArrayList<Section> sections = new ArrayList<Section>();
 65  0
         protected ArrayList<FieldDescriptor> fields = new ArrayList<FieldDescriptor>();
 66  0
         protected LayoutController layoutController = null;
 67  0
         protected boolean isValidationEnabled = true;
 68  0
         protected boolean isDirty = false;
 69  
 
 70  
         /**
 71  
          * Adds a field to this section.  Adds the field to this section's layout.
 72  
          * Attaches an event handler for lost focus events on the field widget
 73  
          * to validate against the metadata defined in its FieldDescriptor as well as firing events for dirty
 74  
          * field handling.
 75  
          * 
 76  
          * Note if a field has been marked as hidden in the dictionary, this method will not add this field to the layout.
 77  
          * If it is not visible the key returned by making call to addField is null.
 78  
          * 
 79  
          * @param field
 80  
          * @return key/path of this field
 81  
          */
 82  
         @Override
 83  
         public String addField(final FieldDescriptor fieldDescriptor) {
 84  0
                 String key = null;
 85  
                 
 86  0
                 if (fieldDescriptor.isVisible()){
 87  0
                         fields.add(fieldDescriptor);
 88  0
                 key = layout.addField(fieldDescriptor.getFieldElement());
 89  
         
 90  0
                 ValidationEventBinding binding = new ValidationEventBindingImpl();
 91  0
                 if(fieldDescriptor.getValidationRequestCallback()== null){
 92  0
                     fieldDescriptor.setValidationCallBack(new Callback<Boolean>() {
 93  
                         @Override
 94  
                         public void exec(Boolean result) {
 95  0
                                 final ModelWidgetBinding mwb = fieldDescriptor.getModelWidgetBinding();
 96  0
                                 if (mwb != null) {
 97  0
                                     final Widget w = fieldDescriptor.getFieldWidget();
 98  0
                                     final String modelId = fieldDescriptor.getModelId();
 99  
                                     final Controller parent;
 100  0
                                 Controller findResult = LayoutController.findParentLayout(w);
 101  0
                                 if(BaseSection.this instanceof View){
 102  0
                                         findResult = ((View)BaseSection.this).getController();
 103  
                                 }
 104  0
                                 parent = findResult;
 105  0
                                 if(parent != null){
 106  0
                                         if (modelId == null) {
 107  0
                                                 parent.requestModel(new ModelRequestCallback<DataModel>() {
 108  
         
 109  
                                                         @Override
 110  
                                                         public void onModelReady(DataModel model) {
 111  0
                                                                 validateField(fieldDescriptor, model, parent);
 112  
                                                 
 113  
                                                                 //Cross referenced field update:
 114  0
                                                                 HashSet<HasCrossConstraints> fds = Application.getApplicationContext().getCrossConstraint(null, Application.getApplicationContext().getParentPath()+fieldDescriptor.getFieldKey());
 115  0
                                                                 if(fds!=null){
 116  0
                                                                         for(HasCrossConstraints fd:fds){
 117  0
                                                                                 fd.reprocessWithUpdatedConstraints();
 118  
                                                                         }
 119  
                                                                 }
 120  0
                                                         }
 121  
         
 122  
                                                         @Override
 123  
                                                         public void onRequestFail(Throwable cause) {
 124  0
                                                                 GWT.log("Unable to retrieve model to validate " + fieldDescriptor.getFieldKey(), null);
 125  0
                                                         }
 126  
         
 127  
                                                 });
 128  
                                         } else {
 129  0
                                                 parent.requestModel(modelId, new ModelRequestCallback<DataModel>() {
 130  
         
 131  
                                                         @Override
 132  
                                                         public void onModelReady(DataModel model) {
 133  0
                                                                 validateField(fieldDescriptor, model, parent);
 134  0
                                                         }
 135  
         
 136  
                                                         @Override
 137  
                                                         public void onRequestFail(Throwable cause) {
 138  0
                                                                 GWT.log("Unable to retrieve model to validate " + fieldDescriptor.getFieldKey(), null);
 139  0
                                                         }
 140  
         
 141  
                                                 });                                }
 142  
                                         }
 143  0
                             } else {
 144  0
                                 GWT.log(fieldDescriptor.getFieldKey() + " has no widget binding.", null);
 145  
                             }
 146  0
                         }
 147  
                     });
 148  
                 }
 149  0
                 binding.bind(fieldDescriptor);
 150  
                 }               
 151  
                 
 152  0
         return key;
 153  
         }
 154  
 
 155  
         private void validateField(
 156  
                         final FieldDescriptor fieldDescriptor, final DataModel model, Controller controller) {
 157  0
                 Widget w = fieldDescriptor.getFieldWidget();
 158  0
                 ModelWidgetBinding mwb = fieldDescriptor.getModelWidgetBinding();
 159  0
                 if(fieldDescriptor.getFieldKey() != null){
 160  0
                         mwb.setModelValue(w, model, fieldDescriptor.getFieldKey());
 161  0
                         dirtyCheckField(fieldDescriptor, model);
 162  0
                         ValidateRequestEvent e = new ValidateRequestEvent();
 163  0
                         e.setFieldDescriptor(fieldDescriptor);
 164  0
                         e.setValidateSingleField(true);
 165  0
                         controller.fireApplicationEvent(e);
 166  
                 }
 167  0
         }
 168  
 
 169  
         private void dirtyCheckField(FieldDescriptor fieldDescriptor, DataModel model){
 170  0
         QueryPath fieldPath = QueryPath.parse(fieldDescriptor.getFieldKey());
 171  0
                 QueryPath qPathDirty = fieldPath.subPath(0, fieldPath.size() - 1);
 172  0
             qPathDirty.add(ModelWidgetBindingSupport.RUNTIME_ROOT);
 173  0
             qPathDirty.add(ModelWidgetBindingSupport.DIRTY_PATH);
 174  0
             qPathDirty.add(fieldPath.get(fieldPath.size()-1));
 175  0
             Boolean dirty = false;
 176  
 
 177  0
             if(ensureDirtyFlagPath(model.getRoot(), qPathDirty)){
 178  0
                     dirty = model.get(qPathDirty);
 179  
             }
 180  0
             if(dirty){
 181  0
                     setIsDirty(true);
 182  0
                     fieldDescriptor.setDirty(true);
 183  
             }
 184  0
         }
 185  
 
 186  
     protected boolean ensureDirtyFlagPath(Data root, QueryPath path) {
 187  0
         Data current = root;
 188  0
         boolean containsFlag = false;
 189  0
         for (int i = 0; i < path.size(); i++) {
 190  0
             Key key = path.get(i);
 191  0
             if(i == path.size() - 1){
 192  0
                     containsFlag = current.containsKey(key);
 193  0
                     break;
 194  
             }
 195  0
             Data d = current.get(key);
 196  0
             if (d == null) {
 197  0
                 containsFlag = false;
 198  0
                 break;
 199  
             }
 200  0
             current = d;
 201  
         }
 202  0
         return containsFlag;
 203  
     }
 204  
 
 205  
         /** 
 206  
          * Adds a section to this section's layout.
 207  
          * 
 208  
          * @see org.kuali.student.common.ui.client.configurable.mvc.sections.Section#addSection(org.kuali.student.common.ui.client.configurable.mvc.sections.Section)
 209  
          */
 210  
         @Override
 211  
         public String addSection(Section section) {
 212  
 
 213  0
         section.setLayoutController(layoutController);
 214  0
                 sections.add(section);
 215  0
         String key = layout.addLayout(section.getLayout());
 216  0
         return key;
 217  
         }
 218  
 
 219  
         /**
 220  
          * Removes a section from this section's layout.
 221  
          * 
 222  
          * @see org.kuali.student.common.ui.client.configurable.mvc.sections.Section#removeSection(org.kuali.student.common.ui.client.configurable.mvc.sections.Section)
 223  
          */
 224  
         @Override
 225  
         public void removeSection(Section section){
 226  0
                 sections.remove(section);
 227  0
                 layout.removeLayoutElement(section.getLayout());
 228  0
         }
 229  
 
 230  
         /**
 231  
          * Clear all validation errors from the layout (removes all red highlight and error text shown on the
 232  
          * screen)
 233  
          */
 234  
         protected void clearValidationErrors() {
 235  0
                 layout.clearValidationErrors();
 236  0
         }
 237  
 
 238  
         /**
 239  
          * Clear all validation warnings from the layout (removes all yellow highlight and warning text shown on the
 240  
          * screen)
 241  
          */
 242  
         public void clearValidationWarnings() {
 243  0
                 layout.clearValidationWarnings();
 244  0
         }
 245  
         
 246  
         /**
 247  
          * Gets all the fields in a section and its subsections.
 248  
          * 
 249  
          * @see org.kuali.student.common.ui.client.configurable.mvc.sections.Section#getFields()
 250  
          */
 251  
         @Override
 252  
         public List<FieldDescriptor> getFields() {
 253  0
         List<FieldDescriptor> allFields = new ArrayList<FieldDescriptor>();
 254  0
         allFields.addAll(fields);
 255  
 
 256  0
         for(Section ns: sections){
 257  0
             allFields.addAll(ns.getFields());
 258  
         }
 259  0
         return allFields;
 260  
         }
 261  
 
 262  
         /**
 263  
          * Gets all the fields in this section, but does not include fields in its nested sections.
 264  
          * @see org.kuali.student.common.ui.client.configurable.mvc.sections.Section#getUnnestedFields()
 265  
          */
 266  
         @Override
 267  
         public List<FieldDescriptor> getUnnestedFields() {
 268  0
         return fields;
 269  
         }
 270  
 
 271  
         /**
 272  
          * Gets all nested sections contained in this section
 273  
          * @see org.kuali.student.common.ui.client.configurable.mvc.sections.Section#getSections()
 274  
          */
 275  
         @Override
 276  
         public List<Section> getSections() {
 277  0
                 return sections;
 278  
         }
 279  
 
 280  
         /**
 281  
          * Processes the validation results passed in and displays the appropriate message on the screen next
 282  
          * to the corresponding field or section.  If clearAllValidation is true, it will clear all validation before
 283  
          * displaying the errors (otherwise will append these errors to the ones already visible on the section).
 284  
          * @see org.kuali.student.common.ui.client.configurable.mvc.sections.Section#processValidationResults(java.util.List, boolean)
 285  
          */
 286  
         @Override
 287  
         public ErrorLevel processValidationResults(List<ValidationResultInfo> results, boolean clearErrors){
 288  0
                 if(clearErrors){
 289  0
                         this.clearValidationErrors();
 290  
                 }
 291  0
                 ErrorLevel status = ErrorLevel.OK;
 292  
 
 293  0
                 if (isValidationEnabled){
 294  
 
 295  0
                         for(FieldDescriptor f: this.fields){
 296  
 
 297  0
                                 if(f.hasHadFocus()){
 298  0
                                         for(ValidationResultInfo vr: results){
 299  0
                         String vrElement = vr.getElement();
 300  0
                         if(vrElement.startsWith("/")){
 301  0
                             vrElement = vrElement.substring(1);
 302  
                         }
 303  
                         //Strip out end indexes for collections of primitives to be handled by the element
 304  0
                         vrElement = vrElement.replaceFirst("^(\\S+)/[0-9]+$", "$1");
 305  
                         
 306  
                         //Check the parent path (mostly for mapping validation to specializations)
 307  0
                         String parentPath = Application.getApplicationContext().getParentPath();
 308  0
                         parentPath = parentPath==null?"":parentPath;
 309  
                         
 310  0
                                                 if(vrElement.equals(parentPath+f.getFieldKey())){
 311  0
                                                         FieldElement element = f.getFieldElement();
 312  0
                                                         if (element != null){
 313  0
                                                                 ErrorLevel fieldStatus = element.processValidationResult(vr);
 314  0
                                                                 if(fieldStatus.getLevel() > status.getLevel()){
 315  0
                                                                         status = fieldStatus;
 316  
                                                                 }
 317  
                                                         }
 318  
                                                 }
 319  0
                                         }
 320  
                                 }
 321  
 
 322  0
                                 if(f.getFieldWidget() instanceof MultiplicityComposite ){
 323  0
                                         MultiplicityComposite mc = (MultiplicityComposite) f.getFieldWidget();
 324  
 
 325  
                                         //possibly return error state from processValidationResults to give composite title bar a separate color
 326  0
                             for(MultiplicityItem item: mc.getItems()){
 327  0
                                     if(item.getItemWidget() instanceof Section && !item.isDeleted()){
 328  0
                                             ErrorLevel fieldStatus = ((Section)item.getItemWidget()).processValidationResults(results, clearErrors);
 329  0
                                                         if(fieldStatus.getLevel() > status.getLevel()){
 330  0
                                                                 status = fieldStatus;
 331  
                                                         }
 332  0
                                     }
 333  
                             }
 334  
                                 }
 335  
                                 // TODO Can we do this without checking for instanceof  MG??
 336  0
                                 if(f.getFieldWidget() instanceof MultiplicityGroup ){
 337  0
                                         MultiplicityGroup mg = (MultiplicityGroup) f.getFieldWidget();
 338  
 
 339  
                                         //possibly return error state from processValidationResults to give composite title bar a separate color
 340  0
                             for(MultiplicityGroupItem item: mg.getItems()){
 341  0
                                     if(item.getItemWidget() instanceof Section && !item.isDeleted()){
 342  0
                                             ErrorLevel fieldStatus = ((Section)item.getItemWidget()).processValidationResults(results, clearErrors);
 343  0
                                                         if(fieldStatus.getLevel() > status.getLevel()){
 344  0
                                                                 status = fieldStatus;
 345  
                                                         }
 346  0
                                     }
 347  
                             }
 348  
                                 }
 349  0
                 if (f.getFieldWidget() instanceof CanProcessValidationResults) {
 350  0
                     ErrorLevel fieldStatus = ((CanProcessValidationResults) f.getFieldWidget()).processValidationResults(f, results, clearErrors);
 351  0
                     if (fieldStatus.getLevel() > status.getLevel()) {
 352  0
                         status = fieldStatus;
 353  
                     }
 354  0
                 }
 355  
                         }
 356  
 
 357  0
                 for(Section s: sections){
 358  0
                     ErrorLevel subsectionStatus = s.processValidationResults(results,clearErrors);
 359  0
                     if(subsectionStatus.getLevel() > status.getLevel()){
 360  0
                             status = subsectionStatus;
 361  
                     }
 362  0
                 }
 363  
                 }
 364  
 
 365  0
         return status;
 366  
         }
 367  
 
 368  
         /**
 369  
          * Same as processValidationResults(results, true)
 370  
          * @see org.kuali.student.common.ui.client.configurable.mvc.sections.Section#processValidationResults(java.util.List)
 371  
          */
 372  
         @Override
 373  
         public ErrorLevel processValidationResults(List<ValidationResultInfo> results) {
 374  0
                 return processValidationResults(results, true);
 375  
         }
 376  
 
 377  
         /**
 378  
          * Gets the defined controller for this section if one exists.
 379  
          * 
 380  
          * @see org.kuali.student.common.ui.client.configurable.mvc.HasLayoutController#getLayoutController()
 381  
          */
 382  
         @Override
 383  
         public LayoutController getLayoutController() {
 384  0
                 return this.layoutController;
 385  
         }
 386  
 
 387  
         @Override
 388  
         public void setLayoutController(LayoutController controller) {
 389  0
                 this.layoutController = controller;
 390  0
         }
 391  
 
 392  
 
 393  
         /**
 394  
          * Use this to add widgets to a sections layout.  DO NOT use the add(Widget widget) call.
 395  
          * @see org.kuali.student.common.ui.client.configurable.mvc.sections.Section#addWidget(com.google.gwt.user.client.ui.Widget)
 396  
          */
 397  
         @Override
 398  
         public String addWidget(Widget w) {
 399  0
                 return layout.addWidget(w);
 400  
         }
 401  
 
 402  
     /**
 403  
      * Sets the fields has had focus flag.  This flag is used for determining if the user has interacted with
 404  
      * any fields on the page or if the fields need to be assumed to have been interacted with.  Used for determining
 405  
      * when validation is necessary on a particular section.
 406  
      * @see org.kuali.student.common.ui.client.configurable.mvc.sections.Section#setFieldHasHadFocusFlags(boolean)
 407  
      */
 408  
     public void setFieldHasHadFocusFlags(boolean hadFocus) {
 409  0
         for(FieldDescriptor f: fields){
 410  0
             f.setHasHadFocus(hadFocus);
 411  0
             if(f.getFieldWidget() instanceof MultiplicityComposite){
 412  0
                                 MultiplicityComposite mc = (MultiplicityComposite) f.getFieldWidget();
 413  
 
 414  0
                     for(MultiplicityItem item: mc.getItems()){
 415  0
                             if(item.getItemWidget() instanceof Section && !item.isDeleted()){
 416  0
                                     ((Section) item.getItemWidget()).setFieldHasHadFocusFlags(hadFocus);
 417  
                             }
 418  
                     }
 419  0
             }else if(f.getFieldWidget() instanceof MultiplicityGroup){
 420  0
                     MultiplicityGroup mg = (MultiplicityGroup) f.getFieldWidget();
 421  
 
 422  0
                     for(MultiplicityGroupItem item: mg.getItems()){
 423  0
                             if(item.getItemWidget() instanceof Section && !item.isDeleted()){
 424  0
                                     ((Section) item.getItemWidget()).setFieldHasHadFocusFlags(hadFocus);
 425  
                             }
 426  
                     }
 427  0
             }
 428  
         }
 429  
 
 430  0
         for(Section s: sections){
 431  0
             s.setFieldHasHadFocusFlags(hadFocus);
 432  
         }
 433  
 
 434  0
     }
 435  
 
 436  
     /**
 437  
      * A section can turn off all validation by setting this flag
 438  
      * @see org.kuali.student.common.ui.client.configurable.mvc.sections.Section#enableValidation(boolean)
 439  
      */
 440  
     @Override
 441  
     public void enableValidation(boolean enableValidation) {
 442  0
             this.isValidationEnabled = enableValidation;
 443  0
     }
 444  
 
 445  
     @Override
 446  
     public boolean isValidationEnabled() {
 447  0
                 return isValidationEnabled;
 448  
         }
 449  
 
 450  
         /**
 451  
          * Update the model passed in with data from the fields on this section.  This method will use the 
 452  
          * modelWidgetBinding defined in each of this sections fields to determine how to add this data to the
 453  
          * model.
 454  
          * @see org.kuali.student.common.ui.client.configurable.mvc.sections.Section#updateModel(org.kuali.student.common.ui.client.mvc.DataModel)
 455  
          */
 456  
         @Override
 457  
     public void updateModel(DataModel model){
 458  0
         SectionBinding.INSTANCE.setModelValue(this, model, "");
 459  0
     }
 460  
 
 461  
     /**
 462  
      * Updates the section's fields with data from the model passed in.  This effects all the data input and
 463  
      * display widgets on the particular section.  This method will use the 
 464  
          * modelWidgetBinding defined in each of this sections fields to determine how to interpret data from the
 465  
          * model and display it on the fields corresponding widget.
 466  
          * 
 467  
      * @see org.kuali.student.common.ui.client.configurable.mvc.sections.Section#updateWidgetData(org.kuali.student.common.ui.client.mvc.DataModel)
 468  
      */
 469  
     @Override
 470  
     public void updateWidgetData(DataModel model) {
 471  0
         SectionBinding.INSTANCE.setWidgetValue(this, model, "");
 472  0
     }
 473  
 
 474  
     /**
 475  
      * Resets all the dirty and focus flags on fields.
 476  
      * @see org.kuali.student.common.ui.client.configurable.mvc.sections.Section#resetFieldInteractionFlags()
 477  
      */
 478  
     @Override
 479  
     public void resetFieldInteractionFlags() {
 480  0
             this.isDirty = false;
 481  0
         for(FieldDescriptor f: fields){
 482  0
             f.setDirty(false);
 483  0
             f.setHasHadFocus(false);
 484  
         }
 485  
 
 486  0
         for(Section s: sections){
 487  0
             s.resetFieldInteractionFlags();
 488  
         }
 489  
 
 490  0
     }
 491  
 
 492  
     @Override
 493  
     public void resetDirtyFlags() {
 494  0
             this.isDirty = false;
 495  0
         for(FieldDescriptor f: fields){
 496  0
             f.setDirty(false);
 497  
         }
 498  
 
 499  0
         for(Section s: sections){
 500  0
             s.resetDirtyFlags();
 501  
         }
 502  0
     }
 503  
 
 504  
 
 505  
         /**
 506  
          * Same as addSection except with an option user defined key (for retrieval of the section if necessary).
 507  
          * 
 508  
          * @see org.kuali.student.common.ui.client.configurable.mvc.sections.Section#addSection(java.lang.String, org.kuali.student.common.ui.client.configurable.mvc.sections.Section)
 509  
          */
 510  
         @Override
 511  
         public String addSection(String key, Section section) {
 512  0
         sections.add(section);
 513  0
         section.getLayout().setKey(key);
 514  0
         String rkey = layout.addLayout(section.getLayout());
 515  0
         return rkey;
 516  
         }
 517  
 
 518  
         @Override
 519  
         public FieldDescriptor getField(String fieldKey) {
 520  0
                 for(FieldDescriptor f: fields){
 521  0
                         if(f.getFieldKey().equals(fieldKey)){
 522  0
                                 return f;
 523  
                         }
 524  
                 }
 525  0
                 return null;
 526  
         }
 527  
 
 528  
         /**
 529  
          * Gets this sections fieldLayout.  The fieldLayout is used to determine how sections will layout the
 530  
          * ui and contains things such as the title and validation panels.
 531  
          * 
 532  
          * @see org.kuali.student.common.ui.client.configurable.mvc.sections.Section#getLayout()
 533  
          */
 534  
         @Override
 535  
         public FieldLayout getLayout() {
 536  0
                 return layout;
 537  
         }
 538  
 
 539  
         @Override
 540  
         public Section getSection(String sectionKey) {
 541  0
                 for(Section s: sections){
 542  0
                         if(s.getLayout().getKey().equals(sectionKey)){
 543  0
                                 return s;
 544  
                         }
 545  
                 }
 546  0
                 return null;
 547  
         }
 548  
 
 549  
         @Override
 550  
         public void removeField(String fieldKey) {
 551  0
                 int index = 0;
 552  0
                 boolean found = false;
 553  0
                 for(FieldDescriptor f: fields){
 554  0
                         if(f.getFieldKey().equals(fieldKey)){
 555  0
                                 index = fields.indexOf(f);
 556  0
                                 found = true;
 557  0
                                 break;
 558  
                         }
 559  
                 }
 560  0
                 if(found){
 561  0
                         fields.remove(index);
 562  
                 }
 563  0
                 layout.removeLayoutElement(fieldKey);
 564  
 
 565  0
         }
 566  
 
 567  
         @Override
 568  
         public void removeField(FieldDescriptor field) {
 569  
 
 570  0
                 fields.remove(field);
 571  0
                 layout.removeLayoutElement(field.getFieldKey());
 572  
 
 573  0
         }
 574  
 
 575  
         @Override
 576  
         public void removeSection(String sectionKey) {
 577  0
                 int index = 0;
 578  0
                 boolean found = false;
 579  0
                 for(Section s: sections){
 580  0
                         if(s.getLayout().getKey().equals(sectionKey)){
 581  0
                                 index = sections.indexOf(s);
 582  0
                                 found = true;
 583  0
                                 break;
 584  
                         }
 585  
                 }
 586  0
                 if(found){
 587  0
                         sections.remove(index);
 588  
                 }
 589  0
                 layout.removeLayoutElement(sectionKey);
 590  
 
 591  0
         }
 592  
 
 593  
         @Override
 594  
         public void removeWidget(Widget widget) {
 595  0
                 layout.removeLayoutElement(widget);
 596  
 
 597  0
         }
 598  
 
 599  
         @Override
 600  
         public void removeWidget(String key) {
 601  0
                 layout.removeLayoutElement(key);
 602  
 
 603  0
         }
 604  
 
 605  
         /**
 606  
          * Returns true if this this section is considered dirty (the user may have entered data into this
 607  
          * section)
 608  
          * 
 609  
          * @see org.kuali.student.common.ui.client.configurable.mvc.sections.Section#isDirty()
 610  
          */
 611  
         public boolean isDirty(){
 612  0
                 if(!this.isDirty){
 613  
                         //Check child sections for dirtyness
 614  0
                         for(Section s: sections){
 615  0
                                 if(s.isDirty()){
 616  0
                                         setIsDirty(true);
 617  0
                                         break;
 618  
                                 }
 619  
                         }
 620  
                 }
 621  0
                 return isDirty;
 622  
         }
 623  
 
 624  
     public void setIsDirty(boolean state) {
 625  
                 //Should this trust layoutController to be already set?
 626  0
             if (layoutController == null){
 627  0
                     layoutController = LayoutController.findParentLayout(layout);
 628  
             }
 629  0
             if (isDirty != state){
 630  0
                 isDirty = state;
 631  0
                     if (layoutController != null && isDirty){
 632  0
                             layoutController.fireApplicationEvent(new ContentDirtyEvent());
 633  
                     }
 634  
             }
 635  0
     }
 636  
 
 637  
         /**
 638  
          * DO NOT use this method for adding sections, fields, or widgets to sections
 639  
          */
 640  
         @Override
 641  
         public void add(Widget w) {
 642  0
                 super.add(w);
 643  0
         }
 644  
 
 645  
         /**
 646  
          * Adds a style to this section's underlying layout.
 647  
          * @see com.google.gwt.user.client.ui.UIObject#addStyleName(java.lang.String)
 648  
          */
 649  
         @Override
 650  
         public void addStyleName(String style) {
 651  0
                 layout.addStyleName(style);
 652  0
         }
 653  
 
 654  
         @Override
 655  
         public void setStyleName(String style) {
 656  0
                 layout.setStyleName(style);
 657  0
         }
 658  
 
 659  
         /**
 660  
          * Sets instructions for this entire section (appears next to section title)
 661  
          * @param html
 662  
          */
 663  
         public void setInstructions(String html){
 664  0
                 layout.setInstructions(html);
 665  0
         }
 666  
 
 667  
         /**
 668  
          * Sets help for this entire section (appears next to section title)
 669  
          * @param html
 670  
          */
 671  
         public void setHelp(String html){
 672  0
                 layout.setHelp(html);
 673  0
         }
 674  
         
 675  
         /**
 676  
          * Sets required for this entire section (appears next to section title)
 677  
          * @param required
 678  
          */
 679  
         public void setRequired(AbbrPanel required){
 680  0
                 layout.setRequired(required);
 681  0
         }
 682  
         
 683  
         public void setSectionId(String id){
 684  0
                 ((Widget)layout).getElement().setId(id);                
 685  0
         }
 686  
 
 687  
 }