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