Coverage Report - org.kuali.rice.krad.uif.layout.StackedLayoutManager
 
Classes in this File Line Coverage Branch Coverage Complexity
StackedLayoutManager
0%
0/67
0%
0/20
1.5
 
 1  
 /*
 2  
  * Copyright 2007 The Kuali Foundation
 3  
  *
 4  
  * Licensed under the Educational Community License, Version 1.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  * http://www.opensource.org/licenses/ecl1.php
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 package org.kuali.rice.krad.uif.layout;
 17  
 
 18  
 import org.apache.commons.lang.StringUtils;
 19  
 import org.kuali.rice.krad.uif.UifConstants.Orientation;
 20  
 import org.kuali.rice.krad.uif.container.CollectionGroup;
 21  
 import org.kuali.rice.krad.uif.container.Container;
 22  
 import org.kuali.rice.krad.uif.container.Group;
 23  
 import org.kuali.rice.krad.uif.container.View;
 24  
 import org.kuali.rice.krad.uif.core.Component;
 25  
 import org.kuali.rice.krad.uif.core.DataBinding;
 26  
 import org.kuali.rice.krad.uif.field.ActionField;
 27  
 import org.kuali.rice.krad.uif.field.Field;
 28  
 import org.kuali.rice.krad.uif.field.GroupField;
 29  
 import org.kuali.rice.krad.uif.util.ComponentUtils;
 30  
 import org.kuali.rice.krad.uif.util.ObjectPropertyUtils;
 31  
 
 32  
 import java.util.ArrayList;
 33  
 import java.util.List;
 34  
 
 35  
 /**
 36  
  * Layout manager that works with <code>CollectionGroup</code> containers and
 37  
  * renders the collection lines in a vertical row
 38  
  * 
 39  
  * <p>
 40  
  * For each line of the collection, a <code>Group</code> instance is created.
 41  
  * The group header contains a label for the line (summary information), the
 42  
  * group fields are the collection line fields, and the group footer contains
 43  
  * the line actions. All the groups are rendered using the
 44  
  * <code>BoxLayoutManager</code> with vertical orientation.
 45  
  * </p>
 46  
  * 
 47  
  * <p>
 48  
  * Modify the lineGroupPrototype to change header/footer styles or any other
 49  
  * customization for the line groups
 50  
  * </p>
 51  
  * 
 52  
  * @author Kuali Rice Team (rice.collab@kuali.org)
 53  
  */
 54  
 public class StackedLayoutManager extends BoxLayoutManager implements CollectionLayoutManager {
 55  
         private static final long serialVersionUID = 4602368505430238846L;
 56  
 
 57  
         private String summaryTitle;
 58  
         private List<String> summaryFields;
 59  
 
 60  
         private Group addLineGroup;
 61  
         private Group lineGroupPrototype;
 62  
         private GroupField subCollectionGroupFieldPrototype;
 63  
 
 64  
         private List<Group> stackedGroups;
 65  
 
 66  
         public StackedLayoutManager() {
 67  0
                 super();
 68  
 
 69  0
                 setOrientation(Orientation.VERTICAL);
 70  
 
 71  0
                 summaryFields = new ArrayList<String>();
 72  0
                 stackedGroups = new ArrayList<Group>();
 73  0
         }
 74  
 
 75  
         /**
 76  
          * The following actions are performed:
 77  
          * 
 78  
          * <ul>
 79  
          * <li>Initializes the prototypes</li>
 80  
          * </ul>
 81  
          * 
 82  
          * @see org.kuali.rice.krad.uif.layout.BoxLayoutManager#performInitialization(org.kuali.rice.krad.uif.container.View,
 83  
          *      org.kuali.rice.krad.uif.container.Container)
 84  
          */
 85  
         @Override
 86  
         public void performInitialization(View view, Container container) {
 87  0
                 super.performInitialization(view, container);
 88  
 
 89  0
                 view.getViewHelperService().performComponentInitialization(view, lineGroupPrototype);
 90  0
                 view.getViewHelperService().performComponentInitialization(view, subCollectionGroupFieldPrototype);
 91  0
         }
 92  
 
 93  
         /**
 94  
          * Builds a <code>Group</code> instance for a collection line. The group is
 95  
          * built by first creating a copy of the configured prototype. Then the
 96  
          * header for the group is created using the configured summary fields on
 97  
          * the <code>CollectionGroup</code>. The line fields passed in are set as
 98  
          * the items for the group, and finally the actions are placed into the
 99  
          * group footer
 100  
          * 
 101  
          * @see org.kuali.rice.krad.uif.layout.CollectionLayoutManager#buildLine(org.kuali.rice.krad.uif.container.View,
 102  
          *      java.lang.Object, org.kuali.rice.krad.uif.container.CollectionGroup,
 103  
          *      java.util.List, java.util.List, java.lang.String, java.util.List,
 104  
          *      java.lang.String, java.lang.Object, int)
 105  
          */
 106  
         public void buildLine(View view, Object model, CollectionGroup collectionGroup, List<Field> lineFields,
 107  
                         List<GroupField> subCollectionFields, String bindingPath, List<ActionField> actions, String idSuffix,
 108  
                         Object currentLine, int lineIndex) {
 109  0
                 boolean isAddLine = lineIndex == -1;
 110  
 
 111  
                 // construct new group
 112  0
                 Group lineGroup = null;
 113  0
                 if (isAddLine) {
 114  0
                         stackedGroups = new ArrayList<Group>();
 115  
 
 116  0
                         if (addLineGroup == null) {
 117  0
                                 lineGroup = ComponentUtils.copy(lineGroupPrototype, idSuffix);
 118  
                         }
 119  
                         else {
 120  0
                                 lineGroup = ComponentUtils.copy(getAddLineGroup(), idSuffix);
 121  
                         }
 122  
                 }
 123  
                 else {
 124  0
                         lineGroup = ComponentUtils.copy(lineGroupPrototype, idSuffix);
 125  
                 }
 126  
 
 127  0
                 ComponentUtils.updateContextForLine(lineGroup, currentLine, lineIndex);
 128  
 
 129  
                 // build header text for group
 130  0
                 String headerText = "";
 131  0
                 if (isAddLine) {
 132  0
                         headerText = collectionGroup.getAddLineLabel();
 133  
                 }
 134  
                 else {
 135  
                         // get the collection for this group from the model
 136  0
                         List<Object> modelCollection = ObjectPropertyUtils.getPropertyValue(model, ((DataBinding) collectionGroup)
 137  
                                         .getBindingInfo().getBindingPath());
 138  
 
 139  0
                         headerText = buildLineHeaderText(modelCollection.get(lineIndex));
 140  
                 }
 141  0
                 lineGroup.getHeader().setHeaderText(headerText);
 142  
 
 143  
                 // stack all fields (including sub-collections) for the group
 144  0
                 List<Field> groupFields = new ArrayList<Field>();
 145  0
                 groupFields.addAll(lineFields);
 146  0
                 groupFields.addAll(subCollectionFields);
 147  
 
 148  0
                 lineGroup.setItems(groupFields);
 149  
 
 150  
                 // set line actions on group footer
 151  0
                 if (collectionGroup.isRenderLineActions() && !collectionGroup.isReadOnly()) {
 152  0
                         lineGroup.getFooter().setItems(actions);
 153  
                 }
 154  
 
 155  0
                 stackedGroups.add(lineGroup);
 156  0
         }
 157  
 
 158  
         /**
 159  
          * Builds the header text for the collection line
 160  
          * 
 161  
          * <p>
 162  
          * Header text is built up by first the collection label, either specified
 163  
          * on the collection definition or retrieved from the dictionary. Then for
 164  
          * each summary field defined, the value from the model is retrieved and
 165  
          * added to the header.
 166  
          * </p>
 167  
          * 
 168  
          * @param line
 169  
          *            - Collection line containing data
 170  
          * @return String header text for line
 171  
          */
 172  
         protected String buildLineHeaderText(Object line) {
 173  0
                 String summaryFieldString = "";
 174  0
                 for (String summaryField : summaryFields) {
 175  0
                         Object summaryFieldValue = ObjectPropertyUtils.getPropertyValue(line, summaryField);
 176  0
                         if (StringUtils.isNotBlank(summaryFieldString)) {
 177  0
                                 summaryFieldString += " - ";
 178  
                         }
 179  
 
 180  0
                         if (summaryFieldValue != null) {
 181  0
                                 summaryFieldString += summaryFieldValue;
 182  
                         }
 183  
                         else {
 184  0
                                 summaryFieldString += "Null";
 185  
                         }
 186  0
                 }
 187  
 
 188  0
                 String headerText = summaryTitle;
 189  0
                 if (StringUtils.isNotBlank(summaryFieldString)) {
 190  0
                         headerText += " ( " + summaryFieldString + " )";
 191  
                 }
 192  
 
 193  0
                 return headerText;
 194  
         }
 195  
 
 196  
         /**
 197  
          * @see org.kuali.rice.krad.uif.layout.ContainerAware#getSupportedContainer()
 198  
          */
 199  
         @Override
 200  
         public Class<? extends Container> getSupportedContainer() {
 201  0
                 return CollectionGroup.class;
 202  
         }
 203  
 
 204  
         /**
 205  
          * @see org.kuali.rice.krad.uif.layout.LayoutManagerBase#getNestedComponents()
 206  
          */
 207  
         @Override
 208  
         public List<Component> getNestedComponents() {
 209  0
                 List<Component> components = super.getNestedComponents();
 210  
 
 211  0
                 components.addAll(stackedGroups);
 212  
 
 213  0
                 return components;
 214  
         }
 215  
 
 216  
         /**
 217  
          * Text to appears in the header for each collection lines Group. Used in
 218  
          * conjunction with {@link #getSummaryFields()} to build up the final header
 219  
          * text
 220  
          * 
 221  
          * @return String summary title text
 222  
          */
 223  
         public String getSummaryTitle() {
 224  0
                 return this.summaryTitle;
 225  
         }
 226  
 
 227  
         /**
 228  
          * Setter for the summary title text
 229  
          * 
 230  
          * @param summaryTitle
 231  
          */
 232  
         public void setSummaryTitle(String summaryTitle) {
 233  0
                 this.summaryTitle = summaryTitle;
 234  0
         }
 235  
 
 236  
         /**
 237  
          * List of attribute names from the collection line class that should be
 238  
          * used to build the line summary. To build the summary the value for each
 239  
          * attribute is retrieved from the line instance. All the values are then
 240  
          * placed together with a separator.
 241  
          * 
 242  
          * @return List<String> summary field names
 243  
          * @see #buildLineHeaderText(java.lang.Object)
 244  
          */
 245  
         public List<String> getSummaryFields() {
 246  0
                 return this.summaryFields;
 247  
         }
 248  
 
 249  
         /**
 250  
          * Setter for the summary field name list
 251  
          * 
 252  
          * @param summaryFields
 253  
          */
 254  
         public void setSummaryFields(List<String> summaryFields) {
 255  0
                 this.summaryFields = summaryFields;
 256  0
         }
 257  
 
 258  
         /**
 259  
          * Group instance that will be used for the add line
 260  
          * 
 261  
          * <p>
 262  
          * Add line fields and actions configured on the
 263  
          * <code>CollectionGroup</code> will be set onto the add line group (if add
 264  
          * line is enabled). If the add line group is not configured, a new instance
 265  
          * of the line group prototype will be used for the add line.
 266  
          * </p>
 267  
          * 
 268  
          * @return Group add line group instance
 269  
          * @see #getAddLineGroup()
 270  
          */
 271  
         public Group getAddLineGroup() {
 272  0
                 return this.addLineGroup;
 273  
         }
 274  
 
 275  
         /**
 276  
          * Setter for the add line group
 277  
          * 
 278  
          * @param addLineGroup
 279  
          */
 280  
         public void setAddLineGroup(Group addLineGroup) {
 281  0
                 this.addLineGroup = addLineGroup;
 282  0
         }
 283  
 
 284  
         /**
 285  
          * Group instance that is used as a prototype for creating the collection
 286  
          * line groups. For each line a copy of the prototype is made and then
 287  
          * adjusted as necessary
 288  
          * 
 289  
          * @return Group instance to use as prototype
 290  
          */
 291  
         public Group getLineGroupPrototype() {
 292  0
                 return this.lineGroupPrototype;
 293  
         }
 294  
 
 295  
         /**
 296  
          * Setter for the line group prototype
 297  
          * 
 298  
          * @param lineGroupPrototype
 299  
          */
 300  
         public void setLineGroupPrototype(Group lineGroupPrototype) {
 301  0
                 this.lineGroupPrototype = lineGroupPrototype;
 302  0
         }
 303  
 
 304  
         /**
 305  
          * @see org.kuali.rice.krad.uif.layout.CollectionLayoutManager#getSubCollectionGroupFieldPrototype()
 306  
          */
 307  
         public GroupField getSubCollectionGroupFieldPrototype() {
 308  0
                 return this.subCollectionGroupFieldPrototype;
 309  
         }
 310  
 
 311  
         /**
 312  
          * Setter for the sub-collection field group prototype
 313  
          * 
 314  
          * @param subCollectionGroupFieldPrototype
 315  
          */
 316  
         public void setSubCollectionGroupFieldPrototype(GroupField subCollectionGroupFieldPrototype) {
 317  0
                 this.subCollectionGroupFieldPrototype = subCollectionGroupFieldPrototype;
 318  0
         }
 319  
 
 320  
         /**
 321  
          * Final <code>List</code> of Groups to render for the collection
 322  
          * 
 323  
          * @return List<Group> collection groups
 324  
          */
 325  
         public List<Group> getStackedGroups() {
 326  0
                 return this.stackedGroups;
 327  
         }
 328  
 
 329  
         /**
 330  
          * Setter for the collection groups
 331  
          * 
 332  
          * @param stackedGroups
 333  
          */
 334  
         public void setStackedGroups(List<Group> stackedGroups) {
 335  0
                 this.stackedGroups = stackedGroups;
 336  0
         }
 337  
 
 338  
 }