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