OSDN Git Service

CommentTypeを別ファイルに切り出し
[coroid/inqubus.git] / frontend / src / saccubus / conv / NicoXMLReader.java
1 package saccubus.conv;
2
3 import java.util.EnumSet;
4 import java.util.Set;
5 import java.util.regex.Pattern;
6
7 import org.slf4j.Logger;
8 import org.slf4j.LoggerFactory;
9 import org.xml.sax.helpers.DefaultHandler;
10 import org.xml.sax.Attributes;
11
12 /**
13  * <p>
14  * タイトル: さきゅばす
15  * </p>
16  *
17  * <p>
18  * 説明: ニコニコ動画の動画をコメントつきで保存
19  * </p>
20  *
21  * <p>
22  * 著作権: Copyright (c) 2007 PSI
23  * </p>
24  *
25  * <p>
26  * 会社名:
27  * </p>
28  *
29  * @author 未入力
30  * @version 1.0
31  */
32 public class NicoXMLReader extends DefaultHandler {
33
34     private static final Logger logger = LoggerFactory.getLogger(NicoXMLReader.class);
35     private final Set<CommentType> processTypes;
36     private final Packet packet;
37     private final Pattern ngWord;
38     private final Pattern ngId;
39     private String mainThreadId;
40     private Chat item;
41     private boolean itemKicked;
42
43     /**
44      * コンストラクタ.
45      * @param types 処理するコメントの種別.
46      * @param packet
47      * @param ng_id NG ID.
48      * @param ng_word NG ワード.
49      */
50     public NicoXMLReader(Set<CommentType> types, Packet packet, String ng_id, String ng_word) {
51         this.processTypes = EnumSet.copyOf(types);
52         this.packet = packet;
53         this.ngWord = makePattern(ng_word);
54         this.ngId = makePattern(ng_id);
55     }
56
57     private static Pattern makePattern(String word) {
58         if (word == null || word.length() <= 0) {
59             return null;
60         }
61         final String tmp[] = word.split(" ");
62         String tmp2[] = new String[tmp.length];
63         int tmp_index = 0;
64         int index;
65         for (index = 0; index < tmp.length && tmp_index < tmp.length; index++) {
66             if (tmp[tmp_index].startsWith("/")) {
67                 final StringBuilder str = new StringBuilder(tmp[tmp_index]);
68                 for (tmp_index++; tmp_index < tmp.length; tmp_index++) {
69                     str.append(" ").append(tmp[tmp_index]);
70                     if (tmp[tmp_index].endsWith("/")) {
71                         tmp_index++;
72                         break;
73                     }
74                 }
75                 tmp2[index] = str.toString();
76             } else if (tmp[tmp_index].startsWith("\"")) {
77                 final StringBuilder str = new StringBuilder(tmp[tmp_index]);
78                 for (tmp_index++; tmp_index < tmp.length; tmp_index++) {
79                     str.append(" ").append(tmp[tmp_index]);
80                     if (tmp[tmp_index].endsWith("\"")) {
81                         tmp_index++;
82                         break;
83                     }
84                 }
85                 tmp2[index] = str.toString();
86             } else {
87                 tmp2[index] = tmp[tmp_index];
88                 tmp_index++;
89             }
90         }
91         final String elt[] = new String[index];
92         System.arraycopy(tmp2, 0, elt, 0, index);
93         final StringBuilder reg = new StringBuilder();
94         for (int i = 0; i < elt.length; i++) {
95             final String e = elt[i];
96             logger.debug(e);
97             if (i > 0) {
98                 reg.append("|");
99             }
100             if (e.indexOf('/') == 0 && e.lastIndexOf('/') == e.length() - 1) {
101                 reg.append("(").append(e.substring(1, e.length() - 1)).append(")");
102             } else if (e.indexOf('\"') == 0
103                     && e.lastIndexOf('\"') == e.length() - 1) {
104                 reg.append("(").append(Pattern.quote(e.substring(1, e.length() - 1))).append(")");
105             } else {
106                 reg.append("(.*(").append(Pattern.quote(e)).append(")+.*)");
107             }
108         }
109         logger.debug("reg:" + reg);
110         return Pattern.compile(reg.toString());
111     }
112
113     private static boolean match(Pattern pat, String word) {
114         if (word == null || word.length() <= 0 || pat == null) {
115             return false;
116         }
117         return pat.matcher(word).matches();
118     }
119
120     /**
121      *
122      */
123     @Override
124     public void startDocument() {
125         logger.debug("Start converting to interval file.");
126     }
127
128     /**
129      *
130      * @param uri
131      *            String
132      * @param localName
133      *            String
134      * @param qName
135      *            String
136      * @param attributes
137      *            Attributes
138      */
139     @Override
140     public void startElement(final String uri, final String localName, final String qName,
141             final Attributes attributes) {
142         if (qName.equalsIgnoreCase("chat")) {
143             item = new Chat();
144             itemKicked = false;
145
146             // 通常コメントを処理するか, 投稿者コメントを処理するか
147             final String fork = attributes.getValue("fork");
148             final boolean isOwner = "1".equals(fork);
149             final String th = attributes.getValue("thread");
150
151             // 初めて見つけたthreadをメインスレッド(非オプショナルスレッド)とみなす
152             if (mainThreadId == null) {
153                 mainThreadId = th;
154             }
155
156             final boolean isOptional = (mainThreadId == null) ? false : !mainThreadId.equals(th);
157
158             if(!processTypes.contains(CommentType.valueOf(isOwner, isOptional))){
159                 itemKicked = true;
160                 return;
161             }
162
163             //マイメモリ削除対象
164             final String deleted = attributes.getValue("deleted");
165             if (deleted != null && deleted.equalsIgnoreCase("1")) {
166                 itemKicked = true;
167                 return;
168             }
169             item.setDate(attributes.getValue("date"));
170             final String mail = attributes.getValue("mail");
171             if (match(ngWord, mail)) {
172                 itemKicked = true;
173                 return;
174             }
175             item.setMail(mail);
176             item.setNo(attributes.getValue("no"));
177             final String user_id = attributes.getValue("user_id");
178             if (match(ngId, user_id)) {
179                 itemKicked = true;
180                 return;
181             }
182             item.setUserID(user_id);
183             item.setVpos(attributes.getValue("vpos"));
184
185         }
186     }
187
188     /**
189      *
190      * @param ch
191      *            char[]
192      * @param offset
193      *            int
194      * @param length
195      *            int
196      */
197     @Override
198     public void characters(final char[] ch, final int offset, final int length) {
199         final char input[] = (new String(ch, offset, length)).toCharArray();
200         for (int i = 0; i < input.length; i++) {
201             if (!Character.isDefined(input[i])) {
202                 input[i] = '?';
203             }
204         }
205         if (item != null) {
206             final String com = new String(input);
207             if (match(ngWord, com)) {
208                 itemKicked = true;
209                 return;
210             }
211             item.setComment(com);
212         }
213     }
214
215     /**
216      *
217      * @param uri
218      *            String
219      * @param localName
220      *            String
221      * @param qName
222      *            String
223      */
224     @Override
225     public void endElement(final String uri, final String localName, final String qName) {
226         if (qName.equalsIgnoreCase("chat")) {
227             if (!itemKicked) {
228                 packet.addChat(item);
229             }
230             item = null;
231         }
232     }
233
234     /**
235      * ドキュメント終了
236      */
237     @Override
238     public void endDocument() {
239         logger.debug("Converting finished.");
240     }
241 }