FileDocCategorySizeDatePackage
ValueResourceParser.javaAPI DocAndroid 1.5 API8501Wed May 06 22:41:10 BST 2009com.android.layoutlib.utils

ValueResourceParser

public final class ValueResourceParser extends DefaultHandler
SAX handler to parser value resource files.

Fields Summary
private static final String
NODE_RESOURCES
private static final String
NODE_ITEM
private static final String
ATTR_NAME
private static final String
ATTR_TYPE
private static final String
ATTR_PARENT
private static final String
RES_STYLE
private static final String
RES_ATTR
private static final String
DEFAULT_NS_PREFIX
private static final int
DEFAULT_NS_PREFIX_LEN
private boolean
inResources
private int
mDepth
private StyleResourceValue
mCurrentStyle
private ResourceValue
mCurrentValue
private IValueResourceRepository
mRepository
private final boolean
mIsFramework
Constructors Summary
public ValueResourceParser(IValueResourceRepository repository, boolean isFramework)

    
         
        mRepository = repository;
        mIsFramework = isFramework;
    
Methods Summary
public voidcharacters(char[] ch, int start, int length)

        if (mCurrentValue != null) {
            String value = mCurrentValue.getValue();
            if (value == null) {
                mCurrentValue.setValue(new String(ch, start, length));
            } else {
                mCurrentValue.setValue(value + new String(ch, start, length));
            }
        }
    
public voidendElement(java.lang.String uri, java.lang.String localName, java.lang.String qName)

        if (mCurrentValue != null) {
            mCurrentValue.setValue(trimXmlWhitespaces(mCurrentValue.getValue()));
        }
        
        if (inResources && qName.equals(NODE_RESOURCES)) {
            inResources = false;
        } else if (mDepth == 2) {
            mCurrentValue = null;
            mCurrentStyle = null;
        } else if (mDepth == 3) {
            mCurrentValue = null;
        }
        
        mDepth--;
        super.endElement(uri, localName, qName);
    
public voidstartElement(java.lang.String uri, java.lang.String localName, java.lang.String qName, org.xml.sax.Attributes attributes)

        try {
            mDepth++;
            if (inResources == false && mDepth == 1) {
                if (qName.equals(NODE_RESOURCES)) {
                    inResources = true;
                }
            } else if (mDepth == 2 && inResources == true) {
                String type;
                
                // if the node is <item>, we get the type from the attribute "type"
                if (NODE_ITEM.equals(qName)) {
                    type = attributes.getValue(ATTR_TYPE);
                } else {
                    // the type is the name of the node.
                    type = qName;
                }

                if (type != null) {
                    if (RES_ATTR.equals(type) == false) {
                        // get the resource name
                        String name = attributes.getValue(ATTR_NAME);
                        if (name != null) {
                            if (RES_STYLE.equals(type)) {
                                String parent = attributes.getValue(ATTR_PARENT);
                                mCurrentStyle = new StyleResourceValue(type, name, parent, mIsFramework);
                                mRepository.addResourceValue(type, mCurrentStyle);
                            } else {
                                mCurrentValue = new ResourceValue(type, name, mIsFramework);
                                mRepository.addResourceValue(type, mCurrentValue);
                            }
                        }
                    }
                }
            } else if (mDepth == 3 && mCurrentStyle != null) {
                // get the resource name
                String name = attributes.getValue(ATTR_NAME);
                if (name != null) {
                    // the name can, in some cases, contain a prefix! we remove it.
                    if (name.startsWith(DEFAULT_NS_PREFIX)) {
                        name = name.substring(DEFAULT_NS_PREFIX_LEN);
                    }
    
                    mCurrentValue = new ResourceValue(null, name, mIsFramework);
                    mCurrentStyle.addItem(mCurrentValue);
                }
            }
        } finally {
            super.startElement(uri, localName, qName, attributes);
        }
    
public static java.lang.StringtrimXmlWhitespaces(java.lang.String value)

        if (value == null) {
            return null;
        }

        // look for carriage return and replace all whitespace around it by just 1 space.
        int index;
        
        while ((index = value.indexOf('\n")) != -1) {
            // look for whitespace on each side
            int left = index - 1;
            while (left >= 0) {
                if (Character.isWhitespace(value.charAt(left))) {
                    left--;
                } else {
                    break;
                }
            }
            
            int right = index + 1;
            int count = value.length();
            while (right < count) {
                if (Character.isWhitespace(value.charAt(right))) {
                    right++;
                } else {
                    break;
                }
            }
            
            // remove all between left and right (non inclusive) and replace by a single space.
            String leftString = null;
            if (left >= 0) {
                leftString = value.substring(0, left + 1);
            }
            String rightString = null;
            if (right < count) {
                rightString = value.substring(right);
            }
            
            if (leftString != null) {
                value = leftString;
                if (rightString != null) {
                    value += " " + rightString;
                }
            } else {
                value = rightString != null ? rightString : "";
            }
        }
        
        // now we un-escape the string
        int length = value.length();
        char[] buffer = value.toCharArray();
        
        for (int i = 0 ; i < length ; i++) {
            if (buffer[i] == '\\" && i + 1 < length) {
                if (buffer[i+1] == 'u") {
                    if (i + 5 < length) {
                        // this is unicode char \u1234
                        int unicodeChar = Integer.parseInt(new String(buffer, i+2, 4), 16);
                        
                        // put the unicode char at the location of the \
                        buffer[i] = (char)unicodeChar;
    
                        // offset the rest of the buffer since we go from 6 to 1 char
                        if (i + 6 < buffer.length) {
                            System.arraycopy(buffer, i+6, buffer, i+1, length - i - 6);
                        }
                        length -= 5;
                    }
                } else {
                    if (buffer[i+1] == 'n") {
                        // replace the 'n' char with \n
                        buffer[i+1] = '\n";
                    }
                    
                    // offset the buffer to erase the \
                    System.arraycopy(buffer, i+1, buffer, i, length - i - 1);
                    length--;
                }
            }
        }
        
        return new String(buffer, 0, length);