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.renderers;
017    
018    import java.io.IOException;
019    
020    import javax.servlet.jsp.JspException;
021    import javax.servlet.jsp.JspWriter;
022    import javax.servlet.jsp.PageContext;
023    import javax.servlet.jsp.tagext.Tag;
024    
025    import org.apache.struts.taglib.html.HiddenTag;
026    import org.kuali.kfs.sys.businessobject.AccountingLine;
027    import org.kuali.kfs.sys.context.SpringContext;
028    import org.kuali.kfs.sys.document.service.AccountingLineRenderingService;
029    import org.kuali.rice.kns.web.ui.Field;
030    import org.springframework.web.util.HtmlUtils;
031    
032    /**
033     * The renderer of an override field
034     */
035    public class OverrideFieldRenderer extends FieldRendererBase {
036        private LabelRenderer overrideLabelRenderer = new LabelRenderer();
037        private FieldRenderer overrideFieldRenderer;
038        private HiddenTag overrideHiddenTag = new HiddenTag();
039        private HiddenTag overrideNeededTag = new HiddenTag();
040        private HiddenTag overridePresentTag = new HiddenTag();
041        private boolean readOnly = false;
042        private String overrideNeededProperty;
043        private String overrideNeededValue;
044        private AccountingLine accountingLine;
045        private String storedFieldValue;
046    
047        /**
048         * We never render quick finders on these
049         * @see org.kuali.kfs.sys.document.web.renderers.FieldRenderer#renderQuickfinder()
050         */
051        public boolean renderQuickfinder() {
052            return false;
053        }
054    
055        /**
056         * Cleans up the tags used to display this field
057         * @see org.kuali.kfs.sys.document.web.renderers.FieldRendererBase#clear()
058         */
059        @Override
060        public void clear() {
061            super.clear();
062            overrideLabelRenderer.clear();
063            overrideFieldRenderer = null;
064            clearOverrideHiddenTag();
065            clearOverrideNeededTag();
066            overrideNeededProperty = null;
067            overrideNeededValue = null;
068            storedFieldValue = null;
069        }
070        
071        /**
072         * Cleans up the hidden that displays information for the override
073         */
074        protected void clearOverrideHiddenTag() {
075            overrideHiddenTag.setPageContext(null);
076            overrideHiddenTag.setParent(null);
077            overrideHiddenTag.setProperty(null);
078            overrideHiddenTag.setValue(null);
079            overridePresentTag.setPageContext(null);
080            overridePresentTag.setParent(null);
081            overridePresentTag.setProperty(null);
082            overridePresentTag.setValue(null);
083        }
084        
085        /**
086         * Cleans up the HiddenTag that renders override needed properties
087         */
088        protected void clearOverrideNeededTag() {
089            overrideNeededTag.setPageContext(null);
090            overrideNeededTag.setParent(null);
091            overrideNeededTag.setProperty(null);
092        }
093    
094        /**
095         * Also sets the overrideNeededProperty name
096         * @see org.kuali.kfs.sys.document.web.renderers.FieldRendererBase#setField(org.kuali.rice.kns.web.ui.Field)
097         */
098        @Override
099        public void setField(Field overrideField) {
100            super.setField(overrideField);
101            this.overrideNeededProperty = overrideField.getPropertyPrefix()+"."+overrideField.getPropertyName()+"Needed";
102            storedFieldValue = overrideField.getPropertyValue();
103            overrideField.setPropertyValue(null);
104        }
105    
106        /**
107         * Gets the readOnly attribute. 
108         * @return Returns the readOnly.
109         */
110        public boolean isReadOnly() {
111            return readOnly;
112        }
113    
114        /**
115         * Sets the readOnly attribute value.
116         * @param readOnly The readOnly to set.
117         */
118        public void setReadOnly(boolean readOnly) {
119            this.readOnly = readOnly;
120        }
121    
122        /**
123         * Gets the overrideNeededValue attribute. 
124         * @return Returns the overrideNeededValue.
125         */
126        public String getOverrideNeededValue() {
127            return overrideNeededValue;
128        }
129    
130        /**
131         * Sets the overrideNeededValue attribute value.
132         * @param overrideNeededValue The overrideNeededValue to set.
133         */
134        public void setOverrideNeededValue(String overrideNeededValue) {
135            this.overrideNeededValue = overrideNeededValue;
136        }
137    
138        /**
139         * Gets the accountingLine attribute. 
140         * @return Returns the accountingLine.
141         */
142        public AccountingLine getAccountingLine() {
143            return accountingLine;
144        }
145    
146        /**
147         * Sets the accountingLine attribute value.
148         * @param accountingLine The accountingLine to set.
149         */
150        public void setAccountingLine(AccountingLine accountingLine) {
151            this.accountingLine = accountingLine;
152        }
153    
154        /**
155         * Renders the override field and its associated override needed field
156         * @see org.kuali.kfs.sys.document.web.renderers.Renderer#render(javax.servlet.jsp.PageContext, javax.servlet.jsp.tagext.Tag)
157         */
158        public void render(PageContext pageContext, Tag parentTag) throws JspException {
159            if ((readOnly && getField().getPropertyValue().equals("Yes")) || overrideNeededValue.equals("Yes")) {
160                renderOverrideAsNonHidden(pageContext, parentTag);
161                if (!readOnly) {
162                    renderOverridePresent(pageContext, parentTag);
163                }
164            } else {
165            }
166       }
167        
168        /**
169         * @return the HTML for a line break
170         */
171        protected String buildLineBreak() {
172            return "<br />";
173        }
174        
175        /**
176         * @return the HTML for a non-breaking space
177         */
178        protected String buildNonBreakingSpace() {
179            return "&nbsp;";
180        }
181    
182        /**
183         * @return builds the opening of the span tag to go around the label
184         */
185        protected String buildLabelSpanOpening() {
186            return "<span style=\"font-weight: normal\">";
187        }
188        
189        /**
190         * @return builds the closing of the span tag to go around the label
191         */
192        protected String buildLabelSpanClosing() {
193            return "</span>";
194        }
195        
196        /**
197         * Renders the override field as non-hidden (probably a checkbox) 
198         * @param pageContext the page context to render to
199         * @param parentTag the tag requesting all this rendering
200         * @throws JspException thrown if rendering fails
201         */
202        protected void renderOverrideAsNonHidden(PageContext pageContext, Tag parentTag) throws JspException {
203            JspWriter out = pageContext.getOut();
204            try {
205                out.write(buildLineBreak());
206                openNoWrapSpan(pageContext, parentTag);
207                out.write(buildLabelSpanOpening());
208                overrideLabelRenderer.setLabel(getField().getFieldLabel());
209                overrideLabelRenderer.setRequired(true);
210                overrideLabelRenderer.setReadOnly(false);
211                overrideLabelRenderer.setLabelFor(getField().getPropertyPrefix()+"."+getField().getPropertyName());
212                overrideLabelRenderer.render(pageContext, parentTag);
213                out.write(buildLabelSpanClosing());
214                out.write(buildNonBreakingSpace());
215                overrideFieldRenderer =  readOnly ? new ReadOnlyRenderer() : SpringContext.getBean(AccountingLineRenderingService.class).getFieldRendererForField(getField(), accountingLine);
216                if (overrideFieldRenderer instanceof ReadOnlyRenderer) {
217                    ((ReadOnlyRenderer)overrideFieldRenderer).setShouldRenderInquiry(false);
218                    out.write(": "); // add a colon to make it prettier
219                    // populate the field again
220                    getField().setPropertyValue(storedFieldValue);
221                }
222                overrideFieldRenderer.setField(getField());
223                overrideFieldRenderer.setArbitrarilyHighTabIndex(getQuickfinderTabIndex());
224                overrideFieldRenderer.render(pageContext, parentTag);
225                closeNoWrapSpan(pageContext, parentTag);
226            }
227            catch (IOException ioe) {
228                throw new JspException("Difficulty rendering override field", ioe);
229            }
230        }
231        
232        /**
233         * Renders the override field as a hidden field
234         * @param pageContext the page context to render to
235         * @param parentTag the tag requesting all this rendering
236         * @throws JspException thrown if rendering fails
237         */
238        protected void renderOverrideAsHidden(PageContext pageContext, Tag parentTag) throws JspException {
239            overrideHiddenTag.setPageContext(pageContext);
240            overrideHiddenTag.setParent(parentTag);
241            overrideHiddenTag.setProperty(getField().getPropertyPrefix()+"."+getField().getPropertyName());
242            if (!readOnly && overrideNeededValue.equals("No")) {
243                overrideHiddenTag.setValue("No");
244            } else {
245                overrideHiddenTag.setValue(HtmlUtils.htmlEscape(getField().getPropertyValue()));
246            }
247            overrideHiddenTag.doStartTag();
248            overrideHiddenTag.doEndTag();
249        }
250        
251        /**
252         * Renders the override field as a hidden field
253         * @param pageContext the page context to render to
254         * @param parentTag the tag requesting all this rendering
255         * @throws JspException thrown if rendering fails
256         */
257        protected void renderOverridePresent(PageContext pageContext, Tag parentTag) throws JspException {
258            overridePresentTag.setPageContext(pageContext);
259            overridePresentTag.setParent(parentTag);
260            overridePresentTag.setProperty(getField().getPropertyPrefix()+"."+getField().getPropertyName()+".present");
261            overridePresentTag.setValue("I'm here yo!");
262            overridePresentTag.doStartTag();
263            overridePresentTag.doEndTag();
264        }
265        
266        /**
267         * Renders the overrideNeeded field (which is always hidden)
268         * @param pageContext the page context to render to
269         * @param parentTag the tag requesting all this rendering
270         * @throws JspException thrown if rendering fails
271         */
272        protected void renderOverrideNeededField(PageContext pageContext, Tag parentTag) throws JspException {
273            overrideNeededTag.setPageContext(pageContext);
274            overrideNeededTag.setParent(parentTag);
275            overrideNeededTag.setProperty(overrideNeededProperty);
276            overrideNeededTag.setValue(HtmlUtils.htmlEscape(overrideNeededValue));
277            overrideNeededTag.doStartTag();
278            overrideNeededTag.doEndTag();
279        }
280    }