001/* 002 * (C) Copyright 2006-2007 Nuxeo SAS <http://nuxeo.com> and others 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the Eclipse Public License v1.0 006 * which accompanies this distribution, and is available at 007 * http://www.eclipse.org/legal/epl-v10.html 008 * 009 * Contributors: 010 * Jean-Marc Orliaguet, Chalmers 011 * 012 * $Id$ 013 */ 014 015package org.nuxeo.theme.properties; 016 017import java.io.IOException; 018import java.lang.reflect.Field; 019import java.lang.reflect.ParameterizedType; 020import java.lang.reflect.Type; 021import java.util.ArrayList; 022import java.util.Collection; 023import java.util.Enumeration; 024import java.util.List; 025import java.util.Properties; 026 027import org.nuxeo.theme.Utils; 028import org.nuxeo.theme.themes.ThemeIOException; 029 030public class FieldIO { 031 032 public static FieldInfo getFieldInfo(Class<?> c, String name) { 033 try { 034 return c.getField(name).getAnnotation(FieldInfo.class); 035 } catch (SecurityException e) { 036 return null; 037 } catch (NoSuchFieldException e) { 038 return null; 039 } 040 } 041 042 public static void updateFieldsFromProperties(Object object, Properties properties) throws ThemeIOException { 043 Enumeration<?> names = properties.propertyNames(); 044 045 while (names.hasMoreElements()) { 046 String name = (String) names.nextElement(); 047 String value = properties.getProperty(name); 048 049 Class<?> c = object.getClass(); 050 051 FieldInfo fieldInfo = getFieldInfo(c, name); 052 if (fieldInfo == null) { 053 continue; 054 } 055 056 Field field; 057 try { 058 field = c.getField(name); 059 } catch (SecurityException e) { 060 throw new ThemeIOException(e); 061 } catch (NoSuchFieldException e) { 062 throw new ThemeIOException("Failed to set field '" + name + "' on " + c.getCanonicalName()); 063 } 064 065 Class<?> fieldType = field.getType(); 066 Type fieldGenericType = field.getGenericType(); 067 068 // boolean fields 069 if (fieldType.equals(boolean.class) || fieldType.equals(Boolean.class)) { 070 try { 071 field.set(object, Boolean.parseBoolean(value)); 072 } catch (IllegalArgumentException e) { 073 throw new ThemeIOException(e); 074 } catch (IllegalAccessException e) { 075 throw new ThemeIOException(e); 076 } 077 } 078 079 // string fields 080 else if (fieldType.equals(String.class)) { 081 try { 082 field.set(object, value); 083 } catch (IllegalArgumentException e) { 084 throw new ThemeIOException(e); 085 } catch (IllegalAccessException e) { 086 throw new ThemeIOException(e); 087 } 088 } 089 090 // integer fields 091 else if (fieldType.equals(int.class) || fieldType.equals(Integer.class)) { 092 try { 093 if ("".equals(value)) { 094 field.set(object, null); 095 } else { 096 field.set(object, Integer.valueOf(value)); 097 } 098 } catch (NumberFormatException e) { 099 throw new ThemeIOException("Failed to parse integer value: '" + value + "'"); 100 } catch (IllegalArgumentException e) { 101 throw new ThemeIOException(e); 102 } catch (IllegalAccessException e) { 103 throw new ThemeIOException(e); 104 } 105 } 106 107 // generics 108 else if (fieldGenericType instanceof ParameterizedType) { 109 if (fieldType.equals(ArrayList.class) || fieldType.equals(List.class) 110 || fieldType.equals(Collection.class)) { 111 112 Type[] actualTypes = ((ParameterizedType) fieldGenericType).getActualTypeArguments(); 113 114 if (actualTypes.length > 1) { 115 throw new ThemeIOException("Only one-dimension arrays are supported."); 116 } 117 118 // Collection<String> 119 if (actualTypes[0].equals(String.class)) { 120 List<String> list = new ArrayList<String>(); 121 try { 122 list = Utils.csvToList(value); 123 } catch (IOException e) { 124 throw new ThemeIOException(e); 125 } 126 try { 127 field.set(object, list); 128 } catch (IllegalArgumentException e) { 129 throw new ThemeIOException(e); 130 } catch (IllegalAccessException e) { 131 throw new ThemeIOException(e); 132 } 133 } 134 } 135 } else { 136 throw new ThemeIOException("Cannot update field type '" + name + "' of " + c.getCanonicalName() 137 + " because " + fieldType.getCanonicalName() + " is not supported."); 138 } 139 } 140 141 } 142 143 @SuppressWarnings("unchecked") 144 public static Properties dumpFieldsToProperties(Object object) throws ThemeIOException { 145 146 Properties properties = new Properties(); 147 148 Class<?> c = object.getClass(); 149 for (Field field : c.getDeclaredFields()) { 150 Class<?> fieldType = field.getType(); 151 Type fieldGenericType = field.getGenericType(); 152 String fieldName = field.getName(); 153 154 FieldInfo fieldInfo = getFieldInfo(c, fieldName); 155 if (fieldInfo == null) { 156 continue; 157 } 158 159 String property = ""; 160 Object value; 161 try { 162 value = field.get(object); 163 } catch (IllegalAccessException e) { 164 throw new ThemeIOException(e); 165 } catch (IllegalArgumentException e) { 166 throw new ThemeIOException(e); 167 } 168 169 // boolean fields 170 if (fieldType.equals(boolean.class) || fieldType.equals(Boolean.class)) { 171 if (value == null) { 172 property = "false"; 173 } else { 174 property = Boolean.parseBoolean(value.toString()) ? "true" : "false"; 175 } 176 } 177 // string fields 178 else if (fieldType.equals(String.class)) { 179 property = value == null ? "" : value.toString(); 180 } 181 // integer fields 182 else if (fieldType.equals(int.class) || fieldType.equals(Integer.class)) { 183 property = value == null ? "" : value.toString(); 184 } 185 // generics 186 else if (fieldGenericType instanceof ParameterizedType) { 187 if (fieldType.equals(ArrayList.class) || fieldType.equals(List.class) 188 || fieldType.equals(Collection.class)) { 189 190 Type[] actualTypes = ((ParameterizedType) fieldGenericType).getActualTypeArguments(); 191 192 if (actualTypes.length > 1) { 193 throw new ThemeIOException("Only one-dimension arrays are supported."); 194 } 195 196 // Collection<String> 197 if (actualTypes[0].equals(String.class)) { 198 if (value == null) { 199 property = ""; 200 } else { 201 property = Utils.listToCsv((List<String>) (value)); 202 } 203 } else { 204 throw new ThemeIOException("Only list of strings are supported."); 205 } 206 207 } 208 } else { 209 throw new ThemeIOException("Cannot extract property from field type '" + fieldName + "' of " 210 + c.getCanonicalName() + " because " + fieldType.getCanonicalName() + " is not supported."); 211 } 212 213 properties.setProperty(fieldName, property); 214 215 } 216 return properties; 217 } 218}