@Test
  public void parameters() throws Throwable {
    // @formatter:off
    String json =
        "[\"vcard\","
            + "["
            + "[\"prop\", { \"a\": \"one\", \"b\": [\"two\"], \"c\": [\"three\", \"four\"] }, \"text\", \"value\"]"
            + "]"
            + "]";
    // @formatter:on

    JCardRawReader reader = createReader(json);
    JCardDataStreamListener listener = mock(JCardDataStreamListener.class);

    reader.readNext(listener);

    VCardParameters expected = new VCardParameters();
    expected.put("a", "one");
    expected.put("b", "two");
    expected.put("c", "three");
    expected.put("c", "four");

    verify(listener).beginVCard();
    verify(listener)
        .readProperty(null, "prop", expected, VCardDataType.TEXT, JCardValue.single("value"));
    verifyNoMoreInteractions(listener);
  }
  @Test
  public void prepareParameters() {
    VCardPropertyScribeImpl m =
        new VCardPropertyScribeImpl() {
          @Override
          protected void _prepareParameters(
              TestProperty property, VCardParameters copy, VCardVersion version, VCard vcard) {
            copy.put("PARAM", "value");
          }
        };

    TestProperty property = new TestProperty("value");
    VCardParameters copy = m.prepareParameters(property, V4_0, new VCard());

    assertNotSame(property.getParameters(), copy);
    assertEquals("value", copy.first("PARAM"));
  }
  private U parseContentType(String value, VCardParameters parameters, VCardVersion version) {
    switch (version) {
      case V2_1:
      case V3_0:
        // get the TYPE parameter
        String type = parameters.getType();
        if (type != null) {
          return _mediaTypeFromTypeParameter(type);
        }
        break;
      case V4_0:
        // get the MEDIATYPE parameter
        String mediaType = parameters.getMediaType();
        if (mediaType != null) {
          return _mediaTypeFromMediaTypeParameter(mediaType);
        }
        break;
    }

    // look for a file extension in the property value
    String extension = getFileExtension(value);
    return (extension == null) ? null : _mediaTypeFromFileExtension(extension);
  }
  private T parse(
      String value,
      VCardDataType dataType,
      VCardParameters parameters,
      VCardVersion version,
      List<String> warnings) {
    U contentType = parseContentType(value, parameters, version);

    switch (version) {
      case V2_1:
      case V3_0:
        // parse as URL
        if (dataType == VCardDataType.URL || dataType == VCardDataType.URI) {
          return _newInstance(value, contentType);
        }

        // parse as binary
        Encoding encodingSubType = parameters.getEncoding();
        if (encodingSubType == Encoding.BASE64 || encodingSubType == Encoding.B) {
          return _newInstance(Base64.decodeBase64(value), contentType);
        }

        break;
      case V4_0:
        try {
          // parse as data URI
          DataUri uri = new DataUri(value);
          contentType = _mediaTypeFromMediaTypeParameter(uri.getContentType());
          return _newInstance(uri.getData(), contentType);
        } catch (IllegalArgumentException e) {
          // not a data URI
        }
        break;
    }

    return cannotUnmarshalValue(value, version, warnings, contentType);
  }
示例#5
0
  /**
   * Parses the next line of the vCard file.
   *
   * @return the next line or null if there are no more lines
   * @throws InvalidVersionException if a VERSION property with an invalid value is encountered
   * @throws VCardParseException if a line cannot be parsed
   * @throws IOException if there's a problem reading from the input stream
   */
  public VCardRawLine readLine() throws IOException {
    String line = reader.readLine();
    if (line == null) {
      return null;
    }

    String group = null;
    String propertyName = null;
    VCardParameters parameters = new VCardParameters();
    String value = null;

    char escapeChar = 0; // is the next char escaped?
    boolean inQuotes = false; // are we inside of double quotes?
    StringBuilder buffer = new StringBuilder();
    String curParamName = null;
    for (int i = 0; i < line.length(); i++) {
      char ch = line.charAt(i);

      if (escapeChar != 0) {
        // this character was escaped
        if (escapeChar == '\\') {
          if (ch == '\\') {
            buffer.append(ch);
          } else if (ch == 'n' || ch == 'N') {
            // newlines appear as "\n" or "\N" (see RFC 2426 p.7)
            buffer.append(NEWLINE);
          } else if (ch == '"' && version != VCardVersion.V2_1) {
            // double quotes don't need to be escaped in 2.1 parameter values because they have no
            // special meaning
            buffer.append(ch);
          } else if (ch == ';' && version == VCardVersion.V2_1) {
            // semi-colons can only be escaped in 2.1 parameter values (see section 2 of specs)
            // if a 3.0/4.0 param value has semi-colons, the value should be surrounded in double
            // quotes
            buffer.append(ch);
          } else {
            // treat the escape character as a normal character because it's not a valid escape
            // sequence
            buffer.append(escapeChar).append(ch);
          }
        } else if (escapeChar == '^') {
          if (ch == '^') {
            buffer.append(ch);
          } else if (ch == 'n') {
            buffer.append(NEWLINE);
          } else if (ch == '\'') {
            buffer.append('"');
          } else {
            // treat the escape character as a normal character because it's not a valid escape
            // sequence
            buffer.append(escapeChar).append(ch);
          }
        }
        escapeChar = 0;
        continue;
      }

      if (ch == '\\' || (ch == '^' && version != VCardVersion.V2_1 && caretDecodingEnabled)) {
        // an escape character was read
        escapeChar = ch;
        continue;
      }

      if (ch == '.' && group == null && propertyName == null) {
        // set the group
        group = buffer.toString();
        buffer.setLength(0);
        continue;
      }

      if ((ch == ';' || ch == ':') && !inQuotes) {
        if (propertyName == null) {
          // property name
          propertyName = buffer.toString();
        } else {
          // parameter value
          String paramValue = buffer.toString();
          if (version == VCardVersion.V2_1) {
            // 2.1 allows whitespace to surround the "=", so remove it
            paramValue = StringUtils.ltrim(paramValue);
          }
          parameters.put(curParamName, paramValue);
          curParamName = null;
        }
        buffer.setLength(0);

        if (ch == ':') {
          // the rest of the line is the property value
          if (i < line.length() - 1) {
            value = line.substring(i + 1);
          } else {
            value = "";
          }
          break;
        }
        continue;
      }

      if (ch == ',' && !inQuotes && version != VCardVersion.V2_1) {
        // multi-valued parameter
        parameters.put(curParamName, buffer.toString());
        buffer.setLength(0);
        continue;
      }

      if (ch == '=' && curParamName == null) {
        // parameter name
        String paramName = buffer.toString();
        if (version == VCardVersion.V2_1) {
          // 2.1 allows whitespace to surround the "=", so remove it
          paramName = StringUtils.rtrim(paramName);
        }
        curParamName = paramName;
        buffer.setLength(0);
        continue;
      }

      if (ch == '"' && version != VCardVersion.V2_1) {
        // 2.1 doesn't use the quoting mechanism
        inQuotes = !inQuotes;
        continue;
      }

      buffer.append(ch);
    }

    if (propertyName == null || value == null) {
      throw new VCardParseException(line);
    }

    if ("VERSION".equalsIgnoreCase(propertyName)) {
      VCardVersion version = VCardVersion.valueOfByStr(value);
      if (version == null) {
        throw new InvalidVersionException(value, line);
      }
      this.version = version;
    }

    return new VCardRawLine(group, propertyName, parameters, value);
  }
  @Override
  protected void _prepareParameters(
      T property, VCardParameters copy, VCardVersion version, VCard vcard) {
    MediaTypeParameter contentType = property.getContentType();
    if (contentType == null) {
      contentType = new MediaTypeParameter(null, null, null);
    }

    if (property.getUrl() != null) {
      copy.setEncoding(null);

      switch (version) {
        case V2_1:
          copy.setType(contentType.getValue());
          copy.setMediaType(null);
          break;
        case V3_0:
          copy.setType(contentType.getValue());
          copy.setMediaType(null);
          break;
        case V4_0:
          copy.setMediaType(contentType.getMediaType());
          break;
      }

      return;
    }

    if (property.getData() != null) {
      copy.setMediaType(null);

      switch (version) {
        case V2_1:
          copy.setEncoding(Encoding.BASE64);
          copy.setType(contentType.getValue());
          break;
        case V3_0:
          copy.setEncoding(Encoding.B);
          copy.setType(contentType.getValue());
          break;
        case V4_0:
          copy.setEncoding(null);
          // don't null out TYPE, it could be set to "home", "work", etc
          break;
      }

      return;
    }
  }