001    /*
002     * Copyright 2011 The Kuali Foundation.
003     * 
004     * Licensed under the Educational Community License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     * 
008     * http://www.opensource.org/licenses/ecl2.php
009     * 
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package org.kuali.kfs.sys.document.web;
017    
018    import java.util.List;
019    import java.util.Map;
020    import java.util.Set;
021    
022    import org.kuali.kfs.sys.KFSKeyConstants;
023    import org.kuali.kfs.sys.businessobject.AccountingLine;
024    import org.kuali.kfs.sys.context.SpringContext;
025    import org.kuali.kfs.sys.document.AccountingDocument;
026    import org.kuali.kfs.sys.document.datadictionary.AccountingLineViewCurrentBaseAmountFieldDefinition;
027    import org.kuali.kfs.sys.document.datadictionary.AccountingLineViewFieldDefinition;
028    import org.kuali.kfs.sys.document.service.AccountingLineFieldRenderingTransformation;
029    import org.kuali.rice.kns.service.KualiConfigurationService;
030    import org.kuali.rice.kns.web.ui.Field;
031    
032    /**
033     * Represents a current/base amount for an accounting line
034     */
035    public class AccountingLineViewCurrentBaseAmount implements TableJoiningWithHeader, ReadOnlyable {
036        private Field currentAmountField;
037        private Field baseAmountField;
038        private AccountingLineViewCurrentBaseAmountFieldDefinition definition;
039        private AccountingLineViewFieldDefinition currentAmountFieldDefinition;
040        private AccountingLineViewFieldDefinition baseAmountFieldDefinition;
041    
042        /**
043         * Returns null; we don't want to participate in normal naming schemes
044         * @see org.kuali.kfs.sys.document.web.TableJoining#getName()
045         */
046        public String getName() {
047            return null;
048        }
049    
050        /**
051         * Checks if either the current amount field or base amount field need to be set to read only
052         * @see org.kuali.kfs.sys.document.web.FieldTableJoining#readOnlyizeReadOnlyBlocks(java.util.Set)
053         */
054        public void readOnlyizeReadOnlyBlocks(Set<String> readOnlyBlocks) {
055            if (currentAmountField != null) {
056                readOnlyizeField(currentAmountField, readOnlyBlocks);
057            }
058            if (baseAmountField != null) {
059                readOnlyizeField(baseAmountField, readOnlyBlocks);
060            }
061            if (baseAmountField != null && currentAmountField != null) {
062                if (baseAmountField.isReadOnly() && !currentAmountField.isReadOnly()) {
063                    currentAmountField.setFieldRequired(true);
064                } else if (currentAmountField.isReadOnly() && !baseAmountField.isReadOnly()) {
065                    baseAmountField.setFieldRequired(true);
066                }
067            }
068        }
069        
070        /**
071         * @see org.kuali.kfs.sys.document.web.ReadOnlyable#isReadOnly()
072         */
073        public boolean isReadOnly() {
074            boolean readOnly = true;
075            if (currentAmountField != null) {
076                readOnly &= currentAmountField.isReadOnly();
077            }
078            if (baseAmountField != null) {
079                readOnly &= baseAmountField.isReadOnly();
080            }
081            return readOnly;
082        }
083    
084        /**
085         * @see org.kuali.kfs.sys.document.web.ReadOnlyable#readOnlyize()
086         */
087        public void readOnlyize() {
088            if (currentAmountField != null) {
089                currentAmountField.setReadOnly(true);
090            }
091            if (baseAmountField != null) {
092                baseAmountField.setReadOnly(true);
093            }
094        }
095    
096        /**
097         * Checks if the given field is named as a readOnlyBlock; if so, makes it read only
098         * @param field the field to check
099         * @param readOnlyBlocks the names of all read only blocks
100         */
101        protected void readOnlyizeField(Field field, Set<String> readOnlyBlocks) {
102            if (field != null && readOnlyBlocks.contains(field.getPropertyName())) {
103                field.setReadOnly(true);
104            }
105        }
106    
107        /**
108         * Always returns 2 - one line for the header, one line for the fields
109         * @see org.kuali.kfs.sys.document.web.TableJoining#getRequestedRowCount()
110         */
111        public int getRequestedRowCount() {
112            return 2;
113        }
114    
115        /**
116         * Adds the header cell to the first row, and the regular cell to the second row
117         * @see org.kuali.kfs.sys.document.web.TableJoining#joinRow(org.kuali.kfs.sys.document.web.AccountingLineTableRow, org.kuali.kfs.sys.document.web.AccountingLineTableRow)
118         */
119        public void joinRow(AccountingLineTableRow headerLabelRow, AccountingLineTableRow row) {
120            if (currentAmountField != null) {
121                headerLabelRow.addCell(createHeaderCellForField(currentAmountField));
122                row.addCell(createCellForField(currentAmountField, currentAmountFieldDefinition));
123            }
124            if (baseAmountField != null) {
125                headerLabelRow.addCell(createHeaderCellForField(baseAmountField));
126                row.addCell(createCellForField(baseAmountField, baseAmountFieldDefinition));
127            }
128        }
129    
130        /**
131         * Adds the header cell to the first row and adds to the second row a cell that spans all remaining rows
132         * @see org.kuali.kfs.sys.document.web.TableJoining#joinTable(java.util.List)
133         */
134        public void joinTable(List<AccountingLineTableRow> rows) {
135            final int remainingRowCount = rows.size() - 1;
136            
137            if (currentAmountField != null) {
138                rows.get(0).addCell(createHeaderCellForField(currentAmountField));
139                
140                AccountingLineTableCell currentCell = createCellForField(currentAmountField, currentAmountFieldDefinition);
141                currentCell.setRowSpan(remainingRowCount);
142                rows.get(1).addCell(currentCell);
143            }
144            if (baseAmountField != null) {
145                rows.get(0).addCell(createHeaderCellForField(baseAmountField));
146                
147                AccountingLineTableCell baseCell = createCellForField(baseAmountField, baseAmountFieldDefinition);
148                baseCell.setRowSpan(remainingRowCount);
149                rows.get(1).addCell(baseCell);
150            }
151            
152        }
153    
154        /**
155         * Does nothing - we don't have action blocks, like, ever
156         * @see org.kuali.kfs.sys.document.web.TableJoining#removeAllActionBlocks()
157         */
158        public void removeAllActionBlocks() {}
159    
160        /**
161         * Checks to see if either the current amount or the base amount are unviewable; if so, sets them to null
162         * @see org.kuali.kfs.sys.document.web.FieldTableJoining#removeUnviewableBlocks(java.util.Set)
163         */
164        public void removeUnviewableBlocks(Set<String> unviewableBlocks) {
165            if (isFieldUnviewable(currentAmountField, unviewableBlocks)) {
166                currentAmountField = null;
167            }
168            if (isFieldUnviewable(baseAmountField, unviewableBlocks)) {
169                baseAmountField = null;
170            }
171        }
172        
173        /**
174         * Determines if the given field is among the blocks which should not be viewable
175         * @param field the field to check for unviewability
176         * @param unviewableBlocks the names of all unviewable blocks
177         * @return true if the field should not be viewable, false if we can see it
178         */
179        protected boolean isFieldUnviewable(Field field, Set<String> unviewableBlocks) {
180            return field != null && unviewableBlocks.contains(field.getPropertyName());
181        }
182        
183        /**
184         * Creates a table cell with a renderable field inside
185         * @param field the field to create a cell for
186         * @return a cell that wraps the given field 
187         */
188        protected AccountingLineTableCell createCellForField(Field field, AccountingLineViewFieldDefinition definition) {
189            AccountingLineTableCell cell = new AccountingLineTableCell();
190            AccountingLineViewField renderableField = new AccountingLineViewField();
191            renderableField.setField(field);
192            renderableField.setDefinition(definition);
193            cell.addRenderableElement(renderableField);
194            return cell;
195        }
196        
197        /**
198         * Creates a header cell for the given field
199         * @param field the field to create a header cell for
200         * @return a header cell
201         */
202        protected AccountingLineTableCell createHeaderCellForField(Field field) {
203            AccountingLineTableCell headerCell = new AccountingLineTableCell();
204            headerCell.setRendersAsHeader(true);
205            headerCell.addRenderableElement(new LiteralHeaderLabel(field.getFieldLabel()));
206            return headerCell;
207        }
208    
209        /**
210         * @see org.kuali.kfs.sys.document.web.FieldTableJoining#performFieldTransformations(java.util.List, org.kuali.kfs.sys.businessobject.AccountingLine, java.util.Map, java.util.Map)
211         */
212        public void performFieldTransformations(List<AccountingLineFieldRenderingTransformation> fieldTransformations, AccountingLine accountingLine, Map unconvertedValues) {
213            for (AccountingLineFieldRenderingTransformation fieldTransformation : fieldTransformations) {
214                fieldTransformation.transformField(accountingLine, getCurrentAmountField(), getCurrentAmountFieldDefinition(), unconvertedValues);
215                fieldTransformation.transformField(accountingLine, getBaseAmountField(), getBaseAmountFieldDefinition(), unconvertedValues);
216            }
217        }
218    
219        /**
220         * Not used; returns null.
221         * @see org.kuali.kfs.sys.document.web.TableJoiningWithHeader#createHeaderLabel()
222         */
223        public HeaderLabel createHeaderLabel() {
224            return null;
225        }
226    
227        /**
228         * This field is never hidden
229         * @see org.kuali.kfs.sys.document.web.TableJoiningWithHeader#isHidden()
230         */
231        public boolean isHidden() {
232            return false;
233        }
234    
235        /**
236         * Gets the baseAmountField attribute. 
237         * @return Returns the baseAmountField.
238         */
239        public Field getBaseAmountField() {
240            return baseAmountField;
241        }
242    
243        /**
244         * Sets the baseAmountField attribute value.
245         * @param baseAmountField The baseAmountField to set.
246         */
247        public void setBaseAmountField(Field baseAmountField) {
248            this.baseAmountField = baseAmountField;
249        }
250    
251        /**
252         * Gets the currentAmountField attribute. 
253         * @return Returns the currentAmountField.
254         */
255        public Field getCurrentAmountField() {
256            return currentAmountField;
257        }
258    
259        /**
260         * Sets the currentAmountField attribute value.
261         * @param currentAmountField The currentAmountField to set.
262         */
263        public void setCurrentAmountField(Field currentAmountField) {
264            this.currentAmountField = currentAmountField;
265        }
266    
267        /**
268         * Gets the definition attribute. 
269         * @return Returns the definition.
270         */
271        public AccountingLineViewCurrentBaseAmountFieldDefinition getDefinition() {
272            return definition;
273        }
274    
275        /**
276         * Sets the definition attribute value.
277         * @param definition The definition to set.
278         */
279        public void setDefinition(AccountingLineViewCurrentBaseAmountFieldDefinition definition) {
280            this.definition = definition;
281        }
282    
283        /**
284         * Gets the baseAmountFieldDefinition attribute. 
285         * @return Returns the baseAmountFieldDefinition.
286         */
287        public AccountingLineViewFieldDefinition getBaseAmountFieldDefinition() {
288            return baseAmountFieldDefinition;
289        }
290    
291        /**
292         * Sets the baseAmountFieldDefinition attribute value.
293         * @param baseAmountFieldDefinition The baseAmountFieldDefinition to set.
294         */
295        public void setBaseAmountFieldDefinition(AccountingLineViewFieldDefinition baseAmountFieldDefinition) {
296            this.baseAmountFieldDefinition = baseAmountFieldDefinition;
297        }
298    
299        /**
300         * Gets the currentAmountFieldDefinition attribute. 
301         * @return Returns the currentAmountFieldDefinition.
302         */
303        public AccountingLineViewFieldDefinition getCurrentAmountFieldDefinition() {
304            return currentAmountFieldDefinition;
305        }
306    
307        /**
308         * Sets the currentAmountFieldDefinition attribute value.
309         * @param currentAmountFieldDefinition The currentAmountFieldDefinition to set.
310         */
311        public void setCurrentAmountFieldDefinition(AccountingLineViewFieldDefinition currentAmountFieldDefinition) {
312            this.currentAmountFieldDefinition = currentAmountFieldDefinition;
313        }
314    
315        /**
316         * @see org.kuali.kfs.sys.document.web.TableJoining#setEditableBlocks(java.util.Set)
317         */
318        public void setEditableBlocks(Set<String> editableBlocks) {
319            if (currentAmountField != null) {
320                setEditableField(currentAmountField, editableBlocks);
321            }
322            if (baseAmountField != null) {
323                setEditableField(baseAmountField, editableBlocks);
324            }
325            
326            if (baseAmountField != null && currentAmountField != null) {
327                if (baseAmountField.isReadOnly() && !currentAmountField.isReadOnly()) {
328                    currentAmountField.setReadOnly(false);
329                } 
330                else if (currentAmountField.isReadOnly() && !baseAmountField.isReadOnly()) {
331                    baseAmountField.setReadOnly(false);
332                }
333            }
334        }
335    
336        /**
337         * @see org.kuali.kfs.sys.document.web.ReadOnlyable#setEditable()
338         */
339        public void setEditable() {
340            if (currentAmountField != null) {
341                currentAmountField.setReadOnly(false);
342            }
343            
344            if (baseAmountField != null) {
345                baseAmountField.setReadOnly(false);
346            }
347        }
348        
349        /**
350         * Checks if the given field is named as an editableBlocks; if so, makes it editable
351         * @param field the field to check
352         * @param editableBlocks the names of all editable blocks
353         */
354        protected void setEditableField(Field field, Set<String> editableBlocks) {
355            if (field != null && editableBlocks.contains(field.getPropertyName())) {
356                field.setReadOnly(false);
357            }
358        }    
359    }