View Javadoc
1   /*
2    * Copyright 2008 The Kuali Foundation
3    * 
4    * Licensed under the Educational Community License, Version 2.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/ecl2.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.ole.sys.document.web;
17  
18  import java.util.ArrayList;
19  import java.util.List;
20  import java.util.Map;
21  
22  import javax.servlet.jsp.JspException;
23  import javax.servlet.jsp.PageContext;
24  import javax.servlet.jsp.tagext.Tag;
25  
26  import org.apache.commons.beanutils.PropertyUtils;
27  import org.apache.commons.lang.StringUtils;
28  import org.kuali.ole.sys.businessobject.AccountingLine;
29  import org.kuali.ole.sys.context.SpringContext;
30  import org.kuali.ole.sys.document.AccountingDocument;
31  import org.kuali.ole.sys.document.authorization.AccountingLineAuthorizer;
32  import org.kuali.ole.sys.web.struts.KualiAccountingDocumentFormBase;
33  import org.kuali.rice.kim.api.identity.Person;
34  import org.kuali.rice.kns.service.DataDictionaryService;
35  import org.kuali.rice.kns.util.FieldUtils;
36  import org.kuali.rice.kns.web.ui.Field;
37  import org.kuali.rice.krad.util.GlobalVariables;
38  import org.kuali.rice.krad.util.KRADConstants;
39  
40  /**
41   * A container which holds a single accounting line and the elements which will render it
42   */
43  public class RenderableAccountingLineContainer implements AccountingLineRenderingContext {
44      private List<AccountingLineTableRow> rows;
45      private List<AccountingLineViewAction> actions;
46      private AccountingLine accountingLine;
47      private String accountingLineProperty;
48      private List<Field> fields;
49      private List<String> fieldNames;
50      private KualiAccountingDocumentFormBase form;
51      private String groupLabel;
52      private Integer lineCount;
53      private List errors;
54      private AccountingLineAuthorizer accountingLineAuthorizer;
55      private boolean editableLine;
56      private boolean deletable = false;
57      
58      /**
59       * Constructs a RenderableAccountingLineContainer
60       * @param form the form being rendered
61       * @param accountingLine the accounting line this container will render
62       * @param accountingLineProperty the property to that accounting line
63       * @param rows the rows to render
64       * @param newLine whether this is a new accounting line or not
65       * @param groupLabel the label for the group this accounting line is being rendered part of
66       * @param errors the set of errors currently on the document
67       * @param accountingLineAuthorizer the accounting line authorizer for the document
68       * @param editableLine whether this line, as a whole _line_ is editable
69       */
70      public RenderableAccountingLineContainer(KualiAccountingDocumentFormBase form, AccountingLine accountingLine, String accountingLineProperty, List<AccountingLineTableRow> rows, Integer lineCount, String groupLabel, List errors, AccountingLineAuthorizer accountingLineAuthorizer, boolean editableLine) {
71          this.form = form;
72          this.accountingLine = accountingLine;
73          this.accountingLineProperty = accountingLineProperty;
74          this.rows = rows;
75          this.lineCount = lineCount;
76          this.groupLabel = groupLabel;
77          this.errors = errors;
78          this.accountingLineAuthorizer = accountingLineAuthorizer;
79          this.editableLine = editableLine;
80      }
81      
82      /**
83       * Gets the accountingLine attribute. 
84       * @return Returns the accountingLine.
85       */
86      public AccountingLine getAccountingLine() {
87          return accountingLine;
88      }
89  
90      /**
91       * Gets the accountingLineProperty attribute. 
92       * @return Returns the accountingLineProperty.
93       */
94      public String getAccountingLineProperty() {
95          return accountingLineProperty;
96      }
97  
98      /**
99       * Gets the actions attribute. 
100      * @return Returns the actions.
101      */
102     public List<AccountingLineViewAction> getActionsForLine() {
103         if (actions == null) {
104             actions = accountingLineAuthorizer.getActions(form.getFinancialDocument(), this, accountingLineProperty, lineCount, GlobalVariables.getUserSession().getPerson(), groupLabel);
105         }
106         return actions;
107     }
108 
109     /**
110      * Gets the newLine attribute. 
111      * @return Returns the newLine.
112      */
113     public boolean isNewLine() {
114         return lineCount == null;
115     }
116 
117     /**
118      * @see org.kuali.ole.sys.document.web.AccountingLineRenderingContext#getCurrentLineCount()
119      */
120     public Integer getCurrentLineCount() {
121         return lineCount;
122     }
123 
124     /**
125      * Gets the rows attribute. 
126      * @return Returns the rows.
127      */
128     public List<AccountingLineTableRow> getRows() {
129         return rows;
130     }
131     
132     /**
133      * @return the number of cells this accounting line container will render
134      */
135     public int getCellCount() {
136         int maxCells = 0;
137         for (AccountingLineTableRow row : rows) {
138             final int maxRowCellCount = row.getChildCellCount();
139             if (maxCells < maxRowCellCount) {
140                 maxCells = maxRowCellCount;
141             }
142         }
143         return maxCells;
144     }
145     
146     /**
147      * Determines how many cells this container will say it wants to render
148      * @see org.kuali.ole.sys.document.web.AccountingLineRenderingContext#getRenderableCellCount()
149      */
150     public int getRenderableCellCount() {
151         int maxCells = 0;
152         for (AccountingLineTableRow row : rows) {
153             final int maxRowCellCount = row.getChildRenderableCount();
154             if (maxCells < maxRowCellCount) {
155                 maxCells = maxRowCellCount;
156             }
157         }
158         return maxCells;
159     }
160     
161     /**
162      * Adds empty cells to a table row
163      * @param cellCount the number of cells we should be rendering
164      * @param row the row to pad out
165      */
166     protected void padOutRow(int cellCount, AccountingLineTableRow row) {
167         while ((cellCount - row.getChildCellCount()) > 0) {
168             row.addCell(new AccountingLineTableCell());
169         }
170     }
171     
172     /**
173      * While holding an action block, this is not an action block
174      * @see org.kuali.ole.sys.document.web.RenderableElement#isActionBlock()
175      */
176     public boolean isActionBlock() {
177         return false;
178     }
179     
180     /**
181      * This is never empty
182      * @see org.kuali.ole.sys.document.web.RenderableElement#isEmpty()
183      */
184     public boolean isEmpty() {
185         return false;
186     }
187     
188     /**
189      * This is not hidden 
190      * @see org.kuali.ole.sys.document.web.RenderableElement#isHidden()
191      */
192     public boolean isHidden() {
193         return false;
194     }
195     
196     /**
197      * Renders all the rows
198      * @see org.kuali.ole.sys.document.web.RenderableElement#renderElement(javax.servlet.jsp.PageContext, javax.servlet.jsp.tagext.Tag, org.kuali.ole.sys.document.web.AccountingLineRenderingContext)
199      */
200     public void renderElement(PageContext pageContext, Tag parentTag, AccountingLineRenderingContext renderingContext) throws JspException {
201         for (AccountingLineTableRow row : rows) {
202             row.renderElement(pageContext, parentTag, renderingContext);
203         }
204     }
205     
206     /**
207      * @see org.kuali.ole.sys.document.web.AccountingLineRenderingContext#getAccountingLinePropertyPath()
208      */
209     public String getAccountingLinePropertyPath() {
210         return accountingLineProperty;
211     }
212     
213     /**
214      * Appends all fields from rows that this contains
215      * @see org.kuali.ole.sys.document.web.RenderableElement#appendFieldNames(java.util.List)
216      */
217     public void appendFields(List<Field> fields) {
218         for (AccountingLineTableRow row : rows) {
219             row.appendFields(fields);
220         }
221     }
222     
223     /**
224      * Returns all of the field names within the accounting line to render
225      * @return a List of field names with the accounting line property prefixed
226      * 
227      * KRAD Conversion: Customization of getting the fields - No use of data dictionary
228      */
229     public List<Field> getFieldsForAccountingLine() {
230         if (fields == null) {
231             fields = new ArrayList<Field>();
232             appendFields(fields);
233         }
234         return fields;
235     }
236     
237     /**
238      * @see org.kuali.ole.sys.document.web.AccountingLineRenderingContext#getFieldNamesForAccountingLine()
239      * 
240      * KRAD Conversion: Customization of the fields - No use of data dictionary
241      */
242     public List<String> getFieldNamesForAccountingLine() {
243         if (fieldNames == null) {
244             fieldNames = new ArrayList<String>();
245             for (Field field : getFieldsForAccountingLine()) {
246                 fieldNames.add(accountingLineProperty+"."+field.getPropertyName());
247             }
248         }
249         return fieldNames;
250     }
251     
252     /**
253      * @see org.kuali.ole.sys.document.web.RenderableElement#populateWithTabIndexIfRequested(int[], int)
254      */
255     public void populateWithTabIndexIfRequested( int reallyHighIndex) {
256         for (AccountingLineTableRow row : rows) {
257             row.populateWithTabIndexIfRequested(reallyHighIndex);
258         }
259     }
260     
261     /**
262      * Returns the unconvertedValues for the current form
263      * @see org.kuali.ole.sys.document.web.AccountingLineRenderingContext#getUnconvertedValues()
264      */
265     public Map getUnconvertedValues() {
266         return form.getUnconvertedValues();
267     }
268     
269     /**
270      * @see org.kuali.ole.sys.document.web.AccountingLineRenderingContext#populateValuesForFields()
271      * 
272      * KRAD Conversion: Customization of populating the field values - Use of data dictionary
273      */
274     public void populateValuesForFields() {
275         FieldUtils.populateFieldsFromBusinessObject(getFieldsForAccountingLine(), accountingLine);
276         
277         org.kuali.rice.krad.datadictionary.BusinessObjectEntry boDDEntry = SpringContext.getBean(DataDictionaryService.class).getDataDictionary().getBusinessObjectEntry(getAccountingLine().getClass().getName());
278         
279         for (Field field : getFieldsForAccountingLine()) {
280             setUnconvertedValueIfNecessary(field);
281             setShouldShowSecure(field, boDDEntry);
282         }
283     }
284     
285     /**
286      * Sees if the given field has an unconverted value living in the unconverted value map and if so,
287      * changes the value to that
288      * @param field the field to possibly set an unconverted value on
289      * 
290      * KRAD Conversion: Customization of the fields - No use of data dictionary
291      */
292     protected void setUnconvertedValueIfNecessary(Field field) {
293         String propertyName = accountingLineProperty+"."+field.getPropertyName();
294         if (getUnconvertedValues().get(propertyName) != null) {
295             field.setPropertyValue((String)getUnconvertedValues().get(propertyName));
296         }
297     }
298     
299     /**
300      * Sets the masked value equal to the value if the current user can see the unmasked value for a secure field
301      * @param field the field to possible change the value for
302      * @param boDDEntry the data dictionary entry for the accounting line
303      * 
304      * KRAD Conversion: Customization of the fields - No use of data dictionary
305      */
306     protected void setShouldShowSecure(Field field, org.kuali.rice.krad.datadictionary.BusinessObjectEntry boDDEntry) {
307         // TODO: FIX
308         
309         // from Warren:  k... org.kuali.rice.kns.service.BusinessObjectAuthorizationService.getMaintenanceDocumentRestrictions(MaintenanceDocument, Person) has the determination of what restrictions there should be
310         // org.kuali.rice.kns.util.FieldUtils.applyAuthorization(Field, String, MaintenanceDocumentRestrictions) applies those restrictions
311     }
312     /**
313      * @see org.kuali.ole.sys.document.web.AccountingLineRenderingContext#getAccountingDocument()
314      */
315     public AccountingDocument getAccountingDocument() {
316         return form.getFinancialDocument();
317     }
318     
319     /**
320      * @see org.kuali.ole.sys.document.web.AccountingLineRenderingContext#fieldsCanRenderDynamicLabels()
321      */
322     public boolean fieldsCanRenderDynamicLabels() {
323         return !form.isHideDetails();
324     }
325     /**
326      * @see org.kuali.ole.sys.document.web.AccountingLineRenderingContext#fieldsShouldRenderHelp()
327      */
328     public boolean fieldsShouldRenderHelp() {
329         return form.isFieldLevelHelpEnabled();
330     }
331     /**
332      * @see org.kuali.ole.sys.document.web.AccountingLineRenderingContext#getTabState(java.lang.String)
333      */
334     public String getTabState(String tabKey) {
335         return form.getTabState(tabKey);
336     }
337     /**
338      * @see org.kuali.ole.sys.document.web.AccountingLineRenderingContext#incrementTabIndex()
339      */
340     public void incrementTabIndex() {
341         form.incrementTabIndex();
342     }
343     
344     /**
345      * @see org.kuali.ole.sys.document.web.AccountingLineRenderingContext#getGroupLabel()
346      */
347     public String getGroupLabel() {
348        return this.groupLabel; 
349     }
350 
351     /**
352      * Gets the errors attribute. 
353      * @return Returns the errors.
354      */
355     public List getErrors() {
356         return errors;
357     }
358 
359     /**
360      * @see org.kuali.ole.sys.document.web.AccountingLineRenderingContext#getForm()
361      */
362     public KualiAccountingDocumentFormBase getForm() {
363         return form;
364     }
365 
366     /**
367      * @see org.kuali.ole.sys.document.web.AccountingLineRenderingContext#getAccountingLineContainingObjectPropertyName()
368      */
369     public String getAccountingLineContainingObjectPropertyName() {
370         return StringUtils.substringBeforeLast(this.getAccountingLinePropertyPath(), String.valueOf(PropertyUtils.NESTED_DELIM));
371     }
372 
373     /**
374      * @see org.kuali.ole.sys.document.web.AccountingLineRenderingContext#isFieldModifyable(org.kuali.ole.sys.document.web.AccountingLineViewField)
375      */
376     public boolean isFieldModifyable(String fieldName) {
377         Person currentUser = GlobalVariables.getUserSession().getPerson();
378         final boolean pageIsEditable = getForm().getDocumentActions().containsKey(KRADConstants.KUALI_ACTION_CAN_EDIT);
379         return accountingLineAuthorizer.hasEditPermissionOnField(getAccountingDocument(), accountingLine, this.accountingLineProperty, fieldName, editableLine, pageIsEditable, currentUser);
380     }
381 
382     /**
383      * Gets the editableLine attribute. 
384      * @return Returns the editableLine.
385      */
386     public boolean isEditableLine() {
387         return editableLine;
388     }
389     
390     /**
391      * Sets the editableLine attribute value.
392      * 
393      * @param editableLine The editableLine to set.
394      */
395     public void setEditableLine(boolean editableLine) {
396         this.editableLine = editableLine;
397     }
398 
399     /**
400      * Determines whether the line within this rendering context can be deleted.
401      * @see org.kuali.ole.sys.document.web.AccountingLineRenderingContext#allowDelete()
402      */
403     public boolean allowDelete() {
404         return deletable;
405     }
406     
407     /**
408      * Makes the line within this accounting line context deletable
409      */
410     public void makeDeletable() {
411         deletable = true;
412     }
413 }
414