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         * Clear id conversion table.
084         */
085        public void clear() {
086            iConversion.clear();
087        }
088    
089        /**
090         * Save id conversion file.
091         * @param file id file to save
092         */
093        public void save(File file) {
094            file.getParentFile().mkdirs();
095            Document document = DocumentHelper.createDocument();
096            Element root = document.addElement("id-convertor");
097            synchronized (iConversion) {
098                for (Map.Entry<String, HashMap<String, String>> entry : iConversion.entrySet()) {
099                    String type = entry.getKey();
100                    HashMap<String, String> conversion = entry.getValue();
101                    Element convEl = root.addElement(type);
102                    for (Map.Entry<String, String> idConv : conversion.entrySet()) {
103                        convEl.addElement("conv").addAttribute("old", idConv.getKey()).addAttribute("new",
104                                idConv.getValue());
105                    }
106                }
107            }
108            FileOutputStream fos = null;
109            try {
110                fos = new FileOutputStream(file);
111                (new XMLWriter(fos, OutputFormat.createPrettyPrint())).write(document);
112                fos.flush();
113                fos.close();
114                fos = null;
115            } catch (Exception e) {
116                sLogger.error("Unable to save id conversions, reason: " + e.getMessage(), e);
117            } finally {
118                try {
119                    if (fos != null)
120                        fos.close();
121                } catch (IOException e) {
122                }
123            }
124        }
125        
126        /**
127         * Save id conversion file. Name of the file needs to be provided by system
128         * property IdConvertor.File
129         */
130        public void save() {
131            if (iFile == null)
132                iFile = System.getProperty("IdConvertor.File");
133            if (iFile != null) save(new File(iFile));
134        }
135    
136        /**
137         * Load id conversion file.
138         * @param file id file to load
139         */
140        public void load(File file) {
141            if (!file.exists()) return;
142            try {
143                Document document = (new SAXReader()).read(file);
144                Element root = document.getRootElement();
145                synchronized (iConversion) {
146                    iConversion.clear();
147                    for (Iterator<?> i = root.elementIterator(); i.hasNext();) {
148                        Element convEl = (Element) i.next();
149                        HashMap<String, String> conversion = new HashMap<String, String>();
150                        iConversion.put(convEl.getName(), conversion);
151                        for (Iterator<?> j = convEl.elementIterator("conv"); j.hasNext();) {
152                            Element e = (Element) j.next();
153                            conversion.put(e.attributeValue("old"), e.attributeValue("new"));
154                        }
155                    }
156                }
157            } catch (Exception e) {
158                sLogger.error("Unable to load id conversions, reason: " + e.getMessage(), e);
159            }
160        }
161        
162        /**
163         * Load id conversion file. Name of the file needs to be provided by system
164         * property IdConvertor.File
165         */
166        public void load() {
167            if (iFile == null)
168                iFile = System.getProperty("IdConvertor.File");
169            if (iFile != null) load(new File(iFile));
170        }
171    }