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