001    package net.sf.cpsolver.coursett;
002    
003    import java.io.File;
004    import java.io.FileOutputStream;
005    import java.io.IOException;
006    import java.util.HashMap;
007    import java.util.Iterator;
008    import java.util.Map;
009    
010    import org.dom4j.Document;
011    import org.dom4j.DocumentHelper;
012    import org.dom4j.Element;
013    import org.dom4j.io.OutputFormat;
014    import org.dom4j.io.SAXReader;
015    import org.dom4j.io.XMLWriter;
016    
017    /**
018     * Conversion of ids to sequential numbers. This class is used by
019     * {@link TimetableXMLSaver} to anonymise benchmark data sets. Conversion file
020     * can be provided by IdConvertor.File system property (e.g.
021     * -DIdConvertor.File=.\idconf.xml). <br>
022     * <br>
023     * 
024     * @version CourseTT 1.2 (University Course Timetabling)<br>
025     *          Copyright (C) 2006 - 2010 Tomas Muller<br>
026     *          <a href="mailto:muller@unitime.org">muller@unitime.org</a><br>
027     *          <a href="http://muller.unitime.org">http://muller.unitime.org</a><br>
028     * <br>
029     *          This library is free software; you can redistribute it and/or modify
030     *          it under the terms of the GNU Lesser General Public License as
031     *          published by the Free Software Foundation; either version 3 of the
032     *          License, or (at your option) any later version. <br>
033     * <br>
034     *          This library is distributed in the hope that it will be useful, but
035     *          WITHOUT ANY WARRANTY; without even the implied warranty of
036     *          MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
037     *          Lesser General Public License for more details. <br>
038     * <br>
039     *          You should have received a copy of the GNU Lesser General Public
040     *          License along with this library; if not see
041     *          <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>.
042     */
043    public class IdConvertor {
044        private static org.apache.log4j.Logger sLogger = org.apache.log4j.Logger.getLogger(IdConvertor.class);
045        private static IdConvertor sInstance = null;
046        private HashMap<String, HashMap<String, String>> iConversion = new HashMap<String, HashMap<String, String>>();
047        private String iFile = null;
048    
049        /**
050         * Constructor -- use {@link IdConvertor#getInstance} to get an instance of
051         * this class.
052         */
053        protected IdConvertor(String file) {
054            iFile = file;
055            load();
056        }
057    
058        /** Get an instance of IdConvertor class. */
059        public static IdConvertor getInstance() {
060            if (sInstance == null)
061                sInstance = new IdConvertor(null);
062            return sInstance;
063        }
064    
065        /** Convert id of given type. */
066        public String convert(String type, String id) {
067            synchronized (iConversion) {
068                HashMap<String, String> conversion = iConversion.get(type);
069                if (conversion == null) {
070                    conversion = new HashMap<String, String>();
071                    iConversion.put(type, conversion);
072                }
073                String newId = conversion.get(id);
074                if (newId == null) {
075                    newId = String.valueOf(conversion.size() + 1);
076                    conversion.put(id, newId);
077                }
078                return newId;
079            }
080        }
081    
082        /**
083         * Save id conversion file. Name of the file needs to be provided by system
084         * property IdConvertor.File
085         */
086        public void save() {
087            (new File(iFile)).getParentFile().mkdirs();
088            Document document = DocumentHelper.createDocument();
089            Element root = document.addElement("id-convertor");
090            synchronized (iConversion) {
091                for (Map.Entry<String, HashMap<String, String>> entry : iConversion.entrySet()) {
092                    String type = entry.getKey();
093                    HashMap<String, String> conversion = entry.getValue();
094                    Element convEl = root.addElement(type);
095                    for (Map.Entry<String, String> idConv : conversion.entrySet()) {
096                        convEl.addElement("conv").addAttribute("old", idConv.getKey()).addAttribute("new",
097                                idConv.getValue());
098                    }
099                }
100            }
101            FileOutputStream fos = null;
102            try {
103                fos = new FileOutputStream(iFile);
104                (new XMLWriter(fos, OutputFormat.createPrettyPrint())).write(document);
105                fos.flush();
106                fos.close();
107                fos = null;
108            } catch (Exception e) {
109                sLogger.error("Unable to save id conversions, reason: " + e.getMessage(), e);
110            } finally {
111                try {
112                    if (fos != null)
113                        fos.close();
114                } catch (IOException e) {
115                }
116            }
117        }
118    
119        /**
120         * Load id conversion file. Name of the file needs to be provided by system
121         * property IdConvertor.File
122         */
123        public void load() {
124            try {
125                if (iFile == null)
126                    iFile = System.getProperty("IdConvertor.File", "idconv.xml");
127                if (iFile == null || !(new File(iFile)).exists())
128                    return;
129                Document document = (new SAXReader()).read(iFile);
130                Element root = document.getRootElement();
131                synchronized (iConversion) {
132                    iConversion.clear();
133                    for (Iterator<?> i = root.elementIterator(); i.hasNext();) {
134                        Element convEl = (Element) i.next();
135                        HashMap<String, String> conversion = new HashMap<String, String>();
136                        iConversion.put(convEl.getName(), conversion);
137                        for (Iterator<?> j = convEl.elementIterator("conv"); j.hasNext();) {
138                            Element e = (Element) j.next();
139                            conversion.put(e.attributeValue("old"), e.attributeValue("new"));
140                        }
141                    }
142                }
143            } catch (Exception e) {
144                sLogger.error("Unable to load id conversions, reason: " + e.getMessage(), e);
145            }
146        }
147    }