OSDN Git Service

Merge branch いんきゅばすv2開発ブランチマージ
[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<ProcessType> processTypes;
36     private final Packet packet;
37     private final Pattern ngWord;
38     private final Pattern ngId;
39     private Chat item;
40     private boolean itemKicked;
41
42     public enum ProcessType {
43
44         NORMAL, OWNER;
45     }
46
47     public NicoXMLReader(Set<ProcessType> types, Packet packet, String ng_id, String ng_word) {
48         this.processTypes = EnumSet.copyOf(types);
49         this.packet = packet;
50         this.ngWord = makePattern(ng_word);
51         this.ngId = makePattern(ng_id);
52     }
53
54     private static Pattern makePattern(String word) {
55         if (word == null || word.length() <= 0) {
56             return null;
57         }
58         final String tmp[] = word.split(" ");
59         String tmp2[] = new String[tmp.length];
60         int tmp_index = 0;
61         int index;
62         for (index = 0; index < tmp.length && tmp_index < tmp.length; index++) {
63             if (tmp[tmp_index].startsWith("/")) {
64                 final StringBuilder str = new StringBuilder(tmp[tmp_index]);
65                 for (tmp_index++; tmp_index < tmp.length; tmp_index++) {
66                     str.append(" ").append(tmp[tmp_index]);
67                     if (tmp[tmp_index].endsWith("/")) {
68                         tmp_index++;
69                         break;
70                     }
71                 }
72                 tmp2[index] = str.toString();
73             } else if (tmp[tmp_index].startsWith("\"")) {
74                 final StringBuilder str = new StringBuilder(tmp[tmp_index]);
75                 for (tmp_index++; tmp_index < tmp.length; tmp_index++) {
76                     str.append(" ").append(tmp[tmp_index]);
77                     if (tmp[tmp_index].endsWith("\"")) {
78                         tmp_index++;
79                         break;
80                     }
81                 }
82                 tmp2[index] = str.toString();
83             } else {
84                 tmp2[index] = tmp[tmp_index];
85                 tmp_index++;
86             }
87         }
88         final String elt[] = new String[index];
89         System.arraycopy(tmp2, 0, elt, 0, index);
90         final StringBuilder reg = new StringBuilder();
91         for (int i = 0; i < elt.length; i++) {
92             final String e = elt[i];
93             logger.debug(e);
94             if (i > 0) {
95                 reg.append("|");
96             }
97             if (e.indexOf('/') == 0 && e.lastIndexOf('/') == e.length() - 1) {
98                 reg.append("(").append(e.substring(1, e.length() - 1)).append(")");
99             } else if (e.indexOf('\"') == 0
100                     && e.lastIndexOf('\"') == e.length() - 1) {
101                 reg.append("(").append(Pattern.quote(e.substring(1, e.length() - 1))).append(")");
102             } else {
103                 reg.append("(.*(").append(Pattern.quote(e)).append(")+.*)");
104             }
105         }
106         logger.debug("reg:" + reg);
107         return Pattern.compile(reg.toString());
108     }
109
110     private static boolean match(Pattern pat, String word) {
111         if (word == null || word.length() <= 0 || pat == null) {
112             return false;
113         }
114         return pat.matcher(word).matches();
115     }
116
117     /**
118      *
119      */
120     @Override
121     public void startDocument() {
122         logger.debug("Start converting to interval file.");
123     }
124
125     /**
126      *
127      * @param uri
128      *            String
129      * @param localName
130      *            String
131      * @param qName
132      *            String
133      * @param attributes
134      *            Attributes
135      */
136     @Override
137     public void startElement(final String uri, final String localName, final String qName,
138             final Attributes attributes) {
139         if (qName.equalsIgnoreCase("chat")) {
140             item = new Chat();
141             itemKicked = false;
142
143             // 通常コメントを処理するか, 投稿者コメントを処理するか
144             final String fork = attributes.getValue("fork");
145             final boolean isOwner = "1".equals(fork);
146             if (isOwner) {
147                 if (!processTypes.contains(ProcessType.OWNER)) {
148                     itemKicked = true;
149                 }
150             } else {
151                 if (!processTypes.contains(ProcessType.NORMAL)) {
152                     itemKicked = true;
153                 }
154             }
155
156             //マイメモリ削除対象
157             final String deleted = attributes.getValue("deleted");
158             if (deleted != null && deleted.equalsIgnoreCase("1")) {
159                 itemKicked = true;
160                 return;
161             }
162             item.setDate(attributes.getValue("date"));
163             final String mail = attributes.getValue("mail");
164             if (match(ngWord, mail)) {
165                 itemKicked = true;
166                 return;
167             }
168             item.setMail(mail);
169             item.setNo(attributes.getValue("no"));
170             final String user_id = attributes.getValue("user_id");
171             if (match(ngId, user_id)) {
172                 itemKicked = true;
173                 return;
174             }
175             item.setUserID(user_id);
176             item.setVpos(attributes.getValue("vpos"));
177
178         }
179     }
180
181     /**
182      *
183      * @param ch
184      *            char[]
185      * @param offset
186      *            int
187      * @param length
188      *            int
189      */
190     @Override
191     public void characters(final char[] ch, final int offset, final int length) {
192         final char input[] = (new String(ch, offset, length)).toCharArray();
193         for (int i = 0; i < input.length; i++) {
194             if (!Character.isDefined(input[i])) {
195                 input[i] = '?';
196             }
197         }
198         if (item != null) {
199             final String com = new String(input);
200             if (match(ngWord, com)) {
201                 itemKicked = true;
202                 return;
203             }
204             item.setComment(com);
205         }
206     }
207
208     /**
209      *
210      * @param uri
211      *            String
212      * @param localName
213      *            String
214      * @param qName
215      *            String
216      */
217     @Override
218     public void endElement(final String uri, final String localName, final String qName) {
219         if (qName.equalsIgnoreCase("chat")) {
220             if (!itemKicked) {
221                 packet.addChat(item);
222             }
223             item = null;
224         }
225     }
226
227     /**
228      * ドキュメント終了
229      */
230     @Override
231     public void endDocument() {
232         logger.debug("Converting finished.");
233     }
234 }