alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 *                 Sun Public License Notice
 * 
 * The contents of this file are subject to the Sun Public License
 * Version 1.0 (the "License"). You may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.sun.com/
 * 
 * The Original Code is NetBeans. The Initial Developer of the Original
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package org.netbeans.modules.web.core.syntax;

import java.util.*;
import javax.swing.text.JTextComponent;
import javax.swing.text.BadLocationException;
import javax.swing.text.Caret;

import javax.servlet.jsp.tagext.TagInfo;
import javax.servlet.jsp.tagext.TagAttributeInfo;

import org.netbeans.editor.*;
import org.netbeans.editor.ext.*;
import org.netbeans.editor.ext.java.JavaSyntaxSupport;
import org.openide.util.NbBundle;

/**
* JSP completion support finder
*
* @author Petr Nejedly
* @version 1.00
*/

public class JspCompletionQuery implements CompletionQuery {
    
    protected CompletionQuery contentQuery;
    protected CompletionQuery scriptingQuery;
    
    public JspCompletionQuery(CompletionQuery contentQuery, CompletionQuery scriptingQuery ) {
        super();
        this.contentQuery = contentQuery;
        this.scriptingQuery = scriptingQuery;
    }

    /** Perform the query on the given component. The query usually
    * gets the component's document, the caret position and searches back
    * to find the last command start. Then it inspects the text up to the caret
    * position and returns the result.
    * @param component the component to use in this query.
    * @param offset position in the component's document to which the query will
    *   be performed. Usually it's a caret position.
    * @param support syntax-support that will be used during resolving of the query.
    * @return result of the query or null if there's no result.
    */
    public CompletionQuery.Result query(JTextComponent component, int offset, SyntaxSupport support) {
        
//System.err.println("--------------------------------Query called------------------------");

        BaseDocument doc = (BaseDocument)component.getDocument();
        JspSyntaxSupport sup = (JspSyntaxSupport)support.get(JspSyntaxSupport.class);

        try {
            // find last separator position

            //TokenItem item = sup.getTokenChain( offset, Math.min( offset+100, doc.getLength() )/*, false*/ );

            SyntaxElement elem = sup.getElementChain( offset );
//System.err.println("element = " + elem );
            
            if (elem == null)
                // this is a legal option, when I don't have anything to say just return null
                return null;
            
//System.err.println("JspCompetionQuery - element text = '" + elem.getImage() + "'");
            CompletionData jspData;
            switch (elem.getCompletionContext()) {
                // TAG COMPLETION
                case JspSyntaxSupport.TAG_COMPLETION_CONTEXT :
                    return queryJspTag(component, offset, sup, 
                        (SyntaxElement.Tag)elem);
                // ENDTAG COMPLETION
                case JspSyntaxSupport.ENDTAG_COMPLETION_CONTEXT :
                    jspData = queryJspEndTag(offset, sup, 
                        (SyntaxElement.EndTag)elem, doc);
//System.out.println(jspData.toString());
                    return new CompletionQuery.DefaultResult(component, 
                        NbBundle.getMessage (JspCompletionQuery.class, "CTL_JSP_Completion_Title"), jspData.completionItems, 
                        offset - jspData.removeLength, jspData.removeLength);
                // DIRECTIVE COMPLETION
                case JspSyntaxSupport.DIRECTIVE_COMPLETION_CONTEXT :
                    return queryJspDirective(component, offset, sup, 
                        (SyntaxElement.Directive)elem, doc);
                // CONTENT LANGUAGE
                case JspSyntaxSupport.CONTENTL_COMPLETION_CONTEXT :
                    // html results
                    CompletionQuery.Result contentLResult = null; 
                    contentLResult = (contentQuery == null) ? 
                        null :
                        contentQuery.query(component, offset, support);
                    // JSP tags results
                    jspData = queryJspTagInContent(offset, sup, (SyntaxElement.ContentL)elem, doc);
                    // JSP directive results
                    CompletionQuery.Result jspDirec = queryJspDirectiveInContent(component, offset, sup, doc);

                    //some presumptions
                    assert jspData != null : "queryJspTagInContent() cannot return null!"; //NOI18N
                    assert jspData.completionItems != null : "jsp tags completion data cannot be null!"; //NOI18N
                    assert jspDirec != null :"queryJspDirectiveInContent() cannot return null!"; //NOI18N
                    assert jspDirec.getData() != null : "jsp directive completion data cannot be null!"; //NOI18N
                    if(contentLResult != null) assert contentLResult.getData() != null : "html completion data cannot be null";  //NOI18N

                    //return null (do not popup completion) if there are no items in any of the completions
                    if(jspData.completionItems.isEmpty() && jspDirec.getData().isEmpty() &&
                       ((contentLResult == null) || contentLResult.getData().isEmpty())) return null;
                    
                    CompletionQuery.Result jspRes = new CompletionQuery.DefaultResult(component, 
                        NbBundle.getMessage (JspCompletionQuery.class, "CTL_JSP_Completion_Title"), jspData.completionItems, 
                        offset - jspData.removeLength, jspData.removeLength);
          
                    CompletionItem.DelegatingResult result = 
                        new CompletionItem.DelegatingResult(
                        NbBundle.getMessage (JspCompletionQuery.class, "CTL_JSP_Completion_Title")
                        );
                    
                    result.addResult(jspDirec);
                    result.addResult(jspRes);
                    result.addResult(contentLResult);
                    // PENDING merge with JSP results
                    return result;
                // SCRIPTING LANGUAGE
                case JspSyntaxSupport.SCRIPTINGL_COMPLETION_CONTEXT :
                    //get java CC completion query
                    CompletionQuery.Result scriptingLResult = (scriptingQuery == null) ?  null : scriptingQuery.query(component, offset, support);
                    
                    //add a jsp directive code completion items if the CC is invoken on a <% token
                    //find a token which I stand on 
                    TokenItem item = sup.getItemAtOrBefore(offset);
                    
                    //test whether it's a scriptlet delimiter (if the CC is invoken just after the <%
                    if (item != null && item.getTokenID() == JspTagTokenContext.SYMBOL2) {
                        //we are after <% => get tag directive CC items
                        CompletionQuery.Result jspDirectResult = queryJspDirectiveInContent(component, offset, sup, doc);
                    
                        //make a delegating completion result
                        CompletionItem.DelegatingResult delegatingCompletionResult = 
                            new CompletionItem.DelegatingResult(NbBundle.getMessage (JspCompletionQuery.class, "CTL_JSP_Completion_Title"));
                        
                        //add both results
                        delegatingCompletionResult.addResult(jspDirectResult);
                        delegatingCompletionResult.addResult(scriptingLResult);
                        
                        return delegatingCompletionResult;
                        
                    } else {
                        //CC is invoked somewhere in the middle of a scriptlet - use only Java CC items
                        return scriptingLResult;
                    }
            }

        } catch (BadLocationException e) {
            e.printStackTrace();
        }
        return null;
    }
    
    /** Gets a list of completion items for JSP tags.
    * @param component editor component
    * @param offset position of caret
    * @param sup JSP syntax support
    * @param elem syntax element representing the current JSP tag
    * @return list of completion items
    */
    protected CompletionQuery.Result queryJspTag(JTextComponent component, int offset, 
        JspSyntaxSupport sup, SyntaxElement.Tag elem) throws BadLocationException {
        BaseDocument doc = (BaseDocument)component.getDocument();
        // find the current item
        List compItems = new ArrayList();
        int removeLength = 0;
        
        TokenItem item = sup.getItemAtOrBefore(offset);
        if (item == null) {
            return result (component, offset, new CompletionData(compItems, 0));
        }
        
        TokenID id = item.getTokenID();
        String tokenPart = item.getImage().substring(0, offset - item.getOffset());
        String token = item.getImage().trim();
        
        // SYMBOL
        if (id == JspTagTokenContext.SYMBOL) {
            if (tokenPart.equals("<")) { // NOI18N
                // just after the beginning of the tag
                removeLength = 0;
                addTagPrefixItems(sup, compItems, sup.getTagPrefixes("")); // NOI18N
            }
            if (tokenPart.endsWith("\"")) { // NOI18N
                // try an attribute value
                String attrName = findAttributeForValue(sup, item);
                if (attrName != null) {
                    AttributeValueSupport attSup = 
                        AttributeValueSupport.getSupport(true, elem.getName(), attrName);
                    if (attSup != null) {
                        return attSup.getResult (component, offset, sup, elem, ""); // NOI18N
                    }
                }
            }
        }
        
        // TAG
        if (id == JspTagTokenContext.TAG) {
            // inside a JSP tag name
            if (isBlank(tokenPart.charAt(tokenPart.length() - 1))) {
                // blank character - do attribute completion
                removeLength = 0;
                addAttributeItems(sup, compItems, elem, sup.getTagAttributes(elem.getName(), ""), null); // NOI18N
            }
            else {
                int colonIndex = tokenPart.indexOf(":"); // NOI18N
                if (colonIndex == -1) {
                    removeLength = tokenPart.length();
                    addTagPrefixItems(sup, compItems, sup.getTagPrefixes(tokenPart));
                }
                else {
                    String prefix = tokenPart.substring(0, colonIndex);
                    removeLength = tokenPart.length();
                    addTagPrefixItems(sup, compItems, prefix, sup.getTags(tokenPart), elem);
                }
            }
        }
        
        // ATTRIBUTE
        if (id == JspTagTokenContext.ATTRIBUTE) {
            // inside or after an attribute
            if (isBlank(tokenPart.charAt(tokenPart.length() - 1))) {
                // blank character - do attribute completion
                removeLength = 0;
                addAttributeItems(sup, compItems, elem, sup.getTagAttributes(elem.getName(), ""), null); // NOI18N
            }
            else {
                removeLength = tokenPart.length();
                addAttributeItems(sup, compItems, elem, sup.getTagAttributes(elem.getName(), tokenPart), token);
            }
        }
        
        // ATTRIBUTE VALUE
        if (id == JspTagTokenContext.ATTR_VALUE) {
            // inside or after an attribute
            String valuePart = tokenPart;
            item = item.getPrevious();
            while ((item != null) && (item.getTokenID() == JspTagTokenContext.ATTR_VALUE)) {
                valuePart = item.getImage() + valuePart;
                item = item.getPrevious();
            }
            // get rid of the first quote
            valuePart = valuePart.substring(1);
            removeLength = valuePart.length ();
            String attrName = findAttributeForValue(sup, item);
            if (attrName != null) {
                AttributeValueSupport attSup = 
                    AttributeValueSupport.getSupport(true, elem.getName(), attrName);
                if (attSup != null) {
                    return attSup.getResult (component, offset, sup, elem, valuePart);
                }
            }
            
        }
        
        return result (component, offset, new CompletionData(compItems, removeLength));
    }
    
    /** Gets a list of completion items for JSP tags.
    * @param offset position of caret
    * @param sup JSP syntax support
    * @param elem syntax element representing the current JSP tag
    * @return list of completion items
    */
    protected CompletionData queryJspEndTag(int offset, JspSyntaxSupport sup, 
        SyntaxElement.EndTag elem, BaseDocument doc) throws BadLocationException {
        // find the current item
        List compItems = new ArrayList();
        int removeLength = 0;
        
        TokenItem item = sup.getItemAtOrBefore(offset);
        if (item == null) {
            return new CompletionData(compItems, 0);
        }
        
        TokenID id = item.getTokenID();
        String tokenPart = item.getImage().substring(0, offset - item.getOffset());

        removeLength = tokenPart.length();
        return new CompletionData (sup.getPossibleEndTags (offset, tokenPart), removeLength);
    }
    
    /** Gets a list of completion items for JSP directives.
    * @param component editor component
    * @param offset position of caret
    * @param sup JSP syntax support
    * @param elem syntax element representing the current JSP tag
    * @return list of completion items
    */
    protected CompletionQuery.Result queryJspDirective(JTextComponent component, int offset, JspSyntaxSupport sup, 
        SyntaxElement.Directive elem, BaseDocument doc) throws BadLocationException {
        // find the current item
        List compItems = new ArrayList();
        int removeLength = 0;
        
        TokenItem item = sup.getItemAtOrBefore(offset);
        if (item == null) {
            return result (component, offset, new CompletionData(compItems, 0));
        }
        
        TokenID id = item.getTokenID();
        String tokenPart = item.getImage().substring(0, offset - item.getOffset());
        String token = item.getImage().trim();

        // SYMBOL
        if (id == JspTagTokenContext.SYMBOL) {
            if (tokenPart.startsWith("<")) { // NOI18N
                //calculate a position of the potential replacement
                removeLength = tokenPart.length() - 1;
                addDirectiveItems(sup, compItems, sup.getDirectives("")); // NOI18N
            }
            if (tokenPart.endsWith("\"")) { // NOI18N
                // try an attribute value
                String attrName = findAttributeForValue(sup, item);
                if (attrName != null) {
                    AttributeValueSupport attSup = 
                        AttributeValueSupport.getSupport(false, elem.getName(), attrName);
                    if (attSup != null) {
                        return attSup.getResult (component, offset, sup, elem, ""); // NOI18N
                    }
                }
            }
        }
        
        // DIRECTIVE
        if (id == JspTagTokenContext.TAG) {
            // inside a JSP directive name
            if (isBlank(tokenPart.charAt(tokenPart.length() - 1))) {
                TokenItem prevItem = item.getPrevious ();
                TokenID prevId = prevItem.getTokenID ();
                String prevToken = prevItem.getImage().trim();
                if (prevId == JspTagTokenContext.TAG
                ||  prevId == JspTagTokenContext.ATTR_VALUE) {
                    // blank character - do attribute completion
                    removeLength = 0;
                    addAttributeItems(sup, compItems, elem, sup.getDirectiveAttributes(elem.getName(), ""), null); // NOI18N
                }
                else if (prevId == JspTagTokenContext.SYMBOL && prevToken.equals("<%@")) { // NOI18N
                    // just after the beginning of the directive
                    removeLength = tokenPart.length() + 2;
                    addDirectiveItems(sup, compItems, sup.getDirectives("")); // NOI18N
                }
            }
            else {
                boolean add = true;
                //I need to get the whitespace token length before the tag name 
                int whitespaceLength = 0;
                TokenItem prevItem = item.getPrevious ();
                TokenID prevId = prevItem.getTokenID ();
                //test whether there is a space before the currently completed tagname
                if(prevId == JspTagTokenContext.TAG && "".equals(prevItem.getImage().trim())) //try to trim the token image - just for sure since I am not absolutely sure if the TAG_ID is only for whitespaces in this case.
                    whitespaceLength = prevItem.getImage().length();
                    
                
                List list = sup.getDirectives(tokenPart);
                if (list.size() == 1){
                    Object directive = list.get(0);
                    //is the cc invoce just after the directive?
                    if (directive instanceof TagInfo && ((TagInfo)directive).getTagName().equals(tokenPart))
                        add = false;
                }
                if (add){    
                    removeLength = whitespaceLength + tokenPart.length() + 2;
                    addDirectiveItems(sup, compItems, list);
                }
            }
        }
        
        // ATTRIBUTE
        if (id == JspTagTokenContext.ATTRIBUTE) {
            // inside or after an attribute
            if (isBlank(tokenPart.charAt(tokenPart.length() - 1))) {
                // blank character - do attribute completion
                removeLength = 0;
                addAttributeItems(sup, compItems, elem, sup.getDirectiveAttributes(elem.getName(), ""), null); // NOI18N
            }
            else {
                removeLength = tokenPart.length();
                addAttributeItems(sup, compItems, elem, sup.getDirectiveAttributes(elem.getName(), tokenPart), token);
            }
        }
        
        // ATTRIBUTE VALUE
        if (id == JspTagTokenContext.ATTR_VALUE) {
            // inside or after an attribute
            String valuePart = tokenPart;
            item = item.getPrevious();
            while ((item != null) && (item.getTokenID() == JspTagTokenContext.ATTR_VALUE)) {
                valuePart = item.getImage() + valuePart;
                item = item.getPrevious();
            }
            // get rid of the first quote
            valuePart = valuePart.substring(1);
            removeLength = valuePart.length ();
            String attrName = findAttributeForValue(sup, item);
            if (attrName != null) {
                AttributeValueSupport attSup = 
                    AttributeValueSupport.getSupport(false, elem.getName(), attrName);
                if (attSup != null) {
                    return attSup.getResult (component, offset, sup, elem, valuePart); // NOI18N
                }
            }
            
        }
        
        return new CompletionQuery.DefaultResult(component,
            NbBundle.getMessage (JspCompletionQuery.class, "CTL_JSP_Completion_Title"), compItems,
            offset - removeLength, removeLength);
    }
    
    
    protected CompletionData queryJspTagInContent(int offset, JspSyntaxSupport sup, 
        SyntaxElement.ContentL elem, BaseDocument doc) throws BadLocationException {
        // find the current item
        List compItems = new ArrayList();
        int removeLength = 0;
        
        TokenItem item = sup.getItemAtOrBefore(offset);
        if (item == null) {
            return new CompletionData(compItems, 0);
        }
        
        String tokenPart = item.getImage().substring(0, offset - item.getOffset());
        int ltIndex = tokenPart.lastIndexOf('<');
        if (ltIndex != -1) {
            tokenPart = tokenPart.substring(ltIndex + 1);
        }
        while (ltIndex == -1) {
            item = item.getPrevious();
            if (item == null) {
                return new CompletionData(compItems, 0);
            }
            String newImage = item.getImage();
            ltIndex = newImage.lastIndexOf('<');
            if (ltIndex != -1)
                tokenPart = newImage.substring(ltIndex + 1) + tokenPart;
            else {
                tokenPart = newImage + tokenPart;
            }
            if (tokenPart.length() > 20) {
                return new CompletionData(compItems, 0);
            }
        }
        // we found ltIndex, tokenPart is either the part of the token we are looking for
        // or '/' + what we are looking for
        if (tokenPart.startsWith("/")) { // NOI18N
            tokenPart = tokenPart.substring(1);
            compItems = sup.getPossibleEndTags (offset, tokenPart);
        }
        else {
            addTagPrefixItems(sup, compItems, sup.getTagPrefixes(tokenPart));
        }
        removeLength = tokenPart.length();
        return new CompletionData(compItems, removeLength);
    }
    
    protected CompletionQuery.Result queryJspDirectiveInContent(JTextComponent component, int offset, JspSyntaxSupport sup, BaseDocument doc) throws BadLocationException {
        // find the current item
        List compItems = new ArrayList();
        int removeLength = 0;
        
        TokenItem item = sup.getItemAtOrBefore(offset);
        if (item == null) {
            //return empty completion result
            return result (component, offset, new CompletionData(compItems, 0));
        }

        String tokenPart = item.getImage().substring(0, offset - item.getOffset());
        //if (tokenPart.lastIndexOf('<') == -1 || !tokenPart.equals("<")) -- the condition is strange - the some should be !tokenPart.equals("<")
        if(!tokenPart.equals("<") && !tokenPart.equals("<%")) // NOI18N
            //return empty completion result
            return result (component, offset, new CompletionData(compItems, 0));
        
        //the removeLenght has to be set 0 if the CC is invoked right after <, 1 for <%
        if("<%".equals(tokenPart)) removeLength = 1; else removeLength = 0; // NOI18N
        
        addDirectiveItems(sup, compItems, sup.getDirectives("")); // NOI18N
        return new CompletionQuery.DefaultResult(component,
            NbBundle.getMessage (JspCompletionQuery.class, "CTL_JSP_Completion_Title"), compItems,
            offset - removeLength, removeLength);
    }
    
    private boolean isBlank(char c) {
        return c == ' ';
    }
    
    /** Finds an attribute name, assuming that the item is either
     * SYMBOL after the attribute name or ATTR_VALUE after this attribute name. 
     * May return null if nothing found.
     */
    protected String findAttributeForValue(JspSyntaxSupport sup, TokenItem item) {
        // get before any ATTR_VALUE
        while ((item != null) && (item.getTokenID() == JspTagTokenContext.ATTR_VALUE))
            item = item.getPrevious();
        // now collect the symbols
        String symbols = ""; // NOI18N
        while ((item != null) && (item.getTokenID() == JspTagTokenContext.SYMBOL)) {
            symbols = item.getImage() + symbols;
            item = item.getPrevious();
        }
        // two quotes at the end are not allowed
        if (!sup.isValueBeginning(symbols)) 
            return null;
        String attributeName = ""; // NOI18N
        while ((item != null) && (item.getTokenID() == JspTagTokenContext.ATTRIBUTE)) {
            attributeName = item.getImage() + attributeName;
            item = item.getPrevious();
        }
        if (attributeName.trim().length() > 0)
            return attributeName.trim();
        return null;
    }
    
    /** Adds to the list of items compItemList new TagPrefix items with prefix 
     * prefix for list of tag names tagStringItems. 
     * @param set - SyntaxElement.Tag
     */
    private void addTagPrefixItems(JspSyntaxSupport sup, List compItemList, String prefix, List tagStringItems, SyntaxElement.Tag set) {
        for (int i = 0; i < tagStringItems.size(); i++) {
            Object item = tagStringItems.get(i);
            if (item instanceof TagInfo)
                compItemList.add(new CompletionItem.PrefixTag(prefix , (TagInfo)item, set));
            else
                compItemList.add(new CompletionItem.PrefixTag(prefix + ":" + (String)item)); // NOI18N
        }
    }

    /** Adds to the list of items compItemList new TagPrefix items with prefix 
     * prefix for list of tag names tagStringItems. 
     */
    private void addTagPrefixItems(JspSyntaxSupport sup, List compItemList, String prefix, List tagStringItems) {
        addTagPrefixItems(sup, compItemList, prefix, tagStringItems, (SyntaxElement.Tag)null);
    }
    
    /** Adds to the list of items compItemList new TagPrefix items for prefix list
     * prefixStringItems, followed by all possible tags for the given prefixes. 
     */
    private void addTagPrefixItems(JspSyntaxSupport sup, List compItemList, List prefixStringItems) {
        for (int i = 0; i < prefixStringItems.size(); i++) {
            String prefix = (String)prefixStringItems.get(i);
            // now get tags for this prefix
            List tags = sup.getTags(prefix, ""); // NOI18N
            for (int j = 0; j < tags.size(); j++) {
                Object item = tags.get(j);
                if (item instanceof TagInfo)
                    compItemList.add(new CompletionItem.PrefixTag(prefix , (TagInfo)item));
                else
                    compItemList.add(new CompletionItem.PrefixTag(prefix + ":" + (String)item)); // NOI18N
            }
        }
    }

    /** Adds to the list of items compItemList new TagPrefix items with prefix 
     * prefix for list of tag names tagStringItems. 
     */
    private void addDirectiveItems(JspSyntaxSupport sup, List compItemList, List directiveStringItems) {
        for (int i = 0; i < directiveStringItems.size(); i++) {
            Object item = directiveStringItems.get(i);
            if(item instanceof TagInfo){
                TagInfo ti = (TagInfo) item;
                compItemList.add(new CompletionItem.Directive( ti.getTagName(), ti));
            }
            else
                compItemList.add(new CompletionItem.Directive( (String)item));
        }
    }
    
    /** Adds to the list of items compItemList new Attribute items. 
     * Only those which are not already in tagDir 
     * @param sup the syntax support
     * @param compItemList list to add to
     * @param tagDir tag or directive element
     * @param attributeItems list of strings containing suitable values (String or TagAttributeInfo)
     * @param currentAttr current attribute, may be null
     */
    private void addAttributeItems(JspSyntaxSupport sup, List compItemList, 
        SyntaxElement.TagDirective tagDir, List attributeItems, String currentAttr) {
        for (int i = 0; i < attributeItems.size(); i++) {
            Object item = attributeItems.get(i);
            String attr;
            if (item instanceof TagAttributeInfo)
                attr = ((TagAttributeInfo)item).getName ();
            else
                attr = (String)item;
            boolean isThere = tagDir.getAttributes().keySet().contains(attr);
            if (!isThere || attr.equals(currentAttr) || 
                (currentAttr != null && attr.startsWith(currentAttr) && attr.length()>currentAttr.length() && !isThere)) {
                if (item instanceof TagAttributeInfo)
                    //XXX This is hack for fixing issue #45302 - CC is to aggressive.
                    //The definition of the tag and declaration doesn't allow
                    //define something like "prefix [uri | tagdir]". In the future
                    //it should be rewritten definition of declaration, which allow
                    //to do it.
                    if ("taglib".equals(tagDir.getName())){ //NOI18N
                        if (attr.equals("prefix")  //NOI18N
                            || (attr.equals("uri") && !tagDir.getAttributes().keySet().contains("tagdir")) //NOI18N
                            || (attr.equals("tagdir") && !tagDir.getAttributes().keySet().contains("uri"))) //NOI18N
                            compItemList.add(new CompletionItem.Attribute((TagAttributeInfo)item));
                    }
                    else {
                        compItemList.add(new CompletionItem.Attribute((TagAttributeInfo)item));
                    }
                else
                    compItemList.add(new CompletionItem.Attribute((String)item));
            }
        }
    }
    
    private CompletionQuery.Result result (JTextComponent component, int offset, CompletionData complData) {
        return new CompletionQuery.DefaultResult(component, 
                        NbBundle.getMessage (JspCompletionQuery.class, "CTL_JSP_Completion_Title"), complData.completionItems, 
                        offset - complData.removeLength, complData.removeLength);
    }
    
    /** Class which encapsulates a list of completion items and length of 
     * the part which should be replaced. */
    public static class CompletionData {
        
        public List completionItems;
        public int removeLength;
        
        public CompletionData(List items, int length) {
            this.completionItems = items;
            this.removeLength = length;
        }
        
        public String toString() {
            StringBuffer sb = new StringBuffer();
            sb.append("------ completion items, remove " + removeLength + " : ----------\n"); // NOI18N
            for (int i = 0; i < completionItems.size(); i++) {
                CompletionQuery.ResultItem item = 
                    (CompletionQuery.DefaultResultItem)completionItems.get(i);
                sb.append(item.getItemText());
                sb.append("\n");   // NOI18N
            }
            return sb.toString();
        }

        
    }

}
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.