    public void startElement(final String uri, final String localName, final String qName, final Attributes atts) throws SAXException {
        switch (this.stage) {
        case 0:
            if (qName.equals("div") && "content_box post_content_box story_content_box".equals(atts.getValue("class"))) {
                this.startStory();
                this.getCurrentBuilder().id(Integer.parseInt(atts.getValue("id").substring(6)));
                this.stage = 1;
            }
            break;
        case 1:
            String src = atts.getValue("src");
            this.author = User.builder();
            if (src != null && !src.equals("//www.fimfiction-static.net/images/avatars/none_64.png")) {
                try {
                    this.author.profileImageUrl(new URL("http:" + src));
                } catch (final MalformedURLException e) {
                    throw new SAXException(e);
                }
            }
            this.stage = 2;
            break;
        case 2:
            if (qName.equals("div") && "right".equals(atts.getValue("class"))) {
                this.stage = 3;
            }
            break;
        case 3:
            this.stage = "track_container".equals(atts.getValue("class")) ? 4 : 6;
            break;
        case 4:
            if (qName.equals("a")) {
                this.favorited = atts.getValue("class").contains("favourite_button_selected");
                this.stage = 5;
            }
            break;
        case 5:
            if (qName.equals("input")) {
                final boolean email = atts.getValue("checked") != null;
                this.getCurrentBuilder().favorited(this.favorited ? email ? FavoriteState.FAVORITED_EMAIL : FavoriteState.FAVORITED : FavoriteState.NOT_FAVORITED);
                this.stage = 6;
            }
            break;
        case 6:
            if (qName.equals("a")) {
                final String onClick = atts.getValue("onclick");
                if (onClick != null && onClick.startsWith("Ra")) {
                    this.getCurrentBuilder().ratingToken(onClick.substring(onClick.indexOf('\'') + 1, onClick.lastIndexOf('\'')));
                }
                this.stage = 7;
            }
            break;
        case 8:
            if (qName.equals("a")) {
                this.stage = 9;
            }
            break;
        case 10:
            if (qName.equals("b")) {
                this.stage = 300;
            }
            break;
        case 301:
            if (qName.equals("span")) {
                final String title = atts.getValue("title");
                if (title != null) {
                    this.getCurrentBuilder().totalViewCount(toIntLiberal(title));
                    this.stage = 11;
                }
            }
            break;
        case 12:
            if (qName.equals("a")) {
                this.getCurrentBuilder().readLater(atts.getValue("class").contains("read_it_later_selected"));
            }
            this.stage = 14;
            break;
        case 14:
            if (qName.equals("a")) {
                try {
                    this.getCurrentBuilder().url(new URL("http://www.fimfiction.net" + atts.getValue("href")));
                } catch (final MalformedURLException e) {
                    throw new SAXException(e);
                }
                this.title = new StringBuilder();
                this.stage = 15;
            }
            break;
        case 16:
            if (qName.equals("a")) {
                this.authorName = new StringBuilder();
                this.stage = 17;
            }
            break;
        case 18:
            if (qName.equals("img") && atts.getValue("src").equals("//www.fimfiction-static.net/images/icons/views.png")) {
                this.stage = 19;
            }
            break;
        case 20:
            if (qName.equals("div") && "description".equals(atts.getValue("class"))) {
                this.stage = 21;
            }
            break;
        case 21:
            this.stage = "story_image".equals(atts.getValue("class")) ? 22 : 25;
            break;
        case 22:
            try {
                this.getCurrentBuilder().imageUrl(new URL("http:" + atts.getValue("href")));
            } catch (final MalformedURLException e) {
                throw new SAXException(e);
            }
            this.stage = 23;
            break;
        case 23:
            try {
                this.getCurrentBuilder().thumbnailUrl(new URL("http:" + atts.getValue("src")));
            } catch (final MalformedURLException e) {
                throw new SAXException(e);
            }
            this.stage = 24;
            break;
        case 24:
            if (qName.equals("a")) {
                this.stage = 25;
            } else {
                if (this.categories != null) {
                    this.getCurrentBuilder().categories(Collections.unmodifiableSet(this.categories));
                    this.categories = null;
                }
                this.description = new StringBuilder();
                this.stage = 26;
            }
            break;
        case 27:
            this.description.append('<');
            this.description.append(qName);
            for (int i = 0; i < atts.getLength(); i++) {
                this.description.append(' ');
                this.description.append(atts.getQName(i));
                this.description.append("=\"");
                this.description.append(atts.getValue(i).replace("\"", "\\\""));
                this.description.append('"');
            }
            this.description.append('>');
            break;
        case 28:
            if (qName.equals("ul")) {
                this.chapters = new ArrayList<Chapter>();
                this.stage = 29;
            }
            break;
        case 29:
            if (qName.equals("div")) {
                final String clazz = atts.getValue("class");
                if (clazz != null && clazz.contains("chapter_container")) {
                    if (!clazz.contains("chapter_expander")) {
                        this.stage = 100;
                    }
                }
            }
            if (qName.equals("li") && "save_ordering".equals(atts.getValue("class"))) {
                this.getCurrentBuilder().chapters(Collections.unmodifiableList(this.chapters));
                this.getCurrentBuilder().chapterCount(this.chapters.size());
                this.chapters = null;
                this.stage = 38;
            }
            break;
        case 100:
            this.stage = 101;
            break;
        case 101:
            this.stage = 30;
            break;
        case 30:
            this.chapter = Chapter.builder();
            if (qName.equals("img")) {
                this.chapter.unread("//www.fimfiction-static.net/images/icons/new.png".equals(atts.getValue("src")));
                this.stage = 31;
            } else if (qName.equals("a")) {
                try {
                    this.chapter.url(new URL("http://www.fimfiction.net" + atts.getValue("href")));
                } catch (final MalformedURLException e) {
                    throw new SAXException(e);
                }
                this.chapterTitle = new StringBuilder();
                this.stage = 32;
            }
            break;
        case 31:
            if (qName.equals("a")) {
                try {
                    this.chapter.url(new URL("http://www.fimfiction.net" + atts.getValue("href")));
                } catch (final MalformedURLException e) {
                    throw new SAXException(e);
                }
                this.chapterTitle = new StringBuilder();
                this.stage = 32;
            }
            break;
        case 35:
            this.stage = 36;
            break;
        case 37:
            if (qName.equals("a")) {
                this.chapter.id(toIntLiberal(atts.getValue("href")));
                this.chapters.add(this.chapter.build());
                this.chapter = null;
                this.stage = 29;
            }
            break;
        case 203:
            if (qName.equals("div")) {
                this.stage = 204;
            }
            break;
        case 205:
            if (qName.equals("br")) {
                this.stage = 39;
            }
            break;
        case 39:
            if (qName.equals("span")) {
                this.stage = 40;
            }
            break;
        case 41:
            if (qName.equals("br")) {
                this.stage = 42;
            }
            if (qName.equals("a")) {
                this.stage = 43;
            }
            break;
        case 42:
            if (qName.equals("span")) {
                this.stage = 43;
            }
            break;
        case 43:
        case 44:
            if (qName.equals("img")) {
                src = atts.getValue("src");
                final int i = src.lastIndexOf('.');
                if (i > 46) {
                    final String id = src.substring(46, i);
                    for (final Character character : Character.values()) {
                        if (id.equals(getImageId(character))) {
                            this.characters.add(character);
                            break;
                        }
                    }
                }
            }
            if (qName.equals("i")) {
                this.getCurrentBuilder().characters(Collections.unmodifiableSet(this.characters));
                this.characters = null;
                this.endStory();
                this.stage = 0;
            }
            ;
            break;
        }
    }

    public void startElement(final String uri, final String localName, final String qName, final Attributes atts) throws SAXException {
        switch (this.stage) {
        case 0:
            if (qName.equals("div") && "content_box post_content_box story_content_box".equals(atts.getValue("class"))) {
                this.startStory();
                this.getCurrentBuilder().id(Integer.parseInt(atts.getValue("id").substring(6)));
                this.stage = 1;
            }
            break;
        case 1:
            String src = atts.getValue("src");
            this.author = User.builder();
            if (src != null && !src.equals("//www.fimfiction-static.net/images/avatars/none_64.png")) {
                try {
                    this.author.profileImageUrl(new URL("http:" + src));
                } catch (final MalformedURLException e) {
                    throw new SAXException(e);
                }
            }
            this.stage = 2;
            break;
        case 2:
            if (qName.equals("div") && "right".equals(atts.getValue("class"))) {
                this.stage = 3;
            }
            break;
        case 3:
            this.stage = "track_container".equals(atts.getValue("class")) ? 4 : 6;
            break;
        case 4:
            if (qName.equals("a")) {
                this.favorited = atts.getValue("class").contains("favourite_button_selected");
                this.stage = 5;
            }
            break;
        case 5:
            if (qName.equals("input")) {
                final boolean email = atts.getValue("checked") != null;
                this.getCurrentBuilder().favorited(this.favorited ? email ? FavoriteState.FAVORITED_EMAIL : FavoriteState.FAVORITED : FavoriteState.NOT_FAVORITED);
                this.stage = 6;
            }
            break;
        case 6:
            if (qName.equals("a")) {
                final String onClick = atts.getValue("onclick");
                if (onClick != null && onClick.startsWith("Ra")) {
                    this.getCurrentBuilder().ratingToken(onClick.substring(onClick.indexOf('\'') + 1, onClick.lastIndexOf('\'')));
                }
                this.stage = 7;
            }
            break;
        case 8:
            if (qName.equals("a")) {
                this.stage = 9;
            }
            break;
        case 10:
            if (qName.equals("b")) {
                this.stage = 300;
            }
            break;
        case 301:
            if (qName.equals("span")) {
                final String title = atts.getValue("title");
                if (title != null) {
                    this.getCurrentBuilder().totalViewCount(toIntLiberal(title));
                    this.stage = 11;
                }
            }
            break;
        case 12:
            if (qName.equals("a")) {
                this.getCurrentBuilder().readLater(atts.getValue("class").contains("read_it_later_selected"));
            }
            this.stage = 14;
            break;
        case 14:
            if (qName.equals("a")) {
                try {
                    this.getCurrentBuilder().url(new URL("http://www.fimfiction.net" + atts.getValue("href")));
                } catch (final MalformedURLException e) {
                    throw new SAXException(e);
                }
                this.title = new StringBuilder();
                this.stage = 15;
            }
            break;
        case 16:
            if (qName.equals("a")) {
                this.authorName = new StringBuilder();
                this.stage = 17;
            }
            break;
        case 18:
            if (qName.equals("img") && atts.getValue("src").equals("//www.fimfiction-static.net/images/icons/views.png")) {
                this.stage = 19;
            }
            break;
        case 20:
            if (qName.equals("div") && "description".equals(atts.getValue("class"))) {
                this.stage = 21;
            }
            break;
        case 21:
            this.stage = "story_image".equals(atts.getValue("class")) ? 22 : 25;
            break;
        case 22:
            try {
                this.getCurrentBuilder().imageUrl(new URL("http:" + atts.getValue("href")));
            } catch (final MalformedURLException e) {
                throw new SAXException(e);
            }
            this.stage = 23;
            break;
        case 23:
            try {
                this.getCurrentBuilder().thumbnailUrl(new URL("http:" + atts.getValue("src")));
            } catch (final MalformedURLException e) {
                throw new SAXException(e);
            }
            this.stage = 24;
            break;
        case 24:
            if (qName.equals("a")) {
                this.stage = 25;
            } else {
                if (this.categories != null) {
                    this.getCurrentBuilder().categories(Collections.unmodifiableSet(this.categories));
                    this.categories = null;
                }
                this.description = new StringBuilder();
                this.stage = 26;
            }
            break;
        case 27:
            this.description.append('<');
            this.description.append(qName);
            for (int i = 0; i < atts.getLength(); i++) {
                this.description.append(' ');
                this.description.append(atts.getQName(i));
                this.description.append("=\"");
                this.description.append(atts.getValue(i).replace("\"", "\\\""));
                this.description.append('"');
            }
            this.description.append('>');
            break;
        case 28:
            if (qName.equals("ul")) {
                this.chapters = new ArrayList<Chapter>();
                this.stage = 29;
            }
            break;
        case 29:
            if (qName.equals("div")) {
                final String clazz = atts.getValue("class");
                if (clazz != null && clazz.contains("chapter_container")) {
                    if (!clazz.contains("chapter_expander")) {
                        this.stage = 100;
                    }
                }
            }
            if (qName.equals("li") && "save_ordering".equals(atts.getValue("class"))) {
                this.getCurrentBuilder().chapters(Collections.unmodifiableList(this.chapters));
                this.getCurrentBuilder().chapterCount(this.chapters.size());
                this.chapters = null;
                this.stage = 38;
            }
            break;
        case 100:
            this.stage = 101;
            break;
        case 101:
            this.stage = 30;
            break;
        case 30:
            this.chapter = Chapter.builder();
            if (qName.equals("i")) {
                this.chapter.unread(atts.getValue("class").length() == 17);
                this.stage = 31;
            } else if (qName.equals("a")) {
                try {
                    this.chapter.url(new URL("http://www.fimfiction.net" + atts.getValue("href")));
                } catch (final MalformedURLException e) {
                    throw new SAXException(e);
                }
                this.chapterTitle = new StringBuilder();
                this.stage = 32;
            }
            break;
        case 31:
            if (qName.equals("a")) {
                try {
                    this.chapter.url(new URL("http://www.fimfiction.net" + atts.getValue("href")));
                } catch (final MalformedURLException e) {
                    throw new SAXException(e);
                }
                this.chapterTitle = new StringBuilder();
                this.stage = 32;
            }
            break;
        case 35:
            this.stage = 36;
            break;
        case 37:
            if (qName.equals("a")) {
                this.chapter.id(toIntLiberal(atts.getValue("href")));
                this.chapters.add(this.chapter.build());
                this.chapter = null;
                this.stage = 29;
            }
            break;
        case 203:
            if (qName.equals("div")) {
                this.stage = 204;
            }
            break;
        case 205:
            if (qName.equals("br")) {
                this.stage = 39;
            }
            break;
        case 39:
            if (qName.equals("span")) {
                this.stage = 40;
            }
            break;
        case 41:
            if (qName.equals("br")) {
                this.stage = 42;
            }
            if (qName.equals("a")) {
                this.stage = 43;
            }
            break;
        case 42:
            if (qName.equals("span")) {
                this.stage = 43;
            }
            break;
        case 43:
        case 44:
            if (qName.equals("img")) {
                src = atts.getValue("src");
                final int i = src.lastIndexOf('.');
                if (i > 46) {
                    final String id = src.substring(46, i);
                    for (final Character character : Character.values()) {
                        if (id.equals(getImageId(character))) {
                            this.characters.add(character);
                            break;
                        }
                    }
                }
            }
            if (qName.equals("i")) {
                this.getCurrentBuilder().characters(Collections.unmodifiableSet(this.characters));
                this.characters = null;
                this.endStory();
                this.stage = 0;
            }
            ;
            break;
        }
    }
