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