OSDN Git Service

nicocache文字列置換方法を追加
[coroid/NicoBrowser.git] / src / nicobrowser / NamePattern.java
1 package nicobrowser;
2
3 import java.io.UnsupportedEncodingException;
4 import org.slf4j.Logger;
5 import org.slf4j.LoggerFactory;
6
7 /**
8  *
9  * @author yuki
10  */
11 public class NamePattern {
12
13     private static final String titlePattern = "{title}";
14     private static final String idPattern = "{id}";
15     private static final String lowPattern = "{low}";
16     private static Logger log = LoggerFactory.getLogger(NamePattern.class);
17     private final String pattern;
18     private String replaceFrom = "";
19     private String replaceTo = "";
20     private String id = "";
21     private String title = "";
22     private boolean isNotLow = true;
23
24     public NamePattern(String pattern) {
25         this.pattern = pattern;
26     }
27
28     /**
29      * 保存ファイル名の命名規則.
30      *
31      * @param pattern 命名パターン.
32      * @param replaceFrom 禁則文字を指定する.
33      * @param replaceTo 禁則文字をこの文字列に置換する.
34      * @param title ファイル名に用いるタイトル文字列.
35      */
36     public NamePattern(String pattern, String replaceFrom, String replaceTo, String title) {
37         this.pattern = pattern;
38         this.replaceFrom = replaceFrom;
39         this.replaceTo = replaceTo;
40         this.title = title;
41     }
42
43     public final String createFileName() {
44         String res = replacePlaceHolder(pattern);
45         return replaceIllegalChar(res);
46     }
47
48     public final String createFileName(String id, boolean isNotLow) {
49         this.id = id;
50         this.isNotLow = isNotLow;
51
52         return createFileName();
53     }
54
55     public final void setId(String id) {
56         this.id = id;
57     }
58
59     public final void setIsNotLow(boolean isNotLow) {
60         this.isNotLow = isNotLow;
61     }
62
63     public final void setReplaceFrom(String replaceFrom) {
64         this.replaceFrom = replaceFrom;
65     }
66
67     public final void setReplaceTo(String replaceTo) {
68         this.replaceTo = replaceTo;
69     }
70
71     public final void setTitle(String title) {
72         this.title = title;
73     }
74
75     protected String replacePlaceHolder(String str) {
76         String res = str.replace(titlePattern, title);
77         res = res.replace(idPattern, id);
78         String low = isNotLow ? "" : "low";
79         res = res.replace(lowPattern, low);
80         return res;
81     }
82
83     private String replaceIllegalChar(String res) {
84         // TODO 正規表現で書き直す
85         char[] replaceds = new char[replaceFrom.length()];
86         replaceFrom.getChars(0, replaceFrom.length(), replaceds, 0);
87         StringBuilder str = new StringBuilder();
88         for (int i = 0; i < res.length(); i++) {
89             char c = res.charAt(i);
90             String moji = String.valueOf(c);
91             for (char replaced : replaceds) {
92                 if (c == replaced) {
93                     moji = replaceTo;
94                 }
95             }
96             str.append(moji);
97         }
98         return getSanitizedDescription(str.toString());
99     }
100
101     public static String getSanitizedDescription(String decodedDesc) {
102         String fileNameCharset = System.getProperty("file.encoding");
103
104         String narrowedDesc = narrowCharset(decodedDesc, fileNameCharset);
105
106         // 実体参照を更に実体参照するケースがあるので二回置換する
107         narrowedDesc = replaceER(replaceER(narrowedDesc));
108
109         char descArray[] = narrowedDesc.toCharArray();
110
111         for (int i = 0; i < descArray.length; i++) {
112             char c = descArray[i];
113             switch (c) {
114                 case '\\':
115                 case '\u00a5':
116                     c = '¥';
117                     break;
118                 case '/':
119                     c = '/';
120                     break;
121                 case ':':
122                     c = ':';
123                     break;
124                 case '*':
125                     c = '*';
126                     break;
127                 case '?':
128                     c = '?';
129                     break;
130                 case '"':
131                     c = '”';
132                     break;
133                 case '<':
134                     c = '<';
135                     break;
136                 case '>':
137                     c = '>';
138                     break;
139                 case '|':
140                     c = '|';
141                     break;
142                 case '\u203e':// c = '~'; break;
143                 case '\u301c':// c = '~'; break;
144                 case '\u2016':
145                 case '\u2212':
146                 case '\u00a2':
147                 case '\u00a3':
148                 case '\u00ac':
149                     c = '-';
150                     break;
151             }
152
153             descArray[i] = c;
154         }
155         return new String(descArray);
156     }
157
158     private static String replaceER(String src) {
159         return src.replaceAll("&amp;", "&").replaceAll("&lt;", "<").replaceAll("&gt;", ">").replaceAll("&quot;", "\"").
160                 replaceAll("&apos;", "'");
161     }
162
163     // 一旦目的の文字コードにしてから戻して、対応してない文字を '?' にする
164     static String narrowCharset(String str, String charsetName) {
165         String narrowedDesc = str;
166         if (!charsetName.equals("")) {
167             try {
168                 narrowedDesc =
169                         new String(str.getBytes(charsetName), charsetName);
170                 // characters which are not supported by the charset
171                 // become '?'
172             } catch (UnsupportedEncodingException e) {
173                 log.warn(e.toString());
174             }
175         }
176         return narrowedDesc;
177     }
178 }