/*  Copyright (c) 2000, 2002 by Oracle Corporation. All Rights Reserved. */

package oracle.portal.provider.v1.http; 
import oracle.portal.provider.v1.PortletRenderRequest; 

/**
 * <p>SelectiveRenderingFilter is an extension of HtmlFilter and is used
 * for rendering links inline on a selective basis. User can specify specific
 * properties of href for which inline rendering should be disabled. Two
 * properties <code>hrefFieldName</code> and <code>disableInlineRenderingID</code>
 * can be set through provider.xml and if a href contains an attribute given by
 * &lt;hrefFieldName> and value given by &lt;disableInlineRenderingID> it will
 * not be rendered inline.
 *
 */
public class SelectiveRenderingFilter extends HtmlFilter 
{ 
    
    //Value of <disableInlineRenderingID>
    private String mDisableInlineRenderingID = null; 
    
    //Value for <hrefFieldName> tag. Default is "id".
    private String mHrefFieldName = "id"; 
    
    /**
     * Gives ID value of href property for which inline rendering should be
     * disabled. 
     * @return HREF ID value which disables inline rendering.
     */
    public String getDisableInlineRenderingID() 
    { 
        return mDisableInlineRenderingID; 
    } 
    
    /**
     * Set method for <disableInlineRenderingID> tag in provider.xml
     * @param dIReneringID value to be looked for HRef attribute, for which
     * Inline Rendering should be disabled. Name of the attribute can be
     * specified by <code> &lt;hrefFieldName> </code> tag.
     */
    public void setDisableInlineRenderingID(String dIRenderingID) 
    { 
        mDisableInlineRenderingID = dIRenderingID; 
    } 
    
    /**
     * Set method for <hrefFieldName> tag in provider.xml
     * @param hrefFieldName Name of the attribute which is responsible for
     * disabling inline rendering of links. If specified none, "id" will be
     * used as default name.
     */
    public void setHrefFieldName(String hrefFieldName) 
    { 
        mHrefFieldName = hrefFieldName; 
    } 
    
    /**
     * Method returns href field name which is used for disabling inline
     * rendering.
     * @return Href field name.
     */
    public String getHrefFieldName() 
    { 
        return mHrefFieldName; 
    } 
    
    /**
     * Overrides super class's function. Introduces an additional check before
     * making the link render inline.
     */
    protected String addJavaScriptToLink(PortletRenderRequest pr, 
      StringBuffer htmlSource, String baseHref, 
      String tag, String attribute, 
      int debugLevel) 
    { 
        
        // Pointers used indicate start and end of tags and attributes, while
        //parsing
        int attribOffset,offset = 0; 
        int tagStart, tagEnd, attribStart, attribEnd; 
        int tagLength = tag.length(); 
        int attributeLength = attribute.length(); 
        int htmlLength = htmlSource.length(); 
        int extractedTagLength; 
        String hashedPortletRefName = UrlServicesUtils.hashString( 
        pr.getPortletReference().getName()); 
        
        // Extracted tag holder in uppercase.
        String extractedTag = ""; 
        String normalTag = ""; 
        
        //Contents Converted to uppercase. To overcome case-issues, while parsing.
        StringBuffer lowerHtmlSource = new StringBuffer( 
        htmlSource.toString().toLowerCase()); 
        do  
        { 
            
            // Content is parsed and the tag is extracted.
            attribOffset = 0; 
            tagStart = lowerHtmlSource.toString().indexOf(tag,offset); 
            if (tagStart ==- 1) 
            break; 
            offset = tagStart; 
            tagEnd = lowerHtmlSource.toString().indexOf('>' ,offset + tagLength); 
            if (tagEnd ==- 1) 
            break; 
            extractedTag = new String(lowerHtmlSource.toString().substring(tagStart,tagEnd + 1)); 
            normalTag = new String(htmlSource.toString().substring(tagStart,tagEnd + 1)); 
            extractedTagLength = extractedTag.length(); 
            
            //Check if the tag has ID = 1 attribute in it. If so, proceed to next
            //href.
            if ( ! isInlineRenderingEnabled(extractedTag)) 
            { 
                offset += extractedTag.length(); 
                continue; 
            } 
            
            // Location of attribute.
            attribStart = extractedTag.indexOf(attribute,attribOffset); 
            
            //If attribute exists, traverse till where its value begins.
            if (attribStart !=- 1) 
            { 
                attribOffset = attribStart + attributeLength; 
                while (extractedTag.charAt(attribOffset) == ' ' && attribOffset < extractedTagLength) 
                attribOffset++; 
                while (extractedTag.charAt(attribOffset) =='='&& attribOffset < extractedTagLength) 
                attribOffset++; 
                while (extractedTag.charAt(attribOffset) == ' ' && attribOffset < extractedTagLength) 
                attribOffset++; 
                while (extractedTag.charAt(attribOffset) == '\'' && attribOffset < extractedTagLength) 
                attribOffset++; 
                if (extractedTag.charAt(attribOffset) == '"') 
                attribOffset++; 
                offset = offset + attribOffset; 
                
                // Find the end of href
                int endOfAttribute = extractedTag.indexOf('"',attribOffset); 
                
                //check if attribute value ends with a '"'
                if (endOfAttribute ==- 1) 
                { 
                    endOfAttribute = extractedTag.indexOf(' ',attribOffset); 
                } 
                
                //If the attribute given is the last in this particualar tag ...
                if (endOfAttribute ==- 1) 
                { 
                    endOfAttribute = extractedTag.indexOf('>' ,attribOffset); 
                } 
                String attributeValue = normalTag.toString().substring( 
                attribOffset,endOfAttribute); 
                int iAttributeEnd = offset + attributeValue.length(); 
                StringBuffer temp = new StringBuffer(); 
                
                //Add javascript to this attribute value.
                temp.append("javascript:submitURL"); 
                temp.append(hashedPortletRefName); 
                temp.append("('"); 
                temp.append(attributeValue); 
                temp.append("')"); 
                htmlSource.replace(offset,iAttributeEnd,temp.toString()); 
                lowerHtmlSource.replace(offset,iAttributeEnd,temp.toString()); 
                htmlLength = htmlSource.length(); 
            } 
            else  
            { 
                offset = offset + extractedTagLength; 
            } 
        } while (true);
        return htmlSource.toString(); 
    } //end of addJavaScriptEvent
    
    /**
     * Checks if the link contains ID specified by the tag
     * disableInlineRenderingID. If true returns true, else false.
     * @return boolean ID for which link should not be rendered inline.
     */
    protected boolean isInlineRenderingEnabled(String tag) 
    { 
        String tempTag = tag.trim(); 
        String dID = getDisableInlineRenderingID().trim(); 
        String idToSearch = getHrefFieldName().trim() + "=\"" + dID + "\""; 
        
        //First search for id with double quotes in it. Example ... id="1"
        if ( tag.indexOf(idToSearch) !=- 1) 
        { 
            return false; 
        } 
        
        //Then for id with single quotes.
        idToSearch = "id='" + dID + "'"; 
        if (tag.indexOf(idToSearch) !=- 1) 
        return false; 
        
        //Finally id having no quotes.
        idToSearch = "id=" + dID; 
        if (tag.indexOf(idToSearch) !=- 1) 
        return false; 
        
        //Not found any, return false.
        return true; 
    } 
} 