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