001package net.sf.cpsolver.coursett; 002 003import java.io.BufferedReader; 004import java.io.File; 005import java.io.FileReader; 006import java.io.StringReader; 007import java.util.ArrayList; 008import java.util.HashMap; 009import java.util.Iterator; 010import java.util.List; 011import java.util.Map; 012import java.util.TreeSet; 013 014import net.sf.cpsolver.coursett.model.Lecture; 015import net.sf.cpsolver.coursett.model.Placement; 016import net.sf.cpsolver.coursett.model.TimetableModel; 017import net.sf.cpsolver.ifs.solution.Solution; 018import net.sf.cpsolver.ifs.util.CSVFile; 019import net.sf.cpsolver.ifs.util.DataProperties; 020import net.sf.cpsolver.ifs.util.Progress; 021 022import org.apache.log4j.BasicConfigurator; 023import org.dom4j.Document; 024import org.dom4j.Element; 025import org.dom4j.io.SAXReader; 026 027/** 028 * Process all solutions (files solution.xml or output.csv) in all subfolders of 029 * the given folder and create a CSV (comma separated values text file) with 030 * solution infos of the found solutions. 031 * 032 * @version CourseTT 1.2 (University Course Timetabling)<br> 033 * Copyright (C) 2007 - 2010 Tomáš Müller<br> 034 * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br> 035 * <a href="http://muller.unitime.org">http://muller.unitime.org</a><br> 036 * <br> 037 * This library is free software; you can redistribute it and/or modify 038 * it under the terms of the GNU Lesser General Public License as 039 * published by the Free Software Foundation; either version 3 of the 040 * License, or (at your option) any later version. <br> 041 * <br> 042 * This library is distributed in the hope that it will be useful, but 043 * WITHOUT ANY WARRANTY; without even the implied warranty of 044 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 045 * Lesser General Public License for more details. <br> 046 * <br> 047 * You should have received a copy of the GNU Lesser General Public 048 * License along with this library; if not see 049 * <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>. 050 */ 051public class GetInfo { 052 053 public static HashMap<String, String> getInfoOfASolution(File file) { 054 try { 055 DataProperties properties = new DataProperties(); 056 properties.setProperty("General.Input", file.getPath()); 057 TimetableXMLLoader loader = new TimetableXMLLoader(new TimetableModel(properties)); 058 loader.load(); 059 File newOutputFile = new File(file.getParentFile(), "new-output.csv"); 060 Test.saveOutputCSV(new Solution<Lecture, Placement>(loader.getModel()), newOutputFile); 061 Progress.removeInstance(loader.getModel()); 062 System.out.println(" Reading " + newOutputFile + " ..."); 063 HashMap<String, String> info = getInfo(newOutputFile); 064 File outputFile = new File(file.getParentFile(), "output.csv"); 065 if (outputFile.exists()) { 066 System.out.println(" Reading " + outputFile + " ..."); 067 HashMap<String, String> info2 = getInfo(outputFile); 068 if (info2.containsKey("000.002 Time [sec]")) 069 info.put("000.002 Time [sec]", info2.get("000.002 Time [sec]")); 070 } 071 return info; 072 } catch (Exception e) { 073 System.err.println("Error reading info, message: " + e.getMessage()); 074 e.printStackTrace(); 075 return null; 076 } 077 } 078 079 public static HashMap<String, String> getInfo(String comment) { 080 try { 081 BufferedReader reader = new BufferedReader(new StringReader(comment)); 082 String line = null; 083 HashMap<String, String> info = new HashMap<String, String>(); 084 while ((line = reader.readLine()) != null) { 085 int idx = line.indexOf(':'); 086 if (idx >= 0) { 087 String key = line.substring(0, idx).trim(); 088 String value = line.substring(idx + 1).trim(); 089 if (value.indexOf('(') >= 0 && value.indexOf(')') >= 0) { 090 value = value.substring(value.indexOf('(') + 1, value.indexOf(')')); 091 if (value.indexOf('/') >= 0) { 092 String bound = value.substring(value.indexOf('/') + 1); 093 if (bound.indexOf("..") >= 0) { 094 String min = bound.substring(0, bound.indexOf("..")); 095 String max = bound.substring(bound.indexOf("..") + 2); 096 info.put(key + " Min", min); 097 info.put(key + " Max", max); 098 } else { 099 info.put(key + " Bound", bound); 100 } 101 value = value.substring(0, value.indexOf('/')); 102 } 103 } 104 if (value.length() > 0) 105 info.put(key, value); 106 } 107 } 108 reader.close(); 109 return info; 110 } catch (Exception e) { 111 System.err.println("Error reading info, message: " + e.getMessage()); 112 e.printStackTrace(); 113 return null; 114 } 115 } 116 117 public static HashMap<String, String> getInfo(File outputFile) { 118 try { 119 BufferedReader reader = new BufferedReader(new FileReader(outputFile)); 120 String line = null; 121 HashMap<String, String> info = new HashMap<String, String>(); 122 while ((line = reader.readLine()) != null) { 123 int idx = line.indexOf(','); 124 if (idx >= 0) { 125 String key = line.substring(0, idx).trim(); 126 String value = line.substring(idx + 1).trim(); 127 if (value.indexOf('(') >= 0 && value.indexOf(')') >= 0) { 128 value = value.substring(value.indexOf('(') + 1, value.indexOf(')')); 129 if (value.indexOf('/') >= 0) { 130 String bound = value.substring(value.indexOf('/') + 1); 131 if (bound.indexOf("..") >= 0) { 132 String min = bound.substring(0, bound.indexOf("..")); 133 String max = bound.substring(bound.indexOf("..") + 2); 134 info.put(key + " Min", min); 135 info.put(key + " Max", max); 136 } else { 137 info.put(key + " Bound", bound); 138 } 139 value = value.substring(0, value.indexOf('/')); 140 } 141 } 142 if (value.length() > 0) 143 info.put(key, value); 144 } 145 } 146 reader.close(); 147 return info; 148 } catch (Exception e) { 149 System.err.println("Error reading info, message: " + e.getMessage()); 150 e.printStackTrace(); 151 return null; 152 } 153 } 154 155 public static HashMap<String, String> getInfo(Element root) { 156 try { 157 HashMap<String, String> info = new HashMap<String, String>(); 158 for (Iterator<?> i = root.elementIterator("property"); i.hasNext();) { 159 Element property = (Element) i.next(); 160 String key = property.attributeValue("name"); 161 String value = property.getText(); 162 if (key == null || value == null) 163 continue; 164 if (value.indexOf('(') >= 0 && value.indexOf(')') >= 0) { 165 value = value.substring(value.indexOf('(') + 1, value.indexOf(')')); 166 if (value.indexOf('/') >= 0) { 167 String bound = value.substring(value.indexOf('/') + 1); 168 if (bound.indexOf("..") >= 0) { 169 String min = bound.substring(0, bound.indexOf("..")); 170 String max = bound.substring(bound.indexOf("..") + 2); 171 info.put(key + " Min", min); 172 info.put(key + " Max", max); 173 } else { 174 info.put(key + " Bound", bound); 175 } 176 value = value.substring(0, value.indexOf('/')); 177 } 178 } 179 if (value.length() > 0) 180 info.put(key, value); 181 182 } 183 return info; 184 } catch (Exception e) { 185 System.err.println("Error reading info, message: " + e.getMessage()); 186 return null; 187 } 188 } 189 190 public static void getInfo(File folder, List<Info> infos, String prefix) { 191 File infoFile = new File(folder, "info.xml"); 192 if (infoFile.exists()) { 193 System.out.println("Reading " + infoFile + " ..."); 194 try { 195 Document document = (new SAXReader()).read(infoFile); 196 HashMap<String, String> info = getInfo(document.getRootElement()); 197 if (info != null && !info.isEmpty()) { 198 infos.add(new Info(prefix, info)); 199 return; 200 } 201 } catch (Exception e) { 202 System.err.println("Error reading file " + infoFile + ", message: " + e.getMessage()); 203 } 204 } 205 File solutionFile = new File(folder, "solution.xml"); 206 if (solutionFile.exists()) { 207 /* 208 * File newOutputFile = new File(folder, "new-output.csv"); if 209 * (newOutputFile.exists()) { 210 * System.out.println("Reading "+newOutputFile+" ..."); try { 211 * HashMap info = getInfo(newOutputFile); if (info!=null && 212 * !info.isEmpty()) { infos.addElement(new Object[]{prefix,info}); 213 * return; } } catch (Exception e) { 214 * System.err.println("Error reading file " 215 * +infoFile+", message: "+e.getMessage()); } } 216 */ 217 System.out.println("Reading " + solutionFile + " ..."); 218 try { 219 HashMap<String, String> info = getInfoOfASolution(solutionFile); 220 if (info != null && !info.isEmpty()) { 221 infos.add(new Info(prefix, info)); 222 return; 223 } 224 } catch (Exception e) { 225 System.err.println("Error reading file " + infoFile + ", message: " + e.getMessage()); 226 } 227 } 228 File outputFile = new File(folder, "output.csv"); 229 if (outputFile.exists()) { 230 System.out.println("Reading " + outputFile + " ..."); 231 try { 232 HashMap<String, String> info = getInfo(outputFile); 233 if (info != null && !info.isEmpty()) { 234 infos.add(new Info(prefix, info)); 235 return; 236 } 237 } catch (Exception e) { 238 System.err.println("Error reading file " + infoFile + ", message: " + e.getMessage()); 239 } 240 } 241 } 242 243 public static void getInfos(File folder, List<Info> infos, String prefix) { 244 System.out.println("Checking " + folder + " ..."); 245 File[] files = folder.listFiles(); 246 getInfo(folder, infos, (prefix == null ? "" : prefix)); 247 for (int i = 0; i < files.length; i++) 248 if (files[i].isDirectory()) 249 getInfos(files[i], infos, (prefix == null ? "" : prefix + "/") + files[i].getName()); 250 } 251 252 public static void writeInfos(List<Info> infos, File file) { 253 try { 254 System.out.println("Writing " + file + " ..."); 255 TreeSet<String> keys = new TreeSet<String>(); 256 ArrayList<CSVFile.CSVField> headers = new ArrayList<CSVFile.CSVField>(); 257 headers.add(new CSVFile.CSVField("")); 258 for (Info o : infos) { 259 keys.addAll(o.getInfo().keySet()); 260 headers.add(new CSVFile.CSVField(o.getPrefix())); 261 } 262 CSVFile csvFile = new CSVFile(); 263 csvFile.setHeader(headers); 264 for (String key : keys) { 265 ArrayList<CSVFile.CSVField> line = new ArrayList<CSVFile.CSVField>(); 266 line.add(new CSVFile.CSVField(key)); 267 for (Info o : infos) { 268 Map<String, String> info = o.getInfo(); 269 String value = info.get(key); 270 line.add(new CSVFile.CSVField(value == null ? "" : value)); 271 } 272 csvFile.addLine(line); 273 } 274 csvFile.save(file); 275 } catch (Exception e) { 276 System.err.println("Error writing file " + file + ", message: " + e.getMessage()); 277 } 278 } 279 280 public static void main(String[] args) { 281 try { 282 BasicConfigurator.configure(); 283 File folder = new File(args[0]); 284 List<Info> infos = new ArrayList<Info>(); 285 getInfos(folder, infos, null); 286 if (!infos.isEmpty()) 287 writeInfos(infos, new File(folder, "info.csv")); 288 } catch (Exception e) { 289 e.printStackTrace(); 290 } 291 } 292 293 public static class Info { 294 private String iPrefix; 295 private HashMap<String, String> iInfo; 296 297 public Info(String prefix, HashMap<String, String> info) { 298 iPrefix = prefix; 299 iInfo = info; 300 } 301 302 public String getPrefix() { 303 return iPrefix; 304 } 305 306 public Map<String, String> getInfo() { 307 return iInfo; 308 } 309 } 310}