    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}