001package arcommon.xml; 002 003import java.lang.reflect.Field; 004import java.util.HashMap; 005import java.util.Map; 006 007import arcommon.ReflectionUtil; 008import arcommon.persistens.AbstractSettingWithFrameDialogAndTableSettings; 009import arcommon.persistens.AbstractWindowSettings; 010import arcommon.persistens.DialogSettings; 011import arcommon.persistens.FrameSettings; 012import arcommon.persistens.MyJTableSettings; 013import arcommon.persistens.PlatformDependentString; 014 015public class XmlDeserializerMapper { 016 public static enum LogLevel {ERROR, WARNING, INFO, IGNORE}; 017 018 public static LogLevel classMissingLogLevel = LogLevel.WARNING; 019 public static LogLevel classMappedLogLevel = LogLevel.WARNING; 020 public static LogLevel fieldMissingLogLevel = LogLevel.WARNING; 021 public static LogLevel fieldMappedLogLevel = LogLevel.WARNING; 022 public static LogLevel fieldTypeMismatchLogLevel = LogLevel.ERROR; 023 024 private static HashMap<String, Class<?>> classMapping = new HashMap<String, Class<?>>(); 025 private static HashMap<Class<?>, HashMap<String, Field>> fieldRenameMapping = new HashMap<Class<?>, HashMap<String, Field>>(); 026 027 static { 028 addClassMapping("util.persistens.AbstractFrameDialogSettings", AbstractWindowSettings.class); // TODO Remove when all settings have been converted. 029 addClassMapping("util.ui.MyJTableSettings", MyJTableSettings.class); // TODO Remove when all settings have been converted. 030 031 addClassMapping("util.persistens.AbstractSettingWithFrameDialogAndTableSettings", AbstractSettingWithFrameDialogAndTableSettings.class); // TODO Remove when all settings have been converted. 032 addClassMapping("util.persistens.AbstractWindowSettings", AbstractWindowSettings.class); // TODO Remove when all settings have been converted. 033 addClassMapping("util.persistens.DialogSettings", DialogSettings.class); // TODO Remove when all settings have been converted. 034 addClassMapping("util.persistens.FrameSettings", FrameSettings.class); // TODO Remove when all settings have been converted. 035 addClassMapping("util.persistens.MyJTableSettings", MyJTableSettings.class); // TODO Remove when all settings have been converted. 036 addClassMapping("util.persistens.PlatformDependentString", PlatformDependentString.class); // TODO Remove when all settings have been converted. 037 } 038 039 public static void addClassMapping(String oldClassName, Class<?> newClass) { 040 if (classMapping.containsKey(oldClassName)) { 041 throw new RuntimeException("The \"" + oldClassName + "\" class is already map to " + classMapping.get(oldClassName).getName()); 042 } 043 if (oldClassName.equals(newClass.getName())) { 044 throw new RuntimeException("The \"" + oldClassName + "\" class can't map to it self " + newClass.getName()); 045 } 046 classMapping.put(oldClassName, newClass); 047 } 048 049 public static void addFieldRenameMapping(Class<?> clazz, String oldFieldName, String newFieldName) { 050 HashMap<String, Field> fieldRenameClassMap = fieldRenameMapping.get(clazz); 051 if (fieldRenameClassMap == null) { 052 fieldRenameClassMap = new HashMap<String, Field>(); 053 fieldRenameMapping.put(clazz, fieldRenameClassMap); 054 } 055 056 if (fieldRenameClassMap.containsKey(oldFieldName)) { 057 throw new RuntimeException("The \"" + oldFieldName + "\" field in \"" + clazz.getName() + "\" class is already map to " + fieldRenameClassMap.get(oldFieldName).getName()); 058 } 059 if (oldFieldName.equals(newFieldName)) { 060 throw new RuntimeException("The \"" + oldFieldName + "\" field can't map to it self " + newFieldName); 061 } 062 063 Field field = ReflectionUtil.findField(clazz, newFieldName, true); 064 fieldRenameClassMap.put(oldFieldName, field); 065 } 066 067 private XmlDeserializer xmlDeserializer; 068 069 private HashMap<String, Class<?>> classCacheMap; 070 private Map<Class<?>, Map<String, Field>> fieldCacheMap; 071 072 public XmlDeserializerMapper(XmlDeserializer pxmlDeserializer) { 073 xmlDeserializer = pxmlDeserializer; 074 classCacheMap = new HashMap<String, Class<?>>(); 075 fieldCacheMap = new HashMap<Class<?>, Map<String, Field>>(); 076 } 077 078 public Class<?> loadClassWithLogLevel(String className) { 079 Class<?> clazz = classCacheMap.get(className); 080 if (clazz != null) { 081 return clazz; 082 } 083 084 String classNameNoArray = className; 085 int dimensions = 0; 086 while (classNameNoArray.endsWith("[]")) { 087 classNameNoArray = classNameNoArray.substring(0, classNameNoArray.length() - 2); 088 dimensions++; 089 } 090 091 clazz = classMapping.get(classNameNoArray); 092 if (clazz != null) { 093 if (dimensions > 0) { 094 String dimensionsString = ""; 095 for (int i = 0; i < dimensions; i++) { 096 dimensionsString += "[]"; 097 } 098 String mappedToClassName = clazz.getName() + dimensionsString; 099 clazz = ReflectionUtil.classNameInJavaSyntaxToClass(mappedToClassName, true); 100 } 101 102 switch (classMappedLogLevel) { 103 case ERROR : 104 throw new RuntimeException("The class \"" + className + "\" was mapped to \"" + clazz.getName() + "\""); 105// break; 106 case WARNING : 107 System.err.println("WARNING: The class \"" + className + "\" was mapped to \"" + clazz.getName() + "\". Note: This warning will only be given once per deserialization."); 108 break; 109 case INFO : 110 System.out.println("Info: The class \"" + className + "\" was mapped to \"" + clazz.getName() + "\". Note: This info will only be given once per deserialization."); 111 break; 112 case IGNORE : 113 ; 114 break; 115 default : 116 throw new RuntimeException("Internal error " + classMappedLogLevel); 117 } 118 119 classCacheMap.put(className, clazz); 120 return clazz; 121 } 122 123 clazz = ReflectionUtil.classNameInJavaSyntaxToClass(className, false); 124 classCacheMap.put(className, clazz); 125 126 if (clazz == null) { 127 if (xmlDeserializer.getResultObject() == null) { 128 throw new RuntimeException("The top level class \"" + className + "\" was not found. Object can't be deserialized."); 129 } 130 switch (classMissingLogLevel) { 131 case ERROR : 132 throw new RuntimeException("The class \"" + className + "\" was not found"); 133// break; 134 case WARNING : 135 System.err.println("WARNING: The class \"" + className + "\" was not found. All values in the object will not be loaded."); 136 break; 137 case INFO : 138 System.out.println("Info: The class \"" + className + "\" was not found. All values in the object will not be loaded."); 139 break; 140 case IGNORE : 141 ; 142 break; 143 default : 144 throw new RuntimeException("Internal error " + classMissingLogLevel); 145 } 146 } 147 148 return clazz; 149 } 150 151 public Field findField(Class<?> clazz, String name) { 152 Map<String, Field> map = fieldCacheMap.get(clazz); 153 if (map == null) { 154 map = new HashMap<String, Field>(); 155 fieldCacheMap.put(clazz, map); 156 } 157 158 Field field = map.get(name); 159 if (field != null) { 160 return field; 161 } 162 163 HashMap<String, Field> fieldRenameClassMap = fieldRenameMapping.get(clazz); 164 if (fieldRenameClassMap != null) { 165 field = fieldRenameClassMap.get(name); 166 if (field != null) { 167 switch (fieldMappedLogLevel) { 168 case ERROR : 169 throw new RuntimeException("The \"" + name + "\" field in \"" + clazz.getName() + "\" class was mapped to \"" + field.getName() + "\""); 170// break; 171 case WARNING : 172 System.err.println("WARNING: The \"" + name + "\" field in \"" + clazz.getName() + "\" class was mapped to \"" + field.getName() + "\". Note: This warning will only be given once per deserialization."); 173 break; 174 case INFO : 175 System.out.println("Info: The \"" + name + "\" field in \"" + clazz.getName() + "\" class was mapped to \"" + field.getName() + "\". Note: This warning will only be given once per deserialization."); 176 break; 177 case IGNORE : 178 ; 179 break; 180 default : 181 throw new RuntimeException("Internal error " + fieldMappedLogLevel); 182 } 183 184 map.put(name, field); 185 return field; 186 } 187 } 188 189 field = ReflectionUtil.findField(clazz, name, false); 190 map.put(name, field); 191 192 if (field == null) { 193 switch (fieldMissingLogLevel) { 194 case ERROR : 195 throw new RuntimeException("Field \"" + name + "\" was not found in class \"" + clazz.toString() + "\""); 196 // break; 197 case WARNING : 198 System.err.println("WARNING: Field \"" + name + "\" was not found in class \"" + clazz.toString() + "\". The field value will not be loaded."); 199 break; 200 case INFO : 201 System.out.println("Info: Field \"" + name + "\" was not found in class \"" + clazz.toString() + "\". The field value will not be loaded."); 202 break; 203 case IGNORE : 204 ; 205 break; 206 default : 207 throw new RuntimeException("Internal error " + fieldMissingLogLevel); 208 } 209 } 210 211 return field; 212 } 213}