001package org.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 * @author Tomáš Müller 025 * @version CourseTT 1.3 (University Course Timetabling)<br> 026 * Copyright (C) 2006 - 2014 Tomáš Müller<br> 027 * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br> 028 * <a href="http://muller.unitime.org">http://muller.unitime.org</a><br> 029 * <br> 030 * This library is free software; you can redistribute it and/or modify 031 * it under the terms of the GNU Lesser General Public License as 032 * published by the Free Software Foundation; either version 3 of the 033 * License, or (at your option) any later version. <br> 034 * <br> 035 * This library is distributed in the hope that it will be useful, but 036 * WITHOUT ANY WARRANTY; without even the implied warranty of 037 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 038 * Lesser General Public License for more details. <br> 039 * <br> 040 * You should have received a copy of the GNU Lesser General Public 041 * License along with this library; if not see 042 * <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>. 043 */ 044public class IdConvertor { 045 private static org.apache.logging.log4j.Logger sLogger = org.apache.logging.log4j.LogManager.getLogger(IdConvertor.class); 046 private static IdConvertor sInstance = null; 047 private HashMap<String, HashMap<String, String>> iConversion = new HashMap<String, HashMap<String, String>>(); 048 private String iFile = null; 049 050 /** 051 * Constructor -- use {@link IdConvertor#getInstance} to get an instance of 052 * this class. 053 * @param file file to load / save 054 */ 055 public IdConvertor(String file) { 056 iFile = file; 057 load(); 058 } 059 060 /** Get an instance of IdConvertor class. 061 * @return static instance 062 **/ 063 public static IdConvertor getInstance() { 064 if (sInstance == null) 065 sInstance = new IdConvertor(null); 066 return sInstance; 067 } 068 069 /** Convert id of given type. 070 * @param type object type 071 * @param id unique id 072 * @return serialized (obfuscated) id 073 **/ 074 public String convert(String type, String id) { 075 synchronized (iConversion) { 076 HashMap<String, String> conversion = iConversion.get(type); 077 if (conversion == null) { 078 conversion = new HashMap<String, String>(); 079 iConversion.put(type, conversion); 080 } 081 String newId = conversion.get(id); 082 if (newId == null) { 083 newId = String.valueOf(conversion.size() + 1); 084 conversion.put(id, newId); 085 } 086 return newId; 087 } 088 } 089 090 /** 091 * Clear id conversion table. 092 */ 093 public void clear() { 094 iConversion.clear(); 095 } 096 097 /** 098 * Save id conversion file. 099 * @param file id file to save 100 */ 101 public void save(File file) { 102 file.getParentFile().mkdirs(); 103 Document document = DocumentHelper.createDocument(); 104 Element root = document.addElement("id-convertor"); 105 synchronized (iConversion) { 106 for (Map.Entry<String, HashMap<String, String>> entry : iConversion.entrySet()) { 107 String type = entry.getKey(); 108 HashMap<String, String> conversion = entry.getValue(); 109 Element convEl = root.addElement(type); 110 for (Map.Entry<String, String> idConv : conversion.entrySet()) { 111 convEl.addElement("conv").addAttribute("old", idConv.getKey()).addAttribute("new", 112 idConv.getValue()); 113 } 114 } 115 } 116 FileOutputStream fos = null; 117 try { 118 fos = new FileOutputStream(file); 119 (new XMLWriter(fos, OutputFormat.createPrettyPrint())).write(document); 120 fos.flush(); 121 fos.close(); 122 fos = null; 123 } catch (Exception e) { 124 sLogger.error("Unable to save id conversions, reason: " + e.getMessage(), e); 125 } finally { 126 try { 127 if (fos != null) 128 fos.close(); 129 } catch (IOException e) { 130 } 131 } 132 } 133 134 /** 135 * Save id conversion file. Name of the file needs to be provided by system 136 * property IdConvertor.File 137 */ 138 public void save() { 139 if (iFile == null) 140 iFile = System.getProperty("IdConvertor.File"); 141 if (iFile != null) save(new File(iFile)); 142 } 143 144 /** 145 * Load id conversion file. 146 * @param file id file to load 147 */ 148 public void load(File file) { 149 if (!file.exists()) return; 150 try { 151 Document document = (new SAXReader()).read(file); 152 Element root = document.getRootElement(); 153 synchronized (iConversion) { 154 iConversion.clear(); 155 for (Iterator<?> i = root.elementIterator(); i.hasNext();) { 156 Element convEl = (Element) i.next(); 157 HashMap<String, String> conversion = new HashMap<String, String>(); 158 iConversion.put(convEl.getName(), conversion); 159 for (Iterator<?> j = convEl.elementIterator("conv"); j.hasNext();) { 160 Element e = (Element) j.next(); 161 conversion.put(e.attributeValue("old"), e.attributeValue("new")); 162 } 163 } 164 } 165 } catch (Exception e) { 166 sLogger.error("Unable to load id conversions, reason: " + e.getMessage(), e); 167 } 168 } 169 170 /** 171 * Load id conversion file. Name of the file needs to be provided by system 172 * property IdConvertor.File 173 */ 174 public void load() { 175 if (iFile == null) 176 iFile = System.getProperty("IdConvertor.File"); 177 if (iFile != null) load(new File(iFile)); 178 } 179}