001package csv2html; 002 003import java.awt.image.BufferedImage; 004import java.io.File; 005import java.lang.reflect.Constructor; 006import java.lang.reflect.InvocationTargetException; 007import java.util.ArrayList; 008import java.util.Calendar; 009import java.util.HashSet; 010import java.util.List; 011 012/** 013 * トランスレータ:CSVファイルをHTMLページへと変換するプログラム。 014 */ 015public class Translator extends Object 016{ 017 /** 018 * CSVに由来するテーブルを記憶するフィールド。 019 */ 020 private Table inputTable; 021 022 /** 023 * HTMLに由来するテーブルを記憶するフィールド。 024 */ 025 private Table outputTable; 026 027 /** 028 * 属性リストのクラスを指定したトランスレータのコンストラクタ。 029 * @param classOfAttributes 属性リストのクラス 030 */ 031 public Translator(Class<? extends Attributes> classOfAttributes) 032 { 033 super(); 034 Attributes.flushBaseDirectory(); 035 036 try 037 { 038 Constructor<? extends Attributes> aConstructor = classOfAttributes.getConstructor(String.class); 039 040 this.inputTable = new Table(aConstructor.newInstance("input")); 041 this.outputTable = new Table(aConstructor.newInstance("output")); 042 } 043 catch (NoSuchMethodException | 044 InstantiationException | 045 IllegalAccessException | 046 InvocationTargetException anException) { anException.printStackTrace(); } 047 048 return; 049 } 050 051 /** 052 * 在位日数を計算して、それを文字列にして応答する。 053 * @param periodString 在位期間の文字列 054 * @return 在位日数の文字列 055 */ 056 public String computeNumberOfDays(String periodString) 057 { 058 String[] stringArray = periodString.split("[0-9]+", 0); // 数字以外の文字列を得る(空文字列を含む) 059 HashSet<String> aSet = new HashSet<String>(); 060 for (String aString : stringArray) // 空文字列を除去しながらダブりも除く 061 { 062 if (!aString.isEmpty()) { aSet.add(aString); } 063 } 064 StringBuffer aBuffer = new StringBuffer(); // 区切り記号の正規表現を作る 065 aBuffer.append('['); 066 boolean firstTime = true; 067 for (String aString : aSet) 068 { 069 if (firstTime) { firstTime = false; } 070 else { aBuffer.append('|'); } 071 aBuffer.append(aString); 072 } 073 aBuffer.append(']'); 074 String regularExpression = aBuffer.toString(); 075 stringArray = periodString.split(regularExpression, 0); // 日付の数字部分を取り出す(空文字列を含む) 076 List<String> aCollection = new ArrayList<String>(); 077 for (String aString : stringArray) 078 { 079 if (!aString.isEmpty()) { aCollection.add(aString); } // 空文字列を除去 080 } 081 082 Calendar aCalendar = Calendar.getInstance(); 083 int year = Integer.valueOf(aCollection.get(0)); 084 int month = Integer.valueOf(aCollection.get(1)) - 1; 085 int day = Integer.valueOf(aCollection.get(2)); 086 aCalendar.set(year, month, day); 087 long start = aCalendar.getTime().getTime(); 088 089 aCalendar = Calendar.getInstance(); 090 if (aCollection.size() > 3) 091 { 092 year = Integer.valueOf(aCollection.get(3)); 093 month = Integer.valueOf(aCollection.get(4)) - 1; 094 day = Integer.valueOf(aCollection.get(5)); 095 aCalendar.set(year, month, day); 096 } 097 long end = aCalendar.getTime().getTime(); 098 099 long distance = ((end - start) / (1000 * 60 * 60 * 24)) + 1; 100 101 return String.format("%1$,d", distance); 102 } 103 104 /** 105 * サムネイル画像から画像へ飛ぶためのHTML文字列を作成して、それを応答する。 106 * @param aString 画像の文字列 107 * @param aTuple タプル 108 * @param no 番号 109 * @return サムネイル画像から画像へ飛ぶためのHTML文字列 110 */ 111 public String computeStringOfImage(String aString, Tuple aTuple, int no) 112 { 113 String noString = aTuple.values().get(aTuple.attributes().indexOfNo()); 114 String thumbnailString = aTuple.values().get(aTuple.attributes().indexOfThumbnail()); 115 BufferedImage thumbnailImage = this.inputTable.thumbnails().get(no); 116 int index = aTuple.attributes().indexOfThumbnail(); 117 List<String> aCollection = IO.splitString(aTuple.values().get(index), "/"); 118 index = aCollection.size() - 1; 119 120 StringBuffer aBuffer = new StringBuffer(); 121 aBuffer.append("<a name=\""); 122 aBuffer.append(noString); 123 aBuffer.append("\" href=\""); 124 aBuffer.append(aString); 125 aBuffer.append("\">"); 126 aBuffer.append("<img class=\"borderless\" src=\""); 127 aBuffer.append(thumbnailString); 128 aBuffer.append("\" width=\""); 129 aBuffer.append(thumbnailImage.getWidth()); 130 aBuffer.append("\" height=\""); 131 aBuffer.append(thumbnailImage.getHeight()); 132 aBuffer.append("\" alt=\""); 133 aBuffer.append(aCollection.get(index)); 134 aBuffer.append("\"></a>"); 135 136 return aBuffer.toString(); 137 } 138 139 /** 140 * CSVファイルをHTMLページへ変換する。 141 */ 142 public void execute() 143 { 144 // 必要な情報をダウンロードする。 145 Downloader aDownloader = new Downloader(this.inputTable); 146 aDownloader.perform(); 147 148 // CSVに由来するテーブルをHTMLに由来するテーブルへと変換する。 149 System.out.println(this.inputTable); 150 this.translate(); 151 System.out.println(this.outputTable); 152 153 // HTMLに由来するテーブルから書き出す。 154 Writer aWriter = new Writer(this.outputTable); 155 aWriter.perform(); 156 157 // ブラウザを立ち上げて閲覧する。 158 try 159 { 160 Attributes attributes = this.outputTable.attributes(); 161 String fileStringOfHTML = attributes.baseDirectory() + attributes.indexHTML(); 162 ProcessBuilder aProcessBuilder = new ProcessBuilder("open", "-a", "Safari", fileStringOfHTML); 163 aProcessBuilder.start(); 164 } 165 catch (Exception anException) { anException.printStackTrace(); } 166 167 return; 168 } 169 170 /** 171 * 属性リストのクラスを受け取って、CSVファイルをHTMLページへと変換するクラスメソッド。 172 * @param classOfAttributes 属性リストのクラス 173 */ 174 public static void perform(Class<? extends Attributes> classOfAttributes) 175 { 176 // トランスレータのインスタンスを生成する。 177 Translator aTranslator = new Translator(classOfAttributes); 178 // トランスレータにCSVファイルをHTMLページへ変換するように依頼する。 179 aTranslator.execute(); 180 181 return; 182 } 183 184 /** 185 * CSVファイルを基にしたテーブルから、HTMLページを基にするテーブルに変換する。 186 */ 187 public void translate() 188 { 189 List<String> nameCollection = new ArrayList<String>(); 190 int index = 0; 191 for (String aString : this.inputTable.attributes().names()) 192 { 193 if (index != this.inputTable.attributes().indexOfThumbnail()) 194 { 195 nameCollection.add(IO.htmlCanonicalString(aString)); 196 197 if (index == this.inputTable.attributes().indexOfPeriod()) 198 { 199 nameCollection.add(IO.htmlCanonicalString("在位日数")); 200 } 201 } 202 index++; 203 } 204 this.outputTable.attributes().names(nameCollection); 205 206 int no = 0; 207 for (Tuple aTuple : this.inputTable.tuples()) 208 { 209 List<String> valueCollection = new ArrayList<String>(); 210 index = 0; 211 for (String aString : aTuple.values()) 212 { 213 if (index != this.inputTable.attributes().indexOfThumbnail()) 214 { 215 if (index == this.inputTable.attributes().indexOfImage()) 216 { 217 valueCollection.add(this.computeStringOfImage(aString, aTuple, no)); 218 } 219 else 220 { 221 valueCollection.add(IO.htmlCanonicalString(aString)); 222 } 223 224 if (index == this.inputTable.attributes().indexOfPeriod()) 225 { 226 valueCollection.add(this.computeNumberOfDays(aString)); 227 } 228 } 229 index++; 230 } 231 Tuple theTuple = new Tuple(this.outputTable.attributes(), valueCollection); 232 this.outputTable.add(theTuple); 233 no++; 234 } 235 236 return; 237 } 238}