Coverage Report - org.kuali.student.common.ui.client.configurable.mvc.binding.ModelWidgetBindingSupport
 
Classes in this File Line Coverage Branch Coverage Complexity
ModelWidgetBindingSupport
0%
0/45
0%
0/48
6.4
 
 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.binding;
 17  
 
 18  
 import java.util.Iterator;
 19  
 
 20  
 import org.kuali.student.common.assembly.data.Data;
 21  
 import org.kuali.student.common.assembly.data.QueryPath;
 22  
 import org.kuali.student.common.assembly.data.Data.Key;
 23  
 import org.kuali.student.common.assembly.data.Data.Property;
 24  
 import org.kuali.student.common.assembly.data.Data.StringKey;
 25  
 import org.kuali.student.common.ui.client.mvc.DataModel;
 26  
 
 27  
 /**
 28  
  * Exposes common functionality to binding classes.
 29  
  * 
 30  
  * @author Kuali Student Team
 31  
  */
 32  0
 public abstract class ModelWidgetBindingSupport<WidgetType> implements ModelWidgetBinding<WidgetType> {
 33  0
     public static final StringKey RUNTIME_ROOT = new StringKey("_runtimeData");
 34  0
     public static final StringKey DIRTY_PATH = new StringKey("dirty");
 35  
 
 36  
     /**
 37  
      * Flags the data at the provided path as dirty
 38  
      * 
 39  
      * @param model
 40  
      *            the DataModel containing the dirty data
 41  
      * @param qPath
 42  
      *            the path to the dirty data
 43  
      */
 44  
     protected void setDirtyFlag(DataModel model, QueryPath qPath) {
 45  0
         QueryPath parent = qPath.subPath(0, qPath.size() - 1);
 46  0
         QueryPath qPathDirty = new QueryPath();
 47  0
         qPathDirty.addAll(parent);
 48  0
         qPathDirty.add(RUNTIME_ROOT);
 49  0
         qPathDirty.add(DIRTY_PATH);
 50  
 
 51  0
         ensureDirtyFlagPath(model.getRoot(), qPathDirty);
 52  
 
 53  0
         Data flags = model.get(qPathDirty);
 54  0
         flags.set(qPath.get(qPath.size() - 1), Boolean.TRUE);
 55  0
     }
 56  
 
 57  
     /**
 58  
      * Ensures that the path to the dirty flag exists
 59  
      * 
 60  
      * @param root
 61  
      *            the DataModel's root node
 62  
      * @param path
 63  
      *            the path to the dirty flag
 64  
      */
 65  
     protected void ensureDirtyFlagPath(Data root, QueryPath path) {
 66  0
         Data current = root;
 67  0
         for (int i = 0; i < path.size(); i++) {
 68  0
             Key key = path.get(i);
 69  0
             Data d = current.get(key);
 70  0
             if (d == null) {
 71  0
                 d = new Data();
 72  0
                 current.set(key, d);
 73  
             }
 74  0
             current = d;
 75  
         }
 76  0
     }
 77  
 
 78  
     /**
 79  
      * Null checks, then compares parameters
 80  
      * 
 81  
      * @return true when either o1 and o2 are null, or when o1.equals(o2) returns true
 82  
      */
 83  
     protected static boolean nullsafeEquals(Object o1, Object o2) {
 84  0
         return (o1 == null && o2 == null) || (o1 != null && o1.equals(o2));
 85  
     }
 86  
 
 87  
     /**
 88  
      * Performs initial comparison of two data hierarchies, then examines them recursively if necessary
 89  
      * 
 90  
      * @return true when all members of the provided hierarchies are equivalent
 91  
      */
 92  
     protected static boolean nullsafeEquals(Data o1, Data o2) {
 93  0
         if (o1 == null && o2 == null) {
 94  0
             return true;
 95  0
         } else if (o1 != null && o2 != null && o1.size() != o2.size()) {
 96  0
             return false;
 97  0
         } else if (o1 != null && o2 != null && o1.size() == o2.size()) {
 98  0
             return deepEquals(o1, o2);
 99  
         } else {
 100  0
             return false;
 101  
         }
 102  
     }
 103  
 
 104  
     /**
 105  
      * Performs a recursive comparison of the two parameters.
 106  
      * 
 107  
      * @return true when all members of the provided hierarchies are equivalent
 108  
      */
 109  
     private static boolean deepEquals(Data o1, Data o2) {
 110  0
         Iterator<Property> iter = o1.iterator();
 111  0
         while (iter.hasNext()) {
 112  0
             Property prop = iter.next();
 113  0
             Key key = prop.getWrappedKey();
 114  0
             Object value1 = prop.getValue();
 115  0
             Object value2 = o2.get(key);
 116  
 
 117  0
             if (value1 == null ^ value2 == null) {
 118  0
                 return false;
 119  0
             } else if (value1 != null && value1 instanceof Data && value2 instanceof Data) {
 120  0
                 boolean recursiveResult = deepEquals((Data) value1, (Data) value2);
 121  0
                 if (!recursiveResult) {
 122  0
                     return false;
 123  
                 }
 124  0
             } else if (value1 != value2 && !(value1.equals(value2))) {
 125  0
                 return false;
 126  
             }
 127  0
         }
 128  0
         return true;
 129  
     }
 130  
 }