private static void parseTitle(Topic.Builder topicBuilder, Element ele) {
    ele = ele.select(".item_title > a").get(0);
    Preconditions.checkState(ele.tagName().equals("a"));
    String url = ele.attr("href");

    topicBuilder.setId(Topic.getIdFromUrl(url));
    topicBuilder.setTitle(ele.html());
  }
  private static Topic parseItemForNode(Element item, Node node) {
    final Elements list = item.children();

    final Topic.Builder topicBuilder = new Topic.Builder();
    parseMember(topicBuilder, list.get(0));

    final Element ele = list.get(2);
    parseTitle(topicBuilder, ele);
    parseInfo(topicBuilder, ele, node);

    parseReplyCount(topicBuilder, list.get(3));

    return topicBuilder.createTopic();
  }
 private static void parseReplyTime(Topic.Builder topicBuilder, TextNode textNode) {
   final String text = textNode.text();
   final Matcher matcher = PATTERN_REPLY_TIME.matcher(text);
   if (!matcher.find()) {
     throw new FatalException("match reply time for topic failed: " + text);
   }
   final String time = matcher.group(1);
   topicBuilder.setReplyTime(time);
 }
 private static void parseReplyCount(Topic.Builder topicBuilder, Element ele) {
   final Elements children = ele.children();
   final int count;
   if (children.size() > 0) {
     final String numStr = ele.child(0).text();
     count = Integer.parseInt(numStr);
   } else {
     // do not have reply yet
     count = 0;
   }
   topicBuilder.setReplyCount(count);
 }
  static void parseMember(Topic.Builder builder, Element ele) {
    final Member.Builder memberBuilder = new Member.Builder();

    // get member url
    ele = ele.child(0);
    Preconditions.checkState(ele.tagName().equals("a"));
    final String url = ele.attr("href");
    memberBuilder.setUsername(Member.getNameFromUrl(url));

    // get member avatar
    final Avatar.Builder avatarBuilder = new Avatar.Builder();
    ele = ele.child(0);
    Preconditions.checkState(ele.tagName().equals("img"));
    avatarBuilder.setUrl(ele.attr("src"));
    memberBuilder.setAvatar(avatarBuilder.createAvatar());

    builder.setMember(memberBuilder.createMember());
  }
  private static void parseInfo(Topic.Builder topicBuilder, Element ele, Node node) {
    ele = ele.select(".small").get(0);

    boolean hasNode;
    if (node == null) {
      hasNode = false;
      final Elements nodeEle = ele.select("> a");
      node = parseNode(nodeEle.get(0));
    } else {
      hasNode = true;
    }
    topicBuilder.setNode(node);

    final int index = hasNode ? 0 : 1;
    Preconditions.checkState(
        ele.textNodes().size() > index,
        "text nodes size should greater than %s to get reply time",
        index);
    parseReplyTime(topicBuilder, ele.textNodes().get(index));
  }