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}