001/*
002 * Copyright 2008 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 */
016package org.kuali.ole.sys.document.web.renderers;
017
018import java.io.IOException;
019
020import javax.servlet.jsp.JspException;
021import javax.servlet.jsp.JspWriter;
022import javax.servlet.jsp.PageContext;
023import javax.servlet.jsp.tagext.Tag;
024
025import org.apache.commons.lang.StringUtils;
026import org.kuali.ole.sys.OLEConstants;
027import org.kuali.ole.sys.context.SpringContext;
028import org.kuali.rice.core.api.config.property.ConfigurationService;
029import org.kuali.rice.core.api.util.KeyValue;
030import org.kuali.rice.kns.lookup.HtmlData.AnchorHtmlData;
031import org.kuali.rice.kns.web.ui.Field;
032
033/**
034 * Renderer which displays a read only field
035 */
036public class ReadOnlyRenderer extends FieldRendererBase {
037    private boolean shouldRenderInquiry = true;
038    
039    /**
040     * @see org.kuali.ole.sys.document.web.renderers.Renderer#render(javax.servlet.jsp.PageContext, javax.servlet.jsp.tagext.Tag)
041     */
042    @Override
043    public void render(PageContext pageContext, Tag parentTag) throws JspException {
044        JspWriter out = pageContext.getOut();
045
046        try {
047            String value = discoverRenderValue();
048            out.write(buildBeginSpan());
049            
050            if (!StringUtils.isEmpty(value)) {
051                if (shouldRenderInquiryLink()) {
052                    out.write(buildBeginInquiryLink());
053                }                
054                out.write(value);                
055                if (shouldRenderInquiryLink()) {
056                    out.write(buildEndInquiryLink());
057                }                                
058            } else {
059                out.write(buildNonBreakingSpace());
060            }
061            
062            out.write(buildEndSpan());
063        }
064        catch (IOException ioe) {
065            throw new JspException("Difficulty rendering read only field", ioe);
066        }
067    }
068
069    /**
070     * Clears the persisting tag.
071     * @see org.kuali.ole.sys.document.web.renderers.FieldRendererBase#clear()
072     */
073    @Override
074    public void clear() {
075        super.clear();
076    }
077
078    /**
079     * Generates the HTML for the opening span tag to wrap the displayed value
080     * @param propertyPrefix the property path from the form the business object being rendered
081     * @return the HTML for the opening span 
082     */
083    protected String buildBeginSpan() {
084        StringBuilder beginSpan = new StringBuilder();        
085        beginSpan.append("<span id=\"");
086        beginSpan.append(getFieldName());
087        beginSpan.append(".div\">");        
088        return beginSpan.toString();
089    }
090    
091    /**
092     * Generates the HTML for the closing span tag to wrap the displayed value
093     * @return the HTML for the closing span
094     */
095    protected String buildEndSpan() {
096        return "</span>";
097    }
098    
099    /**
100     * Builds the opening anchor tag to make the displayed read only value open up an inquiry screen
101     * @return the HTML for the opening inquiry anchor tag
102     */
103    protected String buildBeginInquiryLink() {
104        StringBuilder beginInquiryLink = new StringBuilder();
105        
106        if (getField().getInquiryURL() instanceof AnchorHtmlData) {
107            AnchorHtmlData htmlData = (AnchorHtmlData) getField().getInquiryURL();
108
109            if(htmlData.getHref().startsWith("http")) {
110                beginInquiryLink.append("<a href=\"");
111            }
112            else {
113            beginInquiryLink.append("<a href=\"");
114                beginInquiryLink.append(SpringContext.getBean(ConfigurationService.class).getPropertyValueAsString(OLEConstants.APPLICATION_URL_KEY));
115            beginInquiryLink.append("/kr/");
116            }
117
118            beginInquiryLink.append(htmlData.getHref());
119            beginInquiryLink.append("\" title=\"");
120            beginInquiryLink.append(htmlData.getTitle());
121            beginInquiryLink.append("\" target=\"blank\">");
122            
123        }
124        
125        return beginInquiryLink.toString();
126    }
127    
128    /**
129     * Builds the closing anchor tag for the inquiry link
130     * @return the HTML for the closing inquiry anchor tag
131     */
132    protected String buildEndInquiryLink() {
133        if (getField().getInquiryURL() instanceof AnchorHtmlData) {
134            return "</a>";
135        }
136        return "";
137    }
138    
139    /**
140     * Determines if this read only field should attempt to display the inquiry link around the rendered value
141     * @return true if the inquiry link should be rendered, false otherwise
142     */
143    protected boolean shouldRenderInquiryLink() {
144        return getField().getInquiryURL() != null && !StringUtils.isBlank(((AnchorHtmlData)getField().getInquiryURL()).getHref()) && isInquirableValue(getField().getPropertyValue())  && shouldRenderInquiry;
145    }
146    
147    /**
148     * Determines if the given property value is worthy of having an inquiry for it
149     * @param propertyValue the value of the property to potentially render an inquiry for
150     * @return true if the value is inquirable; false otherwise
151     */
152    protected boolean isInquirableValue(String propertyValue) {
153        return !StringUtils.isBlank(propertyValue) && !propertyValue.matches("^-*$");
154    }
155    
156    /**
157     * Sets the shouldRenderInquiry attribute value.
158     * @param shouldRenderInquiry The shouldRenderInquiry to set.
159     */
160    public void setShouldRenderInquiry(boolean shouldRenderInquiry) {
161        this.shouldRenderInquiry = shouldRenderInquiry;
162    }
163
164    /**
165     * Dropdowns are typically fields with codes, which may be close to meaningless, with more explanative labels.  Therefore,
166     * fields which are drop downs should display the label instead
167     * @return the label for the chosen key on the field if possible; otherwise, an empty String
168     */
169    protected String getValueForDropDown() {
170        for (Object keyLabelPairAsObject : getField().getFieldValidValues()) {
171            final KeyValue keyLabelPair = (KeyValue)keyLabelPairAsObject;
172            if (getField().getPropertyValue().equalsIgnoreCase(keyLabelPair.getKey().toString())) {
173                return keyLabelPair.getValue();
174            }
175        }
176        return null;
177    }
178    
179    /**
180     * An algorithm to discover the actual read only value to render.  If this is a drop down, it finds the renderable value for the drop down;
181     * if the value is unavailable, it searches for the property in unconverted values
182     * @return the value to display
183     * 
184     * KRAD Conversion: Discovering fields values
185     */
186    protected String discoverRenderValue() {
187        String value = getField().getPropertyValue();
188        if (getField().getFieldType().equals(Field.DROPDOWN) && !StringUtils.isEmpty(value)) {
189            value = getValueForDropDown();
190        }
191        
192        return value;
193    }
194    
195    /**
196     * @return the HTML for a non-breaking space, so the box isn't all empty
197     */
198    protected String buildNonBreakingSpace() {
199        return "&nbsp;";
200    }
201
202    /**
203     * Nope, no quick finder here
204     * @see org.kuali.ole.sys.document.web.renderers.FieldRenderer#renderQuickfinder()
205     */
206    @Override
207    public boolean renderQuickfinder() {
208        return false;
209    }
210
211    /**
212     * @see org.kuali.ole.sys.document.web.renderers.FieldRendererBase#closeNoWrapSpan(javax.servlet.jsp.PageContext, javax.servlet.jsp.tagext.Tag)
213     */
214    @Override
215    public void closeNoWrapSpan(PageContext pageContext, Tag parentTag) throws JspException {
216        // do nothing - read onlys don't need "no wrap"
217    }
218
219    /**
220     * @see org.kuali.ole.sys.document.web.renderers.FieldRendererBase#openNoWrapSpan(javax.servlet.jsp.PageContext, javax.servlet.jsp.tagext.Tag)
221     */
222    @Override
223    public void openNoWrapSpan(PageContext pageContext, Tag parentTag) throws JspException {
224        // do nothing - read onlys don't need "no wrap"
225    }
226    
227}