private ObjectMap<String, FieldMetadata> cacheFields(Class type) { ArrayList<Field> allFields = new ArrayList(); Class nextClass = type; while (nextClass != Object.class) { Collections.addAll(allFields, nextClass.getDeclaredFields()); nextClass = nextClass.getSuperclass(); } ObjectMap<String, FieldMetadata> nameToField = new ObjectMap(); for (int i = 0, n = allFields.size(); i < n; i++) { Field field = allFields.get(i); int modifiers = field.getModifiers(); if (Modifier.isTransient(modifiers)) continue; if (Modifier.isStatic(modifiers)) continue; if (field.isSynthetic()) continue; if (!field.isAccessible()) { try { field.setAccessible(true); } catch (AccessControlException ex) { continue; } } nameToField.put(field.getName(), new FieldMetadata(field)); } typeToFields.put(type, nameToField); return nameToField; }
/** * Returns a new or existing pool for the specified type, stored in a a Class to {@link * ReflectionPool} map. The max size of the pool used is 100. */ public <T> Pool<T> get(Class<T> type) { ReflectionPool pool = typePools.get(type); if (pool == null) { pool = new ReflectionPool(type, 4, 100); typePools.put(type, pool); } return pool; }
private Object[] getDefaultValues(Class type) { if (!usePrototypes) return null; if (classToDefaultValues.containsKey(type)) return classToDefaultValues.get(type); Object object; try { object = newInstance(type); } catch (Exception ex) { classToDefaultValues.put(type, null); return null; } ObjectMap<String, FieldMetadata> fields = typeToFields.get(type); if (fields == null) fields = cacheFields(type); Object[] values = new Object[fields.size]; classToDefaultValues.put(type, values); int i = 0; for (FieldMetadata metadata : fields.values()) { Field field = metadata.field; try { values[i++] = field.get(object); } catch (IllegalAccessException ex) { throw new SerializationException( "Error accessing field: " + field.getName() + " (" + type.getName() + ")", ex); } catch (SerializationException ex) { ex.addTrace(field + " (" + type.getName() + ")"); throw ex; } catch (RuntimeException runtimeEx) { SerializationException ex = new SerializationException(runtimeEx); ex.addTrace(field + " (" + type.getName() + ")"); throw ex; } } return values; }
/* (non-Javadoc) * @see Job#setProperty(QualifiedName,Object) */ protected void setProperty(QualifiedName key, Object value) { // thread safety: (Concurrency001 - copy on write) if (value == null) { if (properties == null) return; ObjectMap temp = (ObjectMap) properties.clone(); temp.remove(key); if (temp.isEmpty()) properties = null; else properties = temp; } else { ObjectMap temp = properties; if (temp == null) temp = new ObjectMap(5); else temp = (ObjectMap) properties.clone(); temp.put(key, value); properties = temp; } }
/** * @param type May be null if the type is unknown. * @param elementType May be null if the type is unknown. * @return May be null. */ public <T> T readValue(Class<T> type, Class elementType, Object jsonData) { if (jsonData == null) return null; if (jsonData instanceof OrderedMap) { OrderedMap<String, Object> jsonMap = (OrderedMap) jsonData; String className = typeName == null ? null : (String) jsonMap.remove(typeName); if (className != null) { try { type = (Class<T>) Class.forName(className); } catch (ClassNotFoundException ex) { type = tagToClass.get(className); if (type == null) throw new SerializationException(ex); } } Object object; if (type != null) { Serializer serializer = classToSerializer.get(type); if (serializer != null) return (T) serializer.read(this, jsonMap, type); object = newInstance(type); if (object instanceof Serializable) { ((Serializable) object).read(this, jsonMap); return (T) object; } if (object instanceof HashMap) { HashMap result = (HashMap) object; for (Entry entry : jsonMap.entries()) result.put(entry.key, readValue(elementType, null, entry.value)); return (T) result; } } else object = new OrderedMap(); if (object instanceof ObjectMap) { ObjectMap result = (ObjectMap) object; for (String key : jsonMap.orderedKeys()) result.put(key, readValue(elementType, null, jsonMap.get(key))); return (T) result; } readFields(object, jsonMap); return (T) object; } if (type != null) { Serializer serializer = classToSerializer.get(type); if (serializer != null) return (T) serializer.read(this, jsonData, type); } if (jsonData instanceof Array) { Array array = (Array) jsonData; if (type == null || Array.class.isAssignableFrom(type)) { Array newArray = type == null ? new Array() : (Array) newInstance(type); newArray.ensureCapacity(array.size); for (int i = 0, n = array.size; i < n; i++) newArray.add(readValue(elementType, null, array.get(i))); return (T) newArray; } if (ArrayList.class.isAssignableFrom(type)) { ArrayList newArray = type == null ? new ArrayList() : (ArrayList) newInstance(type); newArray.ensureCapacity(array.size); for (int i = 0, n = array.size; i < n; i++) newArray.add(readValue(elementType, null, array.get(i))); return (T) newArray; } if (type.isArray()) { Class componentType = type.getComponentType(); if (elementType == null) elementType = componentType; Object newArray = java.lang.reflect.Array.newInstance(componentType, array.size); for (int i = 0, n = array.size; i < n; i++) java.lang.reflect.Array.set(newArray, i, readValue(elementType, null, array.get(i))); return (T) newArray; } throw new SerializationException( "Unable to convert value to required type: " + jsonData + " (" + type.getName() + ")"); } if (jsonData instanceof Float) { Float floatValue = (Float) jsonData; try { if (type == null || type == float.class || type == Float.class) return (T) (Float) floatValue; if (type == int.class || type == Integer.class) return (T) (Integer) floatValue.intValue(); if (type == long.class || type == Long.class) return (T) (Long) floatValue.longValue(); if (type == double.class || type == Double.class) return (T) (Double) floatValue.doubleValue(); if (type == short.class || type == Short.class) return (T) (Short) floatValue.shortValue(); if (type == byte.class || type == Byte.class) return (T) (Byte) floatValue.byteValue(); } catch (NumberFormatException ignored) { } jsonData = String.valueOf(jsonData); } if (jsonData instanceof Boolean) jsonData = String.valueOf(jsonData); if (jsonData instanceof String) { String string = (String) jsonData; if (type == null || type == String.class) return (T) jsonData; try { if (type == int.class || type == Integer.class) return (T) Integer.valueOf(string); if (type == float.class || type == Float.class) return (T) Float.valueOf(string); if (type == long.class || type == Long.class) return (T) Long.valueOf(string); if (type == double.class || type == Double.class) return (T) Double.valueOf(string); if (type == short.class || type == Short.class) return (T) Short.valueOf(string); if (type == byte.class || type == Byte.class) return (T) Byte.valueOf(string); } catch (NumberFormatException ignored) { } if (type == boolean.class || type == Boolean.class) return (T) Boolean.valueOf(string); if (type == char.class || type == Character.class) return (T) (Character) string.charAt(0); if (type.isEnum()) { Object[] constants = type.getEnumConstants(); for (int i = 0, n = constants.length; i < n; i++) if (string.equals(constants[i].toString())) return (T) constants[i]; } if (type == CharSequence.class) return (T) string; throw new SerializationException( "Unable to convert value to required type: " + jsonData + " (" + type.getName() + ")"); } return null; }
public void addClassTag(String tag, Class type) { tagToClass.put(tag, type); classToTag.put(type, tag); }
public <T> void setSerializer(Class<T> type, Serializer<T> serializer) { classToSerializer.put(type, serializer); }
public void setAttribute(String name, String value) { if (attributes == null) attributes = new ObjectMap(8); attributes.put(name, value); }
/** * @param clazz May be null if the type is unknown. * @param elementType May be null if the type is unknown. * @return May be null. */ public <T> T readValue(Class<T> clazz, Class elementType, JsonValue jsonData) { if (jsonData == null) return null; Type type = ReflectionCache.getType(clazz); if (jsonData.isObject()) { String className = typeName == null ? null : jsonData.getString(typeName, null); if (className != null) { jsonData.remove(typeName); try { type = ReflectionCache.forName(className); } catch (ClassNotFoundException ex) { type = tagToClass.get(className); if (type == null) throw new SerializationException(ex); } } Object object; if (type != null) { Serializer serializer = classToSerializer.get(type); if (serializer != null) return (T) serializer.read(this, jsonData, type.getClassOfType()); object = newInstance(type); if (object instanceof Serializable) { ((Serializable) object).read(this, jsonData); return (T) object; } if (object instanceof HashMap) { HashMap result = (HashMap) object; for (JsonValue child = jsonData.child(); child != null; child = child.next()) result.put(child.name(), readValue(elementType, null, child)); return (T) result; } } else object = new OrderedMap(); if (object instanceof ObjectMap) { ObjectMap result = (ObjectMap) object; for (JsonValue child = jsonData.child(); child != null; child = child.next()) result.put(child.name(), readValue(elementType, null, child)); return (T) result; } readFields(object, jsonData); return (T) object; } if (type != null) { Serializer serializer = classToSerializer.get(type); if (serializer != null) return (T) serializer.read(this, jsonData, type.getClassOfType()); } if (jsonData.isArray()) { if (type == null || type.isAssignableFrom(ReflectionCache.getType(Array.class))) { Array newArray = new Array(); for (JsonValue child = jsonData.child(); child != null; child = child.next()) newArray.add(readValue(elementType, null, child)); return (T) newArray; } if (type.isAssignableFrom(ReflectionCache.getType(ArrayList.class))) { ArrayList newArray = new ArrayList(); for (JsonValue child = jsonData.child(); child != null; child = child.next()) newArray.add(readValue(elementType, null, child)); return (T) newArray; } if (type.isArray()) { Class componentType = type.getComponentType(); if (elementType == null) elementType = componentType; Object newArray = ReflectionCache.newArray(componentType, jsonData.size()); Type arrayType = ReflectionCache.getType(newArray.getClass()); int i = 0; for (JsonValue child = jsonData.child(); child != null; child = child.next()) arrayType.setArrayElement(newArray, i++, readValue(elementType, null, child)); return (T) newArray; } throw new SerializationException( "Unable to convert value to required type: " + jsonData + " (" + type.getName() + ")"); } Class t = type == null ? null : type.getClassOfType(); if (jsonData.isNumber()) { try { if (type == null || t == float.class || t == Float.class) return (T) (Float) jsonData.asFloat(); if (t == int.class || t == Integer.class) return (T) (Integer) jsonData.asInt(); if (t == long.class || t == Long.class) return (T) (Long) jsonData.asLong(); if (t == double.class || t == Double.class) return (T) (Double) (double) jsonData.asFloat(); if (t == String.class) return (T) Float.toString(jsonData.asFloat()); if (t == short.class || t == Short.class) return (T) (Short) (short) jsonData.asInt(); if (t == byte.class || t == Byte.class) return (T) (Byte) (byte) jsonData.asInt(); } catch (NumberFormatException ignored) { } jsonData = new JsonValue(jsonData.asString()); } if (jsonData.isBoolean()) { try { if (type == null || t == boolean.class || t == Boolean.class) return (T) (Boolean) jsonData.asBoolean(); } catch (NumberFormatException ignored) { } jsonData = new JsonValue(jsonData.asString()); } if (jsonData.isString()) { String string = jsonData.asString(); if (type == null || t == String.class) return (T) string; try { if (t == int.class || t == Integer.class) return (T) Integer.valueOf(string); if (t == float.class || t == Float.class) return (T) Float.valueOf(string); if (t == long.class || t == Long.class) return (T) Long.valueOf(string); if (t == double.class || t == Double.class) return (T) Double.valueOf(string); if (t == short.class || t == Short.class) return (T) Short.valueOf(string); if (t == byte.class || t == Byte.class) return (T) Byte.valueOf(string); } catch (NumberFormatException ignored) { } if (t == boolean.class || t == Boolean.class) return (T) Boolean.valueOf(string); if (t == char.class || t == Character.class) return (T) (Character) string.charAt(0); if (type.isEnum()) { Object[] constants = type.getEnumConstants(); for (int i = 0, n = constants.length; i < n; i++) if (string.equals(constants[i].toString())) return (T) constants[i]; } if (t == CharSequence.class) return (T) string; throw new SerializationException( "Unable to convert value to required type: " + jsonData + " (" + type.getName() + ")"); } return null; }
public <T> void setSerializer(Class<T> type, Serializer<T> serializer) { classToSerializer.put(ReflectionCache.getType(type), serializer); }