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 * @version CourseTT 1.3 (University Course Timetabling)<br> 025 * Copyright (C) 2006 - 2014 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.logging.log4j.Logger sLogger = org.apache.logging.log4j.LogManager.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 * @param file file to load / save 053 */ 054 public IdConvertor(String file) { 055 iFile = file; 056 load(); 057 } 058 059 /** Get an instance of IdConvertor class. 060 * @return static instance 061 **/ 062 public static IdConvertor getInstance() { 063 if (sInstance == null) 064 sInstance = new IdConvertor(null); 065 return sInstance; 066 } 067 068 /** Convert id of given type. 069 * @param type object type 070 * @param id unique id 071 * @return serialized (obfuscated) id 072 **/ 073 public String convert(String type, String id) { 074 synchronized (iConversion) { 075 HashMap<String, String> conversion = iConversion.get(type); 076 if (conversion == null) { 077 conversion = new HashMap<String, String>(); 078 iConversion.put(type, conversion); 079 } 080 String newId = conversion.get(id); 081 if (newId == null) { 082 newId = String.valueOf(conversion.size() + 1); 083 conversion.put(id, newId); 084 } 085 return newId; 086 } 087 } 088 089 /** 090 * Clear id conversion table. 091 */ 092 public void clear() { 093 iConversion.clear(); 094 } 095 096 /** 097 * Save id conversion file. 098 * @param file id file to save 099 */ 100 public void save(File file) { 101 file.getParentFile().mkdirs(); 102 Document document = DocumentHelper.createDocument(); 103 Element root = document.addElement("id-convertor"); 104 synchronized (iConversion) { 105 for (Map.Entry<String, HashMap<String, String>> entry : iConversion.entrySet()) { 106 String type = entry.getKey(); 107 HashMap<String, String> conversion = entry.getValue(); 108 Element convEl = root.addElement(type); 109 for (Map.Entry<String, String> idConv : conversion.entrySet()) { 110 convEl.addElement("conv").addAttribute("old", idConv.getKey()).addAttribute("new", 111 idConv.getValue()); 112 } 113 } 114 } 115 FileOutputStream fos = null; 116 try { 117 fos = new FileOutputStream(file); 118 (new XMLWriter(fos, OutputFormat.createPrettyPrint())).write(document); 119 fos.flush(); 120 fos.close(); 121 fos = null; 122 } catch (Exception e) { 123 sLogger.error("Unable to save id conversions, reason: " + e.getMessage(), e); 124 } finally { 125 try { 126 if (fos != null) 127 fos.close(); 128 } catch (IOException e) { 129 } 130 } 131 } 132 133 /** 134 * Save id conversion file. Name of the file needs to be provided by system 135 * property IdConvertor.File 136 */ 137 public void save() { 138 if (iFile == null) 139 iFile = System.getProperty("IdConvertor.File"); 140 if (iFile != null) save(new File(iFile)); 141 } 142 143 /** 144 * Load id conversion file. 145 * @param file id file to load 146 */ 147 public void load(File file) { 148 if (!file.exists()) return; 149 try { 150 Document document = (new SAXReader()).read(file); 151 Element root = document.getRootElement(); 152 synchronized (iConversion) { 153 iConversion.clear(); 154 for (Iterator<?> i = root.elementIterator(); i.hasNext();) { 155 Element convEl = (Element) i.next(); 156 HashMap<String, String> conversion = new HashMap<String, String>(); 157 iConversion.put(convEl.getName(), conversion); 158 for (Iterator<?> j = convEl.elementIterator("conv"); j.hasNext();) { 159 Element e = (Element) j.next(); 160 conversion.put(e.attributeValue("old"), e.attributeValue("new")); 161 } 162 } 163 } 164 } catch (Exception e) { 165 sLogger.error("Unable to load id conversions, reason: " + e.getMessage(), e); 166 } 167 } 168 169 /** 170 * Load id conversion file. Name of the file needs to be provided by system 171 * property IdConvertor.File 172 */ 173 public void load() { 174 if (iFile == null) 175 iFile = System.getProperty("IdConvertor.File"); 176 if (iFile != null) load(new File(iFile)); 177 } 178}