net.yatomiya.nicherry.services.bbs.model.ThreadURL.java Source code

Java tutorial

Introduction

Here is the source code for net.yatomiya.nicherry.services.bbs.model.ThreadURL.java

Source

/*******************************************************************************
 * Copyright (c) 2014,2015 Hideki Yatomi
 * All rights reserved. This program and the accompanying materials are made
 * available under the terms of the Eclipse Public License v1.0 which
 * accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 ******************************************************************************/
package net.yatomiya.nicherry.services.bbs.model;

import java.util.*;
import java.util.regex.*;
import com.squareup.okhttp.*;
import net.yatomiya.e4.util.*;
import net.yatomiya.nicherry.model.bbs.*;

// "http://aaa.2ch.host/test/read.cgi/board_key/thread_key/message_no
public class ThreadURL {
    HttpUrl httpUrl;
    String boardKey;
    String threadKey;
    MessageParam messageParam;

    public ThreadURL(String urlString) {
        httpUrl = HttpUrl.parse(urlString);
        List<String> seg = httpUrl.pathSegments();

        if (seg.size() != 4 && seg.size() != 5)
            throw new IllegalArgumentException("Thread path segments size should be 5 or 6.");
        if (!seg.get(0).equalsIgnoreCase("test") || !seg.get(1).equalsIgnoreCase("read.cgi"))
            throw new IllegalArgumentException("url does not contain \\\"test/read.cgi\\\".");

        boardKey = seg.get(2);
        threadKey = seg.get(3);

        if (seg.size() >= 5) {
            messageParam = new MessageParam(seg.get(4));
        } else {
            messageParam = MessageParam.ALL;
        }
    }

    public HttpUrl getURL() {
        return httpUrl;
    }

    public String getHost() {
        return httpUrl.host();
    }

    public String getBoardKey() {
        return boardKey;
    }

    public String getThreadKey() {
        return threadKey;
    }

    public MessageParam getMessageParam() {
        return messageParam;
    }

    public static class MessageParam {
        public static final String MESSAGE_RANGE_EXPR = "(?<headPrefix>^[\\-l]?)(?<headNumber>[\\d]+)(?<headSuffix>(-|n-)?)(?<tailNumber>[\\d]*)";
        public static final Pattern MESSAGE_RANGE_PATTERN = Pattern.compile(MESSAGE_RANGE_EXPR);

        static final MessageParam ALL = new MessageParam("");

        static enum Type {
            ALL, RECENT, UNTIL, FIRST_AND_FROM, FROM, ONLY, FIRST_AND_RANGE, RANGE,
        }

        Type type;
        int head;
        int tail;

        MessageParam(String str) {
            if (JUtils.isEmpty(str)) {
                type = Type.ALL;
                return;
            }

            Matcher m = MESSAGE_RANGE_PATTERN.matcher(str);
            if (m.find()) {
                String headPrefix = m.group("headPrefix");
                String headNumber = m.group("headNumber");
                String headSuffix = m.group("headSuffix");
                String tailNumber = m.group("tailNumber");

                head = -1;
                tail = -1;

                try {
                    if (!JUtils.isEmpty(headNumber))
                        head = Integer.valueOf(headNumber);
                    if (!JUtils.isEmpty(tailNumber))
                        tail = Integer.valueOf(tailNumber);

                    if (head < 0 && tail < 0) {
                        type = Type.ALL;
                    } else if (head >= 0 && tail < 0) {
                        if (!JUtils.isEmpty(headPrefix)) {
                            switch (headPrefix) {
                            case "l":
                                type = Type.RECENT;
                                break;
                            case "-":
                                type = Type.UNTIL;
                                break;
                            }
                        } else if (!JUtils.isEmpty(headSuffix)) {
                            switch (headSuffix) {
                            case "-":
                                type = Type.FIRST_AND_FROM;
                                break;
                            case "n-":
                                type = Type.FROM;
                                break;
                            }
                        } else {
                            type = Type.ONLY;
                        }
                    } else if (head >= 0 && tail >= 0 && !JUtils.isEmpty(headSuffix)) {
                        switch (headSuffix) {
                        case "-":
                            type = Type.FIRST_AND_RANGE;
                            break;
                        case "n-":
                            type = Type.RANGE;
                            break;
                        }
                    }
                } catch (NumberFormatException e) {
                    type = Type.ALL;
                }
            }
        }

        public Type getType() {
            return type;
        }

        public int getHead() {
            return head;
        }

        public int getTail() {
            return tail;
        }

        public int getFirstMessageNo() {
            switch (type) {
            case ALL:
                return 1;
            case RECENT:
                return 1;
            case UNTIL:
                return 1;
            case FIRST_AND_FROM:
                return head;
            case FROM:
                return head;
            case ONLY:
                return head;
            case FIRST_AND_RANGE:
                return head;
            case RANGE:
                return head;
            }
            return 1;
        }

        /*
                static void test() {
        MessageParam p;
            
        p = new MessageParam("l50");
        //"l50"???????50?
            
        p = new MessageParam("-50");
        //"-50"?????1??50???
            
        p = new MessageParam("50-");
        // "50-"?????1??????50??
            
        p = new MessageParam("50n-");
        // ????????50??
            
        p = new MessageParam("50");
        //"50"???????50???
            
        p = new MessageParam("50-60");
        //????1?50-60
            
        p = new MessageParam("50n-60");
                }
        */
    }

    public static ImmutableBitSet toMessageNoSet(MThread thread, MessageParam param) {
        int size = thread.getMessageCount();
        if (size == 0)
            return new ImmutableBitSet();
        int head = param.getHead();
        int tail = param.getTail();

        BitSet bs = new BitSet();

        switch (param.getType()) {
        case ALL:
            bs.set(1, size);
            break;
        case RECENT:
            bs.set(Math.max(1, size - head), size);
            break;
        case UNTIL:
            bs.set(1, Math.min(size, head));
            break;
        case FIRST_AND_FROM:
            bs.set(1);
            if (head <= size)
                bs.set(head, size);
            break;
        case FROM:
            if (head <= size)
                bs.set(head, size);
            break;
        case ONLY:
            bs.set(head);
            break;
        case FIRST_AND_RANGE: {
            bs.set(1);
            bs.set(head, tail);
            BitSet all = new BitSet();
            all.set(1, size);
            bs.and(all);
        }
            break;
        case RANGE: {
            bs.set(head, tail);
            BitSet all = new BitSet();
            all.set(1, size);
            bs.and(all);
        }
            break;
        }
        return new ImmutableBitSet(bs);
    }
}