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