    001package net.sf.cpsolver.coursett;
    002
    003import java.io.File;
    004import java.io.FileOutputStream;
    005import java.io.IOException;
    006import java.util.HashMap;
    007import java.util.Iterator;
    008import java.util.Map;
    009
    010import org.dom4j.Document;
    011import org.dom4j.DocumentHelper;
    012import org.dom4j.Element;
    013import org.dom4j.io.OutputFormat;
    014import org.dom4j.io.SAXReader;
    015import 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 Tomáš Müller<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 */
    043public 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}