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 Rich Unger. Portions Copyright 1997-2000 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package org.netbeans.modules.xml.tree.nodes;

import java.util.*;
import java.text.*;
import org.w3c.dom.Attr;

/**
 * I guess that implementation could be replaced by org.openide.util.MapFormat.
 */
public class ElementTextFormatter extends java.text.Format
{
    public ElementTextFormatter()
    {
        super();
    }

    public void setPattern(String sPattern)
    {
        m_sPattern = sPattern;
    }

    public void setTagName(String sTagName)
    {
        m_sTagName = sTagName;
    }

    public void setAttributeNames(List attributeNames)
    {
        m_attributeNames = attributeNames;
    }

    public String format( List attributeNames,
                          String[] attributeValues)
    {
        setAttributeNames(attributeNames);
        StringBuffer strBuf = new StringBuffer();

        return format( attributeValues, strBuf, null ).toString();
    }

    public StringBuffer format( Object obj,
                                StringBuffer strBuf,
                                FieldPosition pos )

    {

        if( m_sPattern == null )
        {
            strBuf.append(m_sTagName);
        } else {
            printToBuffer( (String[])obj, strBuf, 0, m_sPattern.length()-1 );
        }

        return strBuf;
    }

    /**
     * Prints text from the pattern to the buffer, delegating
     * anything in {} to resolve()
     */
    protected void printToBuffer( String[] attributeValues,
                                    StringBuffer strBuf, int i, int j)
    {
        int firstBrace = m_sPattern.indexOf('{', i);
        if( firstBrace == -1 || firstBrace > j )
        {
            // just print the whole thing
            strBuf.append( m_sPattern.substring(i, j+1) );
        }
        else
        {
            int matchingBrace = matchingBrace(firstBrace);

            strBuf.append( m_sPattern.substring(i, firstBrace) );
            resolve( attributeValues, strBuf, firstBrace, matchingBrace );
            printToBuffer( attributeValues, strBuf, matchingBrace+1, j );
        }
    }

    /**
     * Renders a string of the format {attribute} or
     * {attribute, text if attribute non-null, text otherwise}
     */
    protected void resolve( String[] attributeValues, 
                             StringBuffer strBuf, int i, int j )
    {
        int comma = m_sPattern.indexOf( ',', i );

        if( comma == -1 || comma > j )
        {
            // {attribute}
            int iAttribute = indexOf( m_sPattern.substring(i+1, j).trim() );
            if( iAttribute != -1 )
            {
                strBuf.append(attributeValues[iAttribute]);
            }
        }
        else
        {
            // {attribute, text if attribute non-null, text otherwise }
            int iAttribute = indexOf( m_sPattern.substring(i+1, comma).trim() );
            if( iAttribute != -1 )
            {
                int x,y;

                if( attributeValues[iAttribute] != null &&
                    !attributeValues[iAttribute].equals("") )
                {
                    //print out the first argument
                    x = comma+1;
                    y = nextComma(comma)-1;
                }
                else
                {
                    //print out the second argument
                    x = nextComma(comma)+1;
                    y = matchingBrace(i)-1;
                }
                if( x<=y )
                {
                    printToBuffer(attributeValues, strBuf, x, y);
                }
            }
        }
    }

    /**
     * Gets the index of the next comma in the current argument list.
     * So, for a pattern like {foo, {bar, a, b}, baz} the
     * call nextComma(4) would return 17.
     */
    private int nextComma(int i)
    {
        int curOffset = i;

        while( true )
        {
            int nextOpen = m_sPattern.indexOf('{', curOffset+1);
            int nextComma = m_sPattern.indexOf(',', curOffset+1);

            if( nextComma == -1 )
            {
                // syntax error
                return -1;
            }
            else if( nextOpen < nextComma )
            {
                if( nextOpen == -1 )
                {
                    return nextComma;
                }
                int nextClose = matchingBrace(nextOpen);
                if( nextClose == -1 )
                {
                    // syntax error: unmatched '{'
                    return -1;
                }
                curOffset = nextClose;
            }
            else // nextComma < nextOpen
            {
                // found it
                return nextComma;
            }
        }
    }

    /**
     * Gets the index of the matching brace.  So, for a pattern
     * like {foo, {bar, a, b}, baz} the call matchingBrace(0)
     * would return 22.
     */
    private int matchingBrace(int i)
    {
        // start with one open brace (at index i), and
        // get to the point where we have no open braces.
        // the current offset at that point should be the
        // matching brace.
        int numOpen = 1;
        int curOffset = i;

        while( numOpen > 0 )
        {
            int nextOpen = m_sPattern.indexOf('{', curOffset+1);
            int nextClose = m_sPattern.indexOf('}', curOffset+1);
            if( nextClose == -1 )
            {
                // bad syntax: unmatched '{'
                return -1;
            }
            else if( nextOpen == -1 || nextClose < nextOpen )
            {
                curOffset = nextClose;
                numOpen--;
            }
            else // if( nextOpen < nextClose )
            {
                curOffset = nextOpen;
                numOpen++;
            }
        }

        return curOffset;
    }

    /** gets the index corresponding to an attribute name */
    private int indexOf(String sAttribute)
    {
        // could have done a binary search here for
        // faster asymtotic complexity, but for arrays of size
        // < 10, I'm not too worried.
        int i=0;
        Iterator iter = m_attributeNames.iterator();
        while( iter.hasNext() )
        {
            Attr attr = (Attr)iter.next();
            if( attr.getName().equals(sAttribute) )
            {
                return i;
            }
            i++;
        }
        return -1;
    }

    public Object parseObject( String source, ParsePosition status )
    {
        return null;
    }
                             

    protected String m_sPattern;
    protected String m_sTagName;
    protected List m_attributeNames;
}
... 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.