Coverage Report - org.kuali.student.lum.common.client.lo.LOBuilder
 
Classes in this File Line Coverage Branch Coverage Complexity
LOBuilder
0%
0/76
0%
0/24
1.618
LOBuilder$1
0%
0/4
N/A
1.618
LOBuilder$LearningObjectiveList
0%
0/69
0%
0/18
1.618
LOBuilder$LearningObjectiveList$1
0%
0/3
N/A
1.618
LOBuilder$LearningObjectiveList$2
0%
0/5
N/A
1.618
LOBuilder$LearningObjectiveList$3
0%
0/4
N/A
1.618
 
 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.lum.common.client.lo;
 17  
 
 18  
 import java.util.ArrayList;
 19  
 import java.util.HashMap;
 20  
 import java.util.List;
 21  
 import java.util.Map;
 22  
 
 23  
 import org.kuali.student.common.assembly.data.Metadata;
 24  
 import org.kuali.student.common.ui.client.application.Application;
 25  
 import org.kuali.student.common.ui.client.application.ApplicationContext;
 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.sections.Section;
 29  
 import org.kuali.student.common.ui.client.configurable.mvc.sections.VerticalSection;
 30  
 import org.kuali.student.common.ui.client.event.ValidateRequestEvent;
 31  
 import org.kuali.student.common.ui.client.widgets.KSButton;
 32  
 import org.kuali.student.common.ui.client.widgets.KSLabel;
 33  
 import org.kuali.student.common.ui.client.widgets.KSButtonAbstract.ButtonStyle;
 34  
 import org.kuali.student.common.ui.client.widgets.field.layout.element.FieldElement;
 35  
 import org.kuali.student.common.ui.client.widgets.list.SelectionChangeEvent;
 36  
 import org.kuali.student.common.ui.client.widgets.list.SelectionChangeHandler;
 37  
 import org.kuali.student.common.ui.client.widgets.search.KSPicker;
 38  
 import org.kuali.student.common.validation.dto.ValidationResultInfo;
 39  
 import org.kuali.student.common.validation.dto.ValidationResultInfo.ErrorLevel;
 40  
 import org.kuali.student.lum.common.client.lu.LUUIConstants;
 41  
 import org.kuali.student.lum.lo.dto.LoCategoryInfo;
 42  
 
 43  
 import com.google.gwt.core.client.GWT;
 44  
 import com.google.gwt.event.dom.client.ChangeEvent;
 45  
 import com.google.gwt.event.dom.client.ChangeHandler;
 46  
 import com.google.gwt.event.dom.client.ClickEvent;
 47  
 import com.google.gwt.event.dom.client.ClickHandler;
 48  
 import com.google.gwt.event.logical.shared.ValueChangeEvent;
 49  
 import com.google.gwt.event.logical.shared.ValueChangeHandler;
 50  
 import com.google.gwt.event.shared.HandlerRegistration;
 51  
 import com.google.gwt.user.client.ui.HasValue;
 52  
 import com.google.gwt.user.client.ui.HorizontalPanel;
 53  
 
 54  
 /**
 55  
  * This class manages the users interactions when building/updating Learning
 56  
  * Objectives within the context of managing CLUs. It allows the user to type in
 57  
  * LO text directly or execute a search and select one or more of the returned
 58  
  * LOs.
 59  
  * 
 60  
  * Users can then re-organize LOs on the screen including altering the sequence
 61  
  * and creating sub LOs
 62  
  * 
 63  
  * @author Kuali Student Team
 64  
  * 
 65  
  */
 66  0
 public class LOBuilder extends VerticalSection implements HasValue<List<OutlineNode<LOPicker>>>, CanProcessValidationResults {
 67  
 
 68  
         private static String type;
 69  
         private static String state;
 70  
         private static String repoKey;
 71  
         private static String messageGroup;
 72  
     private static String startOfPath;
 73  0
     private static String endOfPath = "loInfo/desc/plain";
 74  0
     private static String middleOfPath = "loDisplayInfoList";
 75  0
         HorizontalPanel searchMainPanel = new HorizontalPanel();
 76  
         KSPicker searchWindow;
 77  
 
 78  
         LearningObjectiveList loList;
 79  
         KSLabel instructions;
 80  
         
 81  
         private static int loListDescLength;
 82  
         
 83  0
         private boolean onTheFlyValidation = true;
 84  
 
 85  0
         protected LOBuilder() {
 86  0
         }
 87  
 
 88  
     public LOBuilder(String luType, String luState, String luGroup, String loRepoKey, String queryPathStart, final Metadata metadata) {
 89  0
                 super();
 90  
                 
 91  0
                 loListDescLength = metadata.getProperties().get("plain").getConstraints().get(0).getMaxLength();
 92  
                 
 93  0
                 type = luType;
 94  0
                 state = luState;
 95  0
                 repoKey = loRepoKey;
 96  0
                 messageGroup = luGroup;
 97  0
         startOfPath = queryPathStart;       
 98  
 
 99  0
         if (metadata.getInitialLookup() != null) {
 100  0
             searchWindow = new KSPicker(metadata.getInitialLookup(), metadata.getAdditionalLookups());
 101  0
             searchWindow.addValuesChangeHandler(new ValueChangeHandler<List<String>>() {
 102  
                 public void onValueChange(ValueChangeEvent<List<String>> event) {
 103  0
                     List<String> selection = event.getValue();
 104  0
                     loList.addSelectedLOs(selection);
 105  0
                 }
 106  
             });
 107  0
             searchMainPanel.add(searchWindow);
 108  
         }
 109  
         
 110  0
         Metadata descMeta = new Metadata();
 111  0
         descMeta = metadata.getProperties().get("plain");
 112  
 
 113  0
                 instructions = new KSLabel(getLabel(LUUIConstants.LO_INSTRUCTIONS_KEY, descMeta));
 114  
 
 115  0
         loList = GWT.create(LearningObjectiveList.class);
 116  0
         loList.setLoInfoMaxLength(loListDescLength);
 117  
 
 118  0
                 searchMainPanel.addStyleName("KS-LOBuilder-Search-Panel");
 119  
 
 120  0
         loList.addStyleName(LUUIConstants.STYLE_SECTION);
 121  0
         loList.addStyleName(LUUIConstants.STYLE_SECTION_DIVIDER);
 122  
 
 123  0
                 instructions.addStyleName("KS-LOBuilder-Instructions");
 124  
 
 125  0
         this.addWidget(searchMainPanel);
 126  0
         this.addWidget(instructions);
 127  0
         this.addSection(loList);
 128  
         
 129  0
         }
 130  
 
 131  
         /**
 132  
          * @see com.google.gwt.user.client.ui.HasValue#setValue(java.lang.Object,
 133  
          *      boolean)
 134  
          */
 135  
         @Override
 136  
         public void setValue(List<OutlineNode<LOPicker>> value, boolean fireEvents) {
 137  0
                 setValue(value);
 138  0
         }
 139  
 
 140  
         /**
 141  
          * @see com.google.gwt.user.client.ui.HasValue#setValue(java.lang.Object)
 142  
          */
 143  
         @Override
 144  
         public void setValue(List<OutlineNode<LOPicker>> data) {
 145  0
                 loList.setValue(data);
 146  0
         }
 147  
 
 148  
         /**
 149  
          * @see com.google.gwt.user.client.ui.HasValue#getValue()
 150  
          */
 151  
         @Override
 152  
         public List<OutlineNode<LOPicker>> getValue() {
 153  0
                 return loList.getValue();
 154  
         }
 155  
 
 156  
         /**
 157  
          * @see com.google.gwt.event.logical.shared.HasValueChangeHandlers#addValueChangeHandler(com.google.gwt.event.logical.shared.ValueChangeHandler)
 158  
          */
 159  
         @Override
 160  
         public HandlerRegistration addValueChangeHandler(ValueChangeHandler<List<OutlineNode<LOPicker>>> handler) {
 161  0
                 return loList.addValueChangeHandler(handler);
 162  
         }
 163  
         
 164  
     private static String getLabel(String labelKey) {
 165  0
         return Application.getApplicationContext().getUILabel(messageGroup, type, state, labelKey);
 166  
     }
 167  
 
 168  
     private static String getLabel(String labelKey, Metadata metadata) {
 169  0
         return Application.getApplicationContext().getUILabel(messageGroup, type, state, labelKey, metadata);
 170  
     }
 171  
 
 172  
         /**
 173  
          * @return the type
 174  
          */
 175  
         public static String getType() {
 176  0
                 return type;
 177  
         }
 178  
 
 179  
         /**
 180  
          * @return the state
 181  
          */
 182  
         public static String getState() {
 183  0
                 return state;
 184  
         }
 185  
 
 186  
         public static String getRepoKey() {
 187  0
                 return repoKey;
 188  
         }
 189  
 
 190  
         /**
 191  
          * @return the messageGroup
 192  
          */
 193  
         public static String getMessageGroup() {
 194  0
                 return messageGroup;
 195  
         }
 196  
 
 197  0
     public static class LearningObjectiveList extends VerticalSection implements HasValue<List<OutlineNode<LOPicker>>> {
 198  0
                 OutlineNodeModel<LOPicker> outlineModel = new OutlineNodeModel<LOPicker>();
 199  
         protected KSButton addNew;
 200  
         OutlineManager outlineComposite;
 201  
         
 202  0
         private int loInfoMaxLength = 0;
 203  
                 
 204  0
                 SelectionChangeHandler loPickerChangeHandler = new SelectionChangeHandler(){
 205  
                         public void onSelectionChange(SelectionChangeEvent event) {
 206  0
                                 fireChangeEvent();
 207  0
                         }                        
 208  
                 };
 209  
                 
 210  0
         public LearningObjectiveList() {
 211  0
             addNew = new KSButton(getLabel(LUUIConstants.LEARNING_OBJECTIVE_ADD_LABEL_KEY), ButtonStyle.SECONDARY,
 212  0
                     new ClickHandler() {
 213  
                         public void onClick(ClickEvent event) {
 214  0
                             setValue(getValue());
 215  0
                             appendLO("");
 216  0
                             reDraw();
 217  0
                         }
 218  
                     });
 219  
                         
 220  0
             addNew.addStyleName("KS-LOBuilder-New");
 221  
 
 222  0
                         outlineModel.addChangeHandler(new ChangeHandler() {
 223  
                                 public void onChange(ChangeEvent event) {
 224  0
                     reDraw();
 225  0
                                         fireChangeEvent();
 226  0
                                 }
 227  
                         });
 228  
 
 229  0
             initEmptyLoList();
 230  
 //                        reDraw();
 231  0
                 }
 232  
 
 233  
                 protected void initEmptyLoList(){
 234  0
                         List<String> list = new ArrayList<String>();
 235  0
                         list.add("");
 236  0
                         list.add("");
 237  0
                         list.add("");
 238  0
                         list.add("");
 239  0
                         list.add("");
 240  0
                         addSelectedLOs(list);                        
 241  0
                 }
 242  
                 
 243  
                 protected void fireChangeEvent(){
 244  0
                         ValueChangeEvent.fire(this, outlineModel.getOutlineNodes());
 245  0
                 }
 246  
                 
 247  
                 public List<OutlineNode<LOPicker>> getValue() {
 248  0
                         return outlineModel.getOutlineNodes();
 249  
                 }
 250  
 
 251  
                 public void setValue(List<OutlineNode<LOPicker>> value) {
 252  0
                         outlineModel.clearNodes();
 253  0
                         outlineModel.getOutlineNodes().addAll(value);
 254  
 
 255  0
                         if (value == null || value.isEmpty()){
 256  0
                                 initEmptyLoList();
 257  
                         } else {
 258  
                                 //Add selection change handler to LOPickers if not set
 259  0
                                 for (OutlineNode<LOPicker> node:value){
 260  0
                                         LOPicker picker = node.getUserObject();
 261  0
                                         if (!picker.hasChangeHandler()){
 262  0
                                                 picker.addSelectionChangeHandler(loPickerChangeHandler);
 263  
                                         }
 264  0
                                 }
 265  
                                 
 266  0
                                 reDraw();
 267  
                         }
 268  0
                 }
 269  
                 
 270  
         public void setLoInfoMaxLength(int loInfoMaxLength) {
 271  0
             this.loInfoMaxLength = loInfoMaxLength;
 272  0
         }
 273  
 
 274  
         private void appendLO(String loValue) {
 275  0
                         OutlineNode<LOPicker> aNode = new OutlineNode<LOPicker>();
 276  0
                         LOPicker newPicker = new LOPicker(messageGroup, type, state, repoKey, this.loInfoMaxLength);
 277  
 
 278  0
                         newPicker.addSelectionChangeHandler(loPickerChangeHandler);
 279  0
                         newPicker.setLOText(loValue);
 280  0
                         aNode.setUserObject(newPicker);
 281  0
                         aNode.setModel(outlineModel);
 282  
 
 283  0
                         outlineModel.addOutlineNode(aNode);
 284  0
                 }
 285  
 
 286  
                 // add one or more description by going through existing LO box and
 287  
                 // populating the empty ones
 288  
                 // if not enough empty LO boxes then add new ones
 289  
                 public void addSelectedLOs(List<String> loDescription) {
 290  
 
 291  0
                         List<OutlineNode<LOPicker>> existingLOs = outlineModel.getOutlineNodes();
 292  
 
 293  0
                         int ix = existingLOs.size();
 294  0
                         for (String strValue : loDescription) {
 295  
 
 296  0
                                 boolean foundEmptyBox = false;
 297  
                                 
 298  0
                                 for(int i=0;i<ix;i++)
 299  
                                 {
 300  0
                                         if (existingLOs.get(i).getUserObject().getLOText().trim()
 301  
                                                         .length() == 0) {
 302  0
                                                 existingLOs.get(i).getUserObject().setLOText(strValue);
 303  0
                                                 foundEmptyBox = true;
 304  0
                                                 i=ix;
 305  
                                         }
 306  
                                 }
 307  
 
 308  
                                 // we didn't find empty LO box so add a new one
 309  0
                                 if (foundEmptyBox == false) {
 310  0
                                         appendLO(strValue);
 311  
                                 }
 312  0
                         }
 313  0
                         reDraw();
 314  0
                 }
 315  
 
 316  
                 private void reDraw() {
 317  0
             if (null != outlineComposite) {
 318  0
                 this.removeSection(outlineComposite);
 319  
             }
 320  0
             this.removeWidget(addNew); // no error if it's not currently there
 321  0
             outlineComposite = new OutlineManager(startOfPath, middleOfPath, endOfPath);
 322  0
             outlineComposite.setValue(outlineModel);
 323  0
             this.addSection(outlineComposite);
 324  0
             this.addWidget(addNew);
 325  0
                         outlineComposite.render();
 326  0
                 }
 327  
 
 328  
                 public HandlerRegistration addValueChangeHandler(ValueChangeHandler<List<OutlineNode<LOPicker>>> handler) {
 329  0
                         return addHandler(handler, ValueChangeEvent.getType());
 330  
                 }
 331  
                 
 332  
                 public SelectionChangeHandler getChangeHandlerForLOPicker(){
 333  0
                         return loPickerChangeHandler;
 334  
                 }
 335  
 
 336  
                 @Override
 337  
                 public void setValue(List<OutlineNode<LOPicker>> value,
 338  
                                 boolean fireEvents) {
 339  0
                         setValue(value);
 340  0
                 }
 341  
         }
 342  
 
 343  
     @Override
 344  
     public ErrorLevel processValidationResults(FieldDescriptor fd, List<ValidationResultInfo> results) {
 345  0
         return processValidationResults(fd, results, true);
 346  
     }
 347  
 
 348  
     @Override
 349  
     public ErrorLevel processValidationResults(FieldDescriptor fd, List<ValidationResultInfo> results, boolean clearErrors) {
 350  
         
 351  0
         ErrorLevel status = ErrorLevel.OK;
 352  
         
 353  0
         for (Section section : getSections()) {
 354  0
             ErrorLevel level = section.processValidationResults(results, clearErrors);
 355  0
             if (level.getLevel() > status.getLevel()) {
 356  0
                 status = level;
 357  
             }
 358  0
         }
 359  0
         return status;
 360  
     }
 361  
     
 362  
     public static int getLoListDescLength() {
 363  0
         return loListDescLength; 
 364  
         
 365  
     }
 366  
 
 367  
     @Override
 368  
     public boolean doesOnTheFlyValidation() {      
 369  0
         return onTheFlyValidation;
 370  
     }
 371  
 
 372  
     @Override
 373  
     public void Validate(ValidateRequestEvent event, List<ValidationResultInfo> result) {
 374  
 
 375  0
         if (event.getFieldDescriptor().hasHadFocus()) {
 376  0
             Map<String, FieldElement> loFieldModelMapping = doLOFieldModelMapping();
 377  
 
 378  0
             for (int i = 0; i < result.size(); i++) {
 379  0
                 ValidationResultInfo vr = result.get(i);
 380  0
                 FieldElement element = loFieldModelMapping.get(vr.getElement());
 381  
 
 382  0
                 if (element != null) {
 383  0
                     element.clearValidationErrors();
 384  0
                     element.processValidationResult(vr);
 385  
                 }
 386  
             }
 387  
         }
 388  
 
 389  0
     }
 390  
     
 391  
     private Map<String, FieldElement> doLOFieldModelMapping() {
 392  0
         Map<String, FieldElement> loFieldModelMapping = new HashMap<String, FieldElement>();
 393  
 
 394  0
         int z = 0;
 395  
 
 396  0
         for (int i = 0; i < this.getValue().size(); i++) {
 397  0
             String startPath = startOfPath + "/";
 398  0
             String endPathFormatted = "/" + "loInfo/desc/formatted";
 399  0
             String endPathPlain = "/" + "loInfo/desc/plain";
 400  
 
 401  0
             this.getFields().get(i).getFieldElement().clearValidationErrors();
 402  
             
 403  0
             String desc = this.getValue().get(i).getUserObject().getLOText();
 404  0
             int indentLevel = this.getValue().get(i).getIndentLevel();
 405  0
             List<LoCategoryInfo> categories = this.getValue().get(i).getUserObject().getLoCategories();
 406  
 
 407  0
             if (desc != null && desc.trim().length() > 0 || indentLevel > 0 || categories != null && !categories.isEmpty()) {
 408  0
                 loFieldModelMapping.put(startPath + z + endPathFormatted, this.getFields().get(i).getFieldElement());
 409  0
                 loFieldModelMapping.put(startPath + z++ + endPathPlain, this.getFields().get(i).getFieldElement());
 410  
             }
 411  
 
 412  
         }        
 413  0
         return loFieldModelMapping;
 414  
     }   
 415  
 
 416  
 }