FileDocCategorySizeDatePackage
VCardParserImpl_V30.javaAPI DocAndroid 5.1 API12330Thu Mar 12 22:22:54 GMT 2015com.android.vcard

VCardParserImpl_V30

public class VCardParserImpl_V30 extends VCardParserImpl_V21

Basic implementation achieving vCard 3.0 parsing.

This class inherits vCard 2.1 implementation since technically they are similar, while specifically there's logical no relevance between them. So that developers are not confused with the inheritance, {@link VCardParser_V30} does not inherit {@link VCardParser_V21}, while {@link VCardParserImpl_V30} inherits {@link VCardParserImpl_V21}.

hide

Fields Summary
private static final String
LOG_TAG
private String
mPreviousLine
private boolean
mEmittedAgentWarning
Constructors Summary
public VCardParserImpl_V30()


      
        super();
    
public VCardParserImpl_V30(int vcardType)

        super(vcardType);
    
Methods Summary
protected java.lang.StringencodeParamValue(java.lang.String paramValue)
Encode a param value using UTF-8.

        return VCardUtils.convertStringCharset(
                paramValue, VCardConfig.DEFAULT_INTERMEDIATE_CHARSET, "UTF-8");
    
protected java.lang.StringgetBase64(java.lang.String firstString)
This is only called from handlePropertyValue(), which has already read the first line of this property. With v3.0, the getNonEmptyLine() routine has already concatenated all following continuation lines. The routine is implemented in the V21 parser to concatenate v2.1 style data blocks, but is unnecessary here.

        return firstString;
    
protected java.util.SetgetKnownPropertyNameSet()

        return VCardParser_V30.sKnownPropertyNameSet;
    
protected java.lang.StringgetLine()

        if (mPreviousLine != null) {
            String ret = mPreviousLine;
            mPreviousLine = null;
            return ret;
        } else {
            return mReader.readLine();
        }
    
protected java.lang.StringgetNonEmptyLine()
vCard 3.0 requires that the line with space at the beginning of the line must be combined with previous line.

        String line;
        StringBuilder builder = null;
        while ((line = mReader.readLine()) != null) {
            // Skip empty lines in order to accomodate implementations that
            // send line termination variations such as \r\r\n.
            if (line.length() == 0) {
                continue;
            } else if (line.charAt(0) == ' " || line.charAt(0) == '\t") {
                // RFC 2425 describes line continuation as \r\n followed by
                // a single ' ' or '\t' whitespace character.
                if (builder == null) {
                    builder = new StringBuilder();
                }
                if (mPreviousLine != null) {
                    builder.append(mPreviousLine);
                    mPreviousLine = null;
                }
                builder.append(line.substring(1));
            } else {
                if (builder != null || mPreviousLine != null) {
                    break;
                }
                mPreviousLine = line;
            }
        }

        String ret = null;
        if (builder != null) {
            ret = builder.toString();
        } else if (mPreviousLine != null) {
            ret = mPreviousLine;
        }
        mPreviousLine = line;
        if (ret == null) {
            throw new VCardException("Reached end of buffer.");
        }
        return ret;
    
protected intgetVersion()

        return VCardConfig.VERSION_30;
    
protected java.lang.StringgetVersionString()

        return VCardConstants.VERSION_V30;
    
protected voidhandleAgent(VCardProperty property)

        // The way how vCard 3.0 supports "AGENT" is completely different from vCard 2.1.
        //
        // e.g.
        // AGENT:BEGIN:VCARD\nFN:Joe Friday\nTEL:+1-919-555-7878\n
        //  TITLE:Area Administrator\, Assistant\n EMAIL\;TYPE=INTERN\n
        //  ET:jfriday@host.com\nEND:VCARD\n
        //
        // TODO: fix this.
        //
        // issue:
        //  vCard 3.0 also allows this as an example.
        //
        // AGENT;VALUE=uri:
        //  CID:JQPUBLIC.part3.960129T083020.xyzMail@host3.com
        //
        // This is not vCard. Should we support this?
        //
        // Just ignore the line for now, since we cannot know how to handle it...
        if (!mEmittedAgentWarning) {
            Log.w(LOG_TAG, "AGENT in vCard 3.0 is not supported yet. Ignore it");
            mEmittedAgentWarning = true;
        }
    
protected voidhandleAnyParam(VCardProperty propertyData, java.lang.String paramName, java.lang.String paramValue)

        splitAndPutParam(propertyData, paramName, paramValue);
    
protected voidhandleParamWithoutName(VCardProperty property, java.lang.String paramValue)

        handleType(property, paramValue);
    
protected voidhandleParams(VCardProperty propertyData, java.lang.String params)
vCard 3.0 allows iana-token as paramType, while vCard 2.1 does not.

        try {
            super.handleParams(propertyData, params);
        } catch (VCardException e) {
            // maybe IANA type
            String[] strArray = params.split("=", 2);
            if (strArray.length == 2) {
                handleAnyParam(propertyData, strArray[0], strArray[1]);
            } else {
                // Must not come here in the current implementation.
                throw new VCardException(
                        "Unknown params value: " + params);
            }
        }
    
protected voidhandleType(VCardProperty property, java.lang.String paramValue)

        splitAndPutParam(property, VCardConstants.PARAM_TYPE, paramValue);
    
protected java.lang.StringmaybeUnescapeCharacter(char ch)

        return unescapeCharacter(ch);
    
protected java.lang.StringmaybeUnescapeText(java.lang.String text)
ESCAPED-CHAR = "\\" / "\;" / "\," / "\n" / "\N") ; \\ encodes \, \n or \N encodes newline ; \; encodes ;, \, encodes , Note: Apple escapes ':' into '\:' while does not escape '\'

        return unescapeText(text);
    
protected booleanreadBeginVCard(boolean allowGarbage)

        // TODO: vCard 3.0 supports group.
        return super.readBeginVCard(allowGarbage);
    
private voidsplitAndPutParam(VCardProperty property, java.lang.String paramName, java.lang.String paramValue)
Splits parameter values into pieces in accordance with vCard 3.0 specification and puts pieces into mInterpreter.

        // "comma,separated:inside.dquote",pref
        //   -->
        // - comma,separated:inside.dquote
        // - pref
        //
        // Note: Though there's a code, we don't need to take much care of
        // wrongly-added quotes like the example above, as they induce
        // parse errors at the top level (when splitting a line into parts).
        StringBuilder builder = null;  // Delay initialization.
        boolean insideDquote = false;
        final int length = paramValue.length();
        for (int i = 0; i < length; i++) {
            final char ch = paramValue.charAt(i);
            if (ch == '"") {
                if (insideDquote) {
                    // End of Dquote.
                    property.addParameter(paramName, encodeParamValue(builder.toString()));
                    builder = null;
                    insideDquote = false;
                } else {
                    if (builder != null) {
                        if (builder.length() > 0) {
                            // e.g.
                            // pref"quoted"
                            Log.w(LOG_TAG, "Unexpected Dquote inside property.");
                        } else {
                            // e.g.
                            // pref,"quoted"
                            // "quoted",pref
                            property.addParameter(paramName, encodeParamValue(builder.toString()));
                        }
                    }
                    insideDquote = true;
                }
            } else if (ch == '," && !insideDquote) {
                if (builder == null) {
                    Log.w(LOG_TAG, "Comma is used before actual string comes. (" +
                            paramValue + ")");
                } else {
                    property.addParameter(paramName, encodeParamValue(builder.toString()));
                    builder = null;
                }
            } else {
                // To stop creating empty StringBuffer at the end of parameter,
                // we delay creating this object until this point.
                if (builder == null) {
                    builder = new StringBuilder();
                }
                builder.append(ch);
            }
        }
        if (insideDquote) {
            // e.g.
            // "non-quote-at-end
            Log.d(LOG_TAG, "Dangling Dquote.");
        }
        if (builder != null) {
            if (builder.length() == 0) {
                Log.w(LOG_TAG, "Unintended behavior. We must not see empty StringBuilder " +
                        "at the end of parameter value parsing.");
            } else {
                property.addParameter(paramName, encodeParamValue(builder.toString()));
            }
        }
    
public static java.lang.StringunescapeCharacter(char ch)

        if (ch == 'n" || ch == 'N") {
            return "\n";
        } else {
            return String.valueOf(ch);
        }
    
public static java.lang.StringunescapeText(java.lang.String text)

        StringBuilder builder = new StringBuilder();
        final int length = text.length();
        for (int i = 0; i < length; i++) {
            char ch = text.charAt(i);
            if (ch == '\\" && i < length - 1) {
                final char next_ch = text.charAt(++i);
                if (next_ch == 'n" || next_ch == 'N") {
                    builder.append("\n");
                } else {
                    builder.append(next_ch);
                }
            } else {
                builder.append(ch);
            }
        }
        return builder.toString();