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.HashSet;
019 import java.util.List;
020 import java.util.Map;
021 import java.util.Set;
022
023 import org.kuali.kfs.sys.businessobject.AccountingLine;
024 import org.kuali.kfs.sys.document.datadictionary.AccountingLineViewLinesDefinition;
025 import org.kuali.kfs.sys.document.service.AccountingLineFieldRenderingTransformation;
026
027 /**
028 * Represents the rendering for a bunch of elements within the accounting line view
029 */
030 public class AccountingLineViewLines implements TableJoining, ReadOnlyable {
031 private List<AccountingLineViewLineFillingElement> elements;
032 private AccountingLineViewLinesDefinition definition;
033
034 /**
035 * Gets the definition attribute.
036 * @return Returns the definition.
037 */
038 public AccountingLineViewLinesDefinition getDefinition() {
039 return definition;
040 }
041 /**
042 * Sets the definition attribute value.
043 * @param definition The definition to set.
044 */
045 public void setDefinition(AccountingLineViewLinesDefinition definition) {
046 this.definition = definition;
047 }
048
049 /**
050 * @see org.kuali.kfs.sys.document.web.AccountingLineViewRenderableElementContainer#getName()
051 */
052 public String getName() {
053 return definition.getElementName();
054 }
055 /**
056 * Gets the elements attribute.
057 * @return Returns the elements.
058 */
059 public List<AccountingLineViewLineFillingElement> getElements() {
060 return elements;
061 }
062 /**
063 * Sets the elements attribute value.
064 * @param elements The elements to set.
065 */
066 public void setElements(List<AccountingLineViewLineFillingElement> lines) {
067 this.elements = lines;
068 }
069
070 /**
071 * The interesting implementation...how many does it need? Let's see here...one for each child row...
072 * yes...that's right, one table row for each child row
073 * @see org.kuali.kfs.sys.document.web.AccountingLineViewRenderableElement#getRequestedRowCount()
074 */
075 public int getRequestedRowCount() {
076 int sum = 0;
077 for (AccountingLineViewLineFillingElement line : elements) {
078 sum += line.getRequestedRowCount();
079 }
080 return sum;
081 }
082
083 /**
084 * Throws an exception - lines should never be asked to join rows
085 * @see org.kuali.kfs.sys.document.web.TableJoining#joinRow(org.kuali.kfs.sys.document.web.AccountingLineTableRow)
086 */
087 public void joinRow(AccountingLineTableRow headerRow, AccountingLineTableRow row) {
088 throw new IllegalStateException("Error in line rendering algorithm - lines cannot join a single row.");
089 }
090
091 /**
092 * Attempts to have each child line join the rows that have been given
093 * @see org.kuali.kfs.sys.document.web.TableJoining#joinTable(java.util.List)
094 */
095 public void joinTable(List<AccountingLineTableRow> rows) {
096 final int maxExpectedLineWidth = getMaxExpectedLineWidth();
097
098 int count = 0;
099 for (AccountingLineViewLineFillingElement line : elements) {
100 AccountingLineTableRow headerRow = rows.get(count);
101
102 if (line.getRequestedRowCount() > 1) {
103 line.joinRow(headerRow, rows.get(count+1));
104 padOutOrStretchCells(line, maxExpectedLineWidth, headerRow, rows.get(count+1));
105
106 count += 2;
107 } else {
108 line.joinRow(headerRow, null);
109 padOutOrStretchCells(line, maxExpectedLineWidth, headerRow, null);
110
111 count += 1;
112 }
113 }
114 }
115
116 /**
117 * Either pads out out the given table rows with an empty cell or stretches the cell to fill the whole line
118 * @param line the line joining the table
119 * @param maxExpectedLineWidth the expected width, in cell count, of the line
120 * @param headerRow the first row to add padding out to
121 * @param row the second row to add padding out to - if we're only filling one row, this will be null
122 */
123 protected void padOutOrStretchCells(AccountingLineViewLineFillingElement line, int maxExpectedLineWidth, AccountingLineTableRow headerRow, AccountingLineTableRow row) {
124 final int shorterThanMax = maxExpectedLineWidth - line.getDisplayingFieldWidth();
125 if (shorterThanMax > 0) {
126 if (line.shouldStretchToFillLine() && headerRow.getChildCellCount() == 1) {
127 headerRow.getCells().get(0).setColSpan(maxExpectedLineWidth);
128 if (row != null) {
129 row.getCells().get(0).setColSpan(maxExpectedLineWidth);
130 }
131 } else {
132 PlaceHoldingLayoutElement placeHolder = new PlaceHoldingLayoutElement(shorterThanMax);
133 placeHolder.joinRow(headerRow, row);
134 }
135 }
136 }
137
138 /**
139 * @see org.kuali.kfs.sys.document.web.ReadOnlyable#readOnlyize()
140 */
141 public void readOnlyize() {
142 for (AccountingLineViewLineFillingElement line : elements) {
143 line.readOnlyize();
144 }
145 }
146
147 /**
148 * @see org.kuali.kfs.sys.document.web.ReadOnlyable#isReadOnly()
149 */
150 public boolean isReadOnly() {
151 for (AccountingLineViewLineFillingElement line : elements) {
152 if (!line.isReadOnly()) {
153 return false;
154 }
155 }
156 return true;
157 }
158
159 /**
160 * @see org.kuali.kfs.sys.document.web.TableJoining#removeAllActionBlocks()
161 */
162 public void removeAllActionBlocks() {
163 for (AccountingLineViewLineFillingElement line : elements) {
164 line.removeAllActionBlocks();
165 }
166 }
167
168 /**
169 * @see org.kuali.kfs.sys.document.web.TableJoining#removeUnviewableBlocks(java.util.Set)
170 */
171 public void removeUnviewableBlocks(Set<String> unviewableBlocks) {
172 Set<AccountingLineViewLineFillingElement> linesToRemove = new HashSet<AccountingLineViewLineFillingElement>();
173 for (AccountingLineViewLineFillingElement line : elements) {
174 if (unviewableBlocks.contains(line.getName())) {
175 linesToRemove.add(line);
176 } else {
177 line.removeUnviewableBlocks(unviewableBlocks);
178 }
179 }
180 elements.removeAll(linesToRemove);
181 }
182
183 /**
184 * @see org.kuali.kfs.sys.document.web.TableJoining#performFieldTransformation(org.kuali.kfs.sys.document.service.AccountingLineFieldRenderingTransformation, org.kuali.kfs.sys.businessobject.AccountingLine, java.util.Map, java.util.Map)
185 */
186 public void performFieldTransformations(List<AccountingLineFieldRenderingTransformation> fieldTransformations, AccountingLine accountingLine, Map unconvertedValues) {
187 for (AccountingLineViewLineFillingElement line : elements) {
188 line.performFieldTransformations(fieldTransformations, accountingLine, unconvertedValues);
189 }
190 }
191
192 /**
193 * @return the maximum expected width of any of the child line elements in cells
194 */
195 public int getMaxExpectedLineWidth() {
196 int maxWidth = 0;
197 for (AccountingLineViewLineFillingElement line: elements) {
198 int width = line.getDisplayingFieldWidth();
199 if (width > maxWidth) {
200 maxWidth = width;
201 }
202 }
203 return maxWidth;
204 }
205
206 /**
207 * Shuffles the responsibility to the child lines
208 * @see org.kuali.kfs.sys.document.web.TableJoining#readOnlyizeReadOnlyBlocks(java.util.Set)
209 */
210 public void readOnlyizeReadOnlyBlocks(Set<String> readOnlyBlocks) {
211 for (AccountingLineViewLineFillingElement line : elements) {
212 line.readOnlyizeReadOnlyBlocks(readOnlyBlocks);
213 }
214 }
215
216 /**
217 * @see org.kuali.kfs.sys.document.web.TableJoining#setEditableBlocks(java.util.Set)
218 */
219 public void setEditableBlocks(Set<String> editableBlocks) {
220 for (AccountingLineViewLineFillingElement line : elements) {
221 line.setEditableBlocks(editableBlocks);
222 }
223 }
224
225 /**
226 * @see org.kuali.kfs.sys.document.web.ReadOnlyable#setEditable()
227 */
228 public void setEditable() {
229 for (AccountingLineViewLineFillingElement line : elements) {
230 line.setEditable();
231 }
232 }
233 }